diff --git a/openstack/block_storage/v3/_proxy.py b/openstack/block_storage/v3/_proxy.py index 58d7e6bd7..a62a1a083 100644 --- a/openstack/block_storage/v3/_proxy.py +++ b/openstack/block_storage/v3/_proxy.py @@ -14,6 +14,7 @@ from openstack.block_storage import _base_proxy from openstack.block_storage.v3 import availability_zone from openstack.block_storage.v3 import backup as _backup from openstack.block_storage.v3 import capabilities as _capabilities +from openstack.block_storage.v3 import group_type as _group_type from openstack.block_storage.v3 import limits as _limits from openstack.block_storage.v3 import resource_filter as _resource_filter from openstack.block_storage.v3 import snapshot as _snapshot @@ -549,6 +550,101 @@ class Proxy(_base_proxy.BaseBlockStorageProxy): return self._list(availability_zone.AvailabilityZone) + def get_group_type(self, group_type): + """Get a specific group type + + :param group_type: The value can be the ID of a group type + or a :class:`~openstack.block_storage.v3.group_type.GroupType` + instance. + + :returns: One :class: + `~openstack.block_storage.v3.group_type.GroupType` instance. + :raises: :class:`~openstack.exceptions.ResourceNotFound` when no + resource can be found. + """ + return self._get(_group_type.GroupType, group_type) + + def find_group_type(self, name_or_id, ignore_missing=True): + """Find a single group type + + :param name_or_id: The name or ID of a group type. + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be raised + when the group type does not exist. + + :returns: One :class:`~openstack.block_storage.v3.group_type + .GroupType' + :raises: :class:`~openstack.exceptions.ResourceNotFound` + when no resource can be found. + """ + return self._find( + _group_type.GroupType, name_or_id, ignore_missing=ignore_missing) + + def group_types(self, **query): + """Retrive a generator of group types + + :param dict query: Optional query parameters to be sent to limit the + resources being returned: + + * sort: Comma-separated list of sort keys and optional sort + directions in the form of [:]. A valid + direction is asc (ascending) or desc (descending). + * limit: Requests a page size of items. Returns a number of items + up to a limit value. Use the limit parameter to make an + initial limited request and use the ID of the last-seen item + from the response as the marker parameter value in a + subsequent limited request. + * offset: Used in conjunction with limit to return a slice of + items. Is where to start in the list. + * marker: The ID of the last-seen item. + + :returns: A generator of group type objects. + """ + return self._list(_group_type.GroupType, **query) + + def create_group_type(self, **attrs): + """Create a group type + + :param dict attrs: Keyword arguments which will be used to create + a :class:`~openstack.block_storage.v3.group_type.GroupType' + comprised of the properties on the GroupType class. + + :returns: The results of group type creation. + :rtype: :class:`~openstack.block_storage.v3.group_type.GroupTye'. + """ + return self._create(_group_type.GroupType, **attrs) + + def delete_group_type(self, group_type, ignore_missing=True): + """Delete a group type + + :param group_type: The value can be the ID of a group type + or a :class:`~openstack.block_storage.v3.group_type.GroupType` + instance. + :param bool ignore_missing: When set to ``False`` + :class:`~openstack.exceptions.ResourceNotFound` will be raised when + the zone does not exist. + When set to ``True``, no exception will be set when attempting to + delete a nonexistent zone. + + :returns: ''None'' + """ + self._delete( + _group_type.GroupType, group_type, ignore_missing=ignore_missing) + + def update_group_type(self, group_type, **attrs): + """Update a group_type + + :param group_type: The value can be the ID of a group type or a + :class:`~openstack.block_storage.v3.group_type.GroupType` + instance. + :param dict attrs: The attributes to update on the group type. + + :returns: The updated group type. + :rtype: :class:`~openstack.block_storage.v3.group_type.GroupType` + """ + return self._update( + _group_type.GroupType, group_type, **attrs) + def wait_for_status(self, res, status='ACTIVE', failures=None, interval=2, wait=120): """Wait for a resource to be in a particular status. diff --git a/openstack/block_storage/v3/group_type.py b/openstack/block_storage/v3/group_type.py new file mode 100644 index 000000000..89f18e4f9 --- /dev/null +++ b/openstack/block_storage/v3/group_type.py @@ -0,0 +1,36 @@ +# 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 GroupType(resource.Resource): + resource_key = "group_type" + resources_key = "group_types" + base_path = "/group_types" + + # capabilities + allow_fetch = True + allow_create = True + allow_delete = True + allow_commit = True + allow_list = True + + _max_microversion = "3.11" + + #: Properties + #: The group type description. + description = resource.Body("description") + #: Contains the specifications for a group type. + group_specs = resource.Body("group_specs", type=dict) + #: Whether the group type is publicly visible. + is_public = resource.Body("is_public", type=bool) diff --git a/openstack/tests/functional/block_storage/v3/test_group_type.py b/openstack/tests/functional/block_storage/v3/test_group_type.py new file mode 100644 index 000000000..0ca5252a8 --- /dev/null +++ b/openstack/tests/functional/block_storage/v3/test_group_type.py @@ -0,0 +1,39 @@ +# 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 group_type as _group_type +from openstack.tests.functional.block_storage.v3 import base + + +class TestGroupType(base.BaseBlockStorageTest): + + def setUp(self): + super(TestGroupType, self).setUp() + + self.GROUP_TYPE_NAME = self.getUniqueString() + self.GROUP_TYPE_ID = None + + group_type = self.conn.block_storage.create_group_type( + name=self.GROUP_TYPE_NAME) + self.assertIsInstance(group_type, _group_type.GroupType) + self.assertEqual(self.GROUP_TYPE_NAME, group_type.name) + self.GROUP_TYPE_ID = group_type.id + + def tearDown(self): + group_type = self.conn.block_storage.delete_group_type( + self.GROUP_TYPE_ID, ignore_missing=False) + self.assertIsNone(group_type) + super(TestGroupType, self).tearDown() + + def test_get(self): + group_type = self.conn.block_storage.get_group_type(self.GROUP_TYPE_ID) + self.assertEqual(self.GROUP_TYPE_NAME, group_type.name) diff --git a/openstack/tests/unit/block_storage/v3/test_group_type.py b/openstack/tests/unit/block_storage/v3/test_group_type.py new file mode 100644 index 000000000..541339dcb --- /dev/null +++ b/openstack/tests/unit/block_storage/v3/test_group_type.py @@ -0,0 +1,46 @@ +# 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 group_type +from openstack.tests.unit import base + +GROUP_TYPE = { + "id": "6685584b-1eac-4da6-b5c3-555430cf68ff", + "name": "grp-type-001", + "description": "group type 001", + "is_public": True, + "group_specs": { + "consistent_group_snapshot_enabled": " False" + } +} + + +class TestGroupType(base.TestCase): + + def test_basic(self): + resource = group_type.GroupType() + self.assertEqual("group_type", resource.resource_key) + self.assertEqual("group_types", resource.resources_key) + self.assertEqual("/group_types", resource.base_path) + self.assertTrue(resource.allow_create) + self.assertTrue(resource.allow_fetch) + self.assertTrue(resource.allow_delete) + self.assertTrue(resource.allow_commit) + self.assertTrue(resource.allow_list) + + def test_make_resource(self): + resource = group_type.GroupType(**GROUP_TYPE) + self.assertEqual(GROUP_TYPE["id"], resource.id) + self.assertEqual(GROUP_TYPE["name"], resource.name) + self.assertEqual(GROUP_TYPE["description"], resource.description) + self.assertEqual(GROUP_TYPE["is_public"], resource.is_public) + self.assertEqual(GROUP_TYPE["group_specs"], resource.group_specs) diff --git a/openstack/tests/unit/block_storage/v3/test_proxy.py b/openstack/tests/unit/block_storage/v3/test_proxy.py index b117e3f1a..a83e5db4e 100644 --- a/openstack/tests/unit/block_storage/v3/test_proxy.py +++ b/openstack/tests/unit/block_storage/v3/test_proxy.py @@ -14,6 +14,7 @@ from unittest import mock from openstack.block_storage.v3 import _proxy from openstack.block_storage.v3 import backup from openstack.block_storage.v3 import capabilities +from openstack.block_storage.v3 import group_type from openstack.block_storage.v3 import limits from openstack.block_storage.v3 import resource_filter from openstack.block_storage.v3 import snapshot @@ -245,3 +246,26 @@ class TestVolumeProxy(test_proxy_base.TestProxyBase): def test_resource_filters(self): self.verify_list(self.proxy.resource_filters, resource_filter.ResourceFilter) + + def test_group_type_get(self): + self.verify_get(self.proxy.get_group_type, group_type.GroupType) + + def test_group_type_find(self): + self.verify_find(self.proxy.find_group_type, group_type.GroupType) + + def test_group_types(self): + self.verify_list(self.proxy.group_types, group_type.GroupType) + + def test_group_type_create(self): + self.verify_create(self.proxy.create_group_type, group_type.GroupType) + + def test_group_type_delete(self): + self.verify_delete( + self.proxy.delete_group_type, group_type.GroupType, False) + + def test_group_type_delete_ignore(self): + self.verify_delete( + self.proxy.delete_group_type, group_type.GroupType, True) + + def test_group_type_update(self): + self.verify_update(self.proxy.update_group_type, group_type.GroupType)