diff options
Diffstat (limited to 'ironic')
-rw-r--r-- | ironic/conductor/manager.py | 39 | ||||
-rw-r--r-- | ironic/tests/unit/conductor/test_manager.py | 40 |
2 files changed, 61 insertions, 18 deletions
diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index c6221a1e6..6ee1da3dc 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -665,6 +665,11 @@ class ConductorManager(base_manager.BaseConductorManager): """Internal RPC method to tear down an existing node deployment.""" node = task.node try: + # stop the console + # do it in this thread since we're already out of the main + # conductor thread. + if node.console_enabled: + self._set_console_mode(task, False) task.driver.deploy.clean_up(task) task.driver.deploy.tear_down(task) except Exception as e: @@ -1848,23 +1853,25 @@ class ConductorManager(base_manager.BaseConductorManager): # take_over() right now. else: task.driver.console.stop_console(task) + except Exception as e: - op = _('enabling') if enabled else _('disabling') - msg = (_('Error %(op)s the console on node %(node)s. ' - 'Reason: %(error)s') % {'op': op, - 'node': node.uuid, - 'error': e}) - node.last_error = msg - LOG.error(msg) - node.save() - notify_utils.emit_console_notification( - task, 'console_set', fields.NotificationStatus.ERROR) - else: - node.console_enabled = enabled - node.last_error = None - node.save() - notify_utils.emit_console_notification( - task, 'console_set', fields.NotificationStatus.END) + with excutils.save_and_reraise_exception(): + op = _('enabling') if enabled else _('disabling') + msg = (_('Error %(op)s the console on node %(node)s. ' + 'Reason: %(error)s') % {'op': op, + 'node': node.uuid, + 'error': e}) + node.last_error = msg + LOG.error(msg) + node.save() + notify_utils.emit_console_notification( + task, 'console_set', fields.NotificationStatus.ERROR) + + node.console_enabled = enabled + node.last_error = None + node.save() + notify_utils.emit_console_notification( + task, 'console_set', fields.NotificationStatus.END) @METRICS.timer('ConductorManager.create_port') @messaging.expected_exceptions(exception.NodeLocked, diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py index 619451efd..eea77adb0 100644 --- a/ironic/tests/unit/conductor/test_manager.py +++ b/ironic/tests/unit/conductor/test_manager.py @@ -1707,17 +1707,43 @@ class DoNodeDeployTearDownTestCase(mgr_utils.ServiceSetUpMixin, self.assertIsNotNone(node.last_error) # Assert instance_info was erased self.assertEqual({}, node.instance_info) - mock_tear_down.assert_called_once_with(mock.ANY) + mock_tear_down.assert_called_once_with(task) + + @mock.patch('ironic.conductor.manager.ConductorManager._set_console_mode') + def test_do_node_tear_down_console_raises_error(self, mock_console): + # test when _set_console_mode raises exception + node = obj_utils.create_test_node( + self.context, driver='fake', provision_state=states.DELETING, + target_provision_state=states.AVAILABLE, + instance_info={'foo': 'bar'}, + console_enabled=True, + driver_internal_info={'is_whole_disk_image': False}) + + task = task_manager.TaskManager(self.context, node.uuid) + self._start_service() + mock_console.side_effect = exception.ConsoleError('test') + self.assertRaises(exception.ConsoleError, + self.service._do_node_tear_down, task) + node.refresh() + self.assertEqual(states.ERROR, node.provision_state) + self.assertEqual(states.NOSTATE, node.target_provision_state) + self.assertIsNotNone(node.last_error) + # Assert instance_info was erased + self.assertEqual({}, node.instance_info) + mock_console.assert_called_once_with(task, False) + @mock.patch('ironic.conductor.manager.ConductorManager._set_console_mode') @mock.patch('ironic.conductor.manager.ConductorManager._do_node_clean') @mock.patch('ironic.drivers.modules.fake.FakeDeploy.tear_down') - def test__do_node_tear_down_ok(self, mock_tear_down, mock_clean): + def _test__do_node_tear_down_ok(self, mock_tear_down, mock_clean, + mock_console, enabled_console=False): # test when driver.deploy.tear_down succeeds node = obj_utils.create_test_node( self.context, driver='fake', provision_state=states.DELETING, target_provision_state=states.AVAILABLE, instance_uuid=uuidutils.generate_uuid(), instance_info={'foo': 'bar'}, + console_enabled=enabled_console, driver_internal_info={'is_whole_disk_image': False, 'instance': {'ephemeral_gb': 10}}) @@ -1734,6 +1760,16 @@ class DoNodeDeployTearDownTestCase(mgr_utils.ServiceSetUpMixin, self.assertNotIn('instance', node.driver_internal_info) mock_tear_down.assert_called_once_with(mock.ANY) mock_clean.assert_called_once_with(mock.ANY) + if enabled_console: + mock_console.assert_called_once_with(task, False) + else: + mock_console.assert_not_called() + + def test__do_node_tear_down_ok_without_console(self): + self._test__do_node_tear_down_ok(enabled_console=False) + + def test__do_node_tear_down_ok_with_console(self): + self._test__do_node_tear_down_ok(enabled_console=True) @mock.patch('ironic.conductor.manager.ConductorManager._do_node_clean') @mock.patch('ironic.drivers.modules.fake.FakeDeploy.tear_down') |