diff options
author | Zuul <zuul@review.opendev.org> | 2019-11-01 19:16:15 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2019-11-01 19:16:15 +0000 |
commit | be583164cbf97aaf4e7cb9bd496bf740f43aa542 (patch) | |
tree | 1286c1f4d57c57af6460f654c39c263b02bd9b64 | |
parent | b5a8a2ca18a6a3dd3e1bbe9ac2b9b167b99e7b4d (diff) | |
parent | 492cf46f63c829ec722c0b8fb06de678e85afc5e (diff) | |
download | cinder-stable/ocata.tar.gz |
Merge "Add Generic Volume Group Into Quota Management" into stable/ocataocata-eolstable/ocata
-rw-r--r-- | cinder/api/contrib/quota_classes.py | 17 | ||||
-rw-r--r-- | cinder/api/contrib/quotas.py | 31 | ||||
-rw-r--r-- | cinder/quota_utils.py | 9 | ||||
-rw-r--r-- | cinder/tests/unit/api/contrib/test_quotas.py | 5 | ||||
-rw-r--r-- | cinder/tests/unit/api/contrib/test_quotas_classes.py | 7 | ||||
-rw-r--r-- | releasenotes/notes/generic-group-quota-manage-support-559629ad07a406f4.yaml | 3 |
6 files changed, 55 insertions, 17 deletions
diff --git a/cinder/api/contrib/quota_classes.py b/cinder/api/contrib/quota_classes.py index a694d856c..bffd1a56f 100644 --- a/cinder/api/contrib/quota_classes.py +++ b/cinder/api/contrib/quota_classes.py @@ -25,6 +25,7 @@ from cinder import utils QUOTAS = quota.QUOTAS +GROUP_QUOTAS = quota.GROUP_QUOTAS authorize = extensions.extension_authorizer('volume', 'quota_classes') @@ -46,9 +47,11 @@ class QuotaClassSetsController(wsgi.Controller): db.sqlalchemy.api.authorize_quota_class_context(context, id) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() + quota_set = QUOTAS.get_class_quotas(context, id) + group_quota_set = GROUP_QUOTAS.get_class_quotas(context, id) + quota_set.update(group_quota_set) - return self._format_quota_set(id, - QUOTAS.get_class_quotas(context, id)) + return self._format_quota_set(id, quota_set) def update(self, req, id, body): context = req.environ['cinder.context'] @@ -63,7 +66,7 @@ class QuotaClassSetsController(wsgi.Controller): raise webob.exc.HTTPBadRequest(explanation=msg) for key, value in body['quota_class_set'].items(): - if key in QUOTAS: + if key in QUOTAS or key in GROUP_QUOTAS: try: value = utils.validate_integer(value, key, min_value=-1, max_value=db.MAX_INT) @@ -72,8 +75,12 @@ class QuotaClassSetsController(wsgi.Controller): db.quota_class_create(context, quota_class, key, value) except exception.AdminRequired: raise webob.exc.HTTPForbidden() - return {'quota_class_set': QUOTAS.get_class_quotas(context, - quota_class)} + + quota_set = QUOTAS.get_class_quotas(context, quota_class) + group_quota_set = GROUP_QUOTAS.get_class_quotas(context, quota_class) + quota_set.update(group_quota_set) + + return {'quota_class_set': quota_set} class Quota_classes(extensions.ExtensionDescriptor): diff --git a/cinder/api/contrib/quotas.py b/cinder/api/contrib/quotas.py index 1dbe8201f..334426eed 100644 --- a/cinder/api/contrib/quotas.py +++ b/cinder/api/contrib/quotas.py @@ -28,6 +28,7 @@ from cinder import quota_utils from cinder import utils QUOTAS = quota.QUOTAS +GROUP_QUOTAS = quota.GROUP_QUOTAS NON_QUOTA_KEYS = ['tenant_id', 'id'] authorize_update = extensions.extension_authorizer('volume', 'quotas:update') @@ -63,6 +64,9 @@ class QuotaSetsController(wsgi.Controller): def _get_quotas(self, context, id, usages=False): values = QUOTAS.get_project_quotas(context, id, usages=usages) + group_values = GROUP_QUOTAS.get_project_quotas(context, id, + usages=usages) + values.update(group_values) if usages: return values @@ -225,7 +229,8 @@ class QuotaSetsController(wsgi.Controller): # NOTE(ankit): Pass #1 - In this loop for body['quota_set'].items(), # we figure out if we have any bad keys. for key, value in body['quota_set'].items(): - if (key not in QUOTAS and key not in NON_QUOTA_KEYS): + if (key not in QUOTAS and key not in GROUP_QUOTAS and key not in + NON_QUOTA_KEYS): bad_keys.append(key) continue @@ -259,6 +264,10 @@ class QuotaSetsController(wsgi.Controller): # resources. quota_values = QUOTAS.get_project_quotas(context, target_project_id, defaults=False) + group_quota_values = GROUP_QUOTAS.get_project_quotas(context, + target_project_id, + defaults=False) + quota_values.update(group_quota_values) valid_quotas = {} reservations = [] for key in body['quota_set'].keys(): @@ -326,17 +335,20 @@ class QuotaSetsController(wsgi.Controller): res_change = new_quota_from_target_proj - orig_quota_from_target_proj if res_change != 0: deltas = {res: res_change} + resources = QUOTAS.resources + resources.update(GROUP_QUOTAS.resources) reservations += quota_utils.update_alloc_to_next_hard_limit( - ctxt, QUOTAS.resources, deltas, res, None, target_project.id) + ctxt, resources, deltas, res, None, target_project.id) return reservations def defaults(self, req, id): context = req.environ['cinder.context'] authorize_show(context) - - return self._format_quota_set(id, QUOTAS.get_defaults( - context, project_id=id)) + defaults = QUOTAS.get_defaults(context, project_id=id) + group_defaults = GROUP_QUOTAS.get_defaults(context, project_id=id) + defaults.update(group_defaults) + return self._format_quota_set(id, defaults) def delete(self, req, id): """Delete Quota for a particular tenant. @@ -366,6 +378,9 @@ class QuotaSetsController(wsgi.Controller): try: project_quotas = QUOTAS.get_project_quotas( ctxt, proj_id, usages=True, defaults=False) + project_group_quotas = GROUP_QUOTAS.get_project_quotas( + ctxt, proj_id, usages=True, defaults=False) + project_quotas.update(project_group_quotas) except exception.NotAuthorized: raise webob.exc.HTTPForbidden() @@ -382,6 +397,7 @@ class QuotaSetsController(wsgi.Controller): parent_id) defaults = QUOTAS.get_defaults(ctxt, proj_id) + defaults.update(GROUP_QUOTAS.get_defaults(ctxt, proj_id)) # If the project which is being deleted has allocated part of its # quota to its subprojects, then subprojects' quotas should be # deleted first. @@ -416,8 +432,11 @@ class QuotaSetsController(wsgi.Controller): ctxt = req.environ['cinder.context'] params = req.params try: + resources = QUOTAS.resources + resources.update(GROUP_QUOTAS.resources) + quota_utils.validate_setup_for_nested_quota_use( - ctxt, QUOTAS.resources, quota.NestedDbQuotaDriver(), + ctxt, resources, quota.NestedDbQuotaDriver(), fix_allocated_quotas=params.get('fix_allocated_quotas')) except exception.InvalidNestedQuotaSetup as e: raise webob.exc.HTTPBadRequest(explanation=e.msg) diff --git a/cinder/quota_utils.py b/cinder/quota_utils.py index eee4ddf28..0425b6f0c 100644 --- a/cinder/quota_utils.py +++ b/cinder/quota_utils.py @@ -147,6 +147,7 @@ def update_alloc_to_next_hard_limit(context, resources, deltas, res, expire, project_id): from cinder import quota QUOTAS = quota.QUOTAS + GROUP_QUOTAS = quota.GROUP_QUOTAS reservations = [] projects = get_project_hierarchy(context, project_id, parents_as_ids=True).parents @@ -156,8 +157,12 @@ def update_alloc_to_next_hard_limit(context, resources, deltas, res, while projects and not hard_limit_found: cur_proj_id = list(projects)[0] projects = projects[cur_proj_id] - cur_quota_lim = QUOTAS.get_by_project_or_default( - context, cur_proj_id, res) + if res == 'groups': + cur_quota_lim = GROUP_QUOTAS.get_by_project_or_default( + context, cur_proj_id, res) + else: + cur_quota_lim = QUOTAS.get_by_project_or_default( + context, cur_proj_id, res) hard_limit_found = (cur_quota_lim != -1) cur_quota = {res: cur_quota_lim} cur_delta = {res: deltas[res]} diff --git a/cinder/tests/unit/api/contrib/test_quotas.py b/cinder/tests/unit/api/contrib/test_quotas.py index cf499136f..8753fa476 100644 --- a/cinder/tests/unit/api/contrib/test_quotas.py +++ b/cinder/tests/unit/api/contrib/test_quotas.py @@ -43,13 +43,14 @@ CONF = cfg.CONF def make_body(root=True, gigabytes=1000, snapshots=10, volumes=10, backups=10, backup_gigabytes=1000, - tenant_id=fake.PROJECT_ID, per_volume_gigabytes=-1): + tenant_id=fake.PROJECT_ID, per_volume_gigabytes=-1, groups=10): resources = {'gigabytes': gigabytes, 'snapshots': snapshots, 'volumes': volumes, 'backups': backups, 'backup_gigabytes': backup_gigabytes, - 'per_volume_gigabytes': per_volume_gigabytes, } + 'per_volume_gigabytes': per_volume_gigabytes, + 'groups': groups} # need to consider preexisting volume types as well volume_types = db.volume_type_get_all(context.get_admin_context()) diff --git a/cinder/tests/unit/api/contrib/test_quotas_classes.py b/cinder/tests/unit/api/contrib/test_quotas_classes.py index 945f693cb..d0b158702 100644 --- a/cinder/tests/unit/api/contrib/test_quotas_classes.py +++ b/cinder/tests/unit/api/contrib/test_quotas_classes.py @@ -33,19 +33,21 @@ from cinder.volume import volume_types QUOTAS = quota.QUOTAS +GROUP_QUOTAS = quota.GROUP_QUOTAS def make_body(root=True, gigabytes=1000, snapshots=10, volumes=10, backups=10, backup_gigabytes=1000, per_volume_gigabytes=-1, volume_types_faked=None, - tenant_id=fake.PROJECT_ID): + tenant_id=fake.PROJECT_ID, groups=10): resources = {'gigabytes': gigabytes, 'snapshots': snapshots, 'volumes': volumes, 'backups': backups, 'per_volume_gigabytes': per_volume_gigabytes, - 'backup_gigabytes': backup_gigabytes} + 'backup_gigabytes': backup_gigabytes, + 'groups': groups} if not volume_types_faked: volume_types_faked = {'fake_type': None} for volume_type in volume_types_faked: @@ -68,6 +70,7 @@ def make_response_body(root=True, ctxt=None, quota_class='foo', if not ctxt: ctxt = context.get_admin_context() resources.update(QUOTAS.get_class_quotas(ctxt, quota_class)) + resources.update(GROUP_QUOTAS.get_class_quotas(ctxt, quota_class)) if not request_body and not request_body['quota_class_set']: resources.update(request_body['quota_class_set']) diff --git a/releasenotes/notes/generic-group-quota-manage-support-559629ad07a406f4.yaml b/releasenotes/notes/generic-group-quota-manage-support-559629ad07a406f4.yaml new file mode 100644 index 000000000..cc058ac78 --- /dev/null +++ b/releasenotes/notes/generic-group-quota-manage-support-559629ad07a406f4.yaml @@ -0,0 +1,3 @@ +--- +features: + - Generic group is added into quota management. |