Merge "Redfish: Add the Storage and its related URIs for local_gb discovery"

This commit is contained in:
Jenkins 2017-08-01 09:15:50 +00:00 committed by Gerrit Code Review
commit 55bd626431
13 changed files with 746 additions and 1 deletions

View File

@ -0,0 +1,35 @@
# Copyright 2017 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.
# There is no explicit collection for Drives. That said, a URI link as
# "/redfish/v1/Systems/1/Storage/1/Drives" will be an invalid URI.
from sushy.resources import base
class Drive(base.ResourceBase):
capacity_bytes = base.Field('CapacityBytes', adapter=int)
"""The size in bytes of this Drive"""
media_type = base.Field('MediaType')
"""The type of media contained in this drive"""
protocol = base.Field('Protocol')
"""The protocol this drive is using to communicate to the storage
controller."""
rotation_speed_rpm = base.Field('RotationSpeedRPM', adapter=int)
"""The rotation speed of this Drive in Revolutions per Minute (RPM)."""

View File

@ -0,0 +1,123 @@
# Copyright 2017 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.
import logging
from proliantutils.redfish.resources.system.storage import drive as sys_drives
from proliantutils.redfish.resources.system.storage \
import volume as sys_volumes
from proliantutils.redfish import utils
from sushy.resources import base
LOG = logging.getLogger(__name__)
class Storage(base.ResourceBase):
identity = base.Field('Id', required=True)
"""The Storage identity string"""
name = base.Field('Name')
"""The name of the resource or array element"""
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"""
_volumes = None
_drives_maximum_size_bytes = None
@property
def volumes(self):
"""This property prepares the list of volumes
:return a list of volumes.
"""
if self._volumes is None:
self._volumes = sys_volumes.VolumeCollection(
self._conn, utils.get_subresource_path_by(self, 'Volumes'),
redfish_version=self.redfish_version)
return self._volumes
def _drives_list(self):
"""This property prepares the list of drives
:return a list of drives.
"""
drives_list = []
for member in self.drives:
drives_list.append(sys_drives.Drive(
self._conn, member.get('@odata.id'), self.redfish_version))
return drives_list
@property
def drives_maximum_size_bytes(self):
"""Gets the biggest disk
:returns the size in MiB.
"""
if self._drives_maximum_size_bytes is None:
self._drives_maximum_size_bytes = (
max([member.capacity_bytes
for member in self._drives_list()]))
return self._drives_maximum_size_bytes
def refresh(self):
super(Storage, self).refresh()
self._drives_maximum_size_bytes = None
self._volumes = None
class StorageCollection(base.ResourceCollectionBase):
_volumes_maximum_size_bytes = None
_drives_maximum_size_bytes = None
@property
def _resource_type(self):
return Storage
@property
def volumes_maximum_size_bytes(self):
"""Gets the biggest logical drive
:returns the size in MiB.
"""
if self._volumes_maximum_size_bytes is None:
self._volumes_maximum_size_bytes = (
max([member.volumes.maximum_size_bytes
for member in self.get_members()]))
return self._volumes_maximum_size_bytes
@property
def drives_maximum_size_bytes(self):
"""Gets the biggest disk
:returns the size in MiB.
"""
if self._drives_maximum_size_bytes is None:
self._drives_maximum_size_bytes = (
max([member.drives_maximum_size_bytes
for member in self.get_members()]))
return self._drives_maximum_size_bytes
def refresh(self):
super(StorageCollection, self).refresh()
self._volumes_maximum_size_bytes = None
self._drives_maximum_size_bytes = None

View File

@ -0,0 +1,52 @@
# Copyright 2017 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 sushy.resources import base
class Volume(base.ResourceBase):
identity = base.Field('Id', required=True)
"""The processor identity string"""
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):
_maximum_size_bytes = None
@property
def _resource_type(self):
return Volume
@property
def maximum_size_bytes(self):
"""Gets the biggest volume
:returns size in bytes.
"""
if self._maximum_size_bytes is None:
self._maximum_size_bytes = (
max([member.capacity_bytes for member in self.get_members()]))
return self._maximum_size_bytes
def refresh(self):
super(VolumeCollection, self).refresh()
self._maximum_size_bytes = None

View File

@ -28,6 +28,7 @@ from proliantutils.redfish.resources.system import pci_device
from proliantutils.redfish.resources.system import secure_boot
from proliantutils.redfish.resources.system.storage import \
smart_storage as hpe_smart_storage
from proliantutils.redfish.resources.system.storage import storage
from proliantutils.redfish import utils
@ -76,7 +77,7 @@ class HPESystem(system.System):
_secure_boot = None # ref to SecureBoot instance
_smart_storage = None
_storages = None
_pci_devices = None
_ethernet_interfaces = None
@ -197,6 +198,7 @@ class HPESystem(system.System):
self._secure_boot = None
self._ethernet_interfaces = None
self._smart_storage = None
self._storages = None
def _get_hpe_sub_resource_collection_path(self, sub_res):
path = None
@ -234,3 +236,16 @@ class HPESystem(system.System):
self, ['Oem', 'Hpe', 'Links', 'SmartStorage']),
redfish_version=self.redfish_version)
return self._smart_storage
@property
def storages(self):
"""This property gets the list of instances for Storages
This property gets the list of instances for Storages
:returns: a list of instances of Storages
"""
if self._storages is None:
self._storages = storage.StorageCollection(
self._conn, utils.get_subresource_path_by(self, 'Storage'),
redfish_version=self.redfish_version)
return self._storages

View File

@ -0,0 +1,82 @@
{
"drive1":{
"@odata.type": "#Drive.v1_1_0.Drive",
"IndicatorLED": "Lit",
"Model": "C123",
"Revision": "100A",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"CapacityBytes": 899527000000,
"FailurePredicted": false,
"Protocol": "SAS",
"MediaType": "HDD",
"Manufacturer": "Contoso",
"SerialNumber": "1234567",
"PartNumber": "C123-1111",
"Identifiers": [{
"DurableNameFormat": "NAA",
"DurableName": "35D38F11ACEF7BD3"
}],
"HotspareType": "None",
"EncryptionAbility": "SelfEncryptingDrive",
"EncryptionStatus": "Unlocked",
"RotationSpeedRPM": 15000,
"BlockSizeBytes": 512,
"CapableSpeedGbs": 12,
"NegotiatedSpeedGbs": 12,
"Links": {
"Volumes": [{
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1"
}]
},
"Actions": {
"#Drive.SecureErase": {
"Target": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/35D38F11ACEF7BD3/Actions/Drive.SecureErase"
}
},
"@odata.context": "/redfish/v1/$metadata#Drive.Drive",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/35D38F11ACEF7BD3"
},
"drive2": {
"@odata.type": "#Drive.v1_1_0.Drive",
"IndicatorLED": "Lit",
"Model": "C123",
"Revision": "100A",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"CapacityBytes": 899527000000,
"FailurePredicted": false,
"Protocol": "SAS",
"MediaType": "HDD",
"Manufacturer": "Contoso",
"SerialNumber": "1234567",
"PartNumber": "C123-1111",
"Identifiers": [{
"DurableNameFormat": "NAA",
"DurableName": "3F5A8C54207B7233"
}],
"HotspareType": "None",
"EncryptionAbility": "SelfEncryptingDrive",
"EncryptionStatus": "Unlocked",
"RotationSpeedRPM": 15000,
"BlockSizeBytes": 512,
"CapableSpeedGbs": 12,
"NegotiatedSpeedGbs": 12,
"Links": {
"Volumes": [{
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1"
}]
},
"Actions": {
"#Drive.SecureErase": {
"Target": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/3F5A8C54207B7233/Actions/Drive.SecureErase"
}
},
"@odata.context": "/redfish/v1/$metadata#Drive.Drive",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/3F5A8C54207B7233"
}
}

View File

@ -0,0 +1,55 @@
{
"@odata.type": "#Storage.v1_1_0.Storage",
"Id": "1",
"Name": "Local Storage Controller",
"Description": "Integrated RAID Controller",
"Status": {
"State": "Enabled",
"Health": "OK",
"HealthRollup": "OK"
},
"StorageControllers": [{
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1#/StorageControllers/0",
"@odata.type": "#Storage.v1_0_0.StorageController",
"Id": "0",
"Name": "Contoso Integrated RAID",
"Description": "Contoso Integrated RAID",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"Identifiers": [{
"DurableNameFormat": "NAA",
"DurableName": "345C59DBD970859C"
}],
"Manufacturer": "Contoso",
"Model": "12Gbs Integrated RAID",
"SerialNumber": "2M220100SL",
"PartNumber": "CT18754",
"SpeedGbps": 12,
"FirmwareVersion": "1.0.0.7",
"SupportedControllerProtocols": [
"PCIe"
],
"SupportedDeviceProtocols": [
"SAS",
"SATA"
]
}],
"Drives": [{
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/35D38F11ACEF7BD3"
}, {
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/3F5A8C54207B7233"
}],
"Volumes": {
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes"
},
"Links": {},
"Actions": {
"#Storage.SetEncryptionKey": {
"Target": "/redfish/v1/Systems/437XR1138R2/Storage/1/Actions/Storage.SetEncryptionKey"
}
},
"@odata.context": "/redfish/v1/$metadata#Storage.Storage",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1"
}

View File

@ -0,0 +1,10 @@
{
"@odata.type": "#StorageCollection.StorageCollection",
"Name": "Storage Collection",
"Members@odata.count": 1,
"Members": [{
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1"
}],
"@odata.context": "/redfish/v1/$metadata#StorageCollection.StorageCollection",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage"
}

View File

@ -0,0 +1,37 @@
{
"@odata.type": "#Volume.v1_0_0.Volume",
"Id": "1",
"Name": "Virtual Disk 1",
"Status": {
"State": "Enabled",
"Health": "OK"
},
"Encrypted": false,
"VolumeType": "Mirrored",
"CapacityBytes": 899527000000,
"Identifiers": [{
"DurableNameFormat": "VPD83type3",
"DurableName": "690b11c02547001d96f0fbe6c1cb31"
}, {
"DurableNameFormat": "UUID",
"DurableName": "38f1818b-111e-463a-aa19-fa54f792e468"
}],
"Links": {
"Drives": [{
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/3F5A8C54207B7233"
}, {
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Drives/35D38F11ACEF7BD3"
}]
},
"Actions": {
"#Volume.Initialize": {
"Target": "/redfish/v1/Systems/3/Storage/RAIDIntegrated/Volumes/1/Actions/Volume.Initialize",
"InitializeType@Redfish.AllowableValues": [
"Fast",
"Slow"
]
}
},
"@odata.context": "/redfish/v1/$metadata#Volume.Volume",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1"
}

View File

@ -0,0 +1,12 @@
{
"@odata.context": "/redfish/v1/$metadata#VolumeCollection.VolumeCollection",
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes",
"@odata.type": "#VolumeCollection.VolumeCollection",
"Name": "Storage Volume Collection",
"Description": "Storage Volume Collection",
"Members@odata.count": 1,
"Members": [{
"@odata.id": "/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1"
}],
"Oem": {}
}

View File

@ -0,0 +1,40 @@
# Copyright 2017 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.
import json
import mock
import testtools
from proliantutils.redfish.resources.system.storage import drive
class DriveTestCase(testtools.TestCase):
def setUp(self):
super(DriveTestCase, self).setUp()
self.conn = mock.Mock()
drive_file = 'proliantutils/tests/redfish/json_samples/drive.json'
with open(drive_file, 'r') as f:
dr_json = json.loads(f.read())
self.conn.get.return_value.json.return_value = dr_json['drive1']
drive_path = ("/redfish/v1/Systems/437XR1138R2/Storage/1/"
"Drives/35D38F11ACEF7BD3")
self.sys_drive = drive.Drive(
self.conn, drive_path, redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_drive._parse_attributes()
self.assertEqual('1.0.2', self.sys_drive.redfish_version)

View File

@ -0,0 +1,172 @@
# Copyright 2017 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.
import json
import mock
import testtools
from proliantutils.redfish.resources.system.storage import storage
class StorageTestCase(testtools.TestCase):
def setUp(self):
super(StorageTestCase, self).setUp()
self.conn = mock.Mock()
storage_file = 'proliantutils/tests/redfish/json_samples/storage.json'
with open(storage_file, 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.stor_json = self.conn.get.return_value.json.return_value
path = ("/redfish/v1/Systems/437XR1138R2/Storage/1")
self.sys_stor = storage.Storage(
self.conn, path, redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_stor._parse_attributes()
self.assertEqual('1.0.2', self.sys_stor.redfish_version)
self.assertEqual('1', self.sys_stor.identity)
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)
def test_volumes(self):
log_coll = None
log_dr = None
self.assertIsNone(self.sys_stor._volumes)
self.conn.get.return_value.json.reset_mock()
with open('proliantutils/tests/redfish/'
'json_samples/volume_collection.json') as f:
log_coll = json.loads(f.read())
with open('proliantutils/tests/redfish/'
'json_samples/volume.json') as f:
log_dr = json.loads(f.read())
self.conn.get.return_value.json.side_effect = [log_coll, log_dr]
actual_log_dr = self.sys_stor.volumes
self.assertIs(actual_log_dr,
self.sys_stor.volumes)
self.sys_stor.refresh()
self.assertIsNone(self.sys_stor._volumes)
def test_drives_list(self):
self.conn.get.return_value.json.reset_mock()
with open('proliantutils/tests/redfish/'
'json_samples/drive.json') as f:
dr_json = json.loads(f.read())
self.conn.get.return_value.json.side_effect = [dr_json['drive1'],
dr_json['drive2']]
actual_dr = self.sys_stor._drives_list()
self.assertIsInstance(actual_dr, list)
def test_drives_maximum_size_bytes(self):
self.assertIsNone(self.sys_stor._drives_maximum_size_bytes)
self.conn.get.return_value.json.reset_mock()
val = []
path = ('proliantutils/tests/redfish/json_samples/'
'drive.json')
with open(path, 'r') as f:
dr_json = json.loads(f.read())
val.append(dr_json['drive1'])
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
expected = 899527000000
actual = self.sys_stor.drives_maximum_size_bytes
self.assertEqual(expected, actual)
class StorageCollectionTestCase(testtools.TestCase):
def setUp(self):
super(StorageCollectionTestCase, self).setUp()
self.conn = mock.Mock()
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.sys_stor_col = storage.StorageCollection(
self.conn, '/redfish/v1/Systems/437XR1138R2/Storage',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_stor_col._parse_attributes()
self.assertEqual('1.0.2', self.sys_stor_col.redfish_version)
self.assertEqual('Storage Collection',
self.sys_stor_col.name)
path = ('/redfish/v1/Systems/437XR1138R2/Storage/1',)
self.assertEqual(path, self.sys_stor_col.members_identities)
@mock.patch.object(storage, 'Storage', autospec=True)
def test_get_member(self, mock_eth):
self.sys_stor_col.get_member(
'/redfish/v1/Systems/437XR1138R2/Storage/1')
mock_eth.assert_called_once_with(
self.sys_stor_col._conn,
('/redfish/v1/Systems/437XR1138R2/Storage/1'),
redfish_version=self.sys_stor_col.redfish_version)
@mock.patch.object(storage, 'Storage', autospec=True)
def test_get_members(self, mock_eth):
members = self.sys_stor_col.get_members()
path = ("/redfish/v1/Systems/437XR1138R2/Storage/1")
calls = [
mock.call(self.sys_stor_col._conn, path,
redfish_version=self.sys_stor_col.redfish_version),
]
mock_eth.assert_has_calls(calls)
self.assertIsInstance(members, list)
self.assertEqual(1, len(members))
def test_volumes_maximum_size_bytes(self):
self.assertIsNone(self.sys_stor_col._volumes_maximum_size_bytes)
self.conn.get.return_value.json.reset_mock()
val = []
path = ('proliantutils/tests/redfish/json_samples/'
'storage.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'volume_collection.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'volume.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
self.conn.get.return_value.json.side_effect = val
expected = 899527000000
actual = self.sys_stor_col.volumes_maximum_size_bytes
self.assertEqual(expected, actual)
def test_drives_maximum_size_bytes(self):
self.assertIsNone(self.sys_stor_col._drives_maximum_size_bytes)
self.conn.get.return_value.json.reset_mock()
val = []
path = ('proliantutils/tests/redfish/json_samples/'
'storage.json')
with open(path, 'r') as f:
val.append(json.loads(f.read()))
path = ('proliantutils/tests/redfish/json_samples/'
'drive.json')
with open(path, 'r') as f:
dr_json = json.loads(f.read())
val.append(dr_json['drive1'])
val.append(dr_json['drive2'])
self.conn.get.return_value.json.side_effect = val
expected = 899527000000
actual = self.sys_stor_col.drives_maximum_size_bytes
self.assertEqual(expected, actual)

View File

@ -0,0 +1,94 @@
# Copyright 2017 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.
import json
import mock
import testtools
from proliantutils.redfish.resources.system.storage import volume
class VolumeTestCase(testtools.TestCase):
def setUp(self):
super(VolumeTestCase, self).setUp()
self.conn = mock.Mock()
vol_file = 'proliantutils/tests/redfish/json_samples/volume.json'
with open(vol_file, 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
vol_path = ("/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1")
self.sys_vol = volume.Volume(
self.conn, vol_path, redfish_version='1.0.2')
def test__parse_attributes(self):
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)
class VolumeCollectionTestCase(testtools.TestCase):
def setUp(self):
super(VolumeCollectionTestCase, self).setUp()
self.conn = mock.Mock()
with open('proliantutils/tests/redfish/json_samples/'
'volume_collection.json', 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
self.sys_vol_col = volume.VolumeCollection(
self.conn, '/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes',
redfish_version='1.0.2')
def test__parse_attributes(self):
self.sys_vol_col._parse_attributes()
self.assertEqual('1.0.2', self.sys_vol_col.redfish_version)
self.assertEqual('Storage Volume Collection',
self.sys_vol_col.name)
vol_path = ('/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1',)
self.assertEqual(vol_path, self.sys_vol_col.members_identities)
@mock.patch.object(volume, 'Volume', autospec=True)
def test_get_member(self, mock_vol):
self.sys_vol_col.get_member(
'/redfish/v1/Systems/437XR1138R2/Volumes/1')
mock_vol.assert_called_once_with(
self.sys_vol_col._conn,
('/redfish/v1/Systems/437XR1138R2/Volumes/1'),
redfish_version=self.sys_vol_col.redfish_version)
@mock.patch.object(volume, 'Volume', autospec=True)
def test_get_members(self, mock_vol):
members = self.sys_vol_col.get_members()
vol_path = ("/redfish/v1/Systems/437XR1138R2/Storage/1/Volumes/1")
calls = [
mock.call(self.sys_vol_col._conn, vol_path,
redfish_version=self.sys_vol_col.redfish_version),
]
mock_vol.assert_has_calls(calls)
self.assertIsInstance(members, list)
self.assertEqual(1, len(members))
def test_maximum_size_bytes(self):
self.assertIsNone(self.sys_vol_col._maximum_size_bytes)
self.conn.get.return_value.json.reset_mock()
path = ('proliantutils/tests/redfish/json_samples/'
'volume.json')
with open(path, 'r') as f:
self.conn.get.return_value.json.return_value = json.loads(f.read())
expected = 899527000000
actual = self.sys_vol_col.maximum_size_bytes
self.assertEqual(expected, actual)

View File

@ -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 secure_boot
from proliantutils.redfish.resources.system.storage import smart_storage
from proliantutils.redfish.resources.system.storage import storage
from proliantutils.redfish.resources.system import system
from proliantutils.redfish import utils
from sushy.resources.system import system as sushy_system
@ -358,3 +359,20 @@ class HPESystemTestCase(testtools.TestCase):
self.sys_inst.smart_storage
self.assertIsInstance(self.sys_inst._smart_storage,
smart_storage.HPESmartStorage)
def test_storages(self):
self.conn.get.return_value.json.reset_mock()
coll = None
value = None
path = ('proliantutils/tests/redfish/json_samples/'
'storage_collection.json')
with open(path, 'r') as f:
coll = json.loads(f.read())
with open('proliantutils/tests/redfish/json_samples/'
'storage.json', 'r') as f:
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)