Update cinder manage quota commands

This patch updates the cinder manage quota commands to leverage the new
method _get_sync_updates from cinder db, allowing us to simplify our
code.

Change-Id: I099d101a3f2bcfbd2026306081a9858c610ab1ff
This commit is contained in:
Gorka Eguileor 2021-03-15 17:58:56 +01:00
parent 1fb0767d88
commit cdd60605f4
1 changed files with 25 additions and 41 deletions

View File

@ -417,15 +417,10 @@ class QuotaCommands(object):
project_ids = [row.project_id for row in projects] project_ids = [row.project_id for row in projects]
return project_ids return project_ids
def _get_quota_syncs(self, ctxt, session, resources, project_id): def _get_usages(self, ctxt, session, resources, project_id):
"""Get data necessary to check out of sync quota usage. """Get data necessary to check out of sync quota usage.
Returns a list of tuples where each tuple contains a QuotaUsage Returns a list QuotaUsage instances for the specific project
instance, the corresponding resource from quota.QUOTAS.resources, the
volume type id, and the volume type name.
Volume type id and name will be None for non volume type entries, as
expected by the DB sync methods.
""" """
usages = db_api.model_query(ctxt, usages = db_api.model_query(ctxt,
db_api.models.QuotaUsage, db_api.models.QuotaUsage,
@ -434,14 +429,7 @@ class QuotaCommands(object):
filter_by(project_id=project_id).\ filter_by(project_id=project_id).\
with_for_update().\ with_for_update().\
all() all()
return usages
res = []
for usage in usages:
resource = resources[usage.resource]
volume_type_id = getattr(resource, 'volume_type_id', None)
volume_type_name = getattr(resource, 'volume_type_name', None)
res.append((usage, resource, volume_type_id, volume_type_name))
return res
def _get_reservations(self, ctxt, session, project_id, usage_id): def _get_reservations(self, ctxt, session, project_id, usage_id):
"""Get reservations for a given project and usage id.""" """Get reservations for a given project and usage id."""
@ -453,33 +441,30 @@ class QuotaCommands(object):
all() all()
return reservations return reservations
def _check_duplicates(self, ctxt, session, sync_data, do_fix): def _check_duplicates(self, ctxt, session, usages, do_fix):
"""Look for duplicated quota used entries (bug#1484343) """Look for duplicated quota used entries (bug#1484343)
If we have duplicates and we are fixing them, then we reassign the If we have duplicates and we are fixing them, then we reassign the
reservations of the usage we are removing. reservations of the usage we are removing.
""" """
resources = collections.defaultdict(list) resources = collections.defaultdict(list)
for sync in sync_data: for usage in usages:
usage = sync[0] resources[usage.resource].append(usage)
resources[usage.resource].append(sync)
duplicates_found = False duplicates_found = False
result = [] result = []
for syncs in resources.values(): for resource_usages in resources.values():
keep_sync = syncs[0] keep_usage = resource_usages[0]
if len(syncs) > 1: if len(resource_usages) > 1:
duplicates_found = True duplicates_found = True
keep_usage = keep_sync[0]
print('\t%s: %s duplicated usage entries - ' % print('\t%s: %s duplicated usage entries - ' %
(keep_usage.resource, len(syncs) - 1), (keep_usage.resource, len(resource_usages) - 1),
end='') end='')
if do_fix: if do_fix:
# Each of the duplicates can have reservations # Each of the duplicates can have reservations
reassigned = 0 reassigned = 0
for sync in syncs[1:]: for usage in resource_usages[1:]:
usage = sync[0]
reservations = self._get_reservations(ctxt, session, reservations = self._get_reservations(ctxt, session,
usage.project_id, usage.project_id,
usage.id) usage.id)
@ -493,7 +478,7 @@ class QuotaCommands(object):
reassigned) reassigned)
else: else:
print('ignored') print('ignored')
result.append(keep_sync) result.append(keep_usage)
return result, duplicates_found return result, duplicates_found
def _check_sync(self, project_id, do_fix): def _check_sync(self, project_id, do_fix):
@ -521,28 +506,27 @@ class QuotaCommands(object):
with session.begin(): with session.begin():
print('Processing quota usage for project %s' % project) print('Processing quota usage for project %s' % project)
# We only want to sync existing quota usage rows # We only want to sync existing quota usage rows
syncs = self._get_quota_syncs(ctxt, session, resources, usages = self._get_usages(ctxt, session, resources, project)
project)
# Check for duplicated entries (bug#1484343) # Check for duplicated entries (bug#1484343)
syncs, duplicates_found = self._check_duplicates(ctxt, session, usages, duplicates_found = self._check_duplicates(ctxt,
syncs, do_fix) session,
usages,
do_fix)
if duplicates_found: if duplicates_found:
discrepancy = True discrepancy = True
# Check quota and reservations # Check quota and reservations
for usage, resource, vol_type_id, vol_type_name in syncs: for usage in usages:
resource_name = usage.resource
# Get the correct value for this quota usage resource # Get the correct value for this quota usage resource
sync = db_api.QUOTA_SYNC_FUNCTIONS[resource.sync] updates = db_api._get_sync_updates(ctxt, project, session,
updates = sync(ctxt, project, resources,
volume_type_id=vol_type_id, resource_name)
volume_type_name=vol_type_name, in_use = updates[resource_name]
session=session)
in_use = list(updates.values())[0]
if in_use != usage.in_use: if in_use != usage.in_use:
print('\t%s: invalid usage saved=%s actual=%s%s' % print('\t%s: invalid usage saved=%s actual=%s%s' %
(usage.resource, usage.in_use, in_use, (resource_name, usage.in_use, in_use,
action_msg)) action_msg))
discrepancy = True discrepancy = True
if do_fix: if do_fix:
@ -554,7 +538,7 @@ class QuotaCommands(object):
if r.delta > 0) if r.delta > 0)
if num_reservations != usage.reserved: if num_reservations != usage.reserved:
print('\t%s: invalid reserved saved=%s actual=%s%s' % print('\t%s: invalid reserved saved=%s actual=%s%s' %
(usage.resource, usage.reserved, (resource_name, usage.reserved,
num_reservations, action_msg)) num_reservations, action_msg))
discrepancy = True discrepancy = True
if do_fix: if do_fix: