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
This commit is contained in:
Aija Jauntēva 2021-08-20 07:46:32 -04:00
parent 743f206d07
commit 391543946b
5 changed files with 114 additions and 3 deletions

View File

@ -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,

View File

@ -1149,6 +1149,83 @@ class DracRedfishManagementTestCase(test_utils.BaseDracTest):
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(
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'}
@ -1156,7 +1233,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
@ -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

View File

@ -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 = (

View File

@ -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

View File

@ -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.