1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
3
# Copyright 2010 United States Government as represented by the
4
# Administrator of the National Aeronautics and Space Administration.
7
# Licensed under the Apache License, Version 2.0 (the "License"); you may
8
# not use this file except in compliance with the License. You may obtain
9
# a copy of the License at
11
# http://www.apache.org/licenses/LICENSE-2.0
13
# Unless required by applicable law or agreed to in writing, software
14
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
16
# License for the specific language governing permissions and limitations
19
"""Quotas for instances, volumes, and floating ips."""
22
from nova.openstack.common import cfg
23
from nova import flags
27
cfg.IntOpt('quota_instances',
29
help='number of instances allowed per project'),
30
cfg.IntOpt('quota_cores',
32
help='number of instance cores allowed per project'),
33
cfg.IntOpt('quota_ram',
35
help='megabytes of instance ram allowed per project'),
36
cfg.IntOpt('quota_volumes',
38
help='number of volumes allowed per project'),
39
cfg.IntOpt('quota_gigabytes',
41
help='number of volume gigabytes allowed per project'),
42
cfg.IntOpt('quota_floating_ips',
44
help='number of floating ips allowed per project'),
45
cfg.IntOpt('quota_metadata_items',
47
help='number of metadata items allowed per instance'),
48
cfg.IntOpt('quota_max_injected_files',
50
help='number of injected files allowed'),
51
cfg.IntOpt('quota_max_injected_file_content_bytes',
53
help='number of bytes allowed per injected file'),
54
cfg.IntOpt('quota_max_injected_file_path_bytes',
56
help='number of bytes allowed per injected file path'),
60
FLAGS.register_opts(quota_opts)
63
def _get_default_quotas():
65
'instances': FLAGS.quota_instances,
66
'cores': FLAGS.quota_cores,
67
'ram': FLAGS.quota_ram,
68
'volumes': FLAGS.quota_volumes,
69
'gigabytes': FLAGS.quota_gigabytes,
70
'floating_ips': FLAGS.quota_floating_ips,
71
'metadata_items': FLAGS.quota_metadata_items,
72
'injected_files': FLAGS.quota_max_injected_files,
73
'injected_file_content_bytes':
74
FLAGS.quota_max_injected_file_content_bytes,
76
# -1 in the quota flags means unlimited
77
for key in defaults.keys():
78
if defaults[key] == -1:
83
def get_project_quotas(context, project_id):
84
rval = _get_default_quotas()
85
quota = db.quota_get_all_by_project(context, project_id)
86
for key in rval.keys():
88
rval[key] = quota[key]
92
def _get_request_allotment(requested, used, quota):
98
def allowed_instances(context, requested_instances, instance_type):
99
"""Check quota and return min(requested_instances, allowed_instances)."""
100
project_id = context.project_id
101
context = context.elevated()
102
requested_cores = requested_instances * instance_type['vcpus']
103
requested_ram = requested_instances * instance_type['memory_mb']
104
usage = db.instance_data_get_for_project(context, project_id)
105
used_instances, used_cores, used_ram = usage
106
quota = get_project_quotas(context, project_id)
107
allowed_instances = _get_request_allotment(requested_instances,
110
allowed_cores = _get_request_allotment(requested_cores, used_cores,
112
allowed_ram = _get_request_allotment(requested_ram, used_ram, quota['ram'])
113
if instance_type['vcpus']:
114
allowed_instances = min(allowed_instances,
115
allowed_cores // instance_type['vcpus'])
116
if instance_type['memory_mb']:
117
allowed_instances = min(allowed_instances,
118
allowed_ram // instance_type['memory_mb'])
120
return min(requested_instances, allowed_instances)
123
def allowed_volumes(context, requested_volumes, size):
124
"""Check quota and return min(requested_volumes, allowed_volumes)."""
125
project_id = context.project_id
126
context = context.elevated()
128
requested_gigabytes = requested_volumes * size
129
used_volumes, used_gigabytes = db.volume_data_get_for_project(context,
131
quota = get_project_quotas(context, project_id)
132
allowed_volumes = _get_request_allotment(requested_volumes, used_volumes,
134
allowed_gigabytes = _get_request_allotment(requested_gigabytes,
138
allowed_volumes = min(allowed_volumes,
139
int(allowed_gigabytes // size))
140
return min(requested_volumes, allowed_volumes)
143
def allowed_floating_ips(context, requested_floating_ips):
144
"""Check quota and return min(requested, allowed) floating ips."""
145
project_id = context.project_id
146
context = context.elevated()
147
used_floating_ips = db.floating_ip_count_by_project(context, project_id)
148
quota = get_project_quotas(context, project_id)
149
allowed_floating_ips = _get_request_allotment(requested_floating_ips,
151
quota['floating_ips'])
152
return min(requested_floating_ips, allowed_floating_ips)
155
def _calculate_simple_quota(context, resource, requested):
156
"""Check quota for resource; return min(requested, allowed)."""
157
quota = get_project_quotas(context, context.project_id)
158
allowed = _get_request_allotment(requested, 0, quota[resource])
159
return min(requested, allowed)
162
def allowed_metadata_items(context, requested_metadata_items):
163
"""Return the number of metadata items allowed."""
164
return _calculate_simple_quota(context, 'metadata_items',
165
requested_metadata_items)
168
def allowed_injected_files(context, requested_injected_files):
169
"""Return the number of injected files allowed."""
170
return _calculate_simple_quota(context, 'injected_files',
171
requested_injected_files)
174
def allowed_injected_file_content_bytes(context, requested_bytes):
175
"""Return the number of bytes allowed per injected file content."""
176
resource = 'injected_file_content_bytes'
177
return _calculate_simple_quota(context, resource, requested_bytes)
180
def allowed_injected_file_path_bytes(context):
181
"""Return the number of bytes allowed in an injected file path."""
182
return FLAGS.quota_max_injected_file_path_bytes