Add Generic Volume Group Into Quota Management
Generic Volume Group currently has it own quota mechanism. But we can't get or set any information about the Generic Volume Group quota at API layer. This patch add Generic Volume Group into quota management. DocImpact APIImpact Change-Id: I9ff0357984a1e95c1ea8c85f8c508402ef7135ac Implements: blueprint add-volumegroup-into-quota-management
This commit is contained in:
parent
ac989f682b
commit
608de666fa
@ -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):
|
||||
|
@ -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)
|
||||
|
@ -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]}
|
||||
|
@ -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())
|
||||
|
||||
|
@ -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'])
|
||||
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- Generic group is added into quota management.
|
Loading…
x
Reference in New Issue
Block a user