Add OEM storage controller extension

Can determine controller's mode and convert to RAID mode for
eligible controllers (PERC 9 and PERC 10).

Depends-On: https://review.opendev.org/c/openstack/sushy/+/850899
Change-Id: I492c476c6d69b458449eed69644b051b66dfdc65
This commit is contained in:
Aija Jauntēva 2022-08-02 10:49:11 -04:00
parent aac2509f7b
commit da9a0e4042
7 changed files with 222 additions and 1 deletions

View File

@ -28,6 +28,8 @@ packages =
[entry_points]
sushy.resources.manager.oems =
dell = sushy_oem_idrac.resources.manager.manager:get_extension
sushy.resources.storage_controller.oems =
dell = sushy_oem_idrac.resources.system.storage.controller:get_extension
sushy.resources.system.oems =
dell = sushy_oem_idrac.resources.system.system:get_extension
sushy.resources.task.oems =

View File

@ -1,4 +1,4 @@
# Copyright (c) 2021 Dell Inc. or its subsidiaries.
# Copyright (c) 2021-2022 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
@ -14,4 +14,5 @@
from sushy_oem_idrac.resources.manager.constants import * # noqa
from sushy_oem_idrac.resources.system.constants import * # noqa
from sushy_oem_idrac.resources.system.storage.constants import * # noqa
from sushy_oem_idrac.resources.taskservice.constants import * # noqa

View File

@ -0,0 +1,28 @@
# Copyright (c) 2022 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import enum
class ControllerMode(enum.Enum):
"""RAID controller modes."""
RAID = "RAID"
"""RAID mode."""
HBA = "HBA"
"""HBA/Passthru mode. Does not support RAID. For PERC 9 controllers."""
EHBA = "EnhancedHBA"
"""Enhanced HBA mode. Limited RAID support. For PERC 10 controllers."""

View File

@ -0,0 +1,56 @@
# Copyright (c) 2022 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import sushy
from sushy.resources import base
from sushy.resources.oem import base as oem_base
from sushy_oem_idrac.resources.system.storage import constants as s_cons
class DellStorageController(base.CompositeField):
controller_mode = base.MappedField('ControllerMode', s_cons.ControllerMode)
"""Mode of RAID controller"""
class DellStorageControllerExtension(oem_base.OEMResourceBase):
dell_storage_controller = DellStorageController('DellStorageController')
def convert_to_raid(self):
"""Converts to RAID mode if applicable
If PERC 9 or PERC 10 controller is in non-RAID mode, then convert
to RAID mode. No changes made for PERC 11 and above as they support
only RAID mode, and BOSS controller as it does not have controller
mode.
:returns: TaskMonitor if controller mode changes applied and need to
reboot, otherwise None
"""
controller_mode = self.dell_storage_controller.controller_mode
# BOSS will have this empty, PERC will have something assigned
if controller_mode and controller_mode != s_cons.ControllerMode.RAID:
patch = {
"Oem": {
"Dell": {
"DellStorageController": {
"ControllerMode":
s_cons.ControllerMode.RAID.value}}}}
return self._parent_resource.update(
patch, apply_time=sushy.ApplyTime.ON_RESET)
def get_extension(*args, **kwargs):
return DellStorageControllerExtension

View File

@ -0,0 +1,58 @@
{
"@Redfish.Settings": {
"@odata.context": "/redfish/v1/$metadata#Settings.Settings",
"@odata.type": "#Settings.v1_3_3.Settings",
"SettingsObject": {
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1/Settings"
},
"SupportedApplyTimes": [
"Immediate",
"OnReset"
]
},
"@odata.context": "/redfish/v1/$metadata#StorageController.StorageController",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1",
"@odata.type": "#StorageController.v1_2_0.StorageController",
"Description": "Integrated RAID Controller",
"FirmwareVersion": "1.0.0.7",
"Id": "1",
"Identifiers": [
{
"@odata.type": "#Resource.v1_1_0.Identifier",
"DurableNameFormat": "NAA",
"DurableName": "345C59DBD970859C"
}
],
"Identifiers@odata.count": 1,
"Manufacturer": "Contoso",
"Model": "12Gbs Integrated RAID",
"Name": "Contoso Integrated RAID",
"Oem": {
"Dell": {
"@odata.type": "#DellOemStorageController.v1_0_0.DellOemStorageController",
"DellStorageController": {
"ControllerMode": "EnhancedHBA"
}
}
},
"SpeedGbps": 12,
"Status": {
"Health": "OK",
"HealthRollup": "OK",
"State": "Enabled"
},
"SupportedControllerProtocols": [
"PCIe"
],
"SupportedControllerProtocols@odata.count": 1,
"SupportedDeviceProtocols": [
"SAS",
"SATA"
],
"SupportedDeviceProtocols@odata.count": 2,
"SupportedRAIDTypes": [
"RAID0",
"RAID1"
],
"SupportedRAIDTypes@odata.count": 2
}

View File

@ -0,0 +1,76 @@
# Copyright (c) 2022 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
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
from unittest import mock
from oslotest.base import BaseTestCase
import sushy
from sushy.resources.system.storage import controller as sushy_constroller
from sushy_oem_idrac.resources.system.storage import constants as ctrl_cons
from sushy_oem_idrac.resources.system.storage import controller as oem_ctrl
class ControllerTestCase(BaseTestCase):
def setUp(self):
super(ControllerTestCase, self).setUp()
self.conn = mock.Mock()
with open('sushy_oem_idrac/tests/unit/json_samples/'
'storage_controller.json') as f:
mock_response = self.conn.get.return_value
mock_response.json.return_value = json.load(f)
mock_response.status_code = 200
self.controller = sushy_constroller.StorageController(
self.conn,
'/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1')
self.oem_controller = oem_ctrl.DellStorageControllerExtension(
self.conn,
'/redfish/v1/Systems/437XR1138R2/Storage/1/Controllers/1')
self.oem_controller = self.oem_controller.set_parent_resource(
self.controller, 'Dell')
def test_parse_attributes(self):
self.assertEqual(
ctrl_cons.ControllerMode.EHBA,
self.oem_controller.dell_storage_controller.controller_mode)
def test_convert_to_raid(self):
mock_controller = mock.Mock()
mock_task_monitor = mock.Mock()
mock_controller.update.return_value = mock_task_monitor
self.oem_controller._parent_resource = mock_controller
res = self.oem_controller.convert_to_raid()
self.assertEqual(mock_task_monitor, res)
patch = {"Oem": {"Dell": {"DellStorageController": {
"ControllerMode": "RAID"}}}}
mock_controller.update.assert_called_once_with(
patch, apply_time=sushy.ApplyTime.ON_RESET)
def test_convert_to_raid_already_raid(self):
mock_controller = mock.Mock()
self.oem_controller._parent_resource = mock_controller
json = self.oem_controller.json
json['Oem']['Dell']['DellStorageController']['ControllerMode'] = 'RAID'
self.oem_controller.refresh()
res = self.oem_controller.convert_to_raid()
self.assertIsNone(res)
mock_controller.update.assert_not_called()