Redfish: Adds 'delete_raid_configuration' API to clear raid
The commit adds functionality to delete logical drives in a SmartStorageConfig redfish systems. Co-Authored-By: Paresh Sao <paresh.sao@hpe.com> Change-Id: Id3a07ab0ca1c0ad8199a28ef2efb22aadc5edfd5
This commit is contained in:
parent
21549e746d
commit
2cf3a473c9
|
@ -80,6 +80,16 @@ class IloCommandNotSupportedInBiosError(IloCommandNotSupportedError):
|
||||||
super(IloCommandNotSupportedInBiosError, self).__init__(message)
|
super(IloCommandNotSupportedInBiosError, self).__init__(message)
|
||||||
|
|
||||||
|
|
||||||
|
class IloLogicalDriveNotFoundError(IloError):
|
||||||
|
"""Logical drive not found error.
|
||||||
|
|
||||||
|
This exception is raised when iLO client library unable to find
|
||||||
|
any logical drive on storage controller
|
||||||
|
"""
|
||||||
|
def __init__(self, message, errorcode=None):
|
||||||
|
super(IloLogicalDriveNotFoundError, self).__init__(message)
|
||||||
|
|
||||||
|
|
||||||
class IloLoginFailError(IloError):
|
class IloLoginFailError(IloError):
|
||||||
"""iLO Login Failed.
|
"""iLO Login Failed.
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
# Copyright 2018 Hewlett-Packard Development Company, L.P.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -25,6 +25,7 @@ from proliantutils.redfish import redfish
|
||||||
SUPPORTED_RIS_METHODS = [
|
SUPPORTED_RIS_METHODS = [
|
||||||
'activate_license',
|
'activate_license',
|
||||||
'clear_secure_boot_keys',
|
'clear_secure_boot_keys',
|
||||||
|
'delete_raid_configuration',
|
||||||
'eject_virtual_media',
|
'eject_virtual_media',
|
||||||
'get_current_bios_settings',
|
'get_current_bios_settings',
|
||||||
'get_current_boot_mode',
|
'get_current_boot_mode',
|
||||||
|
@ -68,6 +69,7 @@ SUPPORTED_RIS_METHODS = [
|
||||||
]
|
]
|
||||||
|
|
||||||
SUPPORTED_REDFISH_METHODS = [
|
SUPPORTED_REDFISH_METHODS = [
|
||||||
|
'delete_raid_configuration',
|
||||||
'get_product_name',
|
'get_product_name',
|
||||||
'get_host_post_state',
|
'get_host_post_state',
|
||||||
'get_host_power_status',
|
'get_host_power_status',
|
||||||
|
@ -637,6 +639,15 @@ class IloClient(operations.IloOperations):
|
||||||
"""
|
"""
|
||||||
return self._call_method('activate_license', key)
|
return self._call_method('activate_license', key)
|
||||||
|
|
||||||
|
def delete_raid_configuration(self):
|
||||||
|
"""Deletes the logical drives from the system
|
||||||
|
|
||||||
|
:raises: IloError, on an error from iLO.
|
||||||
|
:raises: IloCommandNotSupportedError, if the command is not supported
|
||||||
|
on the server.
|
||||||
|
"""
|
||||||
|
return self._call_method('delete_raid_configuration')
|
||||||
|
|
||||||
def update_firmware(self, firmware_url, component_type):
|
def update_firmware(self, firmware_url, component_type):
|
||||||
"""Updates the given firmware on the server
|
"""Updates the given firmware on the server
|
||||||
|
|
||||||
|
|
|
@ -445,3 +445,12 @@ class IloOperations(object):
|
||||||
on the server.
|
on the server.
|
||||||
"""
|
"""
|
||||||
raise exception.IloCommandNotSupportedError(ERRMSG)
|
raise exception.IloCommandNotSupportedError(ERRMSG)
|
||||||
|
|
||||||
|
def delete_raid_configuration(self):
|
||||||
|
"""Deletes the logical drives from the system
|
||||||
|
|
||||||
|
:raises: IloError, on an error from iLO.
|
||||||
|
:raises: IloCommandNotSupportedError, if the command is
|
||||||
|
not supported on the server.
|
||||||
|
"""
|
||||||
|
raise exception.IloCommandNotSupportedError(ERRMSG)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2014 Hewlett-Packard Development Company, L.P.
|
# Copyright 2018 Hewlett-Packard Development Company, L.P.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -1209,6 +1209,17 @@ class RIBCLOperations(operations.IloOperations):
|
||||||
"""
|
"""
|
||||||
self._raise_command_not_supported("get_host_post_state")
|
self._raise_command_not_supported("get_host_post_state")
|
||||||
|
|
||||||
|
def delete_raid_configuration(self):
|
||||||
|
"""Delete the raid configuration on the hardware.
|
||||||
|
|
||||||
|
Loops through each SmartStorageConfig controller and clears the
|
||||||
|
raid configuration.
|
||||||
|
|
||||||
|
:raises: IloError, on an error from iLO
|
||||||
|
:raises: IloCommandNotSupportedError
|
||||||
|
"""
|
||||||
|
self._raise_command_not_supported("delete_raid_configuration")
|
||||||
|
|
||||||
|
|
||||||
# The below block of code is there only for backward-compatibility
|
# The below block of code is there only for backward-compatibility
|
||||||
# reasons (before commit 47608b6 for ris-support).
|
# reasons (before commit 47608b6 for ris-support).
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2017 Hewlett Packard Enterprise Development Company, L.P.
|
# Copyright 2018 Hewlett Packard Enterprise Development Company, L.P.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -1974,3 +1974,20 @@ class RISOperations(rest.RestConnectorBase, operations.IloOperations):
|
||||||
return utils.apply_bios_properties_filter(
|
return utils.apply_bios_properties_filter(
|
||||||
default_settings, constants.SUPPORTED_BIOS_PROPERTIES)
|
default_settings, constants.SUPPORTED_BIOS_PROPERTIES)
|
||||||
return default_settings
|
return default_settings
|
||||||
|
|
||||||
|
def _raise_command_not_supported(self, method):
|
||||||
|
platform = self.get_product_name()
|
||||||
|
msg = ("`%(method)s` is not supported on %(platform)s" %
|
||||||
|
{'method': method, 'platform': platform})
|
||||||
|
raise (exception.IloCommandNotSupportedError(msg))
|
||||||
|
|
||||||
|
def delete_raid_configuration(self):
|
||||||
|
"""Delete the raid configuration on the hardware.
|
||||||
|
|
||||||
|
Loops through each SmartStorageConfig controller and clears the
|
||||||
|
raid configuration.
|
||||||
|
|
||||||
|
:raises: IloError, on an error from iLO
|
||||||
|
:raises: IloCommandNotSupportedError
|
||||||
|
"""
|
||||||
|
self._raise_command_not_supported("delete_raid_configuration")
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
# Copyright 2018 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -1050,3 +1050,8 @@ class RedfishOperations(operations.IloOperations):
|
||||||
"""
|
"""
|
||||||
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
|
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
|
||||||
return GET_POST_STATE_MAP.get(sushy_system.post_state)
|
return GET_POST_STATE_MAP.get(sushy_system.post_state)
|
||||||
|
|
||||||
|
def delete_raid_configuration(self):
|
||||||
|
"""Delete the raid configuration on the hardware."""
|
||||||
|
sushy_system = self._get_sushy_system(PROLIANT_SYSTEM_ID)
|
||||||
|
sushy_system.delete_raid()
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
# Copyright 2018 Hewlett Packard Enterprise Development LP
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from proliantutils import exception
|
||||||
|
from proliantutils import log
|
||||||
|
from sushy.resources import base
|
||||||
|
|
||||||
|
|
||||||
|
LOG = log.get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class LogicalDriveListField(base.ListField):
|
||||||
|
volume_unique_identifier = base.Field('VolumeUniqueIdentifier',
|
||||||
|
required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class HPESmartStorageConfig(base.ResourceBase):
|
||||||
|
"""Class that defines the functionality for SmartSorageConfig Resources."""
|
||||||
|
|
||||||
|
controller_id = base.Field("Id")
|
||||||
|
|
||||||
|
logical_drives = LogicalDriveListField("LogicalDrives", default=[])
|
||||||
|
|
||||||
|
settings_uri = base.Field(["@Redfish.Settings",
|
||||||
|
"SettingsObject", "@odata.id"])
|
||||||
|
|
||||||
|
def delete_raid(self):
|
||||||
|
"""Clears the RAID configuration from the system.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not self.logical_drives:
|
||||||
|
msg = ('No logical drives found on the controller '
|
||||||
|
'%(controller)s' % {'controller': str(self.controller_id)})
|
||||||
|
LOG.debug(msg)
|
||||||
|
raise exception.IloLogicalDriveNotFoundError(msg)
|
||||||
|
|
||||||
|
lds = [{
|
||||||
|
'Actions': [{"Action": "LogicalDriveDelete"}],
|
||||||
|
'VolumeUniqueIdentifier':
|
||||||
|
logical_drive.volume_unique_identifier}
|
||||||
|
for logical_drive in self.logical_drives]
|
||||||
|
|
||||||
|
data = {'LogicalDrives': lds, 'DataGuard': 'Permissive'}
|
||||||
|
self._conn.put(self.settings_uri, data=data)
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
# Copyright 2018 Hewlett Packard Enterprise Development LP
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
@ -17,6 +17,7 @@ __author__ = 'HPE'
|
||||||
import sushy
|
import sushy
|
||||||
from sushy.resources import base
|
from sushy.resources import base
|
||||||
from sushy.resources.system import system
|
from sushy.resources.system import system
|
||||||
|
from sushy import utils as sushy_utils
|
||||||
|
|
||||||
from proliantutils import exception
|
from proliantutils import exception
|
||||||
from proliantutils import log
|
from proliantutils import log
|
||||||
|
@ -27,6 +28,7 @@ from proliantutils.redfish.resources.system import mappings
|
||||||
from proliantutils.redfish.resources.system import memory
|
from proliantutils.redfish.resources.system import memory
|
||||||
from proliantutils.redfish.resources.system import pci_device
|
from proliantutils.redfish.resources.system import pci_device
|
||||||
from proliantutils.redfish.resources.system import secure_boot
|
from proliantutils.redfish.resources.system import secure_boot
|
||||||
|
from proliantutils.redfish.resources.system import smart_storage_config
|
||||||
from proliantutils.redfish.resources.system.storage import simple_storage
|
from proliantutils.redfish.resources.system.storage import simple_storage
|
||||||
from proliantutils.redfish.resources.system.storage import \
|
from proliantutils.redfish.resources.system.storage import \
|
||||||
smart_storage as hpe_smart_storage
|
smart_storage as hpe_smart_storage
|
||||||
|
@ -71,6 +73,11 @@ class HPESystem(system.System):
|
||||||
'Boot',
|
'Boot',
|
||||||
'UefiTargetBootSourceOverride@Redfish.AllowableValues'],
|
'UefiTargetBootSourceOverride@Redfish.AllowableValues'],
|
||||||
adapter=list))
|
adapter=list))
|
||||||
|
|
||||||
|
smart_storage_config_identities = base.Field(
|
||||||
|
['Oem', 'Hpe', 'SmartStorageConfig'],
|
||||||
|
adapter=sushy_utils.get_members_identities)
|
||||||
|
|
||||||
supported_boot_mode = base.MappedField(
|
supported_boot_mode = base.MappedField(
|
||||||
['Oem', 'Hpe', 'Bios', 'UefiClass'], mappings.SUPPORTED_BOOT_MODE,
|
['Oem', 'Hpe', 'Bios', 'UefiClass'], mappings.SUPPORTED_BOOT_MODE,
|
||||||
default=constants.SUPPORTED_LEGACY_BIOS_ONLY)
|
default=constants.SUPPORTED_LEGACY_BIOS_ONLY)
|
||||||
|
@ -323,3 +330,51 @@ class HPESystem(system.System):
|
||||||
|
|
||||||
self._memory.refresh(force=False)
|
self._memory.refresh(force=False)
|
||||||
return self._memory
|
return self._memory
|
||||||
|
|
||||||
|
def get_smart_storage_config(self, smart_storage_config_url):
|
||||||
|
"""Returns a SmartStorageConfig Instance for each controller."""
|
||||||
|
return (smart_storage_config.
|
||||||
|
HPESmartStorageConfig(self._conn, smart_storage_config_url,
|
||||||
|
redfish_version=self.redfish_version))
|
||||||
|
|
||||||
|
def check_smart_storage_config_ids(self):
|
||||||
|
"""Check SmartStorageConfig controllers is there in hardware.
|
||||||
|
|
||||||
|
:raises: IloError, on an error from iLO.
|
||||||
|
"""
|
||||||
|
if self.smart_storage_config_identities is None:
|
||||||
|
msg = ('The Redfish controller failed to get the '
|
||||||
|
'SmartStorageConfig controller configurations.')
|
||||||
|
LOG.debug(msg)
|
||||||
|
raise exception.IloError(msg)
|
||||||
|
|
||||||
|
def delete_raid(self):
|
||||||
|
"""Delete the raid configuration on the hardware.
|
||||||
|
|
||||||
|
Loops through each SmartStorageConfig controller and clears the
|
||||||
|
raid configuration.
|
||||||
|
|
||||||
|
:raises: IloError, on an error from iLO.
|
||||||
|
"""
|
||||||
|
self.check_smart_storage_config_ids()
|
||||||
|
any_exceptions = []
|
||||||
|
ld_exc_count = 0
|
||||||
|
for config_id in self.smart_storage_config_identities:
|
||||||
|
try:
|
||||||
|
ssc_obj = self.get_smart_storage_config(config_id)
|
||||||
|
ssc_obj.delete_raid()
|
||||||
|
except exception.IloLogicalDriveNotFoundError as e:
|
||||||
|
ld_exc_count += 1
|
||||||
|
except sushy.exceptions.SushyError as e:
|
||||||
|
any_exceptions.append((config_id, str(e)))
|
||||||
|
|
||||||
|
if any_exceptions:
|
||||||
|
msg = ('The Redfish controller failed to delete the '
|
||||||
|
'raid configuration in one or more controllers with '
|
||||||
|
'Error: %(error)s' % {'error': str(any_exceptions)})
|
||||||
|
raise exception.IloError(msg)
|
||||||
|
|
||||||
|
if ld_exc_count == len(self.smart_storage_config_identities):
|
||||||
|
msg = ('No logical drives are found in any controllers. Nothing '
|
||||||
|
'to delete.')
|
||||||
|
raise exception.IloLogicalDriveNotFoundError(msg)
|
||||||
|
|
|
@ -756,6 +756,29 @@ class IloClientTestCase(testtools.TestCase):
|
||||||
self.client.activate_license('fake-key')
|
self.client.activate_license('fake-key')
|
||||||
call_mock.assert_called_once_with('activate_license', 'fake-key')
|
call_mock.assert_called_once_with('activate_license', 'fake-key')
|
||||||
|
|
||||||
|
@mock.patch.object(client.IloClient, '_call_method')
|
||||||
|
def test_delete_raid_configuration(self, call_mock):
|
||||||
|
self.client.delete_raid_configuration()
|
||||||
|
call_mock.assert_called_once_with('delete_raid_configuration')
|
||||||
|
|
||||||
|
@mock.patch.object(ris.RISOperations, 'get_product_name')
|
||||||
|
def test_delete_raid_configuration_gen9(self, get_product_mock):
|
||||||
|
self.client.model = 'Gen9'
|
||||||
|
get_product_mock.return_value = 'ProLiant BL460c Gen9'
|
||||||
|
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||||
|
'`delete_raid_configuration` is not supported '
|
||||||
|
'on ProLiant BL460c Gen9',
|
||||||
|
self.client.delete_raid_configuration)
|
||||||
|
|
||||||
|
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
|
||||||
|
def test_delete_raid_configuration_gen8(self, get_product_mock):
|
||||||
|
self.client.model = 'Gen8'
|
||||||
|
get_product_mock.return_value = 'ProLiant DL380 G8'
|
||||||
|
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||||
|
'`delete_raid_configuration` is not supported '
|
||||||
|
'on ProLiant DL380 G8',
|
||||||
|
self.client.delete_raid_configuration)
|
||||||
|
|
||||||
@mock.patch.object(ris.RISOperations, 'eject_virtual_media')
|
@mock.patch.object(ris.RISOperations, 'eject_virtual_media')
|
||||||
def test_eject_virtual_media_gen9(self, eject_virtual_media_mock):
|
def test_eject_virtual_media_gen9(self, eject_virtual_media_mock):
|
||||||
self.client.model = 'Gen9'
|
self.client.model = 'Gen9'
|
||||||
|
|
|
@ -1055,5 +1055,13 @@ class IloRibclTestCaseBeforeRisSupport(unittest.TestCase):
|
||||||
'ProLiant DL380 G7',
|
'ProLiant DL380 G7',
|
||||||
self.ilo.get_host_post_state)
|
self.ilo.get_host_post_state)
|
||||||
|
|
||||||
|
@mock.patch.object(ribcl.RIBCLOperations, 'get_product_name')
|
||||||
|
def test_delete_raid_configuration(self, product_name_mock):
|
||||||
|
product_name_mock.return_value = constants.GET_PRODUCT_NAME
|
||||||
|
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||||
|
'ProLiant DL380 G7',
|
||||||
|
self.ilo.delete_raid_configuration)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
|
@ -2551,3 +2551,10 @@ class TestRISOperationsPrivateMethods(testtools.TestCase):
|
||||||
ret = self.client._is_raid_supported()
|
ret = self.client._is_raid_supported()
|
||||||
self.assertEqual(ret, expt_ret)
|
self.assertEqual(ret, expt_ret)
|
||||||
get_array_mock.assert_called_once_with()
|
get_array_mock.assert_called_once_with()
|
||||||
|
|
||||||
|
@mock.patch.object(ris.RISOperations, 'get_product_name')
|
||||||
|
def test_delete_raid_configuration(self, product_name_mock):
|
||||||
|
product_name_mock.return_value = 'ProLiant BL460c Gen9'
|
||||||
|
self.assertRaisesRegexp(exception.IloCommandNotSupportedError,
|
||||||
|
'ProLiant BL460c Gen9',
|
||||||
|
self.client.delete_raid_configuration)
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
{
|
||||||
|
"@Redfish.Settings": {
|
||||||
|
"@odata.type": "#Settings.v1_0_0.Settings",
|
||||||
|
"ETag": "78F92741",
|
||||||
|
"Messages": [
|
||||||
|
{
|
||||||
|
"MessageId": "SmartStorageMessages.2.0.0.Success"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"SettingsObject": {
|
||||||
|
"@odata.id": "/redfish/v1/systems/1/smartstorageconfig/settings/"
|
||||||
|
},
|
||||||
|
"Time": "2017-10-31T12:12:35+00:00"
|
||||||
|
},
|
||||||
|
"@odata.context": "/redfish/v1/$metadata#SmartStorageConfig.SmartStorageConfig",
|
||||||
|
"@odata.etag": "W/\"90107B96DAE4060606D29991827C7EF7\"",
|
||||||
|
"@odata.id": "/redfish/v1/systems/1/smartstorageconfig/",
|
||||||
|
"@odata.type": "#SmartStorageConfig.v2_0_0.SmartStorageConfig",
|
||||||
|
"CurrentParallelSurfaceScanCount": null,
|
||||||
|
"DataGuard": "Strict",
|
||||||
|
"DegradedPerformanceOptimization": null,
|
||||||
|
"DriveWriteCache": null,
|
||||||
|
"ElevatorSort": null,
|
||||||
|
"EncryptionConfiguration": "None",
|
||||||
|
"EncryptionEULA": null,
|
||||||
|
"ExpandPriority": null,
|
||||||
|
"FlexibleLatencySchedulerSetting": null,
|
||||||
|
"Id": "smartstorageconfig",
|
||||||
|
"InconsistencyRepairPolicy": null,
|
||||||
|
"Location": "Slot 0",
|
||||||
|
"LocationFormat": "PCISlot",
|
||||||
|
"LogicalDrives": [
|
||||||
|
{
|
||||||
|
"Accelerator": "ControllerCache",
|
||||||
|
"BlockSizeBytes": 512,
|
||||||
|
"CapacityBlocks": 4688319664,
|
||||||
|
"CapacityGiB": 2235,
|
||||||
|
"DataDrives": [
|
||||||
|
"2I:1:2",
|
||||||
|
"2I:1:1"
|
||||||
|
],
|
||||||
|
"DriveLocationFormat": "ControllerPort:Box:Bay",
|
||||||
|
"LegacyBootPriority": "None",
|
||||||
|
"LogicalDriveName": "01A27294PFJHD0ARCA218H 63E0",
|
||||||
|
"LogicalDriveNumber": 1,
|
||||||
|
"ParityGroupCount": 0,
|
||||||
|
"Raid": "Raid0",
|
||||||
|
"SpareDrives": [],
|
||||||
|
"SpareRebuildMode": null,
|
||||||
|
"StripSizeBytes": 262144,
|
||||||
|
"StripeSizeBytes": 524288,
|
||||||
|
"VolumeUniqueIdentifier": "600508B1001C045A9BAAC9F4F49498AE"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"MonitorAndPerformanceAnalysisDelaySeconds": null,
|
||||||
|
"NoBatteryWriteCache": null,
|
||||||
|
"Oem": {
|
||||||
|
"Hpe": {
|
||||||
|
"@odata.type": "#HpeBiosExt.v2_0_0.HpeBiosExt",
|
||||||
|
"SettingsObject": {
|
||||||
|
"UnmodifiedETag": "W/\"1BBCED8C1E405050504A92724569294F\""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PhysicalDrives": [
|
||||||
|
{
|
||||||
|
"LegacyBootPriority": "None",
|
||||||
|
"Location": "1I:1:2",
|
||||||
|
"LocationFormat": "ControllerPort:Box:Bay"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Ports": [
|
||||||
|
{
|
||||||
|
"OperatingModeAfterReboot": "Mixed",
|
||||||
|
"PortIndex": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"PowerModeAfterReboot": "MaxPerformance",
|
||||||
|
"PredictiveSpareRebuild": null,
|
||||||
|
"QueueDepth": null,
|
||||||
|
"ReadCachePercent": null,
|
||||||
|
"RebuildPriority": null,
|
||||||
|
"SurfaceScanAnalysisDelaySeconds": null,
|
||||||
|
"SurfaceScanAnalysisPriority": null,
|
||||||
|
"SurvivalPowerMode": "Enabled",
|
||||||
|
"WriteCacheBypassThresholdKiB": null
|
||||||
|
}
|
|
@ -97,6 +97,11 @@
|
||||||
"target": "/redfish/v1/Systems/1/Actions/Oem/Hpe/HpeComputerSystemExt.SystemReset/"
|
"target": "/redfish/v1/Systems/1/Actions/Oem/Hpe/HpeComputerSystemExt.SystemReset/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"SmartStorageConfig": [
|
||||||
|
{
|
||||||
|
"@odata.id": "/redfish/v1/systems/1/smartstorageconfig/"
|
||||||
|
}
|
||||||
|
],
|
||||||
"AggregateHealthStatus": {
|
"AggregateHealthStatus": {
|
||||||
"AgentlessManagementService": "Unavailable",
|
"AgentlessManagementService": "Unavailable",
|
||||||
"BiosOrHardwareHealth": {
|
"BiosOrHardwareHealth": {
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
|
||||||
|
import mock
|
||||||
|
import testtools
|
||||||
|
|
||||||
|
from proliantutils import exception
|
||||||
|
from proliantutils.redfish.resources.system import smart_storage_config
|
||||||
|
|
||||||
|
|
||||||
|
class HPESmartStorageConfigTestCase(testtools.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(HPESmartStorageConfigTestCase, self).setUp()
|
||||||
|
self.conn = mock.MagicMock()
|
||||||
|
with open('proliantutils/tests/redfish/'
|
||||||
|
'json_samples/smart_storage_config.json', 'r') as f:
|
||||||
|
self.conn.get.return_value.json.return_value = (
|
||||||
|
json.load(f))
|
||||||
|
|
||||||
|
self.ssc_inst = smart_storage_config.HPESmartStorageConfig(
|
||||||
|
self.conn, '/redfish/v1/Systems/1/smartstorageconfig',
|
||||||
|
redfish_version='1.0.2')
|
||||||
|
|
||||||
|
def test_attributes(self):
|
||||||
|
self.assertEqual('smartstorageconfig', self.ssc_inst.controller_id)
|
||||||
|
self.assertEqual(
|
||||||
|
'600508B1001C045A9BAAC9F4F49498AE',
|
||||||
|
self.ssc_inst.logical_drives[0].volume_unique_identifier)
|
||||||
|
self.assertEqual("/redfish/v1/systems/1/smartstorageconfig/settings/",
|
||||||
|
self.ssc_inst.settings_uri)
|
||||||
|
|
||||||
|
def test_delete_raid(self):
|
||||||
|
settings_uri = "/redfish/v1/systems/1/smartstorageconfig/settings/"
|
||||||
|
data = {
|
||||||
|
"LogicalDrives": [{
|
||||||
|
"Actions": [{"Action": "LogicalDriveDelete"}],
|
||||||
|
"VolumeUniqueIdentifier": "600508B1001C045A9BAAC9F4F49498AE"}],
|
||||||
|
"DataGuard": "Permissive",
|
||||||
|
}
|
||||||
|
self.ssc_inst.delete_raid()
|
||||||
|
self.ssc_inst._conn.put.assert_called_once_with(settings_uri,
|
||||||
|
data=data)
|
||||||
|
|
||||||
|
def test_delete_raid_logical_drive_not_found(self):
|
||||||
|
type(self.ssc_inst).logical_drives = mock.PropertyMock(
|
||||||
|
return_value=[])
|
||||||
|
self.assertRaises(exception.IloLogicalDriveNotFoundError,
|
||||||
|
self.ssc_inst.delete_raid)
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2017 Hewlett Packard Enterprise Development LP
|
# Copyright 2018 Hewlett Packard Enterprise Development LP
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
@ -25,6 +25,7 @@ from proliantutils.redfish.resources.system import constants as sys_cons
|
||||||
from proliantutils.redfish.resources.system import ethernet_interface
|
from proliantutils.redfish.resources.system import ethernet_interface
|
||||||
from proliantutils.redfish.resources.system import memory
|
from proliantutils.redfish.resources.system import memory
|
||||||
from proliantutils.redfish.resources.system import secure_boot
|
from proliantutils.redfish.resources.system import secure_boot
|
||||||
|
from proliantutils.redfish.resources.system import smart_storage_config
|
||||||
from proliantutils.redfish.resources.system.storage import simple_storage
|
from proliantutils.redfish.resources.system.storage import simple_storage
|
||||||
from proliantutils.redfish.resources.system.storage import smart_storage
|
from proliantutils.redfish.resources.system.storage import smart_storage
|
||||||
from proliantutils.redfish.resources.system.storage import storage
|
from proliantutils.redfish.resources.system.storage import storage
|
||||||
|
@ -497,3 +498,65 @@ class HPESystemTestCase(testtools.TestCase):
|
||||||
def test_get_host_post_state(self):
|
def test_get_host_post_state(self):
|
||||||
expected = sys_cons.POST_STATE_FINISHEDPOST
|
expected = sys_cons.POST_STATE_FINISHEDPOST
|
||||||
self.assertEqual(expected, self.sys_inst.post_state)
|
self.assertEqual(expected, self.sys_inst.post_state)
|
||||||
|
|
||||||
|
@mock.patch.object(smart_storage_config, 'HPESmartStorageConfig',
|
||||||
|
autospec=True)
|
||||||
|
def test_get_smart_storage_config(self, mock_ssc):
|
||||||
|
ssc_element = '/redfish/v1/systems/1/smartstorageconfig/'
|
||||||
|
ssc_inst = self.sys_inst.get_smart_storage_config(ssc_element)
|
||||||
|
self.assertIsInstance(ssc_inst,
|
||||||
|
smart_storage_config.HPESmartStorageConfig.
|
||||||
|
__class__)
|
||||||
|
mock_ssc.assert_called_once_with(
|
||||||
|
self.conn, "/redfish/v1/systems/1/smartstorageconfig/",
|
||||||
|
redfish_version='1.0.2')
|
||||||
|
|
||||||
|
@mock.patch.object(system.HPESystem, 'get_smart_storage_config')
|
||||||
|
def test_delete_raid(self, get_smart_storage_config_mock):
|
||||||
|
config_id = ['/redfish/v1/systems/1/smartstorageconfig/']
|
||||||
|
type(self.sys_inst).smart_storage_config_identities = (
|
||||||
|
mock.PropertyMock(return_value=config_id))
|
||||||
|
self.sys_inst.delete_raid()
|
||||||
|
get_smart_storage_config_mock.assert_called_once_with(config_id[0])
|
||||||
|
(get_smart_storage_config_mock.return_value.
|
||||||
|
delete_raid.assert_called_once_with())
|
||||||
|
|
||||||
|
@mock.patch.object(system.HPESystem, 'get_smart_storage_config')
|
||||||
|
def test_delete_raid_controller_failed(self,
|
||||||
|
get_smart_storage_config_mock):
|
||||||
|
config_id = ['/redfish/v1/systems/1/smartstorageconfig/',
|
||||||
|
'/redfish/v1/systems/1/smartstorageconfig1/',
|
||||||
|
'/redfish/v1/systems/1/smartstorageconfig2/']
|
||||||
|
type(self.sys_inst).smart_storage_config_identities = (
|
||||||
|
mock.PropertyMock(return_value=config_id))
|
||||||
|
get_smart_storage_config_mock.return_value.delete_raid.side_effect = (
|
||||||
|
[None, sushy.exceptions.SushyError, None])
|
||||||
|
self.assertRaisesRegex(
|
||||||
|
exception.IloError,
|
||||||
|
"The Redfish controller failed to delete the "
|
||||||
|
"raid configuration in one or more controllers with",
|
||||||
|
self.sys_inst.delete_raid)
|
||||||
|
|
||||||
|
@mock.patch.object(system.HPESystem, 'get_smart_storage_config')
|
||||||
|
def test_delete_raid_logical_drive_not_found(
|
||||||
|
self, get_smart_storage_config_mock):
|
||||||
|
config_id = ['/redfish/v1/systems/1/smartstorageconfig/',
|
||||||
|
'/redfish/v1/systems/1/smartstorageconfig1/']
|
||||||
|
type(self.sys_inst).smart_storage_config_identities = (
|
||||||
|
mock.PropertyMock(return_value=config_id))
|
||||||
|
get_smart_storage_config_mock.return_value.delete_raid.side_effect = (
|
||||||
|
exception.IloLogicalDriveNotFoundError('No logical drive found'))
|
||||||
|
self.assertRaisesRegex(
|
||||||
|
exception.IloError,
|
||||||
|
"No logical drives are found in any controllers. "
|
||||||
|
"Nothing to delete.",
|
||||||
|
self.sys_inst.delete_raid)
|
||||||
|
|
||||||
|
def test_check_smart_storage_config_ids(self):
|
||||||
|
type(self.sys_inst).smart_storage_config_identities = (
|
||||||
|
mock.PropertyMock(return_value=None))
|
||||||
|
self.assertRaisesRegex(
|
||||||
|
exception.IloError,
|
||||||
|
"The Redfish controller failed to get the SmartStorageConfig "
|
||||||
|
"controller configurations",
|
||||||
|
self.sys_inst.check_smart_storage_config_ids)
|
||||||
|
|
|
@ -1454,3 +1454,8 @@ class RedfishOperationsTestCase(testtools.TestCase):
|
||||||
type(get_system_mock.return_value).post_state = post_state
|
type(get_system_mock.return_value).post_state = post_state
|
||||||
result = self.rf_client.get_host_post_state()
|
result = self.rf_client.get_host_post_state()
|
||||||
self.assertEqual('PowerOff', result)
|
self.assertEqual('PowerOff', result)
|
||||||
|
|
||||||
|
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_system')
|
||||||
|
def test_delete_raid_configuration(self, get_system_mock):
|
||||||
|
self.rf_client.delete_raid_configuration()
|
||||||
|
get_system_mock.return_value.delete_raid.assert_called_once_with()
|
||||||
|
|
Loading…
Reference in New Issue