diff --git a/ironic/drivers/modules/drac/management.py b/ironic/drivers/modules/drac/management.py index eded50bf62..ff265e741c 100644 --- a/ironic/drivers/modules/drac/management.py +++ b/ironic/drivers/modules/drac/management.py @@ -73,6 +73,9 @@ _DRAC_BOOT_MODES = ['Bios', 'Uefi'] # BootMode constant _NON_PERSISTENT_BOOT_MODE = 'OneTime' +# Clear job id's constant +_CLEAR_JOB_IDS = 'JID_CLEARALL_FORCE' + def _get_boot_device(node, drac_boot_devices=None): client = drac_common.get_drac_client(node) @@ -357,3 +360,32 @@ class DracManagement(base.ManagementInterface): sensor type, which can be processed by Ceilometer. """ raise NotImplementedError() + + @METRICS.timer('DracManagement.reset_idrac') + @base.clean_step(priority=0) + def reset_idrac(self, task): + """Reset the iDRAC. + + :param task: a TaskManager instance containing the node to act on. + :returns: None if it is completed. + :raises: DracOperationError on an error from python-dracclient. + """ + node = task.node + + client = drac_common.get_drac_client(node) + client.reset_idrac(force=True, wait=True) + + @METRICS.timer('DracManagement.known_good_state') + @base.clean_step(priority=0) + def known_good_state(self, task): + """Reset the iDRAC, Clear the job queue. + + :param task: a TaskManager instance containing the node to act on. + :returns: None if it is completed. + :raises: DracOperationError on an error from python-dracclient. + """ + node = task.node + + client = drac_common.get_drac_client(node) + client.reset_idrac(force=True, wait=True) + client.delete_jobs(job_ids=[_CLEAR_JOB_IDS]) diff --git a/ironic/tests/unit/drivers/modules/drac/test_management.py b/ironic/tests/unit/drivers/modules/drac/test_management.py index 84a752c6b3..bfb5be8817 100644 --- a/ironic/tests/unit/drivers/modules/drac/test_management.py +++ b/ironic/tests/unit/drivers/modules/drac/test_management.py @@ -532,3 +532,29 @@ class DracManagementTestCase(test_utils.BaseDracTest): shared=False) as task: self.assertRaises(NotImplementedError, task.driver.management.get_sensors_data, task) + + def test_reset_idrac(self, mock_get_drac_client): + mock_client = mock.Mock() + mock_get_drac_client.return_value = mock_client + + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + return_value = task.driver.management.reset_idrac(task) + mock_client.reset_idrac.assert_called_once_with( + force=True, wait=True) + + self.assertIsNone(return_value) + + def test_known_good_state(self, mock_get_drac_client): + mock_client = mock.Mock() + mock_get_drac_client.return_value = mock_client + + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + return_value = task.driver.management.known_good_state(task) + mock_client.reset_idrac.assert_called_once_with( + force=True, wait=True) + mock_client.delete_jobs.assert_called_once_with( + job_ids=['JID_CLEARALL_FORCE']) + + self.assertIsNone(return_value) diff --git a/releasenotes/notes/add_clean_step_reset_idrac_and_known_good_state-cdbebf97d7b87fe7.yaml b/releasenotes/notes/add_clean_step_reset_idrac_and_known_good_state-cdbebf97d7b87fe7.yaml new file mode 100644 index 0000000000..8bd3e758cc --- /dev/null +++ b/releasenotes/notes/add_clean_step_reset_idrac_and_known_good_state-cdbebf97d7b87fe7.yaml @@ -0,0 +1,8 @@ +--- +features: + - | + Adds ``reset_idrac`` and ``known_good_state`` cleaning steps to hardware + type ``idrac``. + ``reset_idrac`` actually resets the iDRAC; ``known_good_state`` also + resets the iDRAC and clears the Lifecycle Controller job queue to make + sure the iDRAC is in good state. \ No newline at end of file