summaryrefslogtreecommitdiff
path: root/nova/db
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-04-12 21:38:27 +0000
committerGerrit Code Review <review@openstack.org>2016-04-12 21:38:28 +0000
commit3c522e8bf2dbf9ba3ca1261eaabc64a4f50d38f5 (patch)
treefcf5b48e4e6a8a5426d26a7cfc81b15409928600 /nova/db
parent3433e44dbd701fc79689d02c0c7d81a5f03a5651 (diff)
parent4a95c1c5ea4600f3068b021329101e891eb79158 (diff)
downloadnova-3c522e8bf2dbf9ba3ca1261eaabc64a4f50d38f5.tar.gz
Merge "DB API changes for the nova-manage quota_usage_refresh command"
Diffstat (limited to 'nova/db')
-rw-r--r--nova/db/api.py28
-rw-r--r--nova/db/sqlalchemy/api.py111
2 files changed, 101 insertions, 38 deletions
diff --git a/nova/db/api.py b/nova/db/api.py
index 7cd9e7aeda..d509a58c42 100644
--- a/nova/db/api.py
+++ b/nova/db/api.py
@@ -1082,6 +1082,13 @@ def quota_get_all_by_project(context, project_id):
return IMPL.quota_get_all_by_project(context, project_id)
+def quota_get_per_project_resources():
+ """Retrieve the names of resources whose quotas are calculated on a
+ per-project rather than a per-user basis.
+ """
+ return IMPL.quota_get_per_project_resources()
+
+
def quota_get_all(context, project_id):
"""Retrieve all user quotas associated with a given project."""
return IMPL.quota_get_all(context, project_id)
@@ -1146,6 +1153,27 @@ def quota_usage_update(context, project_id, user_id, resource, **kwargs):
**kwargs)
+def quota_usage_refresh(context, resources, keys, until_refresh, max_age,
+ project_id=None, user_id=None):
+ """Refresh the quota usages.
+
+ :param context: The request context, for access checks.
+ :param resources: A dictionary of the registered resources.
+ :param keys: Names of the resources whose usage is to be refreshed.
+ :param until_refresh: The until_refresh configuration value.
+ :param max_age: The max_age configuration value.
+ :param project_id: (Optional) The project_id containing the usages
+ to be refreshed. Defaults to the project_id
+ in the context.
+ :param user_id: (Optional) The user_id containing the usages
+ to be refreshed. Defaults to the user_id
+ in the context.
+
+ """
+ return IMPL.quota_usage_refresh(context, resources, keys, until_refresh,
+ max_age, project_id=project_id, user_id=user_id)
+
+
###################
diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py
index b131350fff..3d70876dd3 100644
--- a/nova/db/sqlalchemy/api.py
+++ b/nova/db/sqlalchemy/api.py
@@ -3528,6 +3528,10 @@ def quota_get_all(context, project_id):
return result
+def quota_get_per_project_resources():
+ return PER_PROJECT_QUOTAS
+
+
@main_context_manager.writer
def quota_create(context, project_id, resource, limit, user_id=None):
per_user = user_id and resource not in PER_PROJECT_QUOTAS
@@ -3847,6 +3851,53 @@ def _refresh_quota_usages(quota_usage, until_refresh, in_use):
quota_usage.until_refresh = until_refresh or None
+def _refresh_quota_usages_if_needed(user_usages, context, resources, keys,
+ project_id, user_id, until_refresh,
+ max_age, force_refresh=False):
+ elevated = context.elevated()
+
+ # Handle usage refresh
+ work = set(keys)
+ while work:
+ resource = work.pop()
+
+ # Do we need to refresh the usage?
+ created = _create_quota_usage_if_missing(user_usages, resource,
+ until_refresh, project_id,
+ user_id, context.session)
+
+ refresh = force_refresh
+ if not refresh:
+ refresh = created or \
+ _is_quota_refresh_needed(user_usages[resource], max_age)
+
+ # OK, refresh the usage
+ if refresh:
+ # Grab the sync routine
+ sync = QUOTA_SYNC_FUNCTIONS[resources[resource].sync]
+
+ updates = sync(elevated, project_id, user_id)
+ for res, in_use in updates.items():
+ # Make sure we have a destination for the usage!
+ _create_quota_usage_if_missing(user_usages, res,
+ until_refresh, project_id,
+ user_id, context.session)
+ _refresh_quota_usages(user_usages[res], until_refresh,
+ in_use)
+
+ # Because more than one resource may be refreshed
+ # by the call to the sync routine, and we don't
+ # want to double-sync, we make sure all refreshed
+ # resources are dropped from the work set.
+ work.discard(res)
+
+ # NOTE(Vek): We make the assumption that the sync
+ # routine actually refreshes the
+ # resources that it is the sync routine
+ # for. We don't check, because this is
+ # a best-effort mechanism.
+
+
def _calculate_overquota(project_quotas, user_quotas, deltas,
project_usages, user_usages):
"""Checks if any resources will go over quota based on the request.
@@ -3891,11 +3942,8 @@ def _calculate_overquota(project_quotas, user_quotas, deltas,
@require_context
@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
@main_context_manager.writer
-def quota_reserve(context, resources, project_quotas, user_quotas, deltas,
- expire, until_refresh, max_age, project_id=None,
- user_id=None):
- elevated = context.elevated()
-
+def quota_usage_refresh(context, resources, keys, until_refresh, max_age,
+ project_id=None, user_id=None):
if project_id is None:
project_id = context.project_id
if user_id is None:
@@ -3905,43 +3953,30 @@ def quota_reserve(context, resources, project_quotas, user_quotas, deltas,
project_usages, user_usages = _get_project_user_quota_usages(
context, project_id, user_id)
- # Handle usage refresh
- work = set(deltas.keys())
- while work:
- resource = work.pop()
+ # Force refresh of the usages
+ _refresh_quota_usages_if_needed(user_usages, context, resources, keys,
+ project_id, user_id, until_refresh,
+ max_age, force_refresh=True)
- # Do we need to refresh the usage?
- created = _create_quota_usage_if_missing(user_usages, resource,
- until_refresh, project_id,
- user_id, context.session)
- refresh = created or _is_quota_refresh_needed(
- user_usages[resource], max_age)
-
- # OK, refresh the usage
- if refresh:
- # Grab the sync routine
- sync = QUOTA_SYNC_FUNCTIONS[resources[resource].sync]
- updates = sync(elevated, project_id, user_id)
- for res, in_use in updates.items():
- # Make sure we have a destination for the usage!
- _create_quota_usage_if_missing(user_usages, res,
- until_refresh, project_id,
- user_id, context.session)
- _refresh_quota_usages(user_usages[res], until_refresh,
- in_use)
+@require_context
+@oslo_db_api.wrap_db_retry(max_retries=5, retry_on_deadlock=True)
+@main_context_manager.writer
+def quota_reserve(context, resources, project_quotas, user_quotas, deltas,
+ expire, until_refresh, max_age, project_id=None,
+ user_id=None):
+ if project_id is None:
+ project_id = context.project_id
+ if user_id is None:
+ user_id = context.user_id
- # Because more than one resource may be refreshed
- # by the call to the sync routine, and we don't
- # want to double-sync, we make sure all refreshed
- # resources are dropped from the work set.
- work.discard(res)
+ # Get the current usages
+ project_usages, user_usages = _get_project_user_quota_usages(
+ context, project_id, user_id)
- # NOTE(Vek): We make the assumption that the sync
- # routine actually refreshes the
- # resources that it is the sync routine
- # for. We don't check, because this is
- # a best-effort mechanism.
+ _refresh_quota_usages_if_needed(user_usages, context, resources,
+ deltas.keys(), project_id, user_id,
+ until_refresh, max_age)
# Check for deltas that would go negative
unders = [res for res, delta in deltas.items()