From 3467da690ff5bc101cec89428f76d59023ffe567 Mon Sep 17 00:00:00 2001
From: Galyna Zholtkevych <gzholtkevych@mirantis.com>
Date: Fri, 2 Dec 2016 16:51:47 +0200
Subject: [PATCH] Catch unknown exceptions in validate driver ifaces

The method validate_driver_interfaces in conductor manager
catches only known exceptions. But some third-party can
break this method.

Adding catch of general Exception to this method to avoid
not desirable failure and write detailed information about
exception to result and logs.

Change-Id: Ia3105b21cd42396568317bb26ff4be22cf5c5649
Closes-Bug: 1646854
---
 ironic/conductor/manager.py                    | 12 ++++++++++++
 ironic/tests/unit/conductor/test_manager.py    | 18 ++++++++++++++++++
 ...r-validate-exceptions-94ed2a91c50d2d8e.yaml |  4 ++++
 3 files changed, 34 insertions(+)
 create mode 100644 releasenotes/notes/catch-third-party-driver-validate-exceptions-94ed2a91c50d2d8e.yaml

diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py
index 81931727ef..27487708b4 100644
--- a/ironic/conductor/manager.py
+++ b/ironic/conductor/manager.py
@@ -1438,6 +1438,18 @@ class ConductorManager(base_manager.BaseConductorManager):
                             exception.UnsupportedDriverExtension) as e:
                         result = False
                         reason = str(e)
+                    except Exception as e:
+                        result = False
+                        reason = (_('Unexpected exception, traceback saved '
+                                    'into log by ironic conductor service '
+                                    'that is running on %(host)s: %(error)s')
+                                  % {'host': self.host, 'error': e})
+                        LOG.exception(_LE(
+                            'Unexpected exception occurred while validating '
+                            '%(iface)s driver interface for driver '
+                            '%(driver)s: %(err)s on node %(node)s.'),
+                            {'iface': iface_name, 'driver': task.node.driver,
+                             'err': e, 'node': task.node.uuid})
                 else:
                     reason = _('not supported')
 
diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py
index 39d9c3d312..932dbac809 100644
--- a/ironic/tests/unit/conductor/test_manager.py
+++ b/ironic/tests/unit/conductor/test_manager.py
@@ -2610,6 +2610,24 @@ class MiscTestCase(mgr_utils.ServiceSetUpMixin, mgr_utils.CommonMixIn,
             self.assertEqual(reason, ret['deploy']['reason'])
             mock_iwdi.assert_called_once_with(self.context, node.instance_info)
 
+    @mock.patch.object(images, 'is_whole_disk_image')
+    def test_validate_driver_interfaces_validation_fail_unexpected(
+            self, mock_iwdi):
+        node = obj_utils.create_test_node(self.context, driver='fake')
+        with mock.patch(
+                'ironic.drivers.modules.fake.FakeDeploy.validate'
+        ) as deploy:
+            deploy.side_effect = Exception('boom')
+            ret = self.service.validate_driver_interfaces(self.context,
+                                                          node.uuid)
+            reason = ('Unexpected exception, traceback saved '
+                      'into log by ironic conductor service '
+                      'that is running on test-host: boom')
+            self.assertFalse(ret['deploy']['result'])
+            self.assertEqual(reason, ret['deploy']['reason'])
+
+            mock_iwdi.assert_called_once_with(self.context, node.instance_info)
+
     @mock.patch.object(manager.ConductorManager, '_fail_if_in_state',
                        autospec=True)
     @mock.patch.object(manager.ConductorManager, '_mapped_to_this_conductor')
diff --git a/releasenotes/notes/catch-third-party-driver-validate-exceptions-94ed2a91c50d2d8e.yaml b/releasenotes/notes/catch-third-party-driver-validate-exceptions-94ed2a91c50d2d8e.yaml
new file mode 100644
index 0000000000..955cd91ca9
--- /dev/null
+++ b/releasenotes/notes/catch-third-party-driver-validate-exceptions-94ed2a91c50d2d8e.yaml
@@ -0,0 +1,4 @@
+---
+fixes:
+  - Catch unknown exceptions with traceback
+    when validating driver interfaces.