summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAija Jauntēva <aija.jaunteva@dell.com>2021-08-20 07:46:32 -0400
committerAija Jauntēva <aija.jaunteva@dell.com>2021-09-09 05:13:22 -0400
commit391543946b6c3cb21ae1c08a21b6f730926c9b9d (patch)
treec30dee5976c7a56a95c7cfd15393f22839a26f03
parent743f206d0765da1e7eb97da01117947f7a968710 (diff)
downloadironic-391543946b6c3cb21ae1c08a21b6f730926c9b9d.tar.gz
Fix iDRAC import configuration job with errors
In iDRAC import configuration task can be completed with OK health but having some errors, for example, when one disk failed to be created and another succeeded. Also changed to exclude informational messages for error reporting. Story: 2009198 Task: 43253 Change-Id: I02b63547566c94ffa1a5d0e84bd1b1f10d28bfc3
-rw-r--r--ironic/drivers/modules/drac/management.py18
-rw-r--r--ironic/tests/unit/drivers/modules/drac/test_management.py83
-rw-r--r--ironic/tests/unit/drivers/third_party_driver_mock_specs.py5
-rw-r--r--ironic/tests/unit/drivers/third_party_driver_mocks.py5
-rw-r--r--releasenotes/notes/idrac-import-conf-partial-success-86b8bd1983d227f6.yaml6
5 files changed, 114 insertions, 3 deletions
diff --git a/ironic/drivers/modules/drac/management.py b/ironic/drivers/modules/drac/management.py
index 3bacde962..f20493934 100644
--- a/ironic/drivers/modules/drac/management.py
+++ b/ironic/drivers/modules/drac/management.py
@@ -538,9 +538,21 @@ class DracRedfishManagement(redfish_management.RedfishManagement):
info.pop('import_task_monitor_url', None)
node.driver_internal_info = info
+ succeeded = False
if (import_task.task_state == sushy.TASK_STATE_COMPLETED
and import_task.task_status in
[sushy.HEALTH_OK, sushy.HEALTH_WARNING]):
+
+ # Task could complete with errors (partial success)
+ # iDRAC 5.00.00.00 has stopped reporting Critical messages
+ # so checking also by message_id
+ succeeded = not any(m.message for m in import_task.messages
+ if (m.severity
+ and m.severity != sushy.SEVERITY_OK)
+ or (m.message_id and 'SYS055'
+ in m.message_id))
+
+ if succeeded:
LOG.info('Configuration import %(task_monitor_url)s '
'successful for node %(node)s',
{'node': node.uuid,
@@ -570,7 +582,11 @@ class DracRedfishManagement(redfish_management.RedfishManagement):
# Select all messages, skipping OEM messages that don't have
# `message` field populated.
messages = [m.message for m in import_task.messages
- if m.message is not None]
+ if m.message is not None
+ and ((m.severity
+ and m.severity != sushy.SEVERITY_OK)
+ or (m.message_id
+ and 'SYS055' in m.message_id))]
error_msg = (_("Failed import configuration task: "
"%(task_monitor_url)s. Message: '%(message)s'.")
% {'task_monitor_url': task_monitor_url,
diff --git a/ironic/tests/unit/drivers/modules/drac/test_management.py b/ironic/tests/unit/drivers/modules/drac/test_management.py
index ebc958424..92c010184 100644
--- a/ironic/tests/unit/drivers/modules/drac/test_management.py
+++ b/ironic/tests/unit/drivers/modules/drac/test_management.py
@@ -1150,13 +1150,92 @@ class DracRedfishManagementTestCase(test_utils.BaseDracTest):
task.node.driver_internal_info.get('import_task_monitor_url'))
@mock.patch.object(redfish_utils, 'get_task_monitor', autospec=True)
+ def test__check_import_configuration_task_partial_failed(
+ self, mock_get_task_monitor):
+ driver_internal_info = {'import_task_monitor_url': '/TaskService/123'}
+ self.node.driver_internal_info = driver_internal_info
+ self.node.save()
+
+ mock_message1 = mock.Mock()
+ mock_message1.message_id = 'SYS413'
+ mock_message1.message = 'The operation successfully completed'
+ mock_message1.severity = sushy.SEVERITY_OK
+ mock_message2 = mock.Mock()
+ mock_message2.message_id = 'SYS055'
+ mock_message2.message = 'Firmware upgrade failed'
+ mock_message2.severity = sushy.SEVERITY_CRITICAL
+ mock_import_task = mock.Mock()
+ mock_import_task.task_state = sushy.TASK_STATE_COMPLETED
+ mock_import_task.task_status = sushy.HEALTH_OK
+ mock_import_task.messages = [mock_message1, mock_message2]
+ mock_task_monitor = mock.Mock()
+ mock_task_monitor.is_processing = False
+ mock_task_monitor.get_task.return_value = mock_import_task
+ mock_get_task_monitor.return_value = mock_task_monitor
+
+ self.management._set_success = mock.Mock()
+ self.management._set_failed = mock.Mock()
+
+ with task_manager.acquire(self.context, self.node.uuid,
+ shared=False) as task:
+ self.management._check_import_configuration_task(
+ task, '/TaskService/123')
+
+ self.management._set_failed.assert_called_once_with(
+ task, mock.ANY,
+ "Failed import configuration task: /TaskService/123. Message: "
+ "'Firmware upgrade failed'.")
+ self.management._set_success.assert_not_called()
+ self.assertIsNone(
+ task.node.driver_internal_info.get('import_task_monitor_url'))
+
+ @mock.patch.object(redfish_utils, 'get_task_monitor', autospec=True)
+ def test__check_import_configuration_task_partial_failed_idrac5(
+ self, mock_get_task_monitor):
+ driver_internal_info = {'import_task_monitor_url': '/TaskService/123'}
+ self.node.driver_internal_info = driver_internal_info
+ self.node.save()
+
+ mock_message1 = mock.Mock()
+ mock_message1.message = ('Import of Server Configuration Profile '
+ 'operation completed with errors')
+ mock_message1.message_id = 'IDRAC.2.4.SYS055'
+ mock_import_task = mock.Mock()
+ mock_import_task.task_state = sushy.TASK_STATE_COMPLETED
+ mock_import_task.task_status = sushy.HEALTH_OK
+ mock_import_task.messages = [mock_message1]
+ mock_task_monitor = mock.Mock()
+ mock_task_monitor.is_processing = False
+ mock_task_monitor.get_task.return_value = mock_import_task
+ mock_get_task_monitor.return_value = mock_task_monitor
+
+ self.management._set_success = mock.Mock()
+ self.management._set_failed = mock.Mock()
+
+ with task_manager.acquire(self.context, self.node.uuid,
+ shared=False) as task:
+ self.management._check_import_configuration_task(
+ task, '/TaskService/123')
+
+ self.management._set_failed.assert_called_once_with(
+ task, mock.ANY,
+ "Failed import configuration task: /TaskService/123. Message: "
+ "'Import of Server Configuration Profile "
+ "operation completed with errors'.")
+ self.management._set_success.assert_not_called()
+ self.assertIsNone(
+ task.node.driver_internal_info.get('import_task_monitor_url'))
+
+ @mock.patch.object(redfish_utils, 'get_task_monitor', autospec=True)
def test__check_import_configuration_task(self, mock_get_task_monitor):
driver_internal_info = {'import_task_monitor_url': '/TaskService/123'}
self.node.driver_internal_info = driver_internal_info
self.node.save()
mock_message = mock.Mock()
+ mock_message.message_id = 'SYS413'
mock_message.message = 'Configuration import done'
+ mock_message.severity = sushy.SEVERITY_OK
mock_import_task = mock.Mock()
mock_import_task.task_state = sushy.TASK_STATE_COMPLETED
mock_import_task.task_status = sushy.HEALTH_OK
@@ -1189,7 +1268,9 @@ class DracRedfishManagementTestCase(test_utils.BaseDracTest):
self.node.save()
mock_message = mock.Mock()
+ mock_message.message_id = 'SYS413'
mock_message.message = 'Configuration import done'
+ mock_message.severity = sushy.SEVERITY_OK
mock_import_task = mock.Mock()
mock_import_task.task_state = sushy.TASK_STATE_COMPLETED
mock_import_task.task_status = sushy.HEALTH_OK
@@ -1232,7 +1313,9 @@ class DracRedfishManagementTestCase(test_utils.BaseDracTest):
self.node.save()
mock_message = mock.Mock()
+ mock_message.message_id = 'SYS413'
mock_message.message = 'Configuration import done'
+ mock_message.severity = sushy.SEVERITY_OK
mock_import_task = mock.Mock()
mock_import_task.task_state = sushy.TASK_STATE_COMPLETED
mock_import_task.task_status = sushy.HEALTH_OK
diff --git a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
index 43c89f206..87fb792df 100644
--- a/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
+++ b/ironic/tests/unit/drivers/third_party_driver_mock_specs.py
@@ -166,7 +166,10 @@ SUSHY_SPEC = (
'HEALTH_WARNING',
'SECURE_BOOT_RESET_KEYS_TO_DEFAULT',
'SECURE_BOOT_RESET_KEYS_DELETE_ALL',
- 'VOLUME_TYPE_RAW_DEVICE'
+ 'VOLUME_TYPE_RAW_DEVICE',
+ 'SEVERITY_OK',
+ 'SEVERITY_WARNING',
+ 'SEVERITY_CRITICAL',
)
SUSHY_AUTH_SPEC = (
diff --git a/ironic/tests/unit/drivers/third_party_driver_mocks.py b/ironic/tests/unit/drivers/third_party_driver_mocks.py
index 3c5e2cd7a..cd1b6bb3e 100644
--- a/ironic/tests/unit/drivers/third_party_driver_mocks.py
+++ b/ironic/tests/unit/drivers/third_party_driver_mocks.py
@@ -228,7 +228,10 @@ if not sushy:
HEALTH_WARNING='warning',
SECURE_BOOT_RESET_KEYS_TO_DEFAULT="ResetAllKeysToDefault",
SECURE_BOOT_RESET_KEYS_DELETE_ALL="DeleteAllKeys",
- VOLUME_TYPE_RAW_DEVICE='rawdevice'
+ VOLUME_TYPE_RAW_DEVICE='rawdevice',
+ SEVERITY_OK='ok',
+ SEVERITY_WARNING='warning',
+ SEVERITY_CRITICAL='critical'
)
sys.modules['sushy'] = sushy
diff --git a/releasenotes/notes/idrac-import-conf-partial-success-86b8bd1983d227f6.yaml b/releasenotes/notes/idrac-import-conf-partial-success-86b8bd1983d227f6.yaml
new file mode 100644
index 000000000..01171b949
--- /dev/null
+++ b/releasenotes/notes/idrac-import-conf-partial-success-86b8bd1983d227f6.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Fixes issue in ``idrac-redfish`` clean/deploy step ``import_configuration``
+ where partially successful jobs were treated as fully successful. Such
+ jobs, completed with errors, are now treated as failures.