summaryrefslogtreecommitdiff
path: root/ironic
diff options
context:
space:
mode:
Diffstat (limited to 'ironic')
-rw-r--r--ironic/conductor/manager.py39
-rw-r--r--ironic/tests/unit/conductor/test_manager.py40
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')