Merge "Add support for default volume types"
This commit is contained in:
commit
64138b59c9
@ -173,3 +173,11 @@ Helpers
|
||||
.. autoclass:: openstack.block_storage.v3._proxy.Proxy
|
||||
:noindex:
|
||||
:members: wait_for_status, wait_for_delete
|
||||
|
||||
Default Volume Types
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. autoclass:: openstack.block_storage.v3._proxy.Proxy
|
||||
:noindex:
|
||||
:members: default_types, show_default_type, set_default_type,
|
||||
unset_default_type
|
||||
|
@ -19,6 +19,7 @@ from openstack.block_storage.v3 import availability_zone
|
||||
from openstack.block_storage.v3 import backup as _backup
|
||||
from openstack.block_storage.v3 import block_storage_summary as _summary
|
||||
from openstack.block_storage.v3 import capabilities as _capabilities
|
||||
from openstack.block_storage.v3 import default_type as _default_type
|
||||
from openstack.block_storage.v3 import extension as _extension
|
||||
from openstack.block_storage.v3 import group as _group
|
||||
from openstack.block_storage.v3 import group_snapshot as _group_snapshot
|
||||
@ -535,6 +536,83 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
|
||||
|
||||
return self._update(_type.TypeEncryption, encryption, **attrs)
|
||||
|
||||
# ====== DEFAULT TYPES ======
|
||||
|
||||
def default_types(self):
|
||||
"""Lists default types.
|
||||
|
||||
:returns: List of default types associated to projects.
|
||||
"""
|
||||
# This is required since previously default types did not accept
|
||||
# URL with project ID
|
||||
if not utils.supports_microversion(self, '3.67'):
|
||||
raise exceptions.SDKException(
|
||||
'List default types require at least microversion 3.67'
|
||||
)
|
||||
|
||||
return self._list(_default_type.DefaultType)
|
||||
|
||||
def show_default_type(self, project):
|
||||
"""Show default type for a project.
|
||||
|
||||
:param project: The value can be either the ID of a project or a
|
||||
:class:`~openstack.identity.v3.project.Project` instance.
|
||||
|
||||
:returns: Default type associated to the project.
|
||||
"""
|
||||
# This is required since previously default types did not accept
|
||||
# URL with project ID
|
||||
if not utils.supports_microversion(self, '3.67'):
|
||||
raise exceptions.SDKException(
|
||||
'Show default type require at least microversion 3.67'
|
||||
)
|
||||
|
||||
project_id = resource.Resource._get_id(project)
|
||||
return self._get(_default_type.DefaultType, project_id)
|
||||
|
||||
def set_default_type(self, project, type):
|
||||
"""Set default type for a project.
|
||||
|
||||
:param project: The value can be either the ID of a project or a
|
||||
:class:`~openstack.identity.v3.project.Project` instance.
|
||||
:param type: The value can be either the ID of a type or a
|
||||
:class:`~openstack.block_storage.v3.type.Type` instance.
|
||||
|
||||
:returns: Dictionary of project ID and it's associated default type.
|
||||
"""
|
||||
# This is required since previously default types did not accept
|
||||
# URL with project ID
|
||||
if not utils.supports_microversion(self, '3.67'):
|
||||
raise exceptions.SDKException(
|
||||
'Set default type require at least microversion 3.67'
|
||||
)
|
||||
|
||||
type_id = resource.Resource._get_id(type)
|
||||
project_id = resource.Resource._get_id(project)
|
||||
return self._create(
|
||||
_default_type.DefaultType,
|
||||
id=project_id,
|
||||
volume_type_id=type_id,
|
||||
)
|
||||
|
||||
def unset_default_type(self, project):
|
||||
"""Unset default type for a project.
|
||||
|
||||
:param project: The value can be either the ID of a project or a
|
||||
:class:`~openstack.identity.v3.project.Project` instance.
|
||||
|
||||
:returns: ``None``
|
||||
"""
|
||||
# This is required since previously default types did not accept
|
||||
# URL with project ID
|
||||
if not utils.supports_microversion(self, '3.67'):
|
||||
raise exceptions.SDKException(
|
||||
'Unset default type require at least microversion 3.67'
|
||||
)
|
||||
|
||||
project_id = resource.Resource._get_id(project)
|
||||
self._delete(_default_type.DefaultType, project_id)
|
||||
|
||||
# ====== VOLUMES ======
|
||||
def get_volume(self, volume):
|
||||
"""Get a single volume
|
||||
|
56
openstack/block_storage/v3/default_type.py
Normal file
56
openstack/block_storage/v3/default_type.py
Normal file
@ -0,0 +1,56 @@
|
||||
# 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 import resource
|
||||
|
||||
|
||||
class DefaultType(resource.Resource):
|
||||
resource_key = "default_type"
|
||||
resources_key = "default_types"
|
||||
base_path = "/default-types"
|
||||
|
||||
# capabilities
|
||||
allow_fetch = True
|
||||
allow_create = True
|
||||
allow_delete = True
|
||||
allow_list = True
|
||||
|
||||
# Create and update use the same PUT API
|
||||
create_requires_id = True
|
||||
create_method = 'PUT'
|
||||
|
||||
_max_microversion = "3.67"
|
||||
|
||||
# Properties
|
||||
#: The UUID of the project.
|
||||
project_id = resource.Body("project_id")
|
||||
#: The UUID for an existing volume type.
|
||||
volume_type_id = resource.Body("volume_type_id")
|
||||
|
||||
def _prepare_request_body(
|
||||
self,
|
||||
patch,
|
||||
prepend_key,
|
||||
*,
|
||||
resource_request_key=None,
|
||||
):
|
||||
body = self._body.dirty
|
||||
# Set operation expects volume_type instead of
|
||||
# volume_type_id
|
||||
if body.get('volume_type_id'):
|
||||
body['volume_type'] = body.pop('volume_type_id')
|
||||
# When setting a default type, we want the ID to be
|
||||
# appended in URL but not in the request body
|
||||
if body.get('id'):
|
||||
body.pop('id')
|
||||
body = {self.resource_key: body}
|
||||
return body
|
@ -0,0 +1,66 @@
|
||||
# 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.block_storage.v3 import default_type as _default_type
|
||||
from openstack.tests.functional.block_storage.v3 import base
|
||||
|
||||
|
||||
class TestDefaultType(base.BaseBlockStorageTest):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
if not self._op_name:
|
||||
self.skip("Operator cloud must be set for this test")
|
||||
self._set_operator_cloud(block_storage_api_version='3.67')
|
||||
self.PROJECT_ID = self.create_temporary_project().id
|
||||
|
||||
def test_default_type(self):
|
||||
# Create a volume type
|
||||
type_name = self.getUniqueString()
|
||||
volume_type_id = self.operator_cloud.block_storage.create_type(
|
||||
name=type_name,
|
||||
).id
|
||||
|
||||
# Set default type for a project
|
||||
default_type = self.conn.block_storage.set_default_type(
|
||||
self.PROJECT_ID,
|
||||
volume_type_id,
|
||||
)
|
||||
self.assertIsInstance(default_type, _default_type.DefaultType)
|
||||
|
||||
# Show default type for a project
|
||||
default_type = self.conn.block_storage.show_default_type(
|
||||
self.PROJECT_ID
|
||||
)
|
||||
self.assertIsInstance(default_type, _default_type.DefaultType)
|
||||
self.assertEqual(volume_type_id, default_type.volume_type_id)
|
||||
|
||||
# List all default types
|
||||
default_types = self.conn.block_storage.default_types()
|
||||
for default_type in default_types:
|
||||
self.assertIsInstance(default_type, _default_type.DefaultType)
|
||||
# There could be existing default types set in the environment
|
||||
# Just verify that the default type we have set is correct
|
||||
if self.PROJECT_ID == default_type.project_id:
|
||||
self.assertEqual(volume_type_id, default_type.volume_type_id)
|
||||
|
||||
# Unset default type for a project
|
||||
default_type = self.conn.block_storage.unset_default_type(
|
||||
self.PROJECT_ID
|
||||
)
|
||||
self.assertIsNone(default_type)
|
||||
|
||||
# Delete the volume type
|
||||
vol_type = self.operator_cloud.block_storage.delete_type(
|
||||
volume_type_id,
|
||||
ignore_missing=False,
|
||||
)
|
||||
self.assertIsNone(vol_type)
|
55
openstack/tests/unit/block_storage/v3/test_default_type.py
Normal file
55
openstack/tests/unit/block_storage/v3/test_default_type.py
Normal file
@ -0,0 +1,55 @@
|
||||
# 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 unittest import mock
|
||||
|
||||
from keystoneauth1 import adapter
|
||||
|
||||
from openstack.block_storage.v3 import default_type
|
||||
from openstack.tests.unit import base
|
||||
|
||||
|
||||
PROJECT_ID = 'd5e678b5-f88b-411c-876b-f6ec2ba999bf'
|
||||
VOLUME_TYPE_ID = 'adef1cf8-736e-4b62-a2db-f8b6b6c1d953'
|
||||
|
||||
DEFAULT_TYPE = {
|
||||
'project_id': PROJECT_ID,
|
||||
'volume_type_id': VOLUME_TYPE_ID,
|
||||
}
|
||||
|
||||
|
||||
class TestDefaultType(base.TestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.resp = mock.Mock()
|
||||
self.resp.body = None
|
||||
self.resp.status_code = 200
|
||||
self.resp.json = mock.Mock(return_value=self.resp.body)
|
||||
self.sess = mock.Mock(spec=adapter.Adapter)
|
||||
self.sess.default_microversion = '3.67'
|
||||
self.sess.post = mock.Mock(return_value=self.resp)
|
||||
self.sess._get_connection = mock.Mock(return_value=self.cloud)
|
||||
|
||||
def test_basic(self):
|
||||
sot = default_type.DefaultType(**DEFAULT_TYPE)
|
||||
self.assertEqual("default_type", sot.resource_key)
|
||||
self.assertEqual("default_types", sot.resources_key)
|
||||
self.assertEqual("/default-types", sot.base_path)
|
||||
self.assertTrue(sot.allow_create)
|
||||
self.assertTrue(sot.allow_fetch)
|
||||
self.assertTrue(sot.allow_delete)
|
||||
self.assertTrue(sot.allow_list)
|
||||
|
||||
def test_create(self):
|
||||
sot = default_type.DefaultType(**DEFAULT_TYPE)
|
||||
self.assertEqual(DEFAULT_TYPE["project_id"], sot.project_id)
|
||||
self.assertEqual(DEFAULT_TYPE["volume_type_id"], sot.volume_type_id)
|
@ -0,0 +1,9 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added support for the following operations:
|
||||
|
||||
* Set default volume type
|
||||
* Get default volume type
|
||||
* List default volume type
|
||||
* Unset default volume type
|
Loading…
x
Reference in New Issue
Block a user