summaryrefslogtreecommitdiffstats
path: root/nova/quota.py
diff options
context:
space:
mode:
Diffstat (limited to 'nova/quota.py')
-rw-r--r--nova/quota.py134
1 files changed, 85 insertions, 49 deletions
diff --git a/nova/quota.py b/nova/quota.py
index d8b5d9a93..58766e846 100644
--- a/nova/quota.py
+++ b/nova/quota.py
@@ -28,6 +28,8 @@ flags.DEFINE_integer('quota_instances', 10,
'number of instances allowed per project')
flags.DEFINE_integer('quota_cores', 20,
'number of instance cores allowed per project')
+flags.DEFINE_integer('quota_ram', 50 * 1024,
+ 'megabytes of instance ram allowed per project')
flags.DEFINE_integer('quota_volumes', 10,
'number of volumes allowed per project')
flags.DEFINE_integer('quota_gigabytes', 1000,
@@ -44,82 +46,116 @@ flags.DEFINE_integer('quota_max_injected_file_path_bytes', 255,
'number of bytes allowed per injected file path')
-def get_quota(context, project_id):
- rval = {'instances': FLAGS.quota_instances,
- 'cores': FLAGS.quota_cores,
- 'volumes': FLAGS.quota_volumes,
- 'gigabytes': FLAGS.quota_gigabytes,
- 'floating_ips': FLAGS.quota_floating_ips,
- 'metadata_items': FLAGS.quota_metadata_items}
-
- try:
- quota = db.quota_get(context, project_id)
- for key in rval.keys():
- if quota[key] is not None:
- rval[key] = quota[key]
- except exception.NotFound:
- pass
+def _get_default_quotas():
+ defaults = {
+ 'instances': FLAGS.quota_instances,
+ 'cores': FLAGS.quota_cores,
+ 'ram': FLAGS.quota_ram,
+ 'volumes': FLAGS.quota_volumes,
+ 'gigabytes': FLAGS.quota_gigabytes,
+ 'floating_ips': FLAGS.quota_floating_ips,
+ 'metadata_items': FLAGS.quota_metadata_items,
+ 'injected_files': FLAGS.quota_max_injected_files,
+ 'injected_file_content_bytes':
+ FLAGS.quota_max_injected_file_content_bytes,
+ }
+ # -1 in the quota flags means unlimited
+ for key in defaults.keys():
+ if defaults[key] == -1:
+ defaults[key] = None
+ return defaults
+
+
+def get_project_quotas(context, project_id):
+ rval = _get_default_quotas()
+ quota = db.quota_get_all_by_project(context, project_id)
+ for key in rval.keys():
+ if key in quota:
+ rval[key] = quota[key]
return rval
-def allowed_instances(context, num_instances, instance_type):
- """Check quota and return min(num_instances, allowed_instances)."""
+def _get_request_allotment(requested, used, quota):
+ if quota is None:
+ return requested
+ return quota - used
+
+
+def allowed_instances(context, requested_instances, instance_type):
+ """Check quota and return min(requested_instances, allowed_instances)."""
project_id = context.project_id
context = context.elevated()
- used_instances, used_cores = db.instance_data_get_for_project(context,
- project_id)
- quota = get_quota(context, project_id)
- allowed_instances = quota['instances'] - used_instances
- allowed_cores = quota['cores'] - used_cores
- num_cores = num_instances * instance_type['vcpus']
+ requested_cores = requested_instances * instance_type['vcpus']
+ requested_ram = requested_instances * instance_type['memory_mb']
+ usage = db.instance_data_get_for_project(context, project_id)
+ used_instances, used_cores, used_ram = usage
+ quota = get_project_quotas(context, project_id)
+ allowed_instances = _get_request_allotment(requested_instances,
+ used_instances,
+ quota['instances'])
+ allowed_cores = _get_request_allotment(requested_cores, used_cores,
+ quota['cores'])
+ allowed_ram = _get_request_allotment(requested_ram, used_ram, quota['ram'])
allowed_instances = min(allowed_instances,
- int(allowed_cores // instance_type['vcpus']))
- return min(num_instances, allowed_instances)
+ allowed_cores // instance_type['vcpus'],
+ allowed_ram // instance_type['memory_mb'])
+ return min(requested_instances, allowed_instances)
-def allowed_volumes(context, num_volumes, size):
- """Check quota and return min(num_volumes, allowed_volumes)."""
+def allowed_volumes(context, requested_volumes, size):
+ """Check quota and return min(requested_volumes, allowed_volumes)."""
project_id = context.project_id
context = context.elevated()
+ size = int(size)
+ requested_gigabytes = requested_volumes * size
used_volumes, used_gigabytes = db.volume_data_get_for_project(context,
project_id)
- quota = get_quota(context, project_id)
- allowed_volumes = quota['volumes'] - used_volumes
- allowed_gigabytes = quota['gigabytes'] - used_gigabytes
- size = int(size)
- num_gigabytes = num_volumes * size
+ quota = get_project_quotas(context, project_id)
+ allowed_volumes = _get_request_allotment(requested_volumes, used_volumes,
+ quota['volumes'])
+ allowed_gigabytes = _get_request_allotment(requested_gigabytes,
+ used_gigabytes,
+ quota['gigabytes'])
allowed_volumes = min(allowed_volumes,
int(allowed_gigabytes // size))
- return min(num_volumes, allowed_volumes)
+ return min(requested_volumes, allowed_volumes)
-def allowed_floating_ips(context, num_floating_ips):
- """Check quota and return min(num_floating_ips, allowed_floating_ips)."""
+def allowed_floating_ips(context, requested_floating_ips):
+ """Check quota and return min(requested, allowed) floating ips."""
project_id = context.project_id
context = context.elevated()
used_floating_ips = db.floating_ip_count_by_project(context, project_id)
- quota = get_quota(context, project_id)
- allowed_floating_ips = quota['floating_ips'] - used_floating_ips
- return min(num_floating_ips, allowed_floating_ips)
+ quota = get_project_quotas(context, project_id)
+ allowed_floating_ips = _get_request_allotment(requested_floating_ips,
+ used_floating_ips,
+ quota['floating_ips'])
+ return min(requested_floating_ips, allowed_floating_ips)
-def allowed_metadata_items(context, num_metadata_items):
- """Check quota; return min(num_metadata_items,allowed_metadata_items)."""
- project_id = context.project_id
- context = context.elevated()
- quota = get_quota(context, project_id)
- num_allowed_metadata_items = quota['metadata_items']
- return min(num_metadata_items, num_allowed_metadata_items)
+def _calculate_simple_quota(context, resource, requested):
+ """Check quota for resource; return min(requested, allowed)."""
+ quota = get_project_quotas(context, context.project_id)
+ allowed = _get_request_allotment(requested, 0, quota[resource])
+ return min(requested, allowed)
+
+
+def allowed_metadata_items(context, requested_metadata_items):
+ """Return the number of metadata items allowed."""
+ return _calculate_simple_quota(context, 'metadata_items',
+ requested_metadata_items)
-def allowed_injected_files(context):
+def allowed_injected_files(context, requested_injected_files):
"""Return the number of injected files allowed."""
- return FLAGS.quota_max_injected_files
+ return _calculate_simple_quota(context, 'injected_files',
+ requested_injected_files)
-def allowed_injected_file_content_bytes(context):
+def allowed_injected_file_content_bytes(context, requested_bytes):
"""Return the number of bytes allowed per injected file content."""
- return FLAGS.quota_max_injected_file_content_bytes
+ resource = 'injected_file_content_bytes'
+ return _calculate_simple_quota(context, resource, requested_bytes)
def allowed_injected_file_path_bytes(context):