]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Gracefully handle duplicate rule creation
authorJohn Schwarz <jschwarz@redhat.com>
Mon, 3 Aug 2015 15:33:44 +0000 (18:33 +0300)
committerIhar Hrachyshka <ihrachys@redhat.com>
Wed, 5 Aug 2015 15:28:17 +0000 (17:28 +0200)
Previously, creating a second bandwidth limit rule for a policy raised
an uncaught exception, which eventually caused 'ServerFault' on the
client side. This patch replaces this exception with a NeutronException
which leads to a more correct 'Conflict' error instead.

Note that the code is implemented in the base object class. This means
that future versioned objects will also feature this restriction if
their database implies that no duplicate entries can be created.

Change-Id: I882d60843e1e651f3f9754746ac670f499431466
Partially-Implements: quantum-qos-api

neutron/objects/base.py
neutron/tests/api/test_qos.py
neutron/tests/unit/objects/test_base.py

index 5339fce2741654bd452026d5beedb588837c2924..f10966106baa61e5dd5b371e357659ea1494cd52 100644 (file)
@@ -12,6 +12,7 @@
 
 import abc
 
+from oslo_db import exception as obj_exc
 from oslo_versionedobjects import base as obj_base
 import six
 
@@ -23,6 +24,10 @@ class NeutronObjectUpdateForbidden(exceptions.NeutronException):
     message = _("Unable to update the following object fields: %(fields)s")
 
 
+class NeutronObjectDuplicateEntry(exceptions.Conflict):
+    message = _("Failed to create a duplicate object")
+
+
 def get_updatable_fields(cls, fields):
     fields = fields.copy()
     for field in cls.fields_no_update:
@@ -116,7 +121,10 @@ class NeutronDbObject(NeutronObject):
 
     def create(self):
         fields = self._get_changed_persistent_fields()
-        db_obj = db_api.create_object(self._context, self.db_model, fields)
+        try:
+            db_obj = db_api.create_object(self._context, self.db_model, fields)
+        except obj_exc.DBDuplicateEntry:
+            raise NeutronObjectDuplicateEntry()
         self.from_db_object(db_obj)
 
     def update(self):
index 7a0f027663c70e03368c66b0b3af3cdedf0e051d..453b85387ff7f242a66491957464aa0d26a9a939 100644 (file)
@@ -298,7 +298,7 @@ class QosBandwidthLimitRuleTestJSON(base.BaseAdminNetworkTest):
                                              max_kbps=200,
                                              max_burst_kbps=1337)
 
-        self.assertRaises(exceptions.ServerFault,
+        self.assertRaises(exceptions.Conflict,
                           self.create_qos_bandwidth_limit_rule,
                           policy_id=policy['id'],
                           max_kbps=201, max_burst_kbps=1338)
index 7f8be5b89b84c484ec957dc426cf1a2ea25aa582..84bdb13be233ed50b9cc3db16e91e46409b6f74e 100644 (file)
@@ -14,6 +14,7 @@ import random
 import string
 
 import mock
+from oslo_db import exception as obj_exc
 from oslo_versionedobjects import base as obj_base
 from oslo_versionedobjects import fields as obj_fields
 
@@ -154,6 +155,12 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
             obj.create()
             self._check_equal(obj, self.db_obj)
 
+    def test_create_duplicates(self):
+        with mock.patch.object(db_api, 'create_object',
+                               side_effect=obj_exc.DBDuplicateEntry):
+            obj = self._test_class(self.context, **self.db_obj)
+            self.assertRaises(base.NeutronObjectDuplicateEntry, obj.create)
+
     @mock.patch.object(db_api, 'update_object')
     def test_update_no_changes(self, update_mock):
         with mock.patch.object(base.NeutronDbObject,