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.