From 38201d9f2adff4cae77578445a528cdded9bcc87 Mon Sep 17 00:00:00 2001 From: Shivanand Tendulker Date: Thu, 21 Jan 2016 09:31:53 -0800 Subject: [PATCH] Fixes automated cleaning failure in iLO drivers Automated cleaning fails for iLO driver if iLO is in System POST state. iLO does not allow setting of boot device when it is in System POST state. Node needs to be powered off before initiating boot for cleaning. Closes-Bug: 1536730 Change-Id: Icd0f39d718aabdcad56636e662dec788c4e1b427 --- ironic/drivers/modules/ilo/deploy.py | 42 +++++++++++++++++ .../unit/drivers/modules/ilo/test_deploy.py | 45 +++++++++++++++++++ ...mated-cleaning-fails-14ee438de3dd8690.yaml | 7 +++ 3 files changed, 94 insertions(+) create mode 100644 releasenotes/notes/ilo-automated-cleaning-fails-14ee438de3dd8690.yaml diff --git a/ironic/drivers/modules/ilo/deploy.py b/ironic/drivers/modules/ilo/deploy.py index 0fc4bddf87..2da4f41e67 100644 --- a/ironic/drivers/modules/ilo/deploy.py +++ b/ironic/drivers/modules/ilo/deploy.py @@ -175,6 +175,20 @@ class IloVirtualMediaIscsiDeploy(iscsi_deploy.ISCSIDeploy): super(IloVirtualMediaIscsiDeploy, self).prepare(task) + def prepare_cleaning(self, task): + """Boot into the agent to prepare for cleaning. + + :param task: a TaskManager object containing the node + :returns: states.CLEANWAIT to signify an asynchronous prepare. + :raises NodeCleaningFailure: if the previous cleaning ports cannot + be removed or if new cleaning ports cannot be created + :raises: IloOperationError, if some operation on iLO failed. + """ + # Powering off the Node before initiating boot for node cleaning. + # If node is in system POST, setting boot device fails. + manager_utils.node_power_action(task, states.POWER_OFF) + return super(IloVirtualMediaIscsiDeploy, self).prepare_cleaning(task) + class IloVirtualMediaAgentDeploy(agent.AgentDeploy): """Interface for deploy-related actions.""" @@ -209,6 +223,20 @@ class IloVirtualMediaAgentDeploy(agent.AgentDeploy): super(IloVirtualMediaAgentDeploy, self).prepare(task) + def prepare_cleaning(self, task): + """Boot into the agent to prepare for cleaning. + + :param task: a TaskManager object containing the node + :returns: states.CLEANWAIT to signify an asynchronous prepare. + :raises NodeCleaningFailure: if the previous cleaning ports cannot + be removed or if new cleaning ports cannot be created + :raises: IloOperationError, if some operation on iLO failed. + """ + # Powering off the Node before initiating boot for node cleaning. + # If node is in system POST, setting boot device fails. + manager_utils.node_power_action(task, states.POWER_OFF) + return super(IloVirtualMediaAgentDeploy, self).prepare_cleaning(task) + def get_clean_steps(self, task): """Get the list of clean steps from the agent. @@ -286,3 +314,17 @@ class IloPXEDeploy(iscsi_deploy.ISCSIDeploy): manager_utils.node_power_action(task, states.POWER_OFF) _disable_secure_boot_if_supported(task) return super(IloPXEDeploy, self).tear_down(task) + + def prepare_cleaning(self, task): + """Boot into the agent to prepare for cleaning. + + :param task: a TaskManager object containing the node + :returns: states.CLEANWAIT to signify an asynchronous prepare. + :raises NodeCleaningFailure: if the previous cleaning ports cannot + be removed or if new cleaning ports cannot be created + :raises: IloOperationError, if some operation on iLO failed. + """ + # Powering off the Node before initiating boot for node cleaning. + # If node is in system POST, setting boot device fails. + manager_utils.node_power_action(task, states.POWER_OFF) + return super(IloPXEDeploy, self).prepare_cleaning(task) diff --git a/ironic/tests/unit/drivers/modules/ilo/test_deploy.py b/ironic/tests/unit/drivers/modules/ilo/test_deploy.py index de2a6a99e6..dee0851388 100644 --- a/ironic/tests/unit/drivers/modules/ilo/test_deploy.py +++ b/ironic/tests/unit/drivers/modules/ilo/test_deploy.py @@ -283,6 +283,21 @@ class IloVirtualMediaIscsiDeployTestCase(db_base.DbTestCase): self.assertFalse(func_prepare_node_for_deploy.called) iscsi_deploy_prepare_mock.assert_called_once_with(mock.ANY, task) + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare_cleaning', + spec_set=True, autospec=True) + @mock.patch.object(manager_utils, 'node_power_action', spec_set=True, + autospec=True) + def test_prepare_cleaning(self, node_power_action_mock, + iscsi_prep_clean_mock): + iscsi_prep_clean_mock.return_value = states.CLEANWAIT + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + ret = task.driver.deploy.prepare_cleaning(task) + self.assertEqual(states.CLEANWAIT, ret) + node_power_action_mock.assert_called_once_with(task, + states.POWER_OFF) + iscsi_prep_clean_mock.assert_called_once_with(mock.ANY, task) + class IloVirtualMediaAgentDeployTestCase(db_base.DbTestCase): @@ -415,6 +430,21 @@ class IloVirtualMediaAgentDeployTestCase(db_base.DbTestCase): task, interface='deploy', override_priorities={'erase_devices': None}) + @mock.patch.object(agent.AgentDeploy, 'prepare_cleaning', spec_set=True, + autospec=True) + @mock.patch.object(manager_utils, 'node_power_action', spec_set=True, + autospec=True) + def test_prepare_cleaning(self, node_power_action_mock, + agent_prep_clean_mock): + agent_prep_clean_mock.return_value = states.CLEANWAIT + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + ret = task.driver.deploy.prepare_cleaning(task) + self.assertEqual(states.CLEANWAIT, ret) + node_power_action_mock.assert_called_once_with(task, + states.POWER_OFF) + agent_prep_clean_mock.assert_called_once_with(mock.ANY, task) + class IloPXEDeployTestCase(db_base.DbTestCase): @@ -531,3 +561,18 @@ class IloPXEDeployTestCase(db_base.DbTestCase): states.POWER_OFF) self.assertTrue(mock_log.called) self.assertEqual(states.DELETED, returned_state) + + @mock.patch.object(iscsi_deploy.ISCSIDeploy, 'prepare_cleaning', + spec_set=True, autospec=True) + @mock.patch.object(manager_utils, 'node_power_action', spec_set=True, + autospec=True) + def test_prepare_cleaning(self, node_power_action_mock, + iscsi_prep_clean_mock): + iscsi_prep_clean_mock.return_value = states.CLEANWAIT + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + ret = task.driver.deploy.prepare_cleaning(task) + self.assertEqual(states.CLEANWAIT, ret) + node_power_action_mock.assert_called_once_with(task, + states.POWER_OFF) + iscsi_prep_clean_mock.assert_called_once_with(mock.ANY, task) diff --git a/releasenotes/notes/ilo-automated-cleaning-fails-14ee438de3dd8690.yaml b/releasenotes/notes/ilo-automated-cleaning-fails-14ee438de3dd8690.yaml new file mode 100644 index 0000000000..d9ee80aacb --- /dev/null +++ b/releasenotes/notes/ilo-automated-cleaning-fails-14ee438de3dd8690.yaml @@ -0,0 +1,7 @@ +--- +fixes: + - Fixes issue where automated cleaning fails for iLO + drivers. + Automated cleaning fails for iLO driver if iLO is + in System POST state. iLO does not allow setting + of boot device when it is in System POST state.