From 74ed19310bf6e78898a5b0e5d76808068396f848 Mon Sep 17 00:00:00 2001 From: Zhenguo Niu Date: Thu, 19 Nov 2015 16:41:05 +0800 Subject: [PATCH] Take over console session if enabled Currently there's no support for taking over console session, just leave the console_enabled status True, but no shellinabox process running. This patch tries to start console in the new conductor and sets console_enabled to False if failed. Closes-Bug: #1519725 Change-Id: I62a83aa8adb8d73248e1a8dd6f840263fa60ae60 --- ironic/conductor/manager.py | 14 +++++ ironic/tests/unit/conductor/test_manager.py | 61 +++++++++++++++++++++ 2 files changed, 75 insertions(+) diff --git a/ironic/conductor/manager.py b/ironic/conductor/manager.py index 4e639c971a..167a1d0e06 100644 --- a/ironic/conductor/manager.py +++ b/ironic/conductor/manager.py @@ -1365,6 +1365,20 @@ class ConductorManager(periodic_task.PeriodicTasks): {'cdr': self.host, 'node': task.node.uuid}) task.driver.deploy.prepare(task) task.driver.deploy.take_over(task) + # NOTE(zhenguo): If console enabled, take over the console session + # as well. + if task.node.console_enabled: + try: + task.driver.console.start_console(task) + except Exception as err: + msg = (_('Failed to start console while taking over the ' + 'node %(node)s: %(err)s.') % {'node': task.node.uuid, + 'err': err}) + LOG.error(msg) + # If taking over console failed, set node's console_enabled + # back to False and set node's last error. + task.node.last_error = msg + task.node.console_enabled = False # NOTE(lucasagomes): Set the ID of the new conductor managing # this node task.node.conductor_affinity = self.conductor.id diff --git a/ironic/tests/unit/conductor/test_manager.py b/ironic/tests/unit/conductor/test_manager.py index ce6d551f87..9da9c79191 100644 --- a/ironic/tests/unit/conductor/test_manager.py +++ b/ironic/tests/unit/conductor/test_manager.py @@ -4507,3 +4507,64 @@ class TestIndirectionApiConductor(tests_db_base.DbTestCase): self.assertEqual(result, fake_backported_obj) test_obj.obj_to_primitive.assert_called_once_with( target_version='1.0', version_manifest=fake_version_manifest) + + +@_mock_record_keepalive +class DoNodeTakeOverTestCase(_ServiceSetUpMixin, + tests_db_base.DbTestCase): + + @mock.patch('ironic.drivers.modules.fake.FakeConsole.start_console') + @mock.patch('ironic.drivers.modules.fake.FakeDeploy.take_over') + @mock.patch('ironic.drivers.modules.fake.FakeDeploy.prepare') + def test__do_takeover(self, mock_prepare, mock_take_over, + mock_start_console): + self._start_service() + node = obj_utils.create_test_node(self.context, driver='fake') + task = task_manager.TaskManager(self.context, node.uuid) + + self.service._do_takeover(task) + node.refresh() + self.assertIsNone(node.last_error) + self.assertFalse(node.console_enabled) + mock_prepare.assert_called_once_with(mock.ANY) + mock_take_over.assert_called_once_with(mock.ANY) + self.assertFalse(mock_start_console.called) + + @mock.patch('ironic.drivers.modules.fake.FakeConsole.start_console') + @mock.patch('ironic.drivers.modules.fake.FakeDeploy.take_over') + @mock.patch('ironic.drivers.modules.fake.FakeDeploy.prepare') + def test__do_takeover_with_console_enabled(self, mock_prepare, + mock_take_over, + mock_start_console): + self._start_service() + node = obj_utils.create_test_node(self.context, driver='fake', + console_enabled=True) + task = task_manager.TaskManager(self.context, node.uuid) + + self.service._do_takeover(task) + node.refresh() + self.assertIsNone(node.last_error) + self.assertTrue(node.console_enabled) + mock_prepare.assert_called_once_with(mock.ANY) + mock_take_over.assert_called_once_with(mock.ANY) + mock_start_console.assert_called_once_with(mock.ANY) + + @mock.patch('ironic.drivers.modules.fake.FakeConsole.start_console') + @mock.patch('ironic.drivers.modules.fake.FakeDeploy.take_over') + @mock.patch('ironic.drivers.modules.fake.FakeDeploy.prepare') + def test__do_takeover_with_console_exception(self, mock_prepare, + mock_take_over, + mock_start_console): + self._start_service() + mock_start_console.side_effect = Exception() + node = obj_utils.create_test_node(self.context, driver='fake', + console_enabled=True) + task = task_manager.TaskManager(self.context, node.uuid) + + self.service._do_takeover(task) + node.refresh() + self.assertIsNotNone(node.last_error) + self.assertFalse(node.console_enabled) + mock_prepare.assert_called_once_with(mock.ANY) + mock_take_over.assert_called_once_with(mock.ANY) + mock_start_console.assert_called_once_with(mock.ANY)