Support to create new volume
Change-Id: I909820d590a1f95fe4d3cd4a53ac021ac5dbc6d4
This commit is contained in:
parent
3be4548f07
commit
f04f4a743a
@ -13,12 +13,14 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import jsonschema
|
||||
import logging
|
||||
|
||||
from sushy import exceptions
|
||||
from sushy.resources import base
|
||||
from sushy import utils
|
||||
|
||||
from rsd_lib.resources.v2_3.storage_service import volume_schemas
|
||||
from rsd_lib import utils as rsd_lib_utils
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
@ -207,3 +209,57 @@ class VolumeCollection(base.ResourceCollectionBase):
|
||||
"""
|
||||
super(VolumeCollection, self).__init__(connector, path,
|
||||
redfish_version)
|
||||
|
||||
def _create_volume_request(self, capacity, access_capabilities=None,
|
||||
capacity_sources=None, replica_infos=None,
|
||||
bootable=None):
|
||||
|
||||
request = {}
|
||||
|
||||
jsonschema.validate(capacity,
|
||||
volume_schemas.capacity_req_schema)
|
||||
request['CapacityBytes'] = capacity
|
||||
|
||||
if access_capabilities is not None:
|
||||
jsonschema.validate(
|
||||
access_capabilities,
|
||||
volume_schemas.access_capabilities_req_schema)
|
||||
request['AccessCapabilities'] = access_capabilities
|
||||
|
||||
if capacity_sources is not None:
|
||||
jsonschema.validate(capacity_sources,
|
||||
volume_schemas.capacity_sources_req_schema)
|
||||
request['CapacitySources'] = capacity_sources
|
||||
|
||||
if replica_infos is not None:
|
||||
jsonschema.validate(replica_infos,
|
||||
volume_schemas.replica_infos_req_schema)
|
||||
request['ReplicaInfos'] = replica_infos
|
||||
|
||||
if bootable is not None:
|
||||
jsonschema.validate(bootable,
|
||||
volume_schemas.bootable_req_schema)
|
||||
request['Oem'] = {"Intel_RackScale": {"Bootable": bootable}}
|
||||
|
||||
return request
|
||||
|
||||
def create_volume(self, capacity, access_capabilities=None,
|
||||
capacity_sources=None, replica_infos=None,
|
||||
bootable=None):
|
||||
"""Compose a node from RackScale hardware
|
||||
|
||||
:param capacity: Requested volume capacity in bytes
|
||||
:param access_capabilities: List of volume access capabilities
|
||||
:param capacity_sources: JSON for volume providing source
|
||||
:param replica_infos: JSON for volume replica infos
|
||||
:param bootable: Determines if the volume should be bootable
|
||||
:returns: The uri of the new volume
|
||||
"""
|
||||
properties = self._create_volume_request(
|
||||
capacity=capacity, access_capabilities=access_capabilities,
|
||||
capacity_sources=capacity_sources, replica_infos=replica_infos,
|
||||
bootable=bootable)
|
||||
resp = self._conn.post(self._path, data=properties)
|
||||
LOG.info("Volume created at %s", resp.headers['Location'])
|
||||
volume_url = resp.headers['Location']
|
||||
return volume_url[volume_url.find(self._path):]
|
||||
|
66
rsd_lib/resources/v2_3/storage_service/volume_schemas.py
Normal file
66
rsd_lib/resources/v2_3/storage_service/volume_schemas.py
Normal file
@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2018 Intel, Corp.
|
||||
#
|
||||
# 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.
|
||||
|
||||
capacity_req_schema = {
|
||||
'type': 'number'
|
||||
}
|
||||
|
||||
access_capabilities_req_schema = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'string',
|
||||
'enum': ['Read', 'Write', 'WriteOnce', 'Append', 'Streaming']
|
||||
}
|
||||
}
|
||||
|
||||
capacity_sources_req_schema = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'ProvidingPools': {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'@odata.id': {'type': 'string'}
|
||||
},
|
||||
'additionalProperties': False
|
||||
}
|
||||
}
|
||||
},
|
||||
'additionalProperties': False
|
||||
}
|
||||
}
|
||||
|
||||
replica_infos_req_schema = {
|
||||
'type': 'array',
|
||||
'items': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'ReplicaType': {'type': 'string'},
|
||||
'Replica': {
|
||||
'type': 'object',
|
||||
'properties': {
|
||||
'@odata.id': {'type': 'string'}
|
||||
}
|
||||
}
|
||||
},
|
||||
'additionalProperties': False
|
||||
}
|
||||
}
|
||||
|
||||
bootable_req_schema = {
|
||||
'type': 'boolean'
|
||||
}
|
@ -14,12 +14,14 @@
|
||||
# under the License.
|
||||
|
||||
import json
|
||||
import jsonschema
|
||||
import mock
|
||||
import testtools
|
||||
|
||||
from sushy import exceptions
|
||||
|
||||
from rsd_lib.resources.v2_3.storage_service import volume
|
||||
from rsd_lib.tests.unit.fakes import request_fakes
|
||||
|
||||
|
||||
class StorageServiceTestCase(testtools.TestCase):
|
||||
@ -165,6 +167,10 @@ class VolumeCollectionTestCase(testtools.TestCase):
|
||||
with open('rsd_lib/tests/unit/json_samples/v2_3/'
|
||||
'volume_collection.json', 'r') as f:
|
||||
self.conn.get.return_value.json.return_value = json.loads(f.read())
|
||||
self.conn.post.return_value = request_fakes.fake_request_post(
|
||||
None, headers={"Location": "https://localhost:8443/redfish/v1/"
|
||||
"StorageServices/NVMeoE1/Volumes/2"})
|
||||
|
||||
self.volume_col = volume.VolumeCollection(
|
||||
self.conn, '/redfish/v1/StorageServices/NVMeoE1/Volumes',
|
||||
redfish_version='1.0.2')
|
||||
@ -195,3 +201,98 @@ class VolumeCollectionTestCase(testtools.TestCase):
|
||||
redfish_version=self.volume_col.redfish_version)
|
||||
self.assertIsInstance(members, list)
|
||||
self.assertEqual(1, len(members))
|
||||
|
||||
def test_create_volume(self):
|
||||
reqs = {
|
||||
"AccessCapabilities": [
|
||||
"Read",
|
||||
"Write"
|
||||
],
|
||||
"CapacityBytes": 10737418240,
|
||||
"CapacitySources": [
|
||||
{
|
||||
"ProvidingPools": [
|
||||
{
|
||||
"@odata.id": "/redfish/v1/StorageServices/1/"
|
||||
"StoragePools/2"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"ReplicaInfos": [
|
||||
{
|
||||
"ReplicaType": "Clone",
|
||||
"Replica": {
|
||||
"@odata.id": "/redfish/v1/StorageServices/NVMeoE1/"
|
||||
"Volumes/1"
|
||||
}
|
||||
}
|
||||
],
|
||||
"Oem": {
|
||||
"Intel_RackScale": {
|
||||
"Bootable": True
|
||||
}
|
||||
}
|
||||
}
|
||||
result = self.volume_col.create_volume(
|
||||
capacity=10737418240,
|
||||
access_capabilities=["Read", "Write"],
|
||||
capacity_sources=[{
|
||||
"ProvidingPools": [{
|
||||
"@odata.id": "/redfish/v1/StorageServices/1/StoragePools/2"
|
||||
}]
|
||||
}],
|
||||
replica_infos=[{
|
||||
"ReplicaType": "Clone",
|
||||
"Replica": {
|
||||
"@odata.id": "/redfish/v1/StorageServices/NVMeoE1/"
|
||||
"Volumes/1"
|
||||
}
|
||||
}],
|
||||
bootable=True)
|
||||
self.volume_col._conn.post.assert_called_once_with(
|
||||
'/redfish/v1/StorageServices/NVMeoE1/Volumes', data=reqs)
|
||||
self.assertEqual(result,
|
||||
'/redfish/v1/StorageServices/NVMeoE1/Volumes/2')
|
||||
|
||||
def test_create_volume_with_invalid_reqs(self):
|
||||
self.assertRaises(jsonschema.exceptions.ValidationError,
|
||||
self.volume_col.create_volume,
|
||||
capacity='invalid_capacity')
|
||||
|
||||
result = self.volume_col.create_volume(capacity=1024)
|
||||
self.assertEqual(result,
|
||||
'/redfish/v1/StorageServices/NVMeoE1/Volumes/2')
|
||||
|
||||
invalid_access_capabilities = ["Write", "invalid"]
|
||||
self.assertRaises(jsonschema.exceptions.ValidationError,
|
||||
self.volume_col.create_volume,
|
||||
capacity=1024,
|
||||
access_capabilities=invalid_access_capabilities)
|
||||
|
||||
invalid_capacity_sources = [{
|
||||
"ProvidingPools": {
|
||||
"@odata.id": "/redfish/v1/StorageServices/1/StoragePools/2"
|
||||
}
|
||||
}]
|
||||
self.assertRaises(jsonschema.exceptions.ValidationError,
|
||||
self.volume_col.create_volume,
|
||||
capacity=1024,
|
||||
capacity_sources=invalid_capacity_sources)
|
||||
|
||||
invalid_replica_infos = [{
|
||||
"Invalid": "Clone",
|
||||
"Replica": {
|
||||
"@odata.id": "/redfish/v1/StorageServices/NVMeoE1/"
|
||||
"Volumes/1"
|
||||
}
|
||||
}]
|
||||
self.assertRaises(jsonschema.exceptions.ValidationError,
|
||||
self.volume_col.create_volume,
|
||||
capacity=1024,
|
||||
replica_infos=invalid_replica_infos)
|
||||
|
||||
self.assertRaises(jsonschema.exceptions.ValidationError,
|
||||
self.volume_col.create_volume,
|
||||
capacity=1024,
|
||||
bootable="True")
|
||||
|
Loading…
x
Reference in New Issue
Block a user