Add RAID clear foreign config method
Change-Id: If1669e7a666d0897557bc96554a2e403b2ccecf8
This commit is contained in:
parent
79d4ecb587
commit
c63e28113a
@ -1,3 +1,5 @@
|
||||
# Copyright (c) 2021 Dell Inc. or its subsidiaries.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
@ -12,3 +14,4 @@
|
||||
|
||||
IDRAC_CONFIG_PENDING = 'LC068'
|
||||
IDRAC_JOB_RUNNING = 'RAC0679'
|
||||
NO_FOREIGN_CONFIG = 'STOR018'
|
||||
|
@ -19,6 +19,8 @@ from sushy.resources import base
|
||||
from sushy.resources import common
|
||||
from sushy import taskmonitor
|
||||
|
||||
from sushy_oem_idrac import constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -26,6 +28,8 @@ class ActionsField(base.CompositeField):
|
||||
convert_to_raid = common.ActionField("#DellRaidService.ConvertToRAID")
|
||||
convert_to_nonraid = common.ActionField(
|
||||
"#DellRaidService.ConvertToNonRAID")
|
||||
clear_foreign_config = common.ActionField(
|
||||
"#DellRaidService.ClearForeignConfig")
|
||||
|
||||
|
||||
class DellRaidService(base.ResourceBase):
|
||||
@ -78,6 +82,41 @@ class DellRaidService(base.ResourceBase):
|
||||
LOG.info('Converting to non-RAID mode: %s', physical_disk_fqdds)
|
||||
return task_monitor
|
||||
|
||||
def clear_foreign_config(self, controller_fqdd):
|
||||
"""Clears foreign configuration
|
||||
|
||||
Prepares any foreign physical disks for inclusion in the local
|
||||
configuration
|
||||
|
||||
:param controller_fqdd: FQDD of controller to clear foreign
|
||||
config
|
||||
|
||||
:returns: Sushy's TaskMonitor instance for TaskService task if
|
||||
there are foreign drives to clear, otherwise None.
|
||||
"""
|
||||
target_uri = self._actions.clear_foreign_config.target_uri
|
||||
payload = {'TargetFQDD': controller_fqdd}
|
||||
|
||||
try:
|
||||
response = self._conn.post(target_uri, data=payload)
|
||||
except exceptions.BadRequestError as ex:
|
||||
# Check if failed for no foreign drives
|
||||
errors = ex.body and ex.body.get('@Message.ExtendedInfo') or []
|
||||
|
||||
no_foreign_conf = [x for x in errors if constants.NO_FOREIGN_CONFIG
|
||||
in x.get('MessageId')]
|
||||
|
||||
if len(no_foreign_conf) == 0:
|
||||
raise ex
|
||||
else:
|
||||
LOG.debug('%s: %s', no_foreign_conf[0].get('Message'),
|
||||
controller_fqdd)
|
||||
return
|
||||
|
||||
task_mon = self._get_task_monitor_from_dell_job(response)
|
||||
LOG.info('Clearing foreign config: %s', controller_fqdd)
|
||||
return task_mon
|
||||
|
||||
def _get_task_monitor_from_dell_job(self, response):
|
||||
"""From OEM job response returns generic Task monitor
|
||||
|
||||
|
@ -108,6 +108,25 @@ class DellSystemExtension(oem_base.OEMResourceBase):
|
||||
|
||||
return task_monitors
|
||||
|
||||
def clear_foreign_config(self, storage_list=None):
|
||||
"""Clears foreign config on given controllers
|
||||
|
||||
:param storage_list: List of storage objects, each of which
|
||||
corresponds to a controller
|
||||
:returns: List of task monitors, where each entry is for a
|
||||
controller that has foreign config to clear
|
||||
"""
|
||||
if storage_list is None:
|
||||
storage_list = self._get_storage_list()
|
||||
|
||||
task_monitors = []
|
||||
for storage in storage_list:
|
||||
task_mon = self.raid_service.clear_foreign_config(storage.identity)
|
||||
if task_mon:
|
||||
task_monitors.append(task_mon)
|
||||
|
||||
return task_monitors
|
||||
|
||||
def _get_controller_to_disks(self):
|
||||
"""Gets all RAID controllers and their disks on system
|
||||
|
||||
@ -122,6 +141,20 @@ class DellSystemExtension(oem_base.OEMResourceBase):
|
||||
controller_to_disks[controller] = storage.drives
|
||||
return controller_to_disks
|
||||
|
||||
def _get_storage_list(self):
|
||||
"""Gets all storage items corresponding to RAID controllers
|
||||
|
||||
:returns: list of storage items
|
||||
"""
|
||||
storage_list = []
|
||||
for storage in self._parent_resource.storage.get_members():
|
||||
controller = (storage.storage_controllers[0]
|
||||
if storage.storage_controllers else None)
|
||||
if not controller or controller and not controller.raid_types:
|
||||
continue
|
||||
storage_list.append(storage)
|
||||
return storage_list
|
||||
|
||||
|
||||
def get_extension(*args, **kwargs):
|
||||
return DellSystemExtension
|
||||
|
@ -80,6 +80,93 @@ class DellRaidService(BaseTestCase):
|
||||
data={'PDArray': fqdds})
|
||||
self.assertEqual(mock_task_mon, task_mon)
|
||||
|
||||
@mock.patch.object(raid_service.DellRaidService,
|
||||
'_get_task_monitor_from_dell_job', autospec=True)
|
||||
def test_clear_foreign_config(self, mock_get_task_mon):
|
||||
mock_task_mon = mock.Mock()
|
||||
mock_get_task_mon.return_value = mock_task_mon
|
||||
|
||||
result = self.raid_service.clear_foreign_config('RAID.Integrated.1-1')
|
||||
|
||||
self.conn.post.assert_called_once_with(
|
||||
'/redfish/v1/Systems/System.Embedded.1/Oem/Dell/DellRaidService/'
|
||||
'Actions/DellRaidService.ClearForeignConfig',
|
||||
data={'TargetFQDD': 'RAID.Integrated.1-1'})
|
||||
self.assertEqual(mock_task_mon, result)
|
||||
|
||||
def test_clear_foreign_config_no_config(self):
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status_code = 400
|
||||
mock_response.json.return_value = {
|
||||
"error": {
|
||||
"@Message.ExtendedInfo": [
|
||||
{
|
||||
"Message": "No foreign configurations detected.",
|
||||
"MessageArgs": [],
|
||||
"MessageArgs@odata.count": 0,
|
||||
"MessageId": "IDRAC.2.5.STOR018",
|
||||
"RelatedProperties": [],
|
||||
"RelatedProperties@odata.count": 0,
|
||||
"Resolution": "If the only foreign drives present are "
|
||||
"in a secured locked state, run a "
|
||||
"secure erase operation on the drives "
|
||||
"to securely erase data or unlock these "
|
||||
"drives and retry the operation. "
|
||||
"Otherwise the operation was not "
|
||||
"successful because there are no "
|
||||
"foreign drives.",
|
||||
"Severity": "Warning"
|
||||
}
|
||||
],
|
||||
"code": "Base.1.8.GeneralError",
|
||||
"message": "A general error has occurred. See ExtendedInfo "
|
||||
"for more information"
|
||||
}
|
||||
}
|
||||
no_config_error = exceptions.BadRequestError(
|
||||
'POST', '/redfish/v1/Dell/Systems/System.Embedded.1/'
|
||||
'DellRaidService/Actions/DellRaidService.ClearForeignConfig',
|
||||
mock_response)
|
||||
self.conn.post.side_effect = no_config_error
|
||||
|
||||
result = self.raid_service.clear_foreign_config('RAID.Integrated.1-1')
|
||||
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_clear_foreign_config_bad_request(self):
|
||||
mock_response = mock.Mock()
|
||||
mock_response.status_code = 400
|
||||
mock_response.json.return_value = {
|
||||
"error": {
|
||||
"@Message.ExtendedInfo": [
|
||||
{
|
||||
"Message": "Controller not found.",
|
||||
"MessageArgs": [],
|
||||
"MessageArgs@odata.count": 0,
|
||||
"MessageId": "IDRAC.2.4.STOR030",
|
||||
"RelatedProperties": [],
|
||||
"RelatedProperties@odata.count": 0,
|
||||
"Resolution": "Provide a valid controller FQDD (Fully "
|
||||
"Qualified Device Descriptor) and retry "
|
||||
"the operation.",
|
||||
"Severity": "Warning"
|
||||
}
|
||||
],
|
||||
"code": "Base.1.7.GeneralError",
|
||||
"message": "A general error has occurred. See ExtendedInfo "
|
||||
"for more information"
|
||||
}
|
||||
}
|
||||
no_config_error = exceptions.BadRequestError(
|
||||
'POST', '/redfish/v1/Dell/Systems/System.Embedded.1/'
|
||||
'DellRaidService/Actions/DellRaidService.ClearForeignConfig',
|
||||
mock_response)
|
||||
self.conn.post.side_effect = no_config_error
|
||||
|
||||
self.assertRaises(exceptions.BadRequestError,
|
||||
self.raid_service.clear_foreign_config,
|
||||
'RAID.Integrated.999')
|
||||
|
||||
def test__get_task_monitor_from_dell_job(self):
|
||||
mock_task1 = mock.Mock(identity='JID_111222333444',
|
||||
path='/TaskService/Task/JID_111222333444')
|
||||
|
@ -110,3 +110,14 @@ class SystemTestCase(BaseTestCase):
|
||||
mock_raid.assert_not_called()
|
||||
mock_nonraid.assert_called_once_with(
|
||||
['Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1'])
|
||||
|
||||
def test_clear_foreign_config(self):
|
||||
mock_taskmon = mock.Mock()
|
||||
mock_clear_foreign_config = mock.Mock()
|
||||
mock_clear_foreign_config.side_effect = [None, mock_taskmon]
|
||||
self.oem_system.raid_service.clear_foreign_config =\
|
||||
mock_clear_foreign_config
|
||||
|
||||
task_mons = self.oem_system.clear_foreign_config()
|
||||
|
||||
self.assertEqual([mock_taskmon], task_mons)
|
||||
|
Loading…
Reference in New Issue
Block a user