Add CapacitySources class in RSD 2.4
Change-Id: I049ce331a5a2f430dca4a5e9f56e11dcbfc4fa45
This commit is contained in:
parent
171b075a92
commit
aeacfae878
132
rsd_lib/resources/v2_4/storage_service/capacity.py
Normal file
132
rsd_lib/resources/v2_4/storage_service/capacity.py
Normal file
@ -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,
|
||||
)
|
@ -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
|
||||
|
28
rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json
Normal file
28
rsd_lib/tests/unit/json_samples/v2_4/capacity_sources.json
Normal file
@ -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"
|
||||
}
|
||||
}
|
@ -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"
|
||||
|
@ -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
|
||||
)
|
@ -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))
|
||||
|
Loading…
x
Reference in New Issue
Block a user