diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index de3fc75b5e14..fac8d08a06b3 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -3030,38 +3030,26 @@ def _reservation_create(context, uuid, usage, project_id, user_id, resource, # code always acquires the lock on quota_usages before acquiring the lock # on reservations. -def _get_user_quota_usages(context, session, project_id, user_id): - # Broken out for testability - rows = model_query(context, models.QuotaUsage, - read_deleted="no", - session=session).\ - filter_by(project_id=project_id).\ - filter(or_(models.QuotaUsage.user_id == user_id, - models.QuotaUsage.user_id == None)).\ - with_lockmode('update').\ - all() - return dict((row.resource, row) for row in rows) - - -def _get_project_quota_usages(context, session, project_id): +def _get_project_user_quota_usages(context, session, project_id, + user_id): rows = model_query(context, models.QuotaUsage, read_deleted="no", session=session).\ filter_by(project_id=project_id).\ with_lockmode('update').\ all() - result = dict() + proj_result = dict() + user_result = dict() # Get the total count of in_use,reserved for row in rows: - if row.resource in result: - result[row.resource]['in_use'] += row.in_use - result[row.resource]['reserved'] += row.reserved - result[row.resource]['total'] += (row.in_use + row.reserved) - else: - result[row.resource] = dict(in_use=row.in_use, - reserved=row.reserved, - total=row.in_use + row.reserved) - return result + proj_result.setdefault(row.resource, + dict(in_use=0, reserved=0, total=0)) + proj_result[row.resource]['in_use'] += row.in_use + proj_result[row.resource]['reserved'] += row.reserved + proj_result[row.resource]['total'] += (row.in_use + row.reserved) + if row.user_id is None or row.user_id == user_id: + user_result[row.resource] = row + return proj_result, user_result @require_context @@ -3079,10 +3067,8 @@ def quota_reserve(context, resources, project_quotas, user_quotas, deltas, user_id = context.user_id # Get the current usages - user_usages = _get_user_quota_usages(context, session, - project_id, user_id) - project_usages = _get_project_quota_usages(context, session, - project_id) + project_usages, user_usages = _get_project_user_quota_usages( + context, session, project_id, user_id) # Handle usage refresh work = set(deltas.keys()) @@ -3291,11 +3277,12 @@ def _quota_reservations_query(session, context, reservations): def reservation_commit(context, reservations, project_id=None, user_id=None): session = get_session() with session.begin(): - usages = _get_user_quota_usages(context, session, project_id, user_id) + _project_usages, user_usages = _get_project_user_quota_usages( + context, session, project_id, user_id) reservation_query = _quota_reservations_query(session, context, reservations) for reservation in reservation_query.all(): - usage = usages[reservation.resource] + usage = user_usages[reservation.resource] if reservation.delta >= 0: usage.reserved -= reservation.delta usage.in_use += reservation.delta @@ -3307,11 +3294,12 @@ def reservation_commit(context, reservations, project_id=None, user_id=None): def reservation_rollback(context, reservations, project_id=None, user_id=None): session = get_session() with session.begin(): - usages = _get_user_quota_usages(context, session, project_id, user_id) + _project_usages, user_usages = _get_project_user_quota_usages( + context, session, project_id, user_id) reservation_query = _quota_reservations_query(session, context, reservations) for reservation in reservation_query.all(): - usage = usages[reservation.resource] + usage = user_usages[reservation.resource] if reservation.delta >= 0: usage.reserved -= reservation.delta reservation_query.soft_delete(synchronize_session=False) diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py index 00eef479b5bb..1b2bf6bfec62 100644 --- a/nova/tests/test_quota.py +++ b/nova/tests/test_quota.py @@ -2161,11 +2161,9 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase): def fake_get_session(): return FakeSession() - def fake_get_project_quota_usages(context, session, project_id): - return self.usages.copy() - - def fake_get_user_quota_usages(context, session, project_id, user_id): - return self.usages.copy() + def fake_get_project_user_quota_usages(context, session, project_id, + user_id): + return self.usages.copy(), self.usages.copy() def fake_quota_usage_create(context, project_id, user_id, resource, in_use, reserved, until_refresh, @@ -2190,10 +2188,8 @@ class QuotaReserveSqlAlchemyTestCase(test.TestCase): return reservation_ref self.stubs.Set(sqa_api, 'get_session', fake_get_session) - self.stubs.Set(sqa_api, '_get_project_quota_usages', - fake_get_project_quota_usages) - self.stubs.Set(sqa_api, '_get_user_quota_usages', - fake_get_user_quota_usages) + self.stubs.Set(sqa_api, '_get_project_user_quota_usages', + fake_get_project_user_quota_usages) self.stubs.Set(sqa_api, '_quota_usage_create', fake_quota_usage_create) self.stubs.Set(sqa_api, '_reservation_create', fake_reservation_create)