Redfish: Follow up patch for storage related resources
Change-Id: I6af75c31a29bc08af8abc00f840b9c9749de7ab9
This commit is contained in:
parent
88294f20cf
commit
ba63ad11e6
@ -23,6 +23,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HPEArrayController(base.ResourceBase):
|
||||
"""This class represents the HPEArrayControllers resource"""
|
||||
|
||||
identity = base.Field('Id')
|
||||
"""The identity string"""
|
||||
@ -38,6 +39,8 @@ class HPEArrayController(base.ResourceBase):
|
||||
|
||||
@property
|
||||
def logical_drives(self):
|
||||
"""Gets the resource HPELogicalDriveCollection of ArrayControllers"""
|
||||
|
||||
if self._logical_drives is None:
|
||||
self._logical_drives = (
|
||||
logical_drive.HPELogicalDriveCollection(
|
||||
@ -48,6 +51,8 @@ class HPEArrayController(base.ResourceBase):
|
||||
|
||||
@property
|
||||
def physical_drives(self):
|
||||
"""Gets the resource HPEPhysicalDriveCollection of ArrayControllers"""
|
||||
|
||||
if self._physical_drives is None:
|
||||
self._physical_drives = (
|
||||
physical_drive.HPEPhysicalDriveCollection(
|
||||
@ -63,6 +68,7 @@ class HPEArrayController(base.ResourceBase):
|
||||
|
||||
|
||||
class HPEArrayControllerCollection(base.ResourceCollectionBase):
|
||||
"""This class represents the collection of HPEArrayControllers"""
|
||||
|
||||
_logical_drives_maximum_size_mib = None
|
||||
_physical_drives_maximum_size_mib = None
|
||||
|
53
proliantutils/redfish/resources/system/storage/constants.py
Normal file
53
proliantutils/redfish/resources/system/storage/constants.py
Normal file
@ -0,0 +1,53 @@
|
||||
# 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.
|
||||
|
||||
# Supported device protocols
|
||||
# Taken from http://redfish.dmtf.org/schemas/Storage.v1_2_0.json
|
||||
PROTOCOL_PCIe = "PCI Express (Vendor Proprietary)."
|
||||
PROTOCOL_AHCI = "Advanced Host Controller Interface."
|
||||
PROTOCOL_UHCI = "Universal Host Controller Interface."
|
||||
PROTOCOL_SAS = "Serial Attached SCSI."
|
||||
PROTOCOL_SATA = "Serial AT Attachment."
|
||||
PROTOCOL_USB = "Universal Serial Bus."
|
||||
PROTOCOL_NVMe = "Non-Volatile Memory Express."
|
||||
PROTOCOL_FC = "Fibre Channel."
|
||||
PROTOCOL_iSCSI = "Internet SCSI."
|
||||
PROTOCOL_FCoE = "Fibre Channel over Ethernet."
|
||||
PROTOCOL_FCP = "Fibre Channel Protocol for SCSI."
|
||||
PROTOCOL_FICON = "FIbre CONnection (FICON)."
|
||||
PROTOCOL_NVMeOverFabrics = "NVMe over Fabrics."
|
||||
PROTOCOL_SMB = "Server Message Block (aka CIFS Common Internet File System)."
|
||||
PROTOCOL_NFSv3 = "Network File System version 3."
|
||||
PROTOCOL_NFSv4 = "Network File System version 4."
|
||||
PROTOCOL_HTTP = "Hypertext Transport Protocol."
|
||||
PROTOCOL_HTTPS = "Secure Hypertext Transport Protocol."
|
||||
PROTOCOL_FTP = "File Transfer Protocol."
|
||||
PROTOCOL_SFTP = "Secure File Transfer Protocol."
|
||||
|
||||
# Media types
|
||||
MEDIA_TYPE_SSD = "SSD device"
|
||||
MEDIA_TYPE_HDD = "HDD device"
|
||||
|
||||
# RAID level constants
|
||||
RAID_0 = 'raid 0'
|
||||
RAID_1 = 'raid 1'
|
||||
RAID_5 = 'raid 5'
|
||||
RAID_1_0 = 'raid 1+0'
|
||||
RAID_5_0 = 'raid 5+0'
|
||||
RAID_6 = 'raid 6'
|
||||
RAID_6_0 = 'raid 6+0'
|
||||
RAID_1ADM = 'raid 1adm'
|
||||
RAID_10ADM = 'raid_10adm'
|
@ -16,18 +16,21 @@
|
||||
# "/redfish/v1/Systems/1/Storage/1/Drives" will be an invalid URI.
|
||||
|
||||
|
||||
from proliantutils.redfish.resources.system.storage import mappings
|
||||
|
||||
from sushy.resources import base
|
||||
|
||||
|
||||
class Drive(base.ResourceBase):
|
||||
"""This class represents the Drive resource"""
|
||||
|
||||
capacity_bytes = base.Field('CapacityBytes', adapter=int)
|
||||
"""The size in bytes of this Drive"""
|
||||
|
||||
media_type = base.Field('MediaType')
|
||||
media_type = base.MappedField('MediaType', mappings.MEDIA_TYPE_MAP)
|
||||
"""The type of media contained in this drive"""
|
||||
|
||||
protocol = base.Field('Protocol')
|
||||
protocol = base.MappedField('Protocol', mappings.DEVICE_PROTOCOLS_MAP)
|
||||
"""The protocol this drive is using to communicate to the storage
|
||||
controller."""
|
||||
|
||||
|
@ -16,8 +16,11 @@ from sushy.resources import base
|
||||
|
||||
from proliantutils.redfish import utils
|
||||
|
||||
from proliantutils.redfish.resources.system.storage import mappings
|
||||
|
||||
|
||||
class HPELogicalDrive(base.ResourceBase):
|
||||
"""This class represents the LogicalDrives resource"""
|
||||
|
||||
identity = base.Field('Id')
|
||||
|
||||
@ -27,10 +30,11 @@ class HPELogicalDrive(base.ResourceBase):
|
||||
|
||||
capacity_mib = base.Field('CapacityMiB', adapter=int)
|
||||
|
||||
raid = base.Field('Raid')
|
||||
raid = base.MappedField('Raid', mappings.RAID_LEVEL_MAP)
|
||||
|
||||
|
||||
class HPELogicalDriveCollection(base.ResourceCollectionBase):
|
||||
"""This class represents the collection of LogicalDrives resource"""
|
||||
|
||||
_maximum_size_mib = None
|
||||
|
||||
|
62
proliantutils/redfish/resources/system/storage/mappings.py
Normal file
62
proliantutils/redfish/resources/system/storage/mappings.py
Normal file
@ -0,0 +1,62 @@
|
||||
# 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.
|
||||
|
||||
from sushy import utils
|
||||
|
||||
from proliantutils.redfish.resources.system.storage import constants
|
||||
|
||||
DEVICE_PROTOCOLS_MAP = {
|
||||
'PCIe': constants.PROTOCOL_PCIe,
|
||||
'AHCI': constants.PROTOCOL_AHCI,
|
||||
'UHCI': constants.PROTOCOL_UHCI,
|
||||
'SAS': constants.PROTOCOL_SAS,
|
||||
'SATA': constants.PROTOCOL_SATA,
|
||||
'USB': constants.PROTOCOL_USB,
|
||||
'NVMe': constants.PROTOCOL_NVMe,
|
||||
'FC': constants.PROTOCOL_FC,
|
||||
'iSCSI': constants.PROTOCOL_iSCSI,
|
||||
'FCoE': constants.PROTOCOL_FCoE,
|
||||
'FCP': constants.PROTOCOL_FCP,
|
||||
'FICON': constants.PROTOCOL_FICON,
|
||||
'NVMeOverFabrics': constants.PROTOCOL_NVMeOverFabrics,
|
||||
'SMB': constants.PROTOCOL_SMB,
|
||||
'NFSv3': constants.PROTOCOL_NFSv3,
|
||||
'NFSv4': constants.PROTOCOL_NFSv4,
|
||||
'HTTP': constants.PROTOCOL_HTTP,
|
||||
'HTTPS': constants.PROTOCOL_HTTPS,
|
||||
'FTP': constants.PROTOCOL_FTP,
|
||||
'SFTP': constants.PROTOCOL_SFTP
|
||||
}
|
||||
|
||||
MEDIA_TYPE_MAP = {
|
||||
'SSD': constants.MEDIA_TYPE_SSD,
|
||||
'HDD': constants.MEDIA_TYPE_HDD
|
||||
}
|
||||
|
||||
RAID_LEVEL_MAP = {
|
||||
'0': constants.RAID_0,
|
||||
'1': constants.RAID_1,
|
||||
'5': constants.RAID_5,
|
||||
'10': constants.RAID_1_0,
|
||||
'50': constants.RAID_5_0,
|
||||
'6': constants.RAID_6,
|
||||
'60': constants.RAID_6_0,
|
||||
'1ADM': constants.RAID_1ADM,
|
||||
'10ADM': constants.RAID_10ADM,
|
||||
}
|
||||
|
||||
RAID_LEVEL_MAP_REV = (
|
||||
utils.revert_dictionary(RAID_LEVEL_MAP))
|
@ -12,16 +12,15 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import logging
|
||||
|
||||
from sushy.resources import base
|
||||
|
||||
from proliantutils.redfish import utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
from proliantutils.redfish.resources.system.storage import mappings
|
||||
|
||||
|
||||
class HPEPhysicalDrive(base.ResourceBase):
|
||||
"""This class represents the HPEPhysicalDrives resource"""
|
||||
|
||||
identity = base.Field('Id', required=True)
|
||||
|
||||
@ -31,12 +30,13 @@ class HPEPhysicalDrive(base.ResourceBase):
|
||||
|
||||
capacity_mib = base.Field('CapacityMiB', adapter=int)
|
||||
|
||||
media_type = base.Field('MediaType')
|
||||
media_type = base.MappedField('MediaType', mappings.MEDIA_TYPE_MAP)
|
||||
|
||||
rotational_speed_rpm = base.Field('RotationalSpeedRpm', adapter=int)
|
||||
|
||||
|
||||
class HPEPhysicalDriveCollection(base.ResourceCollectionBase):
|
||||
"""This class represents the collection of HPEPhysicalDrives resource"""
|
||||
|
||||
_maximum_size_mib = None
|
||||
|
||||
|
@ -22,6 +22,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HPESmartStorage(base.ResourceBase):
|
||||
"""This class represents the HPE OEM SmartStorage resource"""
|
||||
|
||||
name = base.Field('Name')
|
||||
"""The name of the resource or array element"""
|
||||
|
@ -24,6 +24,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Storage(base.ResourceBase):
|
||||
"""This class represents the Storage resource"""
|
||||
|
||||
identity = base.Field('Id', required=True)
|
||||
"""The Storage identity string"""
|
||||
@ -34,9 +35,6 @@ class Storage(base.ResourceBase):
|
||||
description = base.Field('Description')
|
||||
"""Description"""
|
||||
|
||||
storage_controllers = base.Field('StorageControllers')
|
||||
"""The set of storage controllers"""
|
||||
|
||||
drives = base.Field('Drives')
|
||||
"""The set of drives attached to the storage controllers"""
|
||||
|
||||
@ -56,7 +54,7 @@ class Storage(base.ResourceBase):
|
||||
return self._volumes
|
||||
|
||||
def _drives_list(self):
|
||||
"""This property prepares the list of drives
|
||||
"""Gets the list of drives
|
||||
|
||||
:return a list of drives.
|
||||
"""
|
||||
@ -85,6 +83,7 @@ class Storage(base.ResourceBase):
|
||||
|
||||
|
||||
class StorageCollection(base.ResourceCollectionBase):
|
||||
"""This class represents the collection of Storage resource"""
|
||||
|
||||
_volumes_maximum_size_bytes = None
|
||||
_drives_maximum_size_bytes = None
|
||||
|
@ -12,13 +12,13 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
|
||||
from sushy.resources import base
|
||||
|
||||
from proliantutils.redfish import utils
|
||||
|
||||
|
||||
class Volume(base.ResourceBase):
|
||||
"""This class represents the Volume resource"""
|
||||
|
||||
identity = base.Field('Id', required=True)
|
||||
"""The processor identity string"""
|
||||
@ -26,11 +26,9 @@ class Volume(base.ResourceBase):
|
||||
capacity_bytes = base.Field('CapacityBytes', adapter=int)
|
||||
"""The size in bytes of this Volume"""
|
||||
|
||||
volume_type = base.Field('VolumeType')
|
||||
"""The type of this volume."""
|
||||
|
||||
|
||||
class VolumeCollection(base.ResourceCollectionBase):
|
||||
"""This class represents the collection of Volume resource"""
|
||||
|
||||
_maximum_size_bytes = None
|
||||
|
||||
|
@ -17,6 +17,7 @@ import json
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
from proliantutils.redfish.resources.system.storage import constants
|
||||
from proliantutils.redfish.resources.system.storage import drive
|
||||
|
||||
|
||||
@ -38,3 +39,6 @@ class DriveTestCase(testtools.TestCase):
|
||||
def test__parse_attributes(self):
|
||||
self.sys_drive._parse_attributes()
|
||||
self.assertEqual('1.0.2', self.sys_drive.redfish_version)
|
||||
self.assertEqual(899527000000, self.sys_drive.capacity_bytes)
|
||||
self.assertEqual(constants.PROTOCOL_SAS, self.sys_drive.protocol)
|
||||
self.assertEqual(constants.MEDIA_TYPE_HDD, self.sys_drive.media_type)
|
||||
|
@ -41,8 +41,6 @@ class StorageTestCase(testtools.TestCase):
|
||||
self.assertEqual('Local Storage Controller', self.sys_stor.name)
|
||||
self.assertEqual('Integrated RAID Controller',
|
||||
self.sys_stor.description)
|
||||
self.assertEqual(self.stor_json.get('StorageControllers'),
|
||||
self.sys_stor.storage_controllers)
|
||||
self.assertEqual(self.stor_json.get('Drives'),
|
||||
self.sys_stor.drives)
|
||||
|
||||
@ -64,7 +62,7 @@ class StorageTestCase(testtools.TestCase):
|
||||
self.sys_stor.refresh()
|
||||
self.assertIsNone(self.sys_stor._volumes)
|
||||
|
||||
def test_drives_list(self):
|
||||
def test__drives_list(self):
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/drive.json') as f:
|
||||
|
@ -37,7 +37,6 @@ class VolumeTestCase(testtools.TestCase):
|
||||
self.sys_vol._parse_attributes()
|
||||
self.assertEqual('1.0.2', self.sys_vol.redfish_version)
|
||||
self.assertEqual('1', self.sys_vol.identity)
|
||||
self.assertEqual('Mirrored', self.sys_vol.volume_type)
|
||||
self.assertEqual(899527000000, self.sys_vol.capacity_bytes)
|
||||
|
||||
|
||||
|
@ -358,9 +358,8 @@ class HPESystemTestCase(testtools.TestCase):
|
||||
value = (json.loads(f.read()))
|
||||
self.conn.get.return_value.json.return_value = value
|
||||
self.assertIsNone(self.sys_inst._smart_storage)
|
||||
self.sys_inst.smart_storage
|
||||
self.assertIsInstance(self.sys_inst._smart_storage,
|
||||
smart_storage.HPESmartStorage)
|
||||
value = self.sys_inst.smart_storage
|
||||
self.assertIsInstance(value, smart_storage.HPESmartStorage)
|
||||
|
||||
def test_storages(self):
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
@ -375,9 +374,8 @@ class HPESystemTestCase(testtools.TestCase):
|
||||
value = (json.loads(f.read()))
|
||||
self.conn.get.return_value.json.side_effect = [coll, value]
|
||||
self.assertIsNone(self.sys_inst._storages)
|
||||
self.sys_inst.storages
|
||||
self.assertIsInstance(self.sys_inst._storages,
|
||||
storage.StorageCollection)
|
||||
value = self.sys_inst.storages
|
||||
self.assertIsInstance(value, storage.StorageCollection)
|
||||
|
||||
def test_simple_storages(self):
|
||||
self.conn.get.return_value.json.reset_mock()
|
||||
@ -392,35 +390,25 @@ class HPESystemTestCase(testtools.TestCase):
|
||||
value = (json.loads(f.read()))
|
||||
self.conn.get.return_value.json.side_effect = [coll, value]
|
||||
self.assertIsNone(self.sys_inst._simple_storages)
|
||||
self.sys_inst.simple_storages
|
||||
self.assertIsInstance(self.sys_inst._simple_storages,
|
||||
simple_storage.SimpleStorageCollection)
|
||||
value = self.sys_inst.simple_storages
|
||||
self.assertIsInstance(value, simple_storage.SimpleStorageCollection)
|
||||
|
||||
def test_simple_storage_on_refresh(self):
|
||||
# | GIVEN |
|
||||
with open('proliantutils/tests/redfish/json_samples/'
|
||||
'simple_storage_collection.json',
|
||||
'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
# | WHEN & THEN |
|
||||
self.assertIsInstance(self.sys_inst.simple_storages,
|
||||
simple_storage.SimpleStorageCollection)
|
||||
|
||||
# On refreshing the system instance...
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/system.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = (
|
||||
json.loads(f.read())['default'])
|
||||
self.sys_inst.refresh()
|
||||
|
||||
# | WHEN & THEN |
|
||||
self.assertIsNone(self.sys_inst._simple_storages)
|
||||
|
||||
# | GIVEN |
|
||||
with open('proliantutils/tests/redfish/json_samples/'
|
||||
'simple_storage_collection.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
# | WHEN & THEN |
|
||||
self.assertIsInstance(self.sys_inst.simple_storages,
|
||||
simple_storage.SimpleStorageCollection)
|
||||
|
||||
@ -466,3 +454,24 @@ class HPESystemTestCase(testtools.TestCase):
|
||||
# | WHEN & THEN |
|
||||
self.assertIsInstance(self.sys_inst.memory,
|
||||
memory.MemoryCollection)
|
||||
|
||||
def test_storage_on_refresh(self):
|
||||
with open('proliantutils/tests/redfish/json_samples/'
|
||||
'storage_collection.json',
|
||||
'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
self.assertIsInstance(self.sys_inst.storages,
|
||||
storage.StorageCollection)
|
||||
# On refreshing the system instance...
|
||||
with open('proliantutils/tests/redfish/'
|
||||
'json_samples/system.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = (
|
||||
json.loads(f.read())['default'])
|
||||
self.sys_inst.refresh()
|
||||
self.assertIsNone(self.sys_inst._storages)
|
||||
|
||||
with open('proliantutils/tests/redfish/json_samples/'
|
||||
'simple_storage_collection.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
self.assertIsInstance(self.sys_inst.storages,
|
||||
storage.StorageCollection)
|
||||
|
@ -743,11 +743,6 @@ class RedfishOperationsTestCase(testtools.TestCase):
|
||||
@mock.patch.object(redfish.RedfishOperations, '_get_sushy_manager')
|
||||
def test_get_server_capabilities_optional_capabilities_absent(
|
||||
self, get_manager_mock, get_system_mock):
|
||||
val = []
|
||||
path = ('proliantutils/tests/redfish/json_samples/'
|
||||
'pci_device.json')
|
||||
with open(path, 'r') as f:
|
||||
val.append(json.loads(f.read()))
|
||||
type(get_system_mock.return_value.pci_devices).gpu_devices = (
|
||||
[mock.MagicMock(spec=pci_device.PCIDevice)])
|
||||
type(get_system_mock.return_value.bios_settings).sriov = (
|
||||
|
Loading…
Reference in New Issue
Block a user