compute, volume: Improve 'update_quota_set'

The implementations of these were rather confusing and required two
separate sets of arguments. Simplify them based on the
'delete_quota_set' methods.

Change-Id: I8bb0bfb039593c5b59f1f9c16523a090d899f099
Signed-off-by: Stephen Finucane <stephenfin@redhat.com>
This commit is contained in:
Stephen Finucane 2024-07-10 14:52:30 +01:00
parent d40d6a2e82
commit 9145dcec64
9 changed files with 157 additions and 80 deletions

View File

@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import warnings
from openstack.block_storage import _base_proxy from openstack.block_storage import _base_proxy
from openstack.block_storage.v2 import backup as _backup from openstack.block_storage.v2 import backup as _backup
from openstack.block_storage.v2 import capabilities as _capabilities from openstack.block_storage.v2 import capabilities as _capabilities
@ -23,6 +25,7 @@ from openstack.block_storage.v2 import type as _type
from openstack.block_storage.v2 import volume as _volume from openstack.block_storage.v2 import volume as _volume
from openstack.identity.v3 import project as _project from openstack.identity.v3 import project as _project
from openstack import resource from openstack import resource
from openstack import warnings as os_warnings
class Proxy(_base_proxy.BaseBlockStorageProxy): class Proxy(_base_proxy.BaseBlockStorageProxy):
@ -769,22 +772,37 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
query = {} query = {}
return res.delete(self, **query) return res.delete(self, **query)
def update_quota_set(self, quota_set, query=None, **attrs): def update_quota_set(self, project, **attrs):
"""Update a QuotaSet. """Update a QuotaSet.
:param quota_set: Either the ID of a quota_set or a :param project: ID or instance of
:class:`~openstack.block_storage.v2.quota_set.QuotaSet` instance. :class:`~openstack.identity.project.Project` of the project for
:param dict query: Optional parameters to be used with update call. which the quota should be reset.
:param attrs: The attributes to update on the QuotaSet represented :param attrs: The attributes to update on the QuotaSet represented
by ``quota_set``. by ``quota_set``.
:returns: The updated QuotaSet :returns: The updated QuotaSet
:rtype: :class:`~openstack.block_storage.v2.quota_set.QuotaSet` :rtype: :class:`~openstack.block_storage.v3.quota_set.QuotaSet`
""" """
res = self._get_resource(_quota_set.QuotaSet, quota_set, **attrs) if 'project_id' in attrs or isinstance(project, _quota_set.QuotaSet):
if not query: warnings.warn(
query = {} "The signature of 'update_quota_set' has changed and it "
return res.commit(self, **query) "now expects a Project as the first argument, in line "
"with the other quota set methods.",
os_warnings.RemovedInSDK50Warning,
)
if isinstance(project, _quota_set.QuotaSet):
attrs['project_id'] = project.project_id
# cinder doesn't support any query parameters so we simply pop
# these
if 'query' in attrs:
attrs.pop('params')
else:
project = self._get_resource(_project.Project, project)
attrs['project_id'] = project.id
return self._update(_quota_set.QuotaSet, None, **attrs)
# ====== VOLUME METADATA ====== # ====== VOLUME METADATA ======
def get_volume_metadata(self, volume): def get_volume_metadata(self, volume):

View File

@ -11,6 +11,7 @@
# under the License. # under the License.
import typing as ty import typing as ty
import warnings
from openstack.block_storage import _base_proxy from openstack.block_storage import _base_proxy
from openstack.block_storage.v3 import attachment as _attachment from openstack.block_storage.v3 import attachment as _attachment
@ -36,6 +37,7 @@ from openstack import exceptions
from openstack.identity.v3 import project as _project from openstack.identity.v3 import project as _project
from openstack import resource from openstack import resource
from openstack import utils from openstack import utils
from openstack import warnings as os_warnings
class Proxy(_base_proxy.BaseBlockStorageProxy): class Proxy(_base_proxy.BaseBlockStorageProxy):
@ -1794,22 +1796,37 @@ class Proxy(_base_proxy.BaseBlockStorageProxy):
return res.delete(self, **query) return res.delete(self, **query)
def update_quota_set(self, quota_set, query=None, **attrs): def update_quota_set(self, project, **attrs):
"""Update a QuotaSet. """Update a QuotaSet.
:param quota_set: Either the ID of a quota_set or a :param project: ID or instance of
:class:`~openstack.block_storage.v3.quota_set.QuotaSet` instance. :class:`~openstack.identity.project.Project` of the project for
:param dict query: Optional parameters to be used with update call. which the quota should be reset.
:param attrs: The attributes to update on the QuotaSet represented :param attrs: The attributes to update on the QuotaSet represented
by ``quota_set``. by ``quota_set``.
:returns: The updated QuotaSet :returns: The updated QuotaSet
:rtype: :class:`~openstack.block_storage.v3.quota_set.QuotaSet` :rtype: :class:`~openstack.block_storage.v3.quota_set.QuotaSet`
""" """
res = self._get_resource(_quota_set.QuotaSet, quota_set, **attrs) if 'project_id' in attrs or isinstance(project, _quota_set.QuotaSet):
if not query: warnings.warn(
query = {} "The signature of 'update_quota_set' has changed and it "
return res.commit(self, **query) "now expects a Project as the first argument, in line "
"with the other quota set methods.",
os_warnings.RemovedInSDK50Warning,
)
if isinstance(project, _quota_set.QuotaSet):
attrs['project_id'] = project.project_id
# cinder doesn't support any query parameters so we simply pop
# these
if 'query' in attrs:
attrs.pop('params')
else:
project = self._get_resource(_project.Project, project)
attrs['project_id'] = project.id
return self._update(_quota_set.QuotaSet, None, **attrs)
# ====== SERVICES ====== # ====== SERVICES ======
@ty.overload @ty.overload

View File

@ -13,7 +13,6 @@
import warnings import warnings
from openstack.block_storage.v3._proxy import Proxy from openstack.block_storage.v3._proxy import Proxy
from openstack.block_storage.v3 import quota_set as _qs
from openstack.cloud import _utils from openstack.cloud import _utils
from openstack import exceptions from openstack import exceptions
from openstack import warnings as os_warnings from openstack import warnings as os_warnings
@ -842,12 +841,9 @@ class BlockStorageCloudMixin:
:raises: :class:`~openstack.exceptions.SDKException` if the resource to :raises: :class:`~openstack.exceptions.SDKException` if the resource to
set the quota does not exist. set the quota does not exist.
""" """
project = self.identity.find_project(name_or_id, ignore_missing=False)
proj = self.identity.find_project(name_or_id, ignore_missing=False) self.block_storage.update_quota_set(project=project, **kwargs)
self.block_storage.update_quota_set(
_qs.QuotaSet(project_id=proj.id), **kwargs
)
def get_volume_quotas(self, name_or_id): def get_volume_quotas(self, name_or_id):
"""Get volume quotas for a project """Get volume quotas for a project

View File

@ -21,7 +21,6 @@ from openstack.cloud import _utils
from openstack.cloud import exc from openstack.cloud import exc
from openstack.cloud import meta from openstack.cloud import meta
from openstack.compute.v2._proxy import Proxy from openstack.compute.v2._proxy import Proxy
from openstack.compute.v2 import quota_set as _qs
from openstack.compute.v2 import server as _server from openstack.compute.v2 import server as _server
from openstack import exceptions from openstack import exceptions
from openstack import utils from openstack import utils
@ -1774,11 +1773,9 @@ class ComputeCloudMixin:
:raises: :class:`~openstack.exceptions.SDKException` if the resource to :raises: :class:`~openstack.exceptions.SDKException` if the resource to
set the quota does not exist. set the quota does not exist.
""" """
proj = self.identity.find_project(name_or_id, ignore_missing=False) project = self.identity.find_project(name_or_id, ignore_missing=False)
kwargs['force'] = True kwargs['force'] = True
self.compute.update_quota_set( self.compute.update_quota_set(project=project, **kwargs)
_qs.QuotaSet(project_id=proj.id), **kwargs
)
def get_compute_quotas(self, name_or_id): def get_compute_quotas(self, name_or_id):
"""Get quota for a project """Get quota for a project

View File

@ -37,6 +37,7 @@ from openstack.compute.v2 import usage as _usage
from openstack.compute.v2 import volume_attachment as _volume_attachment from openstack.compute.v2 import volume_attachment as _volume_attachment
from openstack import exceptions from openstack import exceptions
from openstack.identity.v3 import project as _project from openstack.identity.v3 import project as _project
from openstack.identity.v3 import user as _user
from openstack.network.v2 import security_group as _sg from openstack.network.v2 import security_group as _sg
from openstack import proxy from openstack import proxy
from openstack import resource from openstack import resource
@ -2494,38 +2495,59 @@ class Proxy(proxy.Proxy):
:param project: ID or instance of :param project: ID or instance of
:class:`~openstack.identity.project.Project` of the project for :class:`~openstack.identity.project.Project` of the project for
which the quota should be resetted. which the quota should be reset.
:param dict query: Additional parameters to be used. :param dict query: Additional parameters to be used.
:returns: ``None`` :returns: ``None``
""" """
project = self._get_resource(_project.Project, project) project = self._get_resource(_project.Project, project)
res = self._get_resource( res = self._get_resource(
_quota_set.QuotaSet, _quota_set.QuotaSet, None, project_id=project.id
None,
project_id=project.id,
) )
if not query: if not query:
query = {} query = {}
return res.delete(self, **query) return res.delete(self, **query)
def update_quota_set(self, quota_set, query=None, **attrs): def update_quota_set(self, project, *, user=None, **attrs):
"""Update a QuotaSet. """Update a QuotaSet.
:param quota_set: Either the ID of a quota_set or a :param project: ID or instance of
:class:`~openstack.compute.v2.quota_set.QuotaSet` instance. :class:`~openstack.identity.project.Project` of the project for
:param dict query: Optional parameters to be used with update call. which the quota should be reset.
:param user_id: Optional ID of the user to set quotas as.
:param attrs: The attributes to update on the QuotaSet represented :param attrs: The attributes to update on the QuotaSet represented
by ``quota_set``. by ``quota_set``.
:returns: The updated QuotaSet :returns: The updated QuotaSet
:rtype: :class:`~openstack.compute.v2.quota_set.QuotaSet` :rtype: :class:`~openstack.compute.v2.quota_set.QuotaSet`
""" """
res = self._get_resource(_quota_set.QuotaSet, quota_set, **attrs)
if not query:
query = {} query = {}
return res.commit(self, **query)
if 'project_id' in attrs or isinstance(project, _quota_set.QuotaSet):
warnings.warn(
"The signature of 'update_quota_set' has changed and it "
"now expects a Project as the first argument, in line "
"with the other quota set methods.",
os_warnings.RemovedInSDK50Warning,
)
if isinstance(project, _quota_set.QuotaSet):
attrs['project_id'] = project.project_id
if 'query' in attrs:
query = attrs.pop('query')
else:
project = self._get_resource(_project.Project, project)
attrs['project_id'] = project.id
if user:
user = self._get_resource(_user.User, user)
query['user_id'] = user.id
# we don't use Proxy._update since that doesn't allow passing arbitrary
# query string parameters
quota_set = self._get_resource(_quota_set.QuotaSet, None, **attrs)
return quota_set.commit(self, **query)
# ========== Server actions ========== # ========== Server actions ==========

View File

@ -21,7 +21,8 @@ from openstack.block_storage.v2 import snapshot
from openstack.block_storage.v2 import stats from openstack.block_storage.v2 import stats
from openstack.block_storage.v2 import type from openstack.block_storage.v2 import type
from openstack.block_storage.v2 import volume from openstack.block_storage.v2 import volume
from openstack import resource from openstack.identity.v3 import project
from openstack import proxy as proxy_base
from openstack.tests.unit import test_proxy_base from openstack.tests.unit import test_proxy_base
@ -526,19 +527,17 @@ class TestQuotaSet(TestVolumeProxy):
expected_kwargs={'user_id': 'uid'}, expected_kwargs={'user_id': 'uid'},
) )
@mock.patch('openstack.proxy.Proxy._get_resource', autospec=True) @mock.patch.object(proxy_base.Proxy, '_get_resource')
def test_quota_set_update(self, gr_mock): def test_quota_set_update(self, mock_get):
gr_mock.return_value = resource.Resource() fake_project = project.Project(id='prj')
gr_mock.commit = mock.Mock() mock_get.side_effect = [fake_project]
self._verify( self._verify(
'openstack.resource.Resource.commit', 'openstack.proxy.Proxy._update',
self.proxy.update_quota_set, self.proxy.update_quota_set,
method_args=['qs'], method_args=['prj'],
method_kwargs={ method_kwargs={'volumes': 123},
'query': {'user_id': 'uid'}, expected_args=[quota_set.QuotaSet, None],
'a': 'b', expected_kwargs={'project_id': 'prj', 'volumes': 123},
},
expected_args=[self.proxy],
expected_kwargs={'user_id': 'uid'},
) )
gr_mock.assert_called_with(self.proxy, quota_set.QuotaSet, 'qs', a='b') mock_get.assert_called_once_with(project.Project, 'prj')

View File

@ -28,7 +28,8 @@ from openstack.block_storage.v3 import snapshot
from openstack.block_storage.v3 import stats from openstack.block_storage.v3 import stats
from openstack.block_storage.v3 import type from openstack.block_storage.v3 import type
from openstack.block_storage.v3 import volume from openstack.block_storage.v3 import volume
from openstack import resource from openstack.identity.v3 import project
from openstack import proxy as proxy_base
from openstack.tests.unit import test_proxy_base from openstack.tests.unit import test_proxy_base
@ -1017,19 +1018,17 @@ class TestQuotaSet(TestVolumeProxy):
expected_kwargs={'user_id': 'uid'}, expected_kwargs={'user_id': 'uid'},
) )
@mock.patch('openstack.proxy.Proxy._get_resource', autospec=True) @mock.patch.object(proxy_base.Proxy, '_get_resource')
def test_quota_set_update(self, gr_mock): def test_quota_set_update(self, mock_get):
gr_mock.return_value = resource.Resource() fake_project = project.Project(id='prj')
gr_mock.commit = mock.Mock() mock_get.side_effect = [fake_project]
self._verify( self._verify(
'openstack.resource.Resource.commit', 'openstack.proxy.Proxy._update',
self.proxy.update_quota_set, self.proxy.update_quota_set,
method_args=['qs'], method_args=['prj'],
method_kwargs={ method_kwargs={'volumes': 123},
'query': {'user_id': 'uid'}, expected_args=[quota_set.QuotaSet, None],
'a': 'b', expected_kwargs={'project_id': 'prj', 'volumes': 123},
},
expected_args=[self.proxy],
expected_kwargs={'user_id': 'uid'},
) )
gr_mock.assert_called_with(self.proxy, quota_set.QuotaSet, 'qs', a='b') mock_get.assert_called_once_with(project.Project, 'prj')

View File

@ -38,7 +38,8 @@ from openstack.compute.v2 import server_remote_console
from openstack.compute.v2 import service from openstack.compute.v2 import service
from openstack.compute.v2 import usage from openstack.compute.v2 import usage
from openstack.compute.v2 import volume_attachment from openstack.compute.v2 import volume_attachment
from openstack import resource from openstack.identity.v3 import project
from openstack import proxy as proxy_base
from openstack.tests.unit import test_proxy_base from openstack.tests.unit import test_proxy_base
from openstack import warnings as os_warnings from openstack import warnings as os_warnings
@ -1685,22 +1686,26 @@ class TestQuotaSet(TestComputeProxy):
expected_kwargs={'user_id': 'uid'}, expected_kwargs={'user_id': 'uid'},
) )
@mock.patch('openstack.proxy.Proxy._get_resource', autospec=True) @mock.patch.object(proxy_base.Proxy, "_get_resource")
def test_quota_set_update(self, gr_mock): def test_quota_set_update(self, mock_get):
gr_mock.return_value = resource.Resource() fake_project = project.Project(id='prj')
gr_mock.commit = mock.Mock() fake_quota_set = quota_set.QuotaSet(project_id='prj')
mock_get.side_effect = [fake_project, fake_quota_set]
self._verify( self._verify(
'openstack.resource.Resource.commit', 'openstack.resource.Resource.commit',
self.proxy.update_quota_set, self.proxy.update_quota_set,
method_args=['qs'], method_args=['prj'],
method_kwargs={ method_kwargs={'ram': 123},
'query': {'user_id': 'uid'},
'a': 'b',
},
expected_args=[self.proxy], expected_args=[self.proxy],
expected_kwargs={'user_id': 'uid'}, expected_kwargs={},
)
mock_get.assert_has_calls(
[
mock.call(project.Project, 'prj'),
mock.call(quota_set.QuotaSet, None, project_id='prj', ram=123),
]
) )
gr_mock.assert_called_with(self.proxy, quota_set.QuotaSet, 'qs', a='b')
class TestServerAction(TestComputeProxy): class TestServerAction(TestComputeProxy):

View File

@ -10,6 +10,11 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
# API deprecation warnings
#
# These are for service-related deprecations, such as the removal of an API or
# API field due to a microversion.
class OpenStackDeprecationWarning(DeprecationWarning): class OpenStackDeprecationWarning(DeprecationWarning):
"""Base class for warnings about deprecated features in openstacksdk.""" """Base class for warnings about deprecated features in openstacksdk."""
@ -31,6 +36,25 @@ class LegacyAPIWarning(OpenStackDeprecationWarning):
"""Indicates an API that is in 'legacy' status, a long term deprecation.""" """Indicates an API that is in 'legacy' status, a long term deprecation."""
# Package deprecation warnings
#
# These are for SDK-specific deprecations, such as removed functions or
# function parameters.
class RemovedInSDK40Warning(DeprecationWarning):
"""Indicates an argument that is deprecated for removal in SDK 4.0."""
class RemovedInSDK50Warning(PendingDeprecationWarning):
"""Indicates an argument that is deprecated for removal in SDK 5.0."""
# General warnings
#
# These are usually related to misconfigurations.
class OpenStackWarning(Warning): class OpenStackWarning(Warning):
"""Base class for general warnings in openstacksdk.""" """Base class for general warnings in openstacksdk."""