]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Ensure bulk creations have quota validations
authorGary Kotton <gkotton@redhat.com>
Wed, 26 Dec 2012 07:24:37 +0000 (07:24 +0000)
committerGary Kotton <gkotton@redhat.com>
Thu, 27 Dec 2012 09:22:33 +0000 (09:22 +0000)
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

quantum/api/v2/base.py
quantum/tests/unit/test_db_plugin.py

index ad3caa588403b807a34279c04e3d8ec8bb8565dd..c70509577d7234218105ffdb214c939b0b432ac1 100644 (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)
index 65e0823c69b89624cc2c6efe6a1ec067ab79cb3d..284fd228519fe99092bb6a51d5f0cf0a34264dfe 100644 (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