Add support for Block Storage (v3) VolumeType Encyption resources

Change-Id: I146bdf8e80d4383f61de4b4305bdaaa2e8c80a23
This commit is contained in:
Mark Chappell 2020-10-08 10:22:10 +02:00
parent 4913b61713
commit cc7369c743
5 changed files with 220 additions and 0 deletions

View File

@ -175,6 +175,99 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
"""
return self._update(_type.Type, type, **attrs)
def get_type_encryption(self, volume_type_id):
"""Get the encryption details of a volume type
:param volume_type_id: The value can be the ID of a type or a
:class:`~openstack.volume.v3.type.Type`
instance.
:returns: One :class:`~openstack.volume.v3.type.TypeEncryption`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
when no resource can be found.
"""
volume_type = self._get_resource(_type.Type, volume_type_id)
return self._get(_type.TypeEncryption,
volume_type_id=volume_type.id,
requires_id=False)
def create_type_encryption(self, volume_type, **attrs):
"""Create new type encryption from attributes
:param volume_type: The value can be the ID of a type or a
:class:`~openstack.volume.v3.type.Type`
instance.
:param dict attrs: Keyword arguments which will be used to create
a :class:`~openstack.volume.v3.type.TypeEncryption`,
comprised of the properties on the TypeEncryption
class.
:returns: The results of type encryption creation
:rtype: :class:`~openstack.volume.v3.type.TypeEncryption`
"""
volume_type = self._get_resource(_type.Type, volume_type)
return self._create(_type.TypeEncryption,
volume_type_id=volume_type.id, **attrs)
def delete_type_encryption(self, encryption=None,
volume_type=None, ignore_missing=True):
"""Delete type encryption attributes
:param encryption: The value can be None or a
:class:`~openstack.volume.v3.type.TypeEncryption`
instance. If encryption_id is None then
volume_type_id must be specified.
:param volume_type: The value can be the ID of a type or a
:class:`~openstack.volume.v3.type.Type`
instance. Required if encryption_id is None.
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be
raised when the type does not exist.
When set to ``True``, no exception will be set when
attempting to delete a nonexistent type.
:returns: ``None``
"""
if volume_type:
volume_type = self._get_resource(_type.Type, volume_type)
encryption = self._get(_type.TypeEncryption,
volume_type=volume_type.id,
requires_id=False)
self._delete(_type.TypeEncryption, encryption,
ignore_missing=ignore_missing)
def update_type_encryption(self, encryption=None,
volume_type=None, **attrs):
"""Update a type
:param encryption: The value can be None or a
:class:`~openstack.volume.v3.type.TypeEncryption`
instance. If encryption_id is None then
volume_type_id must be specified.
:param volume_type: The value can be the ID of a type or a
:class:`~openstack.volume.v3.type.Type`
instance. Required if encryption_id is None.
:param dict attrs: The attributes to update on the type encryption.
:returns: The updated type encryption
:rtype: :class:`~openstack.volume.v3.type.TypeEncryption`
"""
if volume_type:
volume_type = self._get_resource(_type.Type, volume_type)
encryption = self._get(_type.TypeEncryption,
volume_type=volume_type.id,
requires_id=False)
return self._update(_type.TypeEncryption, encryption, **attrs)
def get_volume(self, volume):
"""Get a single volume

View File

@ -38,3 +38,38 @@ class Type(resource.Resource):
extra_specs = resource.Body("extra_specs", type=dict)
#: a private volume-type. *Type: bool*
is_public = resource.Body('os-volume-type-access:is_public', type=bool)
class TypeEncryption(resource.Resource):
resource_key = "encryption"
resources_key = "encryption"
base_path = "/types/%(volume_type_id)s/encryption"
# capabilities
allow_fetch = True
allow_create = True
allow_delete = True
allow_list = False
allow_commit = True
# Properties
#: A ID representing this type.
encryption_id = resource.Body("encryption_id", alternate_id=True)
#: The ID of the Volume Type.
volume_type_id = resource.URI("volume_type_id")
#: The Size of encryption key.
key_size = resource.Body("key_size")
#: The class that provides encryption support.
provider = resource.Body("provider")
#: Notional service where encryption is performed.
control_location = resource.Body("control_location")
#: The encryption algorithm or mode.
cipher = resource.Body("cipher")
#: The resource is deleted or not.
deleted = resource.Body("deleted")
#: The date and time when the resource was created.
created_at = resource.Body("created_at")
#: The date and time when the resource was updated.
updated_at = resource.Body("updated_at")
#: The date and time when the resource was deleted.
deleted_at = resource.Body("deleted_at")

View File

@ -75,6 +75,34 @@ class TestVolumeProxy(test_proxy_base.TestProxyBase):
def test_type_update(self):
self.verify_update(self.proxy.update_type, type.Type)
def test_type_encryption_get(self):
self.verify_get(self.proxy.get_type_encryption,
type.TypeEncryption,
expected_args=[type.TypeEncryption],
expected_kwargs={
'volume_type_id': 'value',
'requires_id': False
})
def test_type_encryption_create(self):
self.verify_create(self.proxy.create_type_encryption,
type.TypeEncryption,
method_kwargs={'volume_type': 'id'},
expected_kwargs={'volume_type_id': 'id'}
)
def test_type_encryption_update(self):
self.verify_update(self.proxy.update_type_encryption,
type.TypeEncryption)
def test_type_encryption_delete(self):
self.verify_delete(self.proxy.delete_type_encryption,
type.TypeEncryption, False)
def test_type_encryption_delete_ignore(self):
self.verify_delete(self.proxy.delete_type_encryption,
type.TypeEncryption, True)
def test_volume_get(self):
self.verify_get(self.proxy.get_volume, volume.Volume)

View File

@ -0,0 +1,61 @@
# 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 openstack.tests.unit import base
from openstack.block_storage.v3 import type
FAKE_ID = "479394ab-2f25-416e-8f58-721d8e5e29de"
TYPE_ID = "22373aed-c4a8-4072-b66c-bf0a90dc9a12"
TYPE_ENC = {
"key_size": 256,
"volume_type_id": TYPE_ID,
"encryption_id": FAKE_ID,
"provider": "nova.volume.encryptors.luks.LuksEncryptor",
"control_location": "front-end",
"cipher": "aes-xts-plain64",
"deleted": False,
"created_at": "2020-10-07T07:52:30.000000",
"updated_at": "2020-10-08T07:42:45.000000",
"deleted_at": None,
}
class TestTypeEncryption(base.TestCase):
def test_basic(self):
sot = type.TypeEncryption(**TYPE_ENC)
self.assertEqual("encryption", sot.resource_key)
self.assertEqual("encryption", sot.resources_key)
self.assertEqual("/types/%(volume_type_id)s/encryption", sot.base_path)
self.assertTrue(sot.allow_create)
self.assertTrue(sot.allow_fetch)
self.assertTrue(sot.allow_delete)
self.assertFalse(sot.allow_list)
self.assertTrue(sot.allow_commit)
def test_new(self):
sot = type.TypeEncryption.new(encryption_id=FAKE_ID)
self.assertEqual(FAKE_ID, sot.encryption_id)
def test_create(self):
sot = type.TypeEncryption(**TYPE_ENC)
self.assertEqual(TYPE_ENC["volume_type_id"], sot.volume_type_id)
self.assertEqual(TYPE_ENC["encryption_id"], sot.encryption_id)
self.assertEqual(TYPE_ENC["key_size"], sot.key_size)
self.assertEqual(TYPE_ENC["provider"], sot.provider)
self.assertEqual(TYPE_ENC["control_location"], sot.control_location)
self.assertEqual(TYPE_ENC["cipher"], sot.cipher)
self.assertEqual(TYPE_ENC["deleted"], sot.deleted)
self.assertEqual(TYPE_ENC["created_at"], sot.created_at)
self.assertEqual(TYPE_ENC["updated_at"], sot.updated_at)
self.assertEqual(TYPE_ENC["deleted_at"], sot.deleted_at)

View File

@ -0,0 +1,3 @@
---
features:
- Add support for block storage type encryption parameters.