From 916f9af658b8c0b4e47d1d6fb77ccb7207069ee7 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 8 May 2024 11:47:57 +0100 Subject: [PATCH] compute, block storage: Minor fixes to limits Add a proper RateLimit class for compute (even though this is no longer a thing starting in Newton) and use consistent naming across services. Change-Id: Ib8a926900dca77cf48492839664bf2c5c13aab70 Signed-off-by: Stephen Finucane --- .../resources/block_storage/v2/limits.rst | 6 ++-- .../resources/block_storage/v3/limits.rst | 8 ++--- openstack/block_storage/v2/_proxy.py | 6 ++-- openstack/block_storage/v2/limits.py | 6 +++- openstack/block_storage/v3/_proxy.py | 8 ++--- openstack/block_storage/v3/limits.py | 14 +++++--- openstack/cloud/_block_storage.py | 2 +- openstack/compute/v2/limits.py | 33 ++++++++++++++++--- .../unit/block_storage/v2/test_limits.py | 4 +-- .../tests/unit/block_storage/v2/test_proxy.py | 2 +- .../unit/block_storage/v3/test_limits.py | 4 +-- .../tests/unit/block_storage/v3/test_proxy.py | 2 +- .../tests/unit/compute/v2/test_limits.py | 18 ++++++---- 13 files changed, 75 insertions(+), 38 deletions(-) diff --git a/doc/source/user/resources/block_storage/v2/limits.rst b/doc/source/user/resources/block_storage/v2/limits.rst index ec6e8fd0a..37a925a72 100644 --- a/doc/source/user/resources/block_storage/v2/limits.rst +++ b/doc/source/user/resources/block_storage/v2/limits.rst @@ -12,12 +12,12 @@ The ``AbsoluteLimit`` class inherits from .. autoclass:: openstack.block_storage.v2.limits.AbsoluteLimit :members: -The Limit Class ---------------- +The Limits Class +---------------- The ``Limit`` class inherits from :class:`~openstack.resource.Resource`. -.. autoclass:: openstack.block_storage.v2.limits.Limit +.. autoclass:: openstack.block_storage.v2.limits.Limits :members: The RateLimit Class diff --git a/doc/source/user/resources/block_storage/v3/limits.rst b/doc/source/user/resources/block_storage/v3/limits.rst index 69a7d7a31..d31337325 100644 --- a/doc/source/user/resources/block_storage/v3/limits.rst +++ b/doc/source/user/resources/block_storage/v3/limits.rst @@ -12,12 +12,12 @@ The ``AbsoluteLimit`` class inherits from .. autoclass:: openstack.block_storage.v3.limits.AbsoluteLimit :members: -The Limit Class ---------------- +The Limits Class +---------------- -The ``Limit`` class inherits from :class:`~openstack.resource.Resource`. +The ``Limits`` class inherits from :class:`~openstack.resource.Resource`. -.. autoclass:: openstack.block_storage.v3.limits.Limit +.. autoclass:: openstack.block_storage.v3.limits.Limits :members: The RateLimit Class diff --git a/openstack/block_storage/v2/_proxy.py b/openstack/block_storage/v2/_proxy.py index 6ac642480..46cb472ab 100644 --- a/openstack/block_storage/v2/_proxy.py +++ b/openstack/block_storage/v2/_proxy.py @@ -651,15 +651,15 @@ class Proxy(_base_proxy.BaseBlockStorageProxy): :param project: A project to get limits for. The value can be either the ID of a project or an :class:`~openstack.identity.v2.project.Project` instance. - :returns: A Limit object, including both + :returns: A Limits object, including both :class:`~openstack.block_storage.v2.limits.AbsoluteLimit` and :class:`~openstack.block_storage.v2.limits.RateLimit` - :rtype: :class:`~openstack.block_storage.v2.limits.Limit` + :rtype: :class:`~openstack.block_storage.v2.limits.Limits` """ params = {} if project: params['project_id'] = resource.Resource._get_id(project) - return self._get(_limits.Limit, requires_id=False, **params) + return self._get(_limits.Limits, requires_id=False, **params) # ====== CAPABILITIES ====== def get_capabilities(self, host): diff --git a/openstack/block_storage/v2/limits.py b/openstack/block_storage/v2/limits.py index 490e4e4b8..486a97d0d 100644 --- a/openstack/block_storage/v2/limits.py +++ b/openstack/block_storage/v2/limits.py @@ -67,7 +67,7 @@ class RateLimits(resource.Resource): uri = resource.Body("uri") -class Limit(resource.Resource): +class Limits(resource.Resource): resource_key = "limits" base_path = "/limits" @@ -80,3 +80,7 @@ class Limit(resource.Resource): #: Rate-limit volume copy bandwidth, used to mitigate #: slow down of data access from the instances. rate = resource.Body("rate", type=list, list_type=RateLimits) + + +# legacy alias +Limit = Limits diff --git a/openstack/block_storage/v3/_proxy.py b/openstack/block_storage/v3/_proxy.py index f3bfafaed..aede10aed 100644 --- a/openstack/block_storage/v3/_proxy.py +++ b/openstack/block_storage/v3/_proxy.py @@ -47,7 +47,7 @@ class Proxy(_base_proxy.BaseBlockStorageProxy): "group": _group.Group, "group_snapshot": _group_snapshot.GroupSnapshot, "group_type": _group_type.GroupType, - "limits": _limits.Limit, + "limits": _limits.Limits, "quota_set": _quota_set.QuotaSet, "resource_filter": _resource_filter.ResourceFilter, "snapshot": _snapshot.Snapshot, @@ -1282,15 +1282,15 @@ class Proxy(_base_proxy.BaseBlockStorageProxy): :param project: A project to get limits for. The value can be either the ID of a project or an :class:`~openstack.identity.v3.project.Project` instance. - :returns: A Limit object, including both + :returns: A Limits object, including both :class:`~openstack.block_storage.v3.limits.AbsoluteLimit` and :class:`~openstack.block_storage.v3.limits.RateLimit` - :rtype: :class:`~openstack.block_storage.v3.limits.Limit` + :rtype: :class:`~openstack.block_storage.v3.limits.Limits` """ params = {} if project: params['project_id'] = resource.Resource._get_id(project) - return self._get(_limits.Limit, requires_id=False, **params) + return self._get(_limits.Limits, requires_id=False, **params) # ====== CAPABILITIES ====== def get_capabilities(self, host): diff --git a/openstack/block_storage/v3/limits.py b/openstack/block_storage/v3/limits.py index 490e4e4b8..fe726a6e6 100644 --- a/openstack/block_storage/v3/limits.py +++ b/openstack/block_storage/v3/limits.py @@ -14,7 +14,7 @@ from openstack import resource class AbsoluteLimit(resource.Resource): - #: Properties + # Properties #: The maximum total amount of backups, in gibibytes (GiB). max_total_backup_gigabytes = resource.Body( "maxTotalBackupGigabytes", type=int @@ -44,7 +44,7 @@ class AbsoluteLimit(resource.Resource): class RateLimit(resource.Resource): - #: Properties + # Properties #: Rate limits next availabe time. next_available = resource.Body("next-available") #: Integer for rate limits remaining. @@ -58,7 +58,7 @@ class RateLimit(resource.Resource): class RateLimits(resource.Resource): - #: Properties + # Properties #: A list of the specific limits that apply to the ``regex`` and ``uri``. limits = resource.Body("limit", type=list, list_type=RateLimit) #: A regex representing which routes this rate limit applies to. @@ -67,16 +67,20 @@ class RateLimits(resource.Resource): uri = resource.Body("uri") -class Limit(resource.Resource): +class Limits(resource.Resource): resource_key = "limits" base_path = "/limits" # capabilities allow_fetch = True - #: Properties + # Properties #: An absolute limits object. absolute = resource.Body("absolute", type=AbsoluteLimit) #: Rate-limit volume copy bandwidth, used to mitigate #: slow down of data access from the instances. rate = resource.Body("rate", type=list, list_type=RateLimits) + + +# Legacy alias +Limit = Limits diff --git a/openstack/cloud/_block_storage.py b/openstack/cloud/_block_storage.py index 23acfcf63..2301ea186 100644 --- a/openstack/cloud/_block_storage.py +++ b/openstack/cloud/_block_storage.py @@ -269,7 +269,7 @@ class BlockStorageCloudMixin: :param name_or_id: (optional) Project name or ID to get limits for if different from the current project - :returns: The volume ``Limit`` object if found, else None. + :returns: The volume ``Limits`` object if found, else None. """ params = {} if name_or_id: diff --git a/openstack/compute/v2/limits.py b/openstack/compute/v2/limits.py index 897e86403..8ff7838a6 100644 --- a/openstack/compute/v2/limits.py +++ b/openstack/compute/v2/limits.py @@ -16,6 +16,7 @@ from openstack import resource class AbsoluteLimits(resource.Resource): _max_microversion = '2.57' + # Properties #: The number of key-value pairs that can be set as image metadata. image_meta = resource.Body("maxImageMeta", aka="max_image_meta") #: The maximum number of personality contents that can be supplied. @@ -73,10 +74,23 @@ class AbsoluteLimits(resource.Resource): class RateLimit(resource.Resource): - # TODO(mordred) Make a resource type for the contents of limit and add - # it to list_type here. + # Properties + #: Rate limits next availabe time. + next_available = resource.Body("next-available") + #: Integer for rate limits remaining. + remaining = resource.Body("remaining", type=int) + #: Unit of measurement for the value parameter. + unit = resource.Body("unit") + #: Integer number of requests which can be made. + value = resource.Body("value", type=int) + #: An HTTP verb (POST, PUT, etc.). + verb = resource.Body("verb") + + +class RateLimits(resource.Resource): + # Properties #: A list of the specific limits that apply to the ``regex`` and ``uri``. - limits = resource.Body("limit", type=list) + limits = resource.Body("limit", type=list, list_type=RateLimit) #: A regex representing which routes this rate limit applies to. regex = resource.Body("regex") #: A URI representing which routes this rate limit applies to. @@ -89,10 +103,19 @@ class Limits(resource.Resource): allow_fetch = True - _query_mapping = resource.QueryParameters('tenant_id') + _query_mapping = resource.QueryParameters( + 'tenant_id', + 'reserved', + project_id='tenant_id', + ) + # Properties + #: An absolute limits object. absolute = resource.Body("absolute", type=AbsoluteLimits) - rate = resource.Body("rate", type=list, list_type=RateLimit) + #: Rate-limit compute resources. This is only populated when using the + #: legacy v2 API which was removed in Nova 14.0.0 (Newton). In v2.1 it will + #: always be an empty list. + rate = resource.Body("rate", type=list, list_type=RateLimits) def fetch( self, diff --git a/openstack/tests/unit/block_storage/v2/test_limits.py b/openstack/tests/unit/block_storage/v2/test_limits.py index ec74c3fc9..bb27c970f 100644 --- a/openstack/tests/unit/block_storage/v2/test_limits.py +++ b/openstack/tests/unit/block_storage/v2/test_limits.py @@ -146,7 +146,7 @@ class TestRateLimits(base.TestCase): class TestLimit(base.TestCase): def test_basic(self): - limit_resource = limits.Limit() + limit_resource = limits.Limits() self.assertEqual('limits', limit_resource.resource_key) self.assertEqual('/limits', limit_resource.base_path) self.assertTrue(limit_resource.allow_fetch) @@ -201,6 +201,6 @@ class TestLimit(base.TestCase): self._test_rate_limit(expected[0]['limit'], actual[0].limits) def test_make_limit(self): - limit_resource = limits.Limit(**LIMIT) + limit_resource = limits.Limits(**LIMIT) self._test_rate_limits(LIMIT['rate'], limit_resource.rate) self._test_absolute_limit(LIMIT['absolute'], limit_resource.absolute) diff --git a/openstack/tests/unit/block_storage/v2/test_proxy.py b/openstack/tests/unit/block_storage/v2/test_proxy.py index 63ac98588..9fa293079 100644 --- a/openstack/tests/unit/block_storage/v2/test_proxy.py +++ b/openstack/tests/unit/block_storage/v2/test_proxy.py @@ -321,7 +321,7 @@ class TestLimit(TestVolumeProxy): def test_limits_get(self): self.verify_get( self.proxy.get_limits, - limits.Limit, + limits.Limits, method_args=[], expected_kwargs={'requires_id': False}, ) diff --git a/openstack/tests/unit/block_storage/v3/test_limits.py b/openstack/tests/unit/block_storage/v3/test_limits.py index 2550092dd..b0638cb62 100644 --- a/openstack/tests/unit/block_storage/v3/test_limits.py +++ b/openstack/tests/unit/block_storage/v3/test_limits.py @@ -146,7 +146,7 @@ class TestRateLimits(base.TestCase): class TestLimit(base.TestCase): def test_basic(self): - limit_resource = limits.Limit() + limit_resource = limits.Limits() self.assertEqual('limits', limit_resource.resource_key) self.assertEqual('/limits', limit_resource.base_path) self.assertTrue(limit_resource.allow_fetch) @@ -201,6 +201,6 @@ class TestLimit(base.TestCase): self._test_rate_limit(expected[0]['limit'], actual[0].limits) def test_make_limit(self): - limit_resource = limits.Limit(**LIMIT) + limit_resource = limits.Limits(**LIMIT) self._test_rate_limits(LIMIT['rate'], limit_resource.rate) self._test_absolute_limit(LIMIT['absolute'], limit_resource.absolute) diff --git a/openstack/tests/unit/block_storage/v3/test_proxy.py b/openstack/tests/unit/block_storage/v3/test_proxy.py index cc581bf9d..6882a75f2 100644 --- a/openstack/tests/unit/block_storage/v3/test_proxy.py +++ b/openstack/tests/unit/block_storage/v3/test_proxy.py @@ -137,7 +137,7 @@ class TestLimit(TestVolumeProxy): def test_limits_get(self): self.verify_get( self.proxy.get_limits, - limits.Limit, + limits.Limits, method_args=[], expected_kwargs={'requires_id': False}, ) diff --git a/openstack/tests/unit/compute/v2/test_limits.py b/openstack/tests/unit/compute/v2/test_limits.py index 4971dad1d..b58af6842 100644 --- a/openstack/tests/unit/compute/v2/test_limits.py +++ b/openstack/tests/unit/compute/v2/test_limits.py @@ -107,9 +107,9 @@ class TestAbsoluteLimits(base.TestCase): ) -class TestRateLimit(base.TestCase): +class TestRateLimits(base.TestCase): def test_basic(self): - sot = limits.RateLimit() + sot = limits.RateLimits() self.assertIsNone(sot.resource_key) self.assertIsNone(sot.resources_key) self.assertEqual("", sot.base_path) @@ -120,10 +120,10 @@ class TestRateLimit(base.TestCase): self.assertFalse(sot.allow_list) def test_make_it(self): - sot = limits.RateLimit(**RATE_LIMIT) + sot = limits.RateLimits(**RATE_LIMIT) self.assertEqual(RATE_LIMIT["regex"], sot.regex) self.assertEqual(RATE_LIMIT["uri"], sot.uri) - self.assertEqual(RATE_LIMIT["limit"], sot.limits) + self.assertIsInstance(sot.limits[0], limits.RateLimit) class TestLimits(base.TestCase): @@ -137,7 +137,13 @@ class TestLimits(base.TestCase): self.assertFalse(sot.allow_delete) self.assertFalse(sot.allow_list) self.assertDictEqual( - {'limit': 'limit', 'marker': 'marker', 'tenant_id': 'tenant_id'}, + { + 'limit': 'limit', + 'marker': 'marker', + 'tenant_id': 'tenant_id', + 'project_id': 'tenant_id', + 'reserved': 'reserved', + }, sot._query_mapping._mapping, ) @@ -211,7 +217,7 @@ class TestLimits(base.TestCase): self.assertEqual(RATE_LIMIT["uri"], sot.rate[0].uri) self.assertEqual(RATE_LIMIT["regex"], sot.rate[0].regex) - self.assertEqual(RATE_LIMIT["limit"], sot.rate[0].limits) + self.assertIsInstance(sot.rate[0].limits[0], limits.RateLimit) dsot = sot.to_dict()