Redfish: Follow up patch for storage related resources

Change-Id: I6af75c31a29bc08af8abc00f840b9c9749de7ab9
This commit is contained in:
Nisha Agarwal 2017-07-28 06:31:54 +00:00
parent 88294f20cf
commit ba63ad11e6
14 changed files with 173 additions and 42 deletions

View File

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

View 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'

View File

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

View File

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

View 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))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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