diff options
author | Jacob Anders <janders@redhat.com> | 2022-06-21 13:18:12 +1000 |
---|---|---|
committer | Dmitry Tantsur <dtantsur@protonmail.com> | 2022-09-30 16:04:07 +0000 |
commit | 2ecfc2e999b6810e73ad54072337eeca937f53e0 (patch) | |
tree | cf0b2aa3a5fa0163aabd4b1ba6788101c17c416c | |
parent | 30bdf892d47409f4d4d07c6c61a948f63841b4e7 (diff) | |
download | ironic-2ecfc2e999b6810e73ad54072337eeca937f53e0.tar.gz |
Prevent clear_job_queue and reset_idrac failures on older iDRACs
Currently, clear_job_queue and reset_idrac steps are only supported on
idrac-redfish driver on iDRAC9 hardware. However, Ironic still attempts
to run these steps on iDRAC8 BMCs configured with idrac-redfish driver
which results in verification failures. This change attempts to resolve
it by catching the related exception, logging a warning and continuing
verification. In case of cleaning, it still fails.
Story: 2010091
Task: 45630
Change-Id: Icd8c5378469887962ff32eea2f38697c539f7e95
(cherry picked from commit 1dda97c783653aef638113cb1faa250836ed99e1)
3 files changed, 132 insertions, 8 deletions
diff --git a/ironic/drivers/modules/drac/management.py b/ironic/drivers/modules/drac/management.py index d329a419c..6f6450701 100644 --- a/ironic/drivers/modules/drac/management.py +++ b/ironic/drivers/modules/drac/management.py @@ -33,6 +33,7 @@ from ironic.common import boot_devices from ironic.common import exception from ironic.common.i18n import _ from ironic.common import molds +from ironic.common import states from ironic.conductor import periodics from ironic.conductor import task_manager from ironic.conductor import utils as manager_utils @@ -627,9 +628,22 @@ class DracRedfishManagement(redfish_management.RedfishManagement): on. :raises: RedfishError on an error. """ - drac_utils.execute_oem_manager_method( - task, 'clear job queue', - lambda m: m.job_service.delete_jobs(job_ids=['JID_CLEARALL'])) + try: + drac_utils.execute_oem_manager_method( + task, 'clear job queue', + lambda m: m.job_service.delete_jobs(job_ids=['JID_CLEARALL'])) + except exception.RedfishError as exc: + if "Oem/Dell/DellJobService is missing" in str(exc): + LOG.warning('iDRAC on node %(node)s does not support ' + 'clearing Lifecycle Controller job queue ' + 'using the idrac-redfish driver. ' + 'If using iDRAC9, consider upgrading firmware. ' + 'If using iDRAC8, consider switching to ' + 'idrac-wsman for management interface if ' + 'possible.', + {'node': task.node.uuid}) + if task.node.provision_state != states.VERIFYING: + raise @METRICS.timer('DracRedfishManagement.reset_idrac') @base.verify_step(priority=0) @@ -641,11 +655,23 @@ class DracRedfishManagement(redfish_management.RedfishManagement): on. :raises: RedfishError on an error. """ - drac_utils.execute_oem_manager_method( - task, 'reset iDRAC', lambda m: m.reset_idrac()) - redfish_utils.wait_until_get_system_ready(task.node) - LOG.info('Reset iDRAC for node %(node)s done', - {'node': task.node.uuid}) + try: + drac_utils.execute_oem_manager_method( + task, 'reset iDRAC', lambda m: m.reset_idrac()) + redfish_utils.wait_until_get_system_ready(task.node) + LOG.info('Reset iDRAC for node %(node)s done', + {'node': task.node.uuid}) + except exception.RedfishError as exc: + if "Oem/Dell/DelliDRACCardService is missing" in str(exc): + LOG.warning('iDRAC on node %(node)s does not support ' + 'iDRAC reset using the idrac-redfish driver. ' + 'If using iDRAC9, consider upgrading firmware. ' + 'If using iDRAC8, consider switching to ' + 'idrac-wsman for management interface if ' + 'possible.', + {'node': task.node.uuid}) + if task.node.provision_state != states.VERIFYING: + raise @METRICS.timer('DracRedfishManagement.known_good_state') @base.verify_step(priority=0) diff --git a/ironic/tests/unit/drivers/modules/drac/test_management.py b/ironic/tests/unit/drivers/modules/drac/test_management.py index 3807753ef..b85b920dd 100644 --- a/ironic/tests/unit/drivers/modules/drac/test_management.py +++ b/ironic/tests/unit/drivers/modules/drac/test_management.py @@ -28,6 +28,7 @@ from oslo_utils import importutils import ironic.common.boot_devices from ironic.common import exception from ironic.common import molds +from ironic.common import states from ironic.conductor import periodics from ironic.conductor import task_manager from ironic.conductor import utils as manager_utils @@ -1436,6 +1437,48 @@ class DracRedfishManagementTestCase(test_utils.BaseDracTest): mock_manager_oem.job_service.delete_jobs.assert_called_once_with( job_ids=['JID_CLEARALL']) + @mock.patch.object(drac_mgmt, 'LOG', autospec=True) + @mock.patch.object(drac_utils, 'redfish_utils', autospec=True) + def test_clear_job_queue_missing_attr_verify_step(self, + mock_redfish_utils, + mock_log): + mock_system = mock_redfish_utils.get_system.return_value + mock_manager = mock.MagicMock() + mock_system.managers = [mock_manager] + mock_manager_oem = mock_manager.get_oem_extension.return_value + mock_manager_oem.job_service.delete_jobs.side_effect = ( + exception.RedfishError("Oem/Dell/DellJobService is missing")) + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + task.node.provision_state = states.VERIFYING + task.driver.management.clear_job_queue(task) + mock_log.warning.assert_called_once_with( + 'iDRAC on node %(node)s does not support ' + 'clearing Lifecycle Controller job queue ' + 'using the idrac-redfish driver. ' + 'If using iDRAC9, consider upgrading firmware. ' + 'If using iDRAC8, consider switching to ' + 'idrac-wsman for management interface if ' + 'possible.', + {'node': task.node.uuid}) + + @mock.patch.object(drac_mgmt, 'LOG', autospec=True) + @mock.patch.object(drac_utils, 'redfish_utils', autospec=True) + def test_clear_job_queue_missing_attr_clean_step(self, + mock_redfish_utils, + mock_log): + mock_system = mock_redfish_utils.get_system.return_value + mock_manager = mock.MagicMock() + mock_system.managers = [mock_manager] + mock_manager_oem = mock_manager.get_oem_extension.return_value + mock_manager_oem.job_service.delete_jobs.side_effect = ( + exception.RedfishError("Oem/Dell/DellJobService is missing")) + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + task.node.provision_state = states.CLEANING + self.assertRaises(ironic.common.exception.RedfishError, + task.driver.management.clear_job_queue, task) + @mock.patch.object(redfish_utils, 'wait_until_get_system_ready', autospec=True) @mock.patch.object(drac_utils, 'redfish_utils', autospec=True) @@ -1452,6 +1495,53 @@ class DracRedfishManagementTestCase(test_utils.BaseDracTest): @mock.patch.object(redfish_utils, 'wait_until_get_system_ready', autospec=True) + @mock.patch.object(drac_mgmt, 'LOG', autospec=True) + @mock.patch.object(drac_utils, 'redfish_utils', autospec=True) + def test_reset_idrac_missing_attr_verify_step(self, + mock_redfish_utils, + mock_log, + mock_wait_system_ready): + mock_system = mock_redfish_utils.get_system.return_value + mock_manager = mock.MagicMock() + mock_system.managers = [mock_manager] + mock_manager_oem = mock_manager.get_oem_extension.return_value + mock_manager_oem.reset_idrac.side_effect = ( + exception.RedfishError("Oem/Dell/DelliDRACCardService is missing")) + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + task.node.provision_state = states.VERIFYING + task.driver.management.reset_idrac(task) + mock_log.warning.assert_called_once_with( + 'iDRAC on node %(node)s does not support ' + 'iDRAC reset using the idrac-redfish driver. ' + 'If using iDRAC9, consider upgrading firmware. ' + 'If using iDRAC8, consider switching to ' + 'idrac-wsman for management interface if ' + 'possible.', + {'node': task.node.uuid}) + + @mock.patch.object(redfish_utils, 'wait_until_get_system_ready', + autospec=True) + @mock.patch.object(drac_mgmt, 'LOG', autospec=True) + @mock.patch.object(drac_utils, 'redfish_utils', autospec=True) + def test_reset_idrac_missing_attr_clean_step(self, + mock_redfish_utils, + mock_log, + mock_wait_system_ready): + mock_system = mock_redfish_utils.get_system.return_value + mock_manager = mock.MagicMock() + mock_system.managers = [mock_manager] + mock_manager_oem = mock_manager.get_oem_extension.return_value + mock_manager_oem.reset_idrac.side_effect = ( + exception.RedfishError("Oem/Dell/DelliDRACCardService is missing")) + with task_manager.acquire(self.context, self.node.uuid, + shared=False) as task: + task.node.provision_state = states.CLEANING + self.assertRaises(ironic.common.exception.RedfishError, + task.driver.management.reset_idrac, task) + + @mock.patch.object(redfish_utils, 'wait_until_get_system_ready', + autospec=True) @mock.patch.object(drac_utils, 'redfish_utils', autospec=True) def test_known_good_state(self, mock_redfish_utils, mock_wait_system_ready): diff --git a/releasenotes/notes/skip-clear-job-queue-idrac-reset-if-attr-missing-b2a2b609c906c6c4.yaml b/releasenotes/notes/skip-clear-job-queue-idrac-reset-if-attr-missing-b2a2b609c906c6c4.yaml new file mode 100644 index 000000000..df9bef955 --- /dev/null +++ b/releasenotes/notes/skip-clear-job-queue-idrac-reset-if-attr-missing-b2a2b609c906c6c4.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + Resolved clear_job_queue and reset_idrac verify step failures which occur + when the functionality is not supported by the iDRAC. When this condition + is detected, the code in the step handles the exception and logs a warning + and completes successfully in case of verification steps but fails in case + of cleaning steps. |