From aeacfae878ce67bc5eae2d29ae061d69389f6d21 Mon Sep 17 00:00:00 2001 From: Lin Yang Date: Tue, 28 May 2019 17:03:56 -0700 Subject: [PATCH] Add CapacitySources class in RSD 2.4 Change-Id: I049ce331a5a2f430dca4a5e9f56e11dcbfc4fa45 --- .../v2_4/storage_service/capacity.py | 132 +++++++++++ .../resources/v2_4/storage_service/volume.py | 31 ++- .../json_samples/v2_4/capacity_sources.json | 28 +++ .../tests/unit/json_samples/v2_4/volume.json | 13 +- .../v2_4/storage_service/test_capacity.py | 224 ++++++++++++++++++ .../v2_4/storage_service/test_volume.py | 195 ++++++++++----- 6 files changed, 546 insertions(+), 77 deletions(-) create mode 100644 rsd_lib/resources/v2_4/storage_service/capacity.py create mode 100644 rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json create mode 100644 rsd_lib/tests/unit/resources/v2_4/storage_service/test_capacity.py diff --git a/rsd_lib/resources/v2_4/storage_service/capacity.py b/rsd_lib/resources/v2_4/storage_service/capacity.py new file mode 100644 index 0000000..5a9de67 --- /dev/null +++ b/rsd_lib/resources/v2_4/storage_service/capacity.py @@ -0,0 +1,132 @@ +# Copyright 2019 Intel, Inc. +# 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.resources import base +from sushy import utils + +from rsd_lib import base as rsd_lib_base +from rsd_lib.resources.v2_3.storage_service import drive +from rsd_lib.resources.v2_3.storage_service import storage_pool +from rsd_lib import utils as rsd_lib_utils + + +class CapacityInfoField(base.CompositeField): + """CapacityInfo field + + The capacity of specific data type in a data store. + """ + + consumed_bytes = base.Field( + "ConsumedBytes", adapter=rsd_lib_utils.num_or_none + ) + """The number of bytes consumed in this data store for this data type.""" + + allocated_bytes = base.Field( + "AllocatedBytes", adapter=rsd_lib_utils.num_or_none + ) + """The number of bytes currently allocated by the storage system in this + data store for this data type. + """ + + guaranteed_bytes = base.Field( + "GuaranteedBytes", adapter=rsd_lib_utils.num_or_none + ) + """The number of bytes the storage system guarantees can be allocated in + this data store for this data type. + """ + + provisioned_bytes = base.Field( + "ProvisionedBytes", adapter=rsd_lib_utils.num_or_none + ) + """The maximum number of bytes that can be allocated in this data store + for this data type. + """ + + +class CapacityField(base.CompositeField): + """Capacity field + + This is the schema definition for the Capacity of a device. It + represents the properties for capacity for any data store. + """ + + data = CapacityInfoField("Data") + """The capacity information relating to the user data.""" + + metadata = CapacityInfoField("Metadata") + """The capacity information relating to metadata.""" + + snapshot = CapacityInfoField("Snapshot") + """The capacity information relating to snapshot or backup data.""" + + is_thin_provisioned = base.Field("IsThinProvisioned", adapter=bool) + """Marks that the capacity is not necessarily fully allocated.""" + + +class CapacitySource(rsd_lib_base.ResourceBase): + """CapacitySource resource class + + A description of the type and source of storage. + """ + + provided_capacity = CapacityField("ProvidedCapacity") + """The amount of space that has been provided from the ProvidingDrives, + ProvidingVolumes, ProvidingMemory or ProvidingPools. + """ + + # TODO(lin.yang): Add property for references in CapacitySource resource + + @property + @utils.cache_it + def providing_volumes(self): + """Property to provide reference to `VolumeCollection` instance + + It is calculated once when it is queried for the first time. On + refresh, this property is reset. + """ + from rsd_lib.resources.v2_4.storage_service import volume + return volume.VolumeCollection( + self._conn, + utils.get_sub_resource_path_by(self, "ProvidingVolumes"), + redfish_version=self.redfish_version, + ) + + @property + @utils.cache_it + def providing_pools(self): + """Property to provide reference to `StoragePoolCollection` instance + + It is calculated once when it is queried for the first time. On + refresh, this property is reset. + """ + return storage_pool.StoragePoolCollection( + self._conn, + utils.get_sub_resource_path_by(self, "ProvidingPools"), + redfish_version=self.redfish_version, + ) + + @property + @utils.cache_it + def providing_drives(self): + """Property to provide reference to `DriveCollection` instance + + It is calculated once when it is queried for the first time. On + refresh, this property is reset. + """ + return drive.DriveCollection( + self._conn, + utils.get_sub_resource_path_by(self, "ProvidingDrives"), + redfish_version=self.redfish_version, + ) diff --git a/rsd_lib/resources/v2_4/storage_service/volume.py b/rsd_lib/resources/v2_4/storage_service/volume.py index 0494da2..bbb7736 100644 --- a/rsd_lib/resources/v2_4/storage_service/volume.py +++ b/rsd_lib/resources/v2_4/storage_service/volume.py @@ -14,11 +14,29 @@ # under the License. from sushy import exceptions +from sushy import utils from rsd_lib.resources.v2_3.storage_service import volume +from rsd_lib.resources.v2_4.storage_service import capacity class Volume(volume.Volume): + @property + @utils.cache_it + def capacity_sources(self): + """Property to provide a list of `CapacitySource` instance + + It is calculated once when it is queried for the first time. On + refresh, this property is reset. + """ + return [ + capacity.CapacitySource( + self._conn, path, redfish_version=self.redfish_version + ) + for path in utils.get_sub_resource_path_by( + self, "CapacitySources", is_collection=True + ) + ] def resize(self, num_bytes): """Update volume properties @@ -27,20 +45,21 @@ class Volume(volume.Volume): """ if not isinstance(num_bytes, int): raise exceptions.InvalidParameterValueError( - parameter='num_bytes', value=num_bytes, - valid_values='integer') + parameter="num_bytes", value=num_bytes, valid_values="integer" + ) if self.capacity_bytes and num_bytes <= self.capacity_bytes: raise exceptions.InvalidParameterValueError( - parameter='num_bytes', value=num_bytes, - valid_values='> {0}'.format(self.capacity_bytes)) + parameter="num_bytes", + value=num_bytes, + valid_values="> {0}".format(self.capacity_bytes), + ) - data = {"Capacity": {"Data": {'AllocatedBytes': num_bytes}}} + data = {"Capacity": {"Data": {"AllocatedBytes": num_bytes}}} self._conn.patch(self.path, data=data) class VolumeCollection(volume.VolumeCollection): - @property def _resource_type(self): return Volume diff --git a/rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json b/rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json new file mode 100644 index 0000000..6acc7bf --- /dev/null +++ b/rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json @@ -0,0 +1,28 @@ +{ + "@odata.context": "/redfish/v1/$metadata#Capacity.CapacitySource", + "@odata.id": "/redfish/v1/StorageServices/1/Volumes/1/CapacitySources/1", + "@odata.type": "#Capacity.v1_1_0.CapacitySource", + "Description": "Volume capacity source", + "Id": "1", + "Name": "CapacitySource", + "ProvidingPools": { + "@odata.id": "/redfish/v1/StorageServices/1/Volumes/1/CapacitySources/1/ProvidingPools" + }, + "ProvidingVolumes": { + "@odata.id": "/redfish/v1/StorageServices/1/Volumes/1/CapacitySources/1/ProvidingVolumes" + }, + "ProvidingDrives": { + "@odata.id": "/redfish/v1/StorageServices/1/Volumes/1/CapacitySources/1/ProvidingDrives" + }, + "ProvidedCapacity": { + "Data": { + "AllocatedBytes": 3071983104 + } + }, + "Oem": {}, + "Status": { + "Health": "OK", + "HealthRollup": "OK", + "State": "Enabled" + } +} \ No newline at end of file diff --git a/rsd_lib/tests/unit/json_samples/v2_4/volume.json b/rsd_lib/tests/unit/json_samples/v2_4/volume.json index 7d580ac..f0e2ee1 100644 --- a/rsd_lib/tests/unit/json_samples/v2_4/volume.json +++ b/rsd_lib/tests/unit/json_samples/v2_4/volume.json @@ -26,19 +26,10 @@ }, "CapacitySources": [ { - "ProvidingPools": [ - { - "@odata.id": "/redfish/v1/StorageServices/1/StoragePools/2" - } - ], - "ProvidedCapacity": { - "Data": { - "AllocatedBytes": 3071983104 - } - } + "@odata.id": "/redfish/v1/StorageServices/NVMeoE1/Volumes/1/CapacitySources/1" } ], - "Identifiers": [ + "Identifiers": [ { "DurableName": "/dev/nvme1n1p1", "DurableNameFormat": "SystemPath" diff --git a/rsd_lib/tests/unit/resources/v2_4/storage_service/test_capacity.py b/rsd_lib/tests/unit/resources/v2_4/storage_service/test_capacity.py new file mode 100644 index 0000000..0d419d9 --- /dev/null +++ b/rsd_lib/tests/unit/resources/v2_4/storage_service/test_capacity.py @@ -0,0 +1,224 @@ +# Copyright 2018 Intel, Inc. +# 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 rsd_lib.resources.v2_3.storage_service import drive +from rsd_lib.resources.v2_3.storage_service import storage_pool +from rsd_lib.resources.v2_4.storage_service import capacity +from rsd_lib.resources.v2_4.storage_service import volume + + +class CapacitySourceTestCase(testtools.TestCase): + def setUp(self): + super(CapacitySourceTestCase, self).setUp() + self.conn = mock.Mock() + with open( + "rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.capacity_sources_inst = capacity.CapacitySource( + self.conn, + "/redfish/v1/StorageServices/1/Volumes/1/CapacitySources/1", + redfish_version="1.0.2", + ) + + def test__parse_attributes(self): + self.capacity_sources_inst._parse_attributes() + self.assertEqual("1.0.2", self.capacity_sources_inst.redfish_version) + self.assertEqual( + "Volume capacity source", self.capacity_sources_inst.description + ) + self.assertEqual("1", self.capacity_sources_inst.identity) + self.assertEqual("CapacitySource", self.capacity_sources_inst.name) + self.assertEqual( + 3071983104, + self.capacity_sources_inst.provided_capacity.data.allocated_bytes, + ) + + def test_providing_volumes(self): + # | GIVEN | + self.conn.get.return_value.json.reset_mock() + with open( + "rsd_lib/tests/unit/json_samples/v2_4/volume_collection.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN | + actual_providing_volumes = self.capacity_sources_inst.providing_volumes + # | THEN | + self.assertIsInstance( + actual_providing_volumes, volume.VolumeCollection + ) + self.conn.get.return_value.json.assert_called_once_with() + + # reset mock + self.conn.get.return_value.json.reset_mock() + # | WHEN & THEN | + # tests for same object on invoking subsequently + self.assertIs( + actual_providing_volumes, + self.capacity_sources_inst.providing_volumes, + ) + self.conn.get.return_value.json.assert_not_called() + + def test_providing_volumes_on_refresh(self): + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_4/volume_collection.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance( + self.capacity_sources_inst.providing_volumes, + volume.VolumeCollection, + ) + + # On refreshing the chassis instance... + with open( + "rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.capacity_sources_inst.invalidate() + self.capacity_sources_inst.refresh(force=False) + + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_4/volume_collection.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance( + self.capacity_sources_inst.providing_volumes, + volume.VolumeCollection, + ) + + def test_providing_pools(self): + # | GIVEN | + self.conn.get.return_value.json.reset_mock() + with open( + "rsd_lib/tests/unit/json_samples/v2_3/" + "storage_pool_collection.json", + "r", + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN | + actual_providing_pools = self.capacity_sources_inst.providing_pools + # | THEN | + self.assertIsInstance( + actual_providing_pools, storage_pool.StoragePoolCollection + ) + self.conn.get.return_value.json.assert_called_once_with() + + # reset mock + self.conn.get.return_value.json.reset_mock() + # | WHEN & THEN | + # tests for same object on invoking subsequently + self.assertIs( + actual_providing_pools, self.capacity_sources_inst.providing_pools + ) + self.conn.get.return_value.json.assert_not_called() + + def test_providing_pools_on_refresh(self): + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_3/" + "storage_pool_collection.json", + "r", + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance( + self.capacity_sources_inst.providing_pools, + storage_pool.StoragePoolCollection, + ) + + # On refreshing the chassis instance... + with open( + "rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.capacity_sources_inst.invalidate() + self.capacity_sources_inst.refresh(force=False) + + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_3/" + "storage_pool_collection.json", + "r", + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance( + self.capacity_sources_inst.providing_pools, + storage_pool.StoragePoolCollection, + ) + + def test_providing_drives(self): + # | GIVEN | + self.conn.get.return_value.json.reset_mock() + with open( + "rsd_lib/tests/unit/json_samples/v2_3/drive_collection.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN | + actual_providing_drives = self.capacity_sources_inst.providing_drives + # | THEN | + self.assertIsInstance(actual_providing_drives, drive.DriveCollection) + self.conn.get.return_value.json.assert_called_once_with() + + # reset mock + self.conn.get.return_value.json.reset_mock() + # | WHEN & THEN | + # tests for same object on invoking subsequently + self.assertIs( + actual_providing_drives, + self.capacity_sources_inst.providing_drives, + ) + self.conn.get.return_value.json.assert_not_called() + + def test_providing_drives_on_refresh(self): + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_3/drive_collection.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance( + self.capacity_sources_inst.providing_drives, drive.DriveCollection + ) + + # On refreshing the chassis instance... + with open( + "rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.capacity_sources_inst.invalidate() + self.capacity_sources_inst.refresh(force=False) + + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_3/drive_collection.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance( + self.capacity_sources_inst.providing_drives, drive.DriveCollection + ) diff --git a/rsd_lib/tests/unit/resources/v2_4/storage_service/test_volume.py b/rsd_lib/tests/unit/resources/v2_4/storage_service/test_volume.py index 7930452..d380286 100644 --- a/rsd_lib/tests/unit/resources/v2_4/storage_service/test_volume.py +++ b/rsd_lib/tests/unit/resources/v2_4/storage_service/test_volume.py @@ -19,125 +19,200 @@ import testtools from sushy import exceptions +from rsd_lib.resources.v2_4.storage_service import capacity from rsd_lib.resources.v2_4.storage_service import volume class StorageServiceTestCase(testtools.TestCase): - def setUp(self): super(StorageServiceTestCase, self).setUp() self.conn = mock.Mock() - with open('rsd_lib/tests/unit/json_samples/v2_3/volume.json', - 'r') as f: + with open( + "rsd_lib/tests/unit/json_samples/v2_4/volume.json", "r" + ) as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) self.volume_inst = volume.Volume( - self.conn, '/redfish/v1/StorageServices/NVMeoE1/Volumes/1', - redfish_version='1.0.2') + self.conn, + "/redfish/v1/StorageServices/NVMeoE1/Volumes/1", + redfish_version="1.0.2", + ) def test__parse_attributes(self): self.volume_inst._parse_attributes() - self.assertEqual('1.0.2', self.volume_inst.redfish_version) - self.assertEqual('Volume description', self.volume_inst.description) - self.assertEqual('1', self.volume_inst.identity) - self.assertEqual('NVMe remote storage', self.volume_inst.name) - self.assertEqual('Enabled', self.volume_inst.status.state) - self.assertEqual('OK', self.volume_inst.status.health) - self.assertEqual('OK', self.volume_inst.status.health_rollup) + self.assertEqual("1.0.2", self.volume_inst.redfish_version) + self.assertEqual("Volume description", self.volume_inst.description) + self.assertEqual("1", self.volume_inst.identity) + self.assertEqual("NVMe remote storage", self.volume_inst.name) + self.assertEqual("Enabled", self.volume_inst.status.state) + self.assertEqual("OK", self.volume_inst.status.health) + self.assertEqual("OK", self.volume_inst.status.health_rollup) self.assertIsNone(self.volume_inst.model) self.assertIsNone(self.volume_inst.manufacturer) - self.assertEqual(['Read', 'Write'], - self.volume_inst.access_capabilities) + self.assertEqual( + ["Read", "Write"], self.volume_inst.access_capabilities + ) self.assertEqual(3071983104, self.volume_inst.capacity_bytes) self.assertEqual(3071983104, self.volume_inst.allocated_Bytes) - self.assertEqual(('/redfish/v1/StorageServices/1/StoragePools/2',), - self.volume_inst.capacity_sources[0].providing_pools) - self.assertEqual(3071983104, - self.volume_inst.capacity_sources[0].allocated_Bytes) self.assertEqual( - '/dev/nvme1n1p1', - self.volume_inst.identifiers[0].durable_name) + "/dev/nvme1n1p1", self.volume_inst.identifiers[0].durable_name + ) self.assertEqual( - 'SystemPath', - self.volume_inst.identifiers[0].durable_name_format) + "SystemPath", self.volume_inst.identifiers[0].durable_name_format + ) self.assertEqual( - 'iqn.2001-04.com.example:diskarrays-sn-a8675309', - self.volume_inst.identifiers[1].durable_name) + "iqn.2001-04.com.example:diskarrays-sn-a8675309", + self.volume_inst.identifiers[1].durable_name, + ) self.assertEqual( - 'iQN', - self.volume_inst.identifiers[1].durable_name_format) - self.assertEqual(('/redfish/v1/Fabrics/NVMeoE/Endpoints/1',), - self.volume_inst.links.endpoints) + "iQN", self.volume_inst.identifiers[1].durable_name_format + ) self.assertEqual( - '/redfish/v1/StorageServices/NVMeoE1/Volumes/1/Metrics', - self.volume_inst.links.metrics) + ("/redfish/v1/Fabrics/NVMeoE/Endpoints/1",), + self.volume_inst.links.endpoints, + ) self.assertEqual( - 'SourceElement', - self.volume_inst.replica_infos[0].replica_readonly_access) - self.assertEqual('Snapshot', - self.volume_inst.replica_infos[0].replica_type) - self.assertEqual('Target', - self.volume_inst.replica_infos[0].replica_role) - self.assertEqual('/redfish/v1/StorageServices/NVMeoE1/Volumes/2', - self.volume_inst.replica_infos[0].replica) + "/redfish/v1/StorageServices/NVMeoE1/Volumes/1/Metrics", + self.volume_inst.links.metrics, + ) + self.assertEqual( + "SourceElement", + self.volume_inst.replica_infos[0].replica_readonly_access, + ) + self.assertEqual( + "Snapshot", self.volume_inst.replica_infos[0].replica_type + ) + self.assertEqual( + "Target", self.volume_inst.replica_infos[0].replica_role + ) + self.assertEqual( + "/redfish/v1/StorageServices/NVMeoE1/Volumes/2", + self.volume_inst.replica_infos[0].replica, + ) self.assertEqual(False, self.volume_inst.bootable) self.assertIsNone(self.volume_inst.erased) self.assertEqual(True, self.volume_inst.erase_on_detach) + def test_capacity_sources(self): + # | GIVEN | + self.conn.get.return_value.json.reset_mock() + with open( + "rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN | + actual_capacity_sources = self.volume_inst.capacity_sources + # | THEN | + self.assertIsInstance(actual_capacity_sources, list) + self.assertIsInstance( + actual_capacity_sources[0], capacity.CapacitySource + ) + self.conn.get.return_value.json.assert_called_once_with() + + # reset mock + self.conn.get.return_value.json.reset_mock() + # | WHEN & THEN | + # tests for same object on invoking subsequently + self.assertIs( + actual_capacity_sources, self.volume_inst.capacity_sources + ) + self.conn.get.return_value.json.assert_not_called() + + def test_capacity_sources_on_refresh(self): + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance(self.volume_inst.capacity_sources, list) + self.assertIsInstance( + self.volume_inst.capacity_sources[0], capacity.CapacitySource + ) + + # On refreshing the telemetry service instance... + with open( + "rsd_lib/tests/unit/json_samples/v2_4/volume.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + + self.volume_inst.invalidate() + self.volume_inst.refresh(force=False) + + # | GIVEN | + with open( + "rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json", "r" + ) as f: + self.conn.get.return_value.json.return_value = json.loads(f.read()) + # | WHEN & THEN | + self.assertIsInstance(self.volume_inst.capacity_sources, list) + self.assertIsInstance( + self.volume_inst.capacity_sources[0], capacity.CapacitySource + ) + def test_resize_volume(self): self.volume_inst.resize(3071983105) self.volume_inst._conn.patch.assert_called_once_with( - '/redfish/v1/StorageServices/NVMeoE1/Volumes/1', - data={"Capacity": {"Data": {'AllocatedBytes': 3071983105}}}) + "/redfish/v1/StorageServices/NVMeoE1/Volumes/1", + data={"Capacity": {"Data": {"AllocatedBytes": 3071983105}}}, + ) def test_update_volume_with_invalid_parameter(self): with self.assertRaisesRegex( exceptions.InvalidParameterValueError, - 'The parameter "num_bytes" value "fake-value" is invalid'): - self.volume_inst.resize('fake-value') + 'The parameter "num_bytes" value "fake-value" is invalid', + ): + self.volume_inst.resize("fake-value") with self.assertRaisesRegex( exceptions.InvalidParameterValueError, - 'The parameter "num_bytes" value "1024" is invalid'): + 'The parameter "num_bytes" value "1024" is invalid', + ): self.volume_inst.resize(1024) class VolumeCollectionTestCase(testtools.TestCase): - def setUp(self): super(VolumeCollectionTestCase, self).setUp() self.conn = mock.Mock() - with open('rsd_lib/tests/unit/json_samples/v2_4/' - 'volume_collection.json', 'r') as f: + with open( + "rsd_lib/tests/unit/json_samples/v2_4/volume_collection.json", "r" + ) as f: self.conn.get.return_value.json.return_value = json.loads(f.read()) self.volume_col = volume.VolumeCollection( - self.conn, '/redfish/v1/StorageServices/NVMeoE1/Volumes', - redfish_version='1.0.2') + self.conn, + "/redfish/v1/StorageServices/NVMeoE1/Volumes", + redfish_version="1.0.2", + ) def test__parse_attributes(self): self.volume_col._parse_attributes() - self.assertEqual('1.0.2', self.volume_col.redfish_version) - self.assertEqual('Volume Collection', - self.volume_col.name) - self.assertEqual(('/redfish/v1/StorageServices/NVMeoE1/Volumes/1',), - self.volume_col.members_identities) + self.assertEqual("1.0.2", self.volume_col.redfish_version) + self.assertEqual("Volume Collection", self.volume_col.name) + self.assertEqual( + ("/redfish/v1/StorageServices/NVMeoE1/Volumes/1",), + self.volume_col.members_identities, + ) - @mock.patch.object(volume, 'Volume', autospec=True) + @mock.patch.object(volume, "Volume", autospec=True) def test_get_member(self, mock_volume): self.volume_col.get_member( - '/redfish/v1/StorageServices/NVMeoE1/Volumes/1') + "/redfish/v1/StorageServices/NVMeoE1/Volumes/1" + ) mock_volume.assert_called_once_with( self.volume_col._conn, - '/redfish/v1/StorageServices/NVMeoE1/Volumes/1', - redfish_version=self.volume_col.redfish_version) + "/redfish/v1/StorageServices/NVMeoE1/Volumes/1", + redfish_version=self.volume_col.redfish_version, + ) - @mock.patch.object(volume, 'Volume', autospec=True) + @mock.patch.object(volume, "Volume", autospec=True) def test_get_members(self, mock_volume): members = self.volume_col.get_members() mock_volume.assert_called_once_with( self.volume_col._conn, - '/redfish/v1/StorageServices/NVMeoE1/Volumes/1', - redfish_version=self.volume_col.redfish_version) + "/redfish/v1/StorageServices/NVMeoE1/Volumes/1", + redfish_version=self.volume_col.redfish_version, + ) self.assertIsInstance(members, list) self.assertEqual(1, len(members))