Add quotas for fixed ips.
DocImpact: there is now a default quota of 10 fixed ips per tenant. This will need to be adjusted by deployers if that number does not meet their needs. Resolves bug 1125468 for essex. Change-Id: I2a5afaa47afb182f4917cd43e1ebd0d6cd1330e3
This commit is contained in:
parent
b683ced5df
commit
efaacdaee1
|
@ -30,8 +30,9 @@ authorize = extensions.extension_authorizer('compute', 'quotas')
|
|||
|
||||
|
||||
quota_resources = ['metadata_items', 'injected_file_content_bytes',
|
||||
'volumes', 'gigabytes', 'ram', 'floating_ips', 'instances',
|
||||
'injected_files', 'cores', 'security_groups', 'security_group_rules']
|
||||
'volumes', 'gigabytes', 'ram', 'floating_ips', 'fixed_ips',
|
||||
'instances', 'injected_files', 'cores', 'security_groups',
|
||||
'security_group_rules']
|
||||
|
||||
|
||||
class QuotaTemplate(xmlutil.TemplateBuilder):
|
||||
|
|
|
@ -461,6 +461,12 @@ def fixed_ip_update(context, address, values):
|
|||
"""Create a fixed ip from the values dictionary."""
|
||||
return IMPL.fixed_ip_update(context, address, values)
|
||||
|
||||
|
||||
def fixed_ip_count_by_project(context, project_id, session=None):
|
||||
"""Count fixed ips used by project."""
|
||||
return IMPL.fixed_ip_count_by_project(context, project_id,
|
||||
session=session)
|
||||
|
||||
####################
|
||||
|
||||
|
||||
|
|
|
@ -1114,6 +1114,27 @@ def fixed_ip_update(context, address, values):
|
|||
fixed_ip_ref.save(session=session)
|
||||
|
||||
|
||||
@require_context
|
||||
def fixed_ip_count_by_project(context, project_id, session=None):
|
||||
authorize_project_context(context, project_id)
|
||||
|
||||
# NOTE(mikal): Yes I know this is horrible, but I couldn't
|
||||
# get a query using a join working, mainly because of a failure
|
||||
# to be able to express the where clause sensibly. Patches
|
||||
# welcome.
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
instance_id_query = model_query(context, models.Instance.id,
|
||||
read_deleted="no", session=session).\
|
||||
filter(models.Instance.project_id == \
|
||||
project_id)
|
||||
id_filter = models.FixedIp.instance_id.in_(instance_id_query)
|
||||
return model_query(context, models.FixedIp, read_deleted="no",
|
||||
session=session).\
|
||||
filter(id_filter).\
|
||||
count()
|
||||
|
||||
|
||||
###################
|
||||
|
||||
|
||||
|
|
|
@ -1152,6 +1152,12 @@ class NetworkManager(manager.SchedulerDependentManager):
|
|||
|
||||
def allocate_fixed_ip(self, context, instance_id, network, **kwargs):
|
||||
"""Gets a fixed ip from the pool."""
|
||||
LOG.debug("QUOTA: %s" % quota.allowed_fixed_ips(context, 1))
|
||||
if quota.allowed_fixed_ips(context, 1) < 1:
|
||||
LOG.warn(_('Quota exceeded for %s, tried to allocate address'),
|
||||
context.project_id)
|
||||
raise exception.QuotaError(code='FixedAddressLimitExceeded')
|
||||
|
||||
# TODO(vish): when this is called by compute, we can associate compute
|
||||
# with a network, or a cluster of computes with a network
|
||||
# and use that network here with a method like
|
||||
|
|
|
@ -42,6 +42,10 @@ quota_opts = [
|
|||
cfg.IntOpt('quota_floating_ips',
|
||||
default=10,
|
||||
help='number of floating ips allowed per project'),
|
||||
cfg.IntOpt('quota_fixed_ips',
|
||||
default=10,
|
||||
help=('number of fixed ips allowed per project (this should be '
|
||||
'at least the number of instances allowed)')),
|
||||
cfg.IntOpt('quota_metadata_items',
|
||||
default=128,
|
||||
help='number of metadata items allowed per instance'),
|
||||
|
@ -74,6 +78,7 @@ def _get_default_quotas():
|
|||
'volumes': FLAGS.quota_volumes,
|
||||
'gigabytes': FLAGS.quota_gigabytes,
|
||||
'floating_ips': FLAGS.quota_floating_ips,
|
||||
'fixed_ips': FLAGS.quota_fixed_ips,
|
||||
'metadata_items': FLAGS.quota_metadata_items,
|
||||
'injected_files': FLAGS.quota_max_injected_files,
|
||||
'injected_file_content_bytes':
|
||||
|
@ -173,6 +178,18 @@ def allowed_floating_ips(context, requested_floating_ips):
|
|||
return min(requested_floating_ips, allowed_floating_ips)
|
||||
|
||||
|
||||
def allowed_fixed_ips(context, requested_fixed_ips):
|
||||
"""Check quota and return min(requested, allowed) fixed ips."""
|
||||
project_id = context.project_id
|
||||
context = context.elevated()
|
||||
used_fixed_ips = db.fixed_ip_count_by_project(context, project_id)
|
||||
quota = get_project_quotas(context, project_id)
|
||||
allowed_fixed_ips = _get_request_allotment(requested_fixed_ips,
|
||||
used_fixed_ips,
|
||||
quota['fixed_ips'])
|
||||
return min(requested_fixed_ips, allowed_fixed_ips)
|
||||
|
||||
|
||||
def allowed_security_groups(context, requested_security_groups):
|
||||
"""Check quota and return min(requested, allowed) security groups."""
|
||||
project_id = context.project_id
|
||||
|
|
|
@ -27,8 +27,8 @@ from nova.tests.api.openstack import fakes
|
|||
def quota_set(id):
|
||||
return {'quota_set': {'id': id, 'metadata_items': 128, 'volumes': 10,
|
||||
'gigabytes': 1000, 'ram': 51200, 'floating_ips': 10,
|
||||
'instances': 10, 'injected_files': 5, 'cores': 20,
|
||||
'injected_file_content_bytes': 10240,
|
||||
'fixed_ips': 10, 'instances': 10, 'injected_files': 5,
|
||||
'cores': 20, 'injected_file_content_bytes': 10240,
|
||||
'security_groups': 10, 'security_group_rules': 20}}
|
||||
|
||||
|
||||
|
@ -50,6 +50,8 @@ class QuotaSetsTest(test.TestCase):
|
|||
'ram': 51200,
|
||||
'volumes': 10,
|
||||
'floating_ips': 10,
|
||||
'fixed_ips': 10,
|
||||
'fixed_ips': 10,
|
||||
'metadata_items': 128,
|
||||
'gigabytes': 1000,
|
||||
'injected_files': 5,
|
||||
|
@ -69,6 +71,7 @@ class QuotaSetsTest(test.TestCase):
|
|||
self.assertEqual(qs['volumes'], 10)
|
||||
self.assertEqual(qs['gigabytes'], 1000)
|
||||
self.assertEqual(qs['floating_ips'], 10)
|
||||
self.assertEqual(qs['fixed_ips'], 10)
|
||||
self.assertEqual(qs['metadata_items'], 128)
|
||||
self.assertEqual(qs['injected_files'], 5)
|
||||
self.assertEqual(qs['injected_file_content_bytes'], 10240)
|
||||
|
@ -89,6 +92,7 @@ class QuotaSetsTest(test.TestCase):
|
|||
'volumes': 10,
|
||||
'gigabytes': 1000,
|
||||
'floating_ips': 10,
|
||||
'fixed_ips': 10,
|
||||
'metadata_items': 128,
|
||||
'injected_files': 5,
|
||||
'injected_file_content_bytes': 10240,
|
||||
|
@ -114,7 +118,8 @@ class QuotaSetsTest(test.TestCase):
|
|||
body = {'quota_set': {'instances': 50, 'cores': 50,
|
||||
'ram': 51200, 'volumes': 10,
|
||||
'gigabytes': 1000, 'floating_ips': 10,
|
||||
'metadata_items': 128, 'injected_files': 5,
|
||||
'fixed_ips': 10, 'metadata_items': 128,
|
||||
'injected_files': 5,
|
||||
'injected_file_content_bytes': 10240,
|
||||
'security_groups': 10,
|
||||
'security_group_rules': 20}}
|
||||
|
@ -129,7 +134,8 @@ class QuotaSetsTest(test.TestCase):
|
|||
body = {'quota_set': {'instances': 50, 'cores': 50,
|
||||
'ram': 51200, 'volumes': 10,
|
||||
'gigabytes': 1000, 'floating_ips': 10,
|
||||
'metadata_items': 128, 'injected_files': 5,
|
||||
'fixed_ips': 10, 'metadata_items': 128,
|
||||
'injected_files': 5,
|
||||
'injected_file_content_bytes': 10240,
|
||||
'security_groups': 10,
|
||||
'security_group_rules': 20}}
|
||||
|
@ -154,6 +160,7 @@ class QuotaXMLSerializerTest(test.TestCase):
|
|||
gigabytes=40,
|
||||
ram=50,
|
||||
floating_ips=60,
|
||||
fixed_ips=10,
|
||||
instances=70,
|
||||
injected_files=80,
|
||||
security_groups=10,
|
||||
|
@ -179,6 +186,7 @@ class QuotaXMLSerializerTest(test.TestCase):
|
|||
gigabytes='40',
|
||||
ram='50',
|
||||
floating_ips='60',
|
||||
fixed_ips='10',
|
||||
instances='70',
|
||||
injected_files='80',
|
||||
security_groups='10',
|
||||
|
@ -193,6 +201,7 @@ class QuotaXMLSerializerTest(test.TestCase):
|
|||
'<gigabytes>40</gigabytes>'
|
||||
'<ram>50</ram>'
|
||||
'<floating_ips>60</floating_ips>'
|
||||
'<fixed_ips>10</fixed_ips>'
|
||||
'<instances>70</instances>'
|
||||
'<injected_files>80</injected_files>'
|
||||
'<security_groups>10</security_groups>'
|
||||
|
|
|
@ -432,6 +432,7 @@ class VlanNetworkTestCase(test.TestCase):
|
|||
db.instance_get(mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn({'security_groups':
|
||||
[{'id': 0}]})
|
||||
|
||||
db.fixed_ip_associate_pool(mox.IgnoreArg(),
|
||||
mox.IgnoreArg(),
|
||||
mox.IgnoreArg()).AndReturn('192.168.0.1')
|
||||
|
|
Loading…
Reference in New Issue