From af625b8b19567ff8618ab9f0a0ba76c086a5042f Mon Sep 17 00:00:00 2001 From: Lucas Alvares Gomes Date: Thu, 2 Apr 2015 14:14:39 +0100 Subject: Fix VM stuck when deploying with pxe_ssh + local boot When deploying a machine with the DIB ramdisk, pxe_ssh driver and local boot the VM will keep rebooting forever after the deployment is completed. This happens because Ironic will change the boot device from PXE to DISK as part of the deployment but the change will only take effect after the VM is powered off and on again (that's a virsh problem). This patch is fixing this problem by making Ironic reboot the machine after the deployment is completed (reboot in Ironic means power it off and on again). Closes-Bug: #1439664 Change-Id: I4aa859b00a8bba186e920e09734ec2e4c45dec3e --- ironic/drivers/modules/iscsi_deploy.py | 12 ++++++++++++ ironic/tests/drivers/test_iscsi_deploy.py | 25 +++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/ironic/drivers/modules/iscsi_deploy.py b/ironic/drivers/modules/iscsi_deploy.py index 411ceda2b..1f3234b74 100644 --- a/ironic/drivers/modules/iscsi_deploy.py +++ b/ironic/drivers/modules/iscsi_deploy.py @@ -26,7 +26,9 @@ from ironic.common.i18n import _LE from ironic.common.i18n import _LI from ironic.common import image_service as service from ironic.common import keystone +from ironic.common import states from ironic.common import utils +from ironic.conductor import utils as manager_utils from ironic.drivers.modules import deploy_utils from ironic.drivers.modules import image_cache from ironic.drivers import utils as driver_utils @@ -613,5 +615,15 @@ def finish_deploy(task, address): deploy_utils.set_failed_state(task, msg) raise exception.InstanceDeployFailure(msg) + # TODO(lucasagomes): When deploying a node with the DIB ramdisk + # Ironic will not power control the node at the end of the deployment, + # it's the DIB ramdisk that reboots the node. But, for the SSH driver + # some changes like setting the boot device only gets applied when the + # machine is powered off and on again. So the code below is enforcing + # it. For Liberty we need to change the DIB ramdisk so that Ironic + # always controls the power state of the node for all drivers. + if get_boot_option(node) == "local" and 'ssh' in node.driver: + manager_utils.node_power_action(task, states.REBOOT) + LOG.info(_LI('Deployment to node %s done'), node.uuid) task.process_event('done') diff --git a/ironic/tests/drivers/test_iscsi_deploy.py b/ironic/tests/drivers/test_iscsi_deploy.py index 70bc3b765..a0b1f40ba 100644 --- a/ironic/tests/drivers/test_iscsi_deploy.py +++ b/ironic/tests/drivers/test_iscsi_deploy.py @@ -868,3 +868,28 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase): self.assertRaises(exception.InstanceDeployFailure, iscsi_deploy.finish_deploy, task, '1.2.3.4') set_fail_state_mock.assert_called_once_with(task, mock.ANY) + + @mock.patch.object(manager_utils, 'node_power_action') + @mock.patch.object(deploy_utils, 'notify_ramdisk_to_proceed', + autospec=True) + def test_finish_deploy_ssh_with_local_boot(self, notify_mock, + node_power_mock): + instance_info = dict(INST_INFO_DICT) + instance_info['capabilities'] = {'boot_option': 'local'} + n = { + 'uuid': uuidutils.generate_uuid(), + 'driver': 'fake_ssh', + 'instance_info': instance_info, + 'provision_state': states.DEPLOYING, + 'target_provision_state': states.ACTIVE, + } + mgr_utils.mock_the_extension_manager(driver="fake_ssh") + node = obj_utils.create_test_node(self.context, **n) + + with task_manager.acquire(self.context, node.uuid, + shared=False) as task: + iscsi_deploy.finish_deploy(task, '1.2.3.4') + notify_mock.assert_called_once_with('1.2.3.4') + self.assertEqual(states.ACTIVE, task.node.provision_state) + self.assertEqual(states.NOSTATE, task.node.target_provision_state) + node_power_mock.assert_called_once_with(task, states.REBOOT) -- cgit v1.2.1