Ensure bulk creations have quota validations

Fixes bug 1093749

The patch set also returns a proper error instead of a internal server
error when the quotas are reached.

Change-Id: Ifc74ffa8b54faa70f5558bf5263830f5e71f58ae
This commit is contained in:
Gary Kotton 2012-12-26 07:24:37 +00:00
parent 5e4368b32f
commit 164db207fd
2 changed files with 73 additions and 4 deletions

View File

@ -49,6 +49,7 @@ FAULT_MAP = {exceptions.NotFound: webob.exc.HTTPNotFound,
AttributeError: webob.exc.HTTPBadRequest,
ValueError: webob.exc.HTTPBadRequest,
exceptions.IpAddressGenerationFailure: webob.exc.HTTPConflict,
exceptions.OverQuota: webob.exc.HTTPConflict,
}
QUOTAS = quota.QUOTAS
@ -293,8 +294,11 @@ class Controller(object):
if self._collection in body:
# Have to account for bulk create
items = body[self._collection]
deltas = {}
bulk = True
else:
items = [body]
bulk = False
for item in items:
self._validate_network_tenant_ownership(request,
item[self._resource])
@ -303,10 +307,16 @@ class Controller(object):
item[self._resource],
plugin=self._plugin)
try:
tenant_id = item[self._resource]['tenant_id']
count = QUOTAS.count(request.context, self._resource,
self._plugin, self._collection,
item[self._resource]['tenant_id'])
kwargs = {self._resource: count + 1}
tenant_id)
if bulk:
delta = deltas.get(tenant_id, 0) + 1
deltas[tenant_id] = delta
else:
delta = 1
kwargs = {self._resource: count + delta}
except exceptions.QuotaResourceUnknown as e:
# We don't want to quota this resource
LOG.debug(e)

View File

@ -172,6 +172,21 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
data = self._deserializers[ctype].deserialize(response.body)['body']
return data
def _create_bulk_from_list(self, fmt, resource, objects, **kwargs):
""" Creates a bulk request from a list of objects """
collection = "%ss" % resource
req_data = {collection: objects}
req = self.new_create_request(collection, req_data, fmt)
if ('set_context' in kwargs and
kwargs['set_context'] is True and
'tenant_id' in kwargs):
# create a specific auth context for this request
req.environ['quantum.context'] = context.Context(
'', kwargs['tenant_id'])
elif 'context' in kwargs:
req.environ['quantum.context'] = kwargs['context']
return req.get_response(self.api)
def _create_bulk(self, fmt, number, resource, data, name='test', **kwargs):
""" Creates a bulk request for any kind of resource """
objects = []
@ -386,8 +401,8 @@ class QuantumDbPluginV2TestCase(unittest2.TestCase):
patched_plugin.side_effect = second_call
return orig(*args, **kwargs)
def _validate_behavior_on_bulk_failure(self, res, collection):
self.assertEqual(res.status_int, 400)
def _validate_behavior_on_bulk_failure(self, res, collection, errcode=400):
self.assertEqual(res.status_int, errcode)
req = self.new_list_request(collection)
res = req.get_response(self.api)
self.assertEqual(res.status_int, 200)
@ -1621,6 +1636,50 @@ class TestNetworksV2(QuantumDbPluginV2TestCase):
res = self._create_network_bulk('json', 2, 'test', True)
self._validate_behavior_on_bulk_success(res, 'networks')
def test_create_networks_bulk_native_quotas(self):
if self._skip_native_bulk:
self.skipTest("Plugin does not support native bulk network create")
quota = 4
cfg.CONF.set_override('quota_network', quota, group='QUOTAS')
res = self._create_network_bulk('json', quota + 1, 'test', True)
self._validate_behavior_on_bulk_failure(res, 'networks', errcode=409)
def test_create_networks_bulk_tenants_and_quotas(self):
if self._skip_native_bulk:
self.skipTest("Plugin does not support native bulk network create")
quota = 2
cfg.CONF.set_override('quota_network', quota, group='QUOTAS')
networks = [{'network': {'name': 'n1',
'tenant_id': self._tenant_id}},
{'network': {'name': 'n2',
'tenant_id': self._tenant_id}},
{'network': {'name': 'n1',
'tenant_id': 't1'}},
{'network': {'name': 'n2',
'tenant_id': 't1'}}]
res = self._create_bulk_from_list('json', 'network', networks)
self.assertEqual(res.status_int, 201)
def test_create_networks_bulk_tenants_and_quotas_fail(self):
if self._skip_native_bulk:
self.skipTest("Plugin does not support native bulk network create")
quota = 2
cfg.CONF.set_override('quota_network', quota, group='QUOTAS')
networks = [{'network': {'name': 'n1',
'tenant_id': self._tenant_id}},
{'network': {'name': 'n2',
'tenant_id': self._tenant_id}},
{'network': {'name': 'n1',
'tenant_id': 't1'}},
{'network': {'name': 'n3',
'tenant_id': self._tenant_id}},
{'network': {'name': 'n2',
'tenant_id': 't1'}}]
res = self._create_bulk_from_list('json', 'network', networks)
self.assertEqual(res.status_int, 409)
def test_create_networks_bulk_emulated(self):
real_has_attr = hasattr