diff options
author | Jenkins <jenkins@review.openstack.org> | 2016-04-12 21:38:27 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2016-04-12 21:38:28 +0000 |
commit | 3c522e8bf2dbf9ba3ca1261eaabc64a4f50d38f5 (patch) | |
tree | fcf5b48e4e6a8a5426d26a7cfc81b15409928600 /nova/db | |
parent | 3433e44dbd701fc79689d02c0c7d81a5f03a5651 (diff) | |
parent | 4a95c1c5ea4600f3068b021329101e891eb79158 (diff) | |
download | nova-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.py | 28 | ||||
-rw-r--r-- | nova/db/sqlalchemy/api.py | 111 |
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() |