Implement security group quotas.

Fixes LP Bug #969545

Change-Id: I60d4300aa04597e2d8b0eea31ab0303b0b3c48f9
This commit is contained in:
Dan Prince
2012-04-03 14:07:07 -04:00
parent ab7e5907ff
commit 1f644d2105
10 changed files with 238 additions and 10 deletions

View File

@@ -41,6 +41,7 @@ from nova import flags
from nova.image import s3 from nova.image import s3
from nova import log as logging from nova import log as logging
from nova import network from nova import network
from nova import quota
from nova import utils from nova import utils
from nova import volume from nova import volume
@@ -725,6 +726,13 @@ class CloudController(object):
raise exception.EC2APIError(err % values_for_rule) raise exception.EC2APIError(err % values_for_rule)
postvalues.append(values_for_rule) postvalues.append(values_for_rule)
allowed = quota.allowed_security_group_rules(context,
security_group['id'],
1)
if allowed < 1:
msg = _("Quota exceeded, too many security group rules.")
raise exception.EC2APIError(msg)
rule_ids = [] rule_ids = []
for values_for_rule in postvalues: for values_for_rule in postvalues:
security_group_rule = db.security_group_rule_create( security_group_rule = db.security_group_rule_create(
@@ -782,6 +790,10 @@ class CloudController(object):
msg = _('group %s already exists') msg = _('group %s already exists')
raise exception.EC2APIError(msg % group_name) raise exception.EC2APIError(msg % group_name)
if quota.allowed_security_groups(context, 1) < 1:
msg = _("Quota exceeded, too many security groups.")
raise exception.EC2APIError(msg)
group = {'user_id': context.user_id, group = {'user_id': context.user_id,
'project_id': context.project_id, 'project_id': context.project_id,
'name': group_name, 'name': group_name,

View File

@@ -31,6 +31,7 @@ from nova import db
from nova import exception from nova import exception
from nova import flags from nova import flags
from nova import log as logging from nova import log as logging
from nova import quota
from nova import utils from nova import utils
@@ -289,6 +290,10 @@ class SecurityGroupController(SecurityGroupControllerBase):
group_name = group_name.strip() group_name = group_name.strip()
group_description = group_description.strip() group_description = group_description.strip()
if quota.allowed_security_groups(context, 1) < 1:
msg = _("Quota exceeded, too many security groups.")
raise exc.HTTPBadRequest(explanation=msg)
LOG.audit(_("Create Security Group %s"), group_name, context=context) LOG.audit(_("Create Security Group %s"), group_name, context=context)
self.compute_api.ensure_default_security_group(context) self.compute_api.ensure_default_security_group(context)
if db.security_group_exists(context, context.project_id, group_name): if db.security_group_exists(context, context.project_id, group_name):
@@ -376,6 +381,13 @@ class SecurityGroupRulesController(SecurityGroupControllerBase):
msg = _('This rule already exists in group %s') % parent_group_id msg = _('This rule already exists in group %s') % parent_group_id
raise exc.HTTPBadRequest(explanation=msg) raise exc.HTTPBadRequest(explanation=msg)
allowed = quota.allowed_security_group_rules(context,
parent_group_id,
1)
if allowed < 1:
msg = _("Quota exceeded, too many security group rules.")
raise exc.HTTPBadRequest(explanation=msg)
security_group_rule = db.security_group_rule_create(context, values) security_group_rule = db.security_group_rule_create(context, values)
self.sgh.trigger_security_group_rule_create_refresh( self.sgh.trigger_security_group_rule_create_refresh(
context, [security_group_rule['id']]) context, [security_group_rule['id']])

View File

@@ -1151,6 +1151,11 @@ def security_group_destroy(context, security_group_id):
return IMPL.security_group_destroy(context, security_group_id) return IMPL.security_group_destroy(context, security_group_id)
def security_group_count_by_project(context, project_id):
"""Count number of security groups in a project."""
return IMPL.security_group_count_by_project(context, project_id)
#################### ####################
@@ -1182,6 +1187,11 @@ def security_group_rule_get(context, security_group_rule_id):
return IMPL.security_group_rule_get(context, security_group_rule_id) return IMPL.security_group_rule_get(context, security_group_rule_id)
def security_group_rule_count_by_group(context, security_group_id):
"""Count rules in a given security group."""
return IMPL.security_group_rule_count_by_group(context, security_group_id)
################### ###################

View File

@@ -2903,6 +2903,13 @@ def security_group_destroy(context, security_group_id):
'updated_at': literal_column('updated_at')}) 'updated_at': literal_column('updated_at')})
@require_context
def security_group_count_by_project(context, project_id):
authorize_project_context(context, project_id)
return model_query(context, models.SecurityGroup, read_deleted="no").\
filter_by(project_id=project_id).\
count()
################### ###################
@@ -2961,6 +2968,14 @@ def security_group_rule_destroy(context, security_group_rule_id):
security_group_rule.delete(session=session) security_group_rule.delete(session=session)
@require_context
def security_group_rule_count_by_group(context, security_group_id):
return model_query(context, models.SecurityGroupIngressRule,
read_deleted="no").\
filter_by(parent_group_id=security_group_id).\
count()
#
################### ###################

View File

@@ -54,6 +54,12 @@ quota_opts = [
cfg.IntOpt('quota_injected_file_path_bytes', cfg.IntOpt('quota_injected_file_path_bytes',
default=255, default=255,
help='number of bytes allowed per injected file path'), help='number of bytes allowed per injected file path'),
cfg.IntOpt('quota_security_groups',
default=10,
help='number of security groups per project'),
cfg.IntOpt('quota_security_group_rules',
default=20,
help='number of security rules per security group'),
] ]
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
@@ -62,7 +68,7 @@ FLAGS.register_opts(quota_opts)
quota_resources = ['metadata_items', 'injected_file_content_bytes', quota_resources = ['metadata_items', 'injected_file_content_bytes',
'volumes', 'gigabytes', 'ram', 'floating_ips', 'instances', 'volumes', 'gigabytes', 'ram', 'floating_ips', 'instances',
'injected_files', 'cores'] 'injected_files', 'cores', 'security_groups', 'security_group_rules']
def _get_default_quotas(): def _get_default_quotas():
@@ -77,6 +83,8 @@ def _get_default_quotas():
'injected_files': FLAGS.quota_injected_files, 'injected_files': FLAGS.quota_injected_files,
'injected_file_content_bytes': 'injected_file_content_bytes':
FLAGS.quota_injected_file_content_bytes, FLAGS.quota_injected_file_content_bytes,
'security_groups': FLAGS.quota_security_groups,
'security_group_rules': FLAGS.quota_security_group_rules,
} }
# -1 in the quota flags means unlimited # -1 in the quota flags means unlimited
return defaults return defaults
@@ -170,6 +178,32 @@ def allowed_floating_ips(context, requested_floating_ips):
return min(requested_floating_ips, allowed_floating_ips) return min(requested_floating_ips, allowed_floating_ips)
def allowed_security_groups(context, requested_security_groups):
"""Check quota and return min(requested, allowed) security groups."""
project_id = context.project_id
context = context.elevated()
used_sec_groups = db.security_group_count_by_project(context, project_id)
quota = get_project_quotas(context, project_id)
allowed_sec_groups = _get_request_allotment(requested_security_groups,
used_sec_groups,
quota['security_groups'])
return min(requested_security_groups, allowed_sec_groups)
def allowed_security_group_rules(context, security_group_id,
requested_rules):
"""Check quota and return min(requested, allowed) sec group rules."""
project_id = context.project_id
context = context.elevated()
used_rules = db.security_group_rule_count_by_group(context,
security_group_id)
quota = get_project_quotas(context, project_id)
allowed_rules = _get_request_allotment(requested_rules,
used_rules,
quota['security_group_rules'])
return min(requested_rules, allowed_rules)
def _calculate_simple_quota(context, resource, requested): def _calculate_simple_quota(context, resource, requested):
"""Check quota for resource; return min(requested, allowed).""" """Check quota for resource; return min(requested, allowed)."""
quota = get_project_quotas(context, context.project_id) quota = get_project_quotas(context, context.project_id)

View File

@@ -271,6 +271,18 @@ class CloudTestCase(test.TestCase):
delete = self.cloud.delete_security_group delete = self.cloud.delete_security_group
self.assertTrue(delete(self.context, 'testgrp')) self.assertTrue(delete(self.context, 'testgrp'))
def test_security_group_quota_limit(self):
self.flags(quota_security_groups=10)
for i in range(1, 10):
name = 'test name %i' % i
descript = 'test description %i' % i
create = self.cloud.create_security_group
result = create(self.context, name, descript)
# 11'th group should fail
self.assertRaises(exception.EC2APIError,
create, self.context, 'foo', 'bar')
def test_delete_security_group_by_id(self): def test_delete_security_group_by_id(self):
sec = db.security_group_create(self.context, sec = db.security_group_create(self.context,
{'project_id': self.context.project_id, {'project_id': self.context.project_id,
@@ -436,6 +448,19 @@ class CloudTestCase(test.TestCase):
self.assertRaises(exception.EC2APIError, authz, self.context, self.assertRaises(exception.EC2APIError, authz, self.context,
group_name=sec['name'], **kwargs) group_name=sec['name'], **kwargs)
def test_security_group_ingress_quota_limit(self):
self.flags(quota_security_group_rules=20)
kwargs = {'project_id': self.context.project_id, 'name': 'test'}
sec_group = db.security_group_create(self.context, kwargs)
authz = self.cloud.authorize_security_group_ingress
for i in range(100, 120):
kwargs = {'to_port': i, 'from_port': i, 'ip_protocol': 'tcp'}
authz(self.context, group_id=sec_group['id'], **kwargs)
kwargs = {'to_port': 121, 'from_port': 121, 'ip_protocol': 'tcp'}
self.assertRaises(exception.EC2APIError, authz, self.context,
group_id=sec_group['id'], **kwargs)
def _test_authorize_security_group_no_ports_with_source_group(self, proto): def _test_authorize_security_group_no_ports_with_source_group(self, proto):
kwargs = {'project_id': self.context.project_id, 'name': 'test'} kwargs = {'project_id': self.context.project_id, 'name': 'test'}
sec = db.security_group_create(self.context, kwargs) sec = db.security_group_create(self.context, kwargs)

View File

@@ -26,7 +26,8 @@ def quota_set(class_name):
return {'quota_class_set': {'id': class_name, 'metadata_items': 128, return {'quota_class_set': {'id': class_name, 'metadata_items': 128,
'volumes': 10, 'gigabytes': 1000, 'ram': 51200, 'volumes': 10, 'gigabytes': 1000, 'ram': 51200,
'floating_ips': 10, 'instances': 10, 'injected_files': 5, 'floating_ips': 10, 'instances': 10, 'injected_files': 5,
'cores': 20, 'injected_file_content_bytes': 10240}} 'cores': 20, 'injected_file_content_bytes': 10240,
'security_groups': 10, 'security_group_rules': 20}}
class QuotaClassSetsTest(test.TestCase): class QuotaClassSetsTest(test.TestCase):
@@ -45,7 +46,10 @@ class QuotaClassSetsTest(test.TestCase):
'metadata_items': 128, 'metadata_items': 128,
'gigabytes': 1000, 'gigabytes': 1000,
'injected_files': 5, 'injected_files': 5,
'injected_file_content_bytes': 10240} 'injected_file_content_bytes': 10240,
'security_groups': 10,
'security_group_rules': 20,
}
quota_set = self.controller._format_quota_set('test_class', quota_set = self.controller._format_quota_set('test_class',
raw_quota_set) raw_quota_set)
@@ -61,6 +65,8 @@ class QuotaClassSetsTest(test.TestCase):
self.assertEqual(qs['metadata_items'], 128) self.assertEqual(qs['metadata_items'], 128)
self.assertEqual(qs['injected_files'], 5) self.assertEqual(qs['injected_files'], 5)
self.assertEqual(qs['injected_file_content_bytes'], 10240) self.assertEqual(qs['injected_file_content_bytes'], 10240)
self.assertEqual(qs['security_groups'], 10)
self.assertEqual(qs['security_group_rules'], 20)
def test_quotas_show_as_admin(self): def test_quotas_show_as_admin(self):
req = fakes.HTTPRequest.blank( req = fakes.HTTPRequest.blank(
@@ -81,7 +87,10 @@ class QuotaClassSetsTest(test.TestCase):
'ram': 51200, 'volumes': 10, 'ram': 51200, 'volumes': 10,
'gigabytes': 1000, 'floating_ips': 10, 'gigabytes': 1000, 'floating_ips': 10,
'metadata_items': 128, 'injected_files': 5, 'metadata_items': 128, 'injected_files': 5,
'injected_file_content_bytes': 10240}} 'injected_file_content_bytes': 10240,
'security_groups': 10,
'security_group_rules': 20,
}}
req = fakes.HTTPRequest.blank( req = fakes.HTTPRequest.blank(
'/v2/fake4/os-quota-class-sets/test_class', '/v2/fake4/os-quota-class-sets/test_class',
@@ -95,7 +104,10 @@ class QuotaClassSetsTest(test.TestCase):
'ram': 51200, 'volumes': 10, 'ram': 51200, 'volumes': 10,
'gigabytes': 1000, 'floating_ips': 10, 'gigabytes': 1000, 'floating_ips': 10,
'metadata_items': 128, 'injected_files': 5, 'metadata_items': 128, 'injected_files': 5,
'injected_file_content_bytes': 10240}} 'injected_file_content_bytes': 10240,
'security_groups': 10,
'security_group_rules': 20,
}}
req = fakes.HTTPRequest.blank( req = fakes.HTTPRequest.blank(
'/v2/fake4/os-quota-class-sets/test_class') '/v2/fake4/os-quota-class-sets/test_class')
@@ -120,6 +132,8 @@ class QuotaTemplateXMLSerializerTest(test.TestCase):
floating_ips=60, floating_ips=60,
instances=70, instances=70,
injected_files=80, injected_files=80,
security_groups=10,
security_group_rules=20,
cores=90)) cores=90))
text = self.serializer.serialize(exemplar) text = self.serializer.serialize(exemplar)
@@ -144,6 +158,8 @@ class QuotaTemplateXMLSerializerTest(test.TestCase):
floating_ips='60', floating_ips='60',
instances='70', instances='70',
injected_files='80', injected_files='80',
security_groups='10',
security_group_rules='20',
cores='90')) cores='90'))
intext = ("<?xml version='1.0' encoding='UTF-8'?>\n" intext = ("<?xml version='1.0' encoding='UTF-8'?>\n"
'<quota_class_set>' '<quota_class_set>'
@@ -157,6 +173,8 @@ class QuotaTemplateXMLSerializerTest(test.TestCase):
'<instances>70</instances>' '<instances>70</instances>'
'<injected_files>80</injected_files>' '<injected_files>80</injected_files>'
'<cores>90</cores>' '<cores>90</cores>'
'<security_groups>10</security_groups>'
'<security_group_rules>20</security_group_rules>'
'</quota_class_set>') '</quota_class_set>')
result = self.deserializer.deserialize(intext)['body'] result = self.deserializer.deserialize(intext)['body']

View File

@@ -28,7 +28,8 @@ def quota_set(id):
return {'quota_set': {'id': id, 'metadata_items': 128, 'volumes': 10, return {'quota_set': {'id': id, 'metadata_items': 128, 'volumes': 10,
'gigabytes': 1000, 'ram': 51200, 'floating_ips': 10, 'gigabytes': 1000, 'ram': 51200, 'floating_ips': 10,
'instances': 10, 'injected_files': 5, 'cores': 20, 'instances': 10, 'injected_files': 5, 'cores': 20,
'injected_file_content_bytes': 10240}} 'injected_file_content_bytes': 10240,
'security_groups': 10, 'security_group_rules': 20}}
class QuotaSetsTest(test.TestCase): class QuotaSetsTest(test.TestCase):
@@ -47,7 +48,10 @@ class QuotaSetsTest(test.TestCase):
'metadata_items': 128, 'metadata_items': 128,
'gigabytes': 1000, 'gigabytes': 1000,
'injected_files': 5, 'injected_files': 5,
'injected_file_content_bytes': 10240} 'injected_file_content_bytes': 10240,
'security_groups': 10,
'security_group_rules': 20,
}
quota_set = self.controller._format_quota_set('1234', raw_quota_set) quota_set = self.controller._format_quota_set('1234', raw_quota_set)
qs = quota_set['quota_set'] qs = quota_set['quota_set']
@@ -62,6 +66,8 @@ class QuotaSetsTest(test.TestCase):
self.assertEqual(qs['metadata_items'], 128) self.assertEqual(qs['metadata_items'], 128)
self.assertEqual(qs['injected_files'], 5) self.assertEqual(qs['injected_files'], 5)
self.assertEqual(qs['injected_file_content_bytes'], 10240) self.assertEqual(qs['injected_file_content_bytes'], 10240)
self.assertEqual(qs['security_groups'], 10)
self.assertEqual(qs['security_group_rules'], 20)
def test_quotas_defaults(self): def test_quotas_defaults(self):
uri = '/v2/fake_tenant/os-quota-sets/fake_tenant/defaults' uri = '/v2/fake_tenant/os-quota-sets/fake_tenant/defaults'
@@ -79,7 +85,10 @@ class QuotaSetsTest(test.TestCase):
'floating_ips': 10, 'floating_ips': 10,
'metadata_items': 128, 'metadata_items': 128,
'injected_files': 5, 'injected_files': 5,
'injected_file_content_bytes': 10240}} 'injected_file_content_bytes': 10240,
'security_groups': 10,
'security_group_rules': 20,
}}
self.assertEqual(res_dict, expected) self.assertEqual(res_dict, expected)
@@ -100,7 +109,9 @@ class QuotaSetsTest(test.TestCase):
'ram': 51200, 'volumes': 10, 'ram': 51200, 'volumes': 10,
'gigabytes': 1000, 'floating_ips': 10, 'gigabytes': 1000, 'floating_ips': 10,
'metadata_items': 128, 'injected_files': 5, 'metadata_items': 128, 'injected_files': 5,
'injected_file_content_bytes': 10240}} 'injected_file_content_bytes': 10240,
'security_groups': 10,
'security_group_rules': 20}}
req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me', req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me',
use_admin_context=True) use_admin_context=True)
@@ -113,7 +124,9 @@ class QuotaSetsTest(test.TestCase):
'ram': 51200, 'volumes': 10, 'ram': 51200, 'volumes': 10,
'gigabytes': 1000, 'floating_ips': 10, 'gigabytes': 1000, 'floating_ips': 10,
'metadata_items': 128, 'injected_files': 5, 'metadata_items': 128, 'injected_files': 5,
'injected_file_content_bytes': 10240}} 'injected_file_content_bytes': 10240,
'security_groups': 10,
'security_group_rules': 20}}
req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me') req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me')
self.assertRaises(webob.exc.HTTPForbidden, self.controller.update, self.assertRaises(webob.exc.HTTPForbidden, self.controller.update,
@@ -149,6 +162,8 @@ class QuotaXMLSerializerTest(test.TestCase):
floating_ips=60, floating_ips=60,
instances=70, instances=70,
injected_files=80, injected_files=80,
security_groups=10,
security_group_rules=20,
cores=90)) cores=90))
text = self.serializer.serialize(exemplar) text = self.serializer.serialize(exemplar)
@@ -172,6 +187,8 @@ class QuotaXMLSerializerTest(test.TestCase):
floating_ips='60', floating_ips='60',
instances='70', instances='70',
injected_files='80', injected_files='80',
security_groups='10',
security_group_rules='20',
cores='90')) cores='90'))
intext = ("<?xml version='1.0' encoding='UTF-8'?>\n" intext = ("<?xml version='1.0' encoding='UTF-8'?>\n"
'<quota_set>' '<quota_set>'
@@ -184,6 +201,8 @@ class QuotaXMLSerializerTest(test.TestCase):
'<floating_ips>60</floating_ips>' '<floating_ips>60</floating_ips>'
'<instances>70</instances>' '<instances>70</instances>'
'<injected_files>80</injected_files>' '<injected_files>80</injected_files>'
'<security_groups>10</security_groups>'
'<security_group_rules>20</security_group_rules>'
'<cores>90</cores>' '<cores>90</cores>'
'</quota_set>') '</quota_set>')

View File

@@ -25,12 +25,15 @@ from nova.api.openstack.compute.contrib import security_groups
from nova.api.openstack import wsgi from nova.api.openstack import wsgi
import nova.db import nova.db
from nova import exception from nova import exception
from nova import flags
from nova import test from nova import test
from nova.tests.api.openstack import fakes from nova.tests.api.openstack import fakes
FAKE_UUID = 'a47ae74e-ab08-447f-8eee-ffd43fc46c16' FAKE_UUID = 'a47ae74e-ab08-447f-8eee-ffd43fc46c16'
FLAGS = flags.FLAGS
class AttrDict(dict): class AttrDict(dict):
def __getattr__(self, k): def __getattr__(self, k):
@@ -219,6 +222,18 @@ class TestSecurityGroups(test.TestCase):
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
req, {'security_group': sg}) req, {'security_group': sg})
def test_create_security_group_quota_limit(self):
req = fakes.HTTPRequest.blank('/v2/fake/os-security-groups')
for num in range(1, FLAGS.quota_security_groups):
name = 'test%s' % num
sg = security_group_template(name=name)
res_dict = self.controller.create(req, {'security_group': sg})
self.assertEqual(res_dict['security_group']['name'], name)
sg = security_group_template()
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
req, {'security_group': sg})
def test_get_security_group_list(self): def test_get_security_group_list(self):
groups = [] groups = []
for i, name in enumerate(['default', 'test']): for i, name in enumerate(['default', 'test']):
@@ -894,6 +909,22 @@ class TestSecurityGroupRules(test.TestCase):
self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete, self.assertRaises(webob.exc.HTTPNotFound, self.controller.delete,
req, '22222222222222') req, '22222222222222')
def test_create_rule_quota_limit(self):
req = fakes.HTTPRequest.blank('/v2/fake/os-security-group-rules')
for num in range(100, 100 + FLAGS.quota_security_group_rules):
rule = {
'ip_protocol': 'tcp', 'from_port': num,
'to_port': num, 'parent_group_id': '2', 'group_id': '1'
}
self.controller.create(req, {'security_group_rule': rule})
rule = {
'ip_protocol': 'tcp', 'from_port': '121', 'to_port': '121',
'parent_group_id': '2', 'group_id': '1'
}
self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create,
req, {'security_group_rule': rule})
class TestSecurityGroupRulesXMLDeserializer(unittest.TestCase): class TestSecurityGroupRulesXMLDeserializer(unittest.TestCase):

View File

@@ -41,6 +41,8 @@ class GetQuotaTestCase(test.TestCase):
quota_volumes=10, quota_volumes=10,
quota_gigabytes=1000, quota_gigabytes=1000,
quota_floating_ips=10, quota_floating_ips=10,
quota_security_groups=10,
quota_security_group_rules=20,
quota_metadata_items=128, quota_metadata_items=128,
quota_injected_files=5, quota_injected_files=5,
quota_injected_file_content_bytes=10 * 1024) quota_injected_file_content_bytes=10 * 1024)
@@ -57,6 +59,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=5, volumes=5,
gigabytes=500, gigabytes=500,
floating_ips=5, floating_ips=5,
quota_security_groups=10,
quota_security_group_rules=20,
metadata_items=64, metadata_items=64,
injected_files=2, injected_files=2,
injected_file_content_bytes=5 * 1024, injected_file_content_bytes=5 * 1024,
@@ -78,6 +82,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=2, volumes=2,
gigabytes=250, gigabytes=250,
floating_ips=2, floating_ips=2,
security_groups=5,
security_group_rules=10,
metadata_items=32, metadata_items=32,
injected_files=1, injected_files=1,
injected_file_content_bytes=2 * 1024, injected_file_content_bytes=2 * 1024,
@@ -97,6 +103,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=10, volumes=10,
gigabytes=1000, gigabytes=1000,
floating_ips=10, floating_ips=10,
security_groups=10,
security_group_rules=20,
metadata_items=128, metadata_items=128,
injected_files=5, injected_files=5,
injected_file_content_bytes=10 * 1024, injected_file_content_bytes=10 * 1024,
@@ -109,6 +117,8 @@ class GetQuotaTestCase(test.TestCase):
quota_volumes=-1, quota_volumes=-1,
quota_gigabytes=-1, quota_gigabytes=-1,
quota_floating_ips=-1, quota_floating_ips=-1,
quota_security_groups=-1,
quota_security_group_rules=-1,
quota_metadata_items=-1, quota_metadata_items=-1,
quota_injected_files=-1, quota_injected_files=-1,
quota_injected_file_content_bytes=-1) quota_injected_file_content_bytes=-1)
@@ -120,6 +130,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=-1, volumes=-1,
gigabytes=-1, gigabytes=-1,
floating_ips=-1, floating_ips=-1,
security_groups=-1,
security_group_rules=-1,
metadata_items=-1, metadata_items=-1,
injected_files=-1, injected_files=-1,
injected_file_content_bytes=-1, injected_file_content_bytes=-1,
@@ -135,6 +147,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=10, volumes=10,
gigabytes=1000, gigabytes=1000,
floating_ips=10, floating_ips=10,
security_groups=10,
security_group_rules=20,
metadata_items=128, metadata_items=128,
injected_files=5, injected_files=5,
injected_file_content_bytes=10 * 1024, injected_file_content_bytes=10 * 1024,
@@ -150,6 +164,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=5, volumes=5,
gigabytes=500, gigabytes=500,
floating_ips=5, floating_ips=5,
security_groups=10,
security_group_rules=20,
metadata_items=64, metadata_items=64,
injected_files=2, injected_files=2,
injected_file_content_bytes=5 * 1024, injected_file_content_bytes=5 * 1024,
@@ -166,6 +182,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=10, volumes=10,
gigabytes=1000, gigabytes=1000,
floating_ips=10, floating_ips=10,
security_groups=10,
security_group_rules=20,
metadata_items=128, metadata_items=128,
injected_files=5, injected_files=5,
injected_file_content_bytes=10 * 1024, injected_file_content_bytes=10 * 1024,
@@ -182,6 +200,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=2, volumes=2,
gigabytes=250, gigabytes=250,
floating_ips=2, floating_ips=2,
security_groups=5,
security_group_rules=10,
metadata_items=32, metadata_items=32,
injected_files=1, injected_files=1,
injected_file_content_bytes=2 * 1024, injected_file_content_bytes=2 * 1024,
@@ -199,6 +219,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=5, volumes=5,
gigabytes=500, gigabytes=500,
floating_ips=5, floating_ips=5,
security_groups=10,
security_group_rules=20,
metadata_items=64, metadata_items=64,
injected_files=2, injected_files=2,
injected_file_content_bytes=5 * 1024, injected_file_content_bytes=5 * 1024,
@@ -216,6 +238,8 @@ class GetQuotaTestCase(test.TestCase):
volumes=2, volumes=2,
gigabytes=250, gigabytes=250,
floating_ips=2, floating_ips=2,
security_groups=5,
security_group_rules=10,
metadata_items=32, metadata_items=32,
injected_files=1, injected_files=1,
injected_file_content_bytes=2 * 1024, injected_file_content_bytes=2 * 1024,
@@ -404,6 +428,34 @@ class QuotaTestCase(test.TestCase):
floating_ips = quota.allowed_floating_ips(self.context, 101) floating_ips = quota.allowed_floating_ips(self.context, 101)
self.assertEqual(floating_ips, 101) self.assertEqual(floating_ips, 101)
def test_unlimited_security_groups(self):
self.flags(quota_security_groups=10)
security_groups = quota.allowed_security_groups(self.context, 100)
self.assertEqual(security_groups, 10)
db.quota_create(self.context, self.project_id, 'security_groups', -1)
security_groups = quota.allowed_security_groups(self.context, 100)
self.assertEqual(security_groups, 100)
security_groups = quota.allowed_security_groups(self.context, 101)
self.assertEqual(security_groups, 101)
def test_unlimited_security_group_rules(self):
def fake_security_group_rule_count_by_group(context, sec_group_id):
return 0
self.stubs.Set(db, 'security_group_rule_count_by_group',
fake_security_group_rule_count_by_group)
self.flags(quota_security_group_rules=20)
rules = quota.allowed_security_group_rules(self.context, 1234, 100)
self.assertEqual(rules, 20)
db.quota_create(self.context, self.project_id, 'security_group_rules',
-1)
rules = quota.allowed_security_group_rules(self.context, 1234, 100)
self.assertEqual(rules, 100)
rules = quota.allowed_security_group_rules(self.context, 1234, 101)
self.assertEqual(rules, 101)
def test_unlimited_metadata_items(self): def test_unlimited_metadata_items(self):
self.flags(quota_metadata_items=10) self.flags(quota_metadata_items=10)
items = quota.allowed_metadata_items(self.context, 100) items = quota.allowed_metadata_items(self.context, 100)