compute, block storage: Add support for quota class sets

Change-Id: I2d0b9a900d60d666ba07b759eccdb9a8e1c164bb
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane
2024-05-16 17:13:00 +01:00
parent 0f311ff3e2
commit 4275dfc53c
13 changed files with 348 additions and 25 deletions

View File

@@ -67,8 +67,16 @@ Stats Operations
:noindex:
:members: backend_pools
QuotaClassSet Operations
^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: openstack.block_storage.v2._proxy.Proxy
:noindex:
:members: get_quota_class_set, update_quota_class_set
QuotaSet Operations
^^^^^^^^^^^^^^^^^^^
.. autoclass:: openstack.block_storage.v2._proxy.Proxy
:noindex:
:members: get_quota_set, get_quota_set_defaults,

View File

@@ -129,6 +129,13 @@ Stats Operations
:noindex:
:members: backend_pools
QuotaClassSet Operations
^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: openstack.block_storage.v3._proxy.Proxy
:noindex:
:members: get_quota_class_set, update_quota_class_set
QuotaSet Operations
^^^^^^^^^^^^^^^^^^^
@@ -137,13 +144,6 @@ QuotaSet Operations
:members: get_quota_set, get_quota_set_defaults,
revert_quota_set, update_quota_set
Helpers
^^^^^^^
.. autoclass:: openstack.block_storage.v3._proxy.Proxy
:noindex:
:members: wait_for_status, wait_for_delete
BlockStorageSummary Operations
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -166,3 +166,10 @@ Transfer Operations
:noindex:
:members: create_transfer, delete_transfer, find_transfer,
get_transfer, transfers, accept_transfer
Helpers
^^^^^^^
.. autoclass:: openstack.block_storage.v3._proxy.Proxy
:noindex:
:members: wait_for_status, wait_for_delete

View File

@@ -157,6 +157,13 @@ Extension Operations
:noindex:
:members: find_extension, extensions
QuotaClassSet Operations
^^^^^^^^^^^^^^^^^^^^^^^^
.. autoclass:: openstack.compute.v2._proxy.Proxy
:noindex:
:members: get_quota_class_set, update_quota_class_set
QuotaSet Operations
^^^^^^^^^^^^^^^^^^^

View File

@@ -15,6 +15,7 @@ from openstack.block_storage.v2 import backup as _backup
from openstack.block_storage.v2 import capabilities as _capabilities
from openstack.block_storage.v2 import extension as _extension
from openstack.block_storage.v2 import limits as _limits
from openstack.block_storage.v2 import quota_class_set as _quota_class_set
from openstack.block_storage.v2 import quota_set as _quota_set
from openstack.block_storage.v2 import snapshot as _snapshot
from openstack.block_storage.v2 import stats as _stats
@@ -674,6 +675,43 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
"""
return self._get(_capabilities.Capabilities, host)
# ====== QUOTA CLASS SETS ======
def get_quota_class_set(self, quota_class_set='default'):
"""Get a single quota class set
Only one quota class is permitted, ``default``.
:param quota_class_set: The value can be the ID of a quota class set
(only ``default`` is supported) or a
:class:`~openstack.block_storage.v2.quota_class_set.QuotaClassSet`
instance.
:returns: One
:class:`~openstack.block_storage.v2.quota_class_set.QuotaClassSet`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
when no resource can be found.
"""
return self._get(_quota_class_set.QuotaClassSet, quota_class_set)
def update_quota_class_set(self, quota_class_set, **attrs):
"""Update a QuotaClassSet.
Only one quota class is permitted, ``default``.
:param quota_class_set: Either the ID of a quota class set (only
``default`` is supported) or a
:class:`~openstack.block_storage.v2.quota_class_set.QuotaClassSet`
instance.
:param attrs: The attributes to update on the QuotaClassSet represented
by ``quota_class_set``.
:returns: The updated QuotaSet
:rtype: :class:`~openstack.block_storage.v2.quota_set.QuotaSet`
"""
return self._update(
_quota_class_set.QuotaClassSet, quota_class_set, **attrs
)
# ====== QUOTA SETS ======
def get_quota_set(self, project, usage=False, **query):
"""Show QuotaSet information for the project

View File

@@ -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 import resource
class QuotaClassSet(resource.Resource):
resource_key = 'quota_class_set'
base_path = '/os-quota-class-sets'
# Capabilities
allow_fetch = True
allow_commit = True
# Properties
#: The size (GB) of backups that are allowed for each project.
backup_gigabytes = resource.Body('backup_gigabytes', type=int)
#: The number of backups that are allowed for each project.
backups = resource.Body('backups', type=int)
#: The size (GB) of volumes and snapshots that are allowed for each
#: project.
gigabytes = resource.Body('gigabytes', type=int)
#: The number of groups that are allowed for each project.
groups = resource.Body('groups', type=int)
#: The size (GB) of volumes in request that are allowed for each volume.
per_volume_gigabytes = resource.Body('per_volume_gigabytes', type=int)
#: The number of snapshots that are allowed for each project.
snapshots = resource.Body('snapshots', type=int)
#: The number of volumes that are allowed for each project.
volumes = resource.Body('volumes', type=int)

View File

@@ -23,6 +23,7 @@ from openstack.block_storage.v3 import group as _group
from openstack.block_storage.v3 import group_snapshot as _group_snapshot
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 quota_class_set as _quota_class_set
from openstack.block_storage.v3 import quota_set as _quota_set
from openstack.block_storage.v3 import resource_filter as _resource_filter
from openstack.block_storage.v3 import service as _service
@@ -1701,7 +1702,44 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
group_type = self._get_resource(_group_type.GroupType, group_type)
return group_type.delete_group_specs_property(self, prop)
# ====== QUOTA CLASS SETS ======
def get_quota_class_set(self, quota_class_set='default'):
"""Get a single quota class set
Only one quota class is permitted, ``default``.
:param quota_class_set: The value can be the ID of a quota class set
(only ``default`` is supported) or a
:class:`~openstack.block_storage.v3.quota_class_set.QuotaClassSet`
instance.
:returns: One
:class:`~openstack.block_storage.v3.quota_class_set.QuotaClassSet`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
when no resource can be found.
"""
return self._get(_quota_class_set.QuotaClassSet, quota_class_set)
def update_quota_class_set(self, quota_class_set, **attrs):
"""Update a QuotaClassSet.
Only one quota class is permitted, ``default``.
:param quota_class_set: Either the ID of a quota class set (only
``default`` is supported) or a
:param attrs: The attributes to update on the QuotaClassSet represented
by ``quota_class_set``.
:returns: The updated QuotaSet
:rtype: :class:`~openstack.block_storage.v3.quota_set.QuotaSet`
"""
return self._update(
_quota_class_set.QuotaClassSet, quota_class_set, **attrs
)
# ====== QUOTA SETS ======
def get_quota_set(self, project, usage=False, **query):
"""Show QuotaSet information for the project

View File

@@ -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 import resource
class QuotaClassSet(resource.Resource):
resource_key = 'quota_class_set'
base_path = '/os-quota-class-sets'
# Capabilities
allow_fetch = True
allow_commit = True
# Properties
#: The size (GB) of backups that are allowed for each project.
backup_gigabytes = resource.Body('backup_gigabytes', type=int)
#: The number of backups that are allowed for each project.
backups = resource.Body('backups', type=int)
#: The size (GB) of volumes and snapshots that are allowed for each
#: project.
gigabytes = resource.Body('gigabytes', type=int)
#: The number of groups that are allowed for each project.
groups = resource.Body('groups', type=int)
#: The size (GB) of volumes in request that are allowed for each volume.
per_volume_gigabytes = resource.Body('per_volume_gigabytes', type=int)
#: The number of snapshots that are allowed for each project.
snapshots = resource.Body('snapshots', type=int)
#: The number of volumes that are allowed for each project.
volumes = resource.Body('volumes', type=int)

View File

@@ -22,6 +22,7 @@ from openstack.compute.v2 import image as _image
from openstack.compute.v2 import keypair as _keypair
from openstack.compute.v2 import limits
from openstack.compute.v2 import migration as _migration
from openstack.compute.v2 import quota_class_set as _quota_class_set
from openstack.compute.v2 import quota_set as _quota_set
from openstack.compute.v2 import server as _server
from openstack.compute.v2 import server_action as _server_action
@@ -54,6 +55,7 @@ class Proxy(proxy.Proxy):
"keypair": _keypair.Keypair,
"limits": limits.Limits,
"migration": _migration.Migration,
"quota_class_set": _quota_class_set.QuotaClassSet,
"quota_set": _quota_set.QuotaSet,
"server": _server.Server,
"server_action": _server_action.ServerAction,
@@ -2403,6 +2405,44 @@ class Proxy(proxy.Proxy):
else:
return server.get_console_url(self, console_type)
# ========== Quota class sets ==========
def get_quota_class_set(self, quota_class_set='default'):
"""Get a single quota class set
Only one quota class is permitted, ``default``.
:param quota_class_set: The value can be the ID of a quota class set
(only ``default`` is supported) or a
:class:`~openstack.compute.v2.quota_class_set.QuotaClassSet`
instance.
:returns: One
:class:`~openstack.compute.v2.quota_class_set.QuotaClassSet`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
when no resource can be found.
"""
return self._get(_quota_class_set.QuotaClassSet, quota_class_set)
def update_quota_class_set(self, quota_class_set, **attrs):
"""Update a QuotaClassSet.
Only one quota class is permitted, ``default``.
:param quota_class_set: Either the ID of a quota class set (only
``default`` is supported) or a
:class:`~openstack.compute.v2.quota_class_set.QuotaClassSet`
instance.
:param attrs: The attributes to update on the QuotaClassSet represented
by ``quota_class_set``.
:returns: The updated QuotaSet
:rtype: :class:`~openstack.compute.v2.quota_set.QuotaSet`
"""
return self._update(
_quota_class_set.QuotaClassSet, quota_class_set, **attrs
)
# ========== Quota sets ==========
def get_quota_set(self, project, usage=False, **query):

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 import resource
class QuotaClassSet(resource.Resource):
resource_key = 'quota_class_set'
base_path = '/os-quota-class-sets'
_max_microversion = '2.56'
# capabilities
allow_fetch = True
allow_commit = True
#: Properties
#: The number of allowed server cores for each tenant.
cores = resource.Body('cores', type=int)
#: The number of allowed fixed IP addresses for each tenant. Must be
#: equal to or greater than the number of allowed servers.
fixed_ips = resource.Body('fixed_ips', type=int)
#: The number of allowed floating IP addresses for each tenant.
floating_ips = resource.Body('floating_ips', type=int)
#: The number of allowed bytes of content for each injected file.
injected_file_content_bytes = resource.Body(
'injected_file_content_bytes', type=int
)
#: The number of allowed bytes for each injected file path.
injected_file_path_bytes = resource.Body(
'injected_file_path_bytes', type=int
)
#: The number of allowed injected files for each tenant.
injected_files = resource.Body('injected_files', type=int)
#: The number of allowed servers for each tenant.
instances = resource.Body('instances', type=int)
#: The number of allowed key pairs for each user.
key_pairs = resource.Body('key_pairs', type=int)
#: The number of allowed metadata items for each server.
metadata_items = resource.Body('metadata_items', type=int)
#: The number of private networks that can be created per project.
networks = resource.Body('networks', type=int)
#: The amount of allowed server RAM, in MiB, for each tenant.
ram = resource.Body('ram', type=int)
#: The number of allowed rules for each security group.
security_group_rules = resource.Body('security_group_rules', type=int)
#: The number of allowed security groups for each tenant.
security_groups = resource.Body('security_groups', type=int)
#: The number of allowed server groups for each tenant.
server_groups = resource.Body('server_groups', type=int)
#: The number of allowed members for each server group.
server_group_members = resource.Body('server_group_members', type=int)

View File

@@ -9,6 +9,7 @@
# 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.common import quota_set
from openstack import resource

View File

@@ -15,6 +15,7 @@ from openstack.block_storage.v2 import _proxy
from openstack.block_storage.v2 import backup
from openstack.block_storage.v2 import capabilities
from openstack.block_storage.v2 import limits
from openstack.block_storage.v2 import quota_class_set
from openstack.block_storage.v2 import quota_set
from openstack.block_storage.v2 import snapshot
from openstack.block_storage.v2 import stats
@@ -457,8 +458,22 @@ class TestType(TestVolumeProxy):
)
class TestQuota(TestVolumeProxy):
def test_get(self):
class TestQuotaClassSet(TestVolumeProxy):
def test_quota_class_set_get(self):
self.verify_get(
self.proxy.get_quota_class_set, quota_class_set.QuotaClassSet
)
def test_quota_class_set_update(self):
self.verify_update(
self.proxy.update_quota_class_set,
quota_class_set.QuotaClassSet,
False,
)
class TestQuotaSet(TestVolumeProxy):
def test_quota_set_get(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set,
@@ -473,7 +488,7 @@ class TestQuota(TestVolumeProxy):
expected_result=quota_set.QuotaSet(),
)
def test_get_query(self):
def test_quota_set_get_query(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set,
@@ -488,7 +503,7 @@ class TestQuota(TestVolumeProxy):
},
)
def test_get_defaults(self):
def test_quota_set_get_defaults(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set_defaults,
@@ -501,7 +516,7 @@ class TestQuota(TestVolumeProxy):
},
)
def test_reset(self):
def test_quota_set_reset(self):
self._verify(
'openstack.resource.Resource.delete',
self.proxy.revert_quota_set,
@@ -512,7 +527,7 @@ class TestQuota(TestVolumeProxy):
)
@mock.patch('openstack.proxy.Proxy._get_resource', autospec=True)
def test_update(self, gr_mock):
def test_quota_set_update(self, gr_mock):
gr_mock.return_value = resource.Resource()
gr_mock.commit = mock.Mock()
self._verify(

View File

@@ -20,6 +20,7 @@ from openstack.block_storage.v3 import group
from openstack.block_storage.v3 import group_snapshot
from openstack.block_storage.v3 import group_type
from openstack.block_storage.v3 import limits
from openstack.block_storage.v3 import quota_class_set
from openstack.block_storage.v3 import quota_set
from openstack.block_storage.v3 import resource_filter
from openstack.block_storage.v3 import service
@@ -948,8 +949,22 @@ class TestType(TestVolumeProxy):
)
class TestQuota(TestVolumeProxy):
def test_get(self):
class TestQuotaClassSet(TestVolumeProxy):
def test_quota_class_set_get(self):
self.verify_get(
self.proxy.get_quota_class_set, quota_class_set.QuotaClassSet
)
def test_quota_class_set_update(self):
self.verify_update(
self.proxy.update_quota_class_set,
quota_class_set.QuotaClassSet,
False,
)
class TestQuotaSet(TestVolumeProxy):
def test_quota_set_get(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set,
@@ -964,7 +979,7 @@ class TestQuota(TestVolumeProxy):
expected_result=quota_set.QuotaSet(),
)
def test_get_query(self):
def test_quota_set_get_query(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set,
@@ -979,7 +994,7 @@ class TestQuota(TestVolumeProxy):
},
)
def test_get_defaults(self):
def test_quota_set_get_defaults(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set_defaults,
@@ -992,7 +1007,7 @@ class TestQuota(TestVolumeProxy):
},
)
def test_reset(self):
def test_quota_set_reset(self):
self._verify(
'openstack.resource.Resource.delete',
self.proxy.revert_quota_set,
@@ -1003,7 +1018,7 @@ class TestQuota(TestVolumeProxy):
)
@mock.patch('openstack.proxy.Proxy._get_resource', autospec=True)
def test_update(self, gr_mock):
def test_quota_set_update(self, gr_mock):
gr_mock.return_value = resource.Resource()
gr_mock.commit = mock.Mock()
self._verify(

View File

@@ -26,6 +26,7 @@ from openstack.compute.v2 import hypervisor
from openstack.compute.v2 import image
from openstack.compute.v2 import keypair
from openstack.compute.v2 import migration
from openstack.compute.v2 import quota_class_set
from openstack.compute.v2 import quota_set
from openstack.compute.v2 import server
from openstack.compute.v2 import server_action
@@ -1617,8 +1618,22 @@ class TestCompute(TestComputeProxy):
self.assertEqual(console_fake['url'], ret['url'])
class TestQuota(TestComputeProxy):
def test_get(self):
class TestQuotaClassSet(TestComputeProxy):
def test_quota_class_set_get(self):
self.verify_get(
self.proxy.get_quota_class_set, quota_class_set.QuotaClassSet
)
def test_quota_class_set_update(self):
self.verify_update(
self.proxy.update_quota_class_set,
quota_class_set.QuotaClassSet,
False,
)
class TestQuotaSet(TestComputeProxy):
def test_quota_set_get(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set,
@@ -1633,7 +1648,7 @@ class TestQuota(TestComputeProxy):
expected_result=quota_set.QuotaSet(),
)
def test_get_query(self):
def test_quota_set_get_query(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set,
@@ -1648,7 +1663,7 @@ class TestQuota(TestComputeProxy):
},
)
def test_get_defaults(self):
def test_quota_set_get_defaults(self):
self._verify(
'openstack.resource.Resource.fetch',
self.proxy.get_quota_set_defaults,
@@ -1661,7 +1676,7 @@ class TestQuota(TestComputeProxy):
},
)
def test_reset(self):
def test_quota_set_reset(self):
self._verify(
'openstack.resource.Resource.delete',
self.proxy.revert_quota_set,
@@ -1672,7 +1687,7 @@ class TestQuota(TestComputeProxy):
)
@mock.patch('openstack.proxy.Proxy._get_resource', autospec=True)
def test_update(self, gr_mock):
def test_quota_set_update(self, gr_mock):
gr_mock.return_value = resource.Resource()
gr_mock.commit = mock.Mock()
self._verify(