]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Make NeutronDbObjectDuplicateEntry exception more verbose
authorMiguel Angel Ajo <mangelajo@redhat.com>
Wed, 19 Aug 2015 13:15:21 +0000 (15:15 +0200)
committerMiguel Angel Ajo <mangelajo@redhat.com>
Mon, 24 Aug 2015 10:00:38 +0000 (12:00 +0200)
NeutronObjectDuplicateEntry is an exception derived from Conflict,
which is mapped to HTTPConflict. When such exception is thrown
during an API layer call, we will provide more detail to the caller
about what was exactly duplicated, and for which fields,
the information is extracted from the DB exception.

NeutronObjectDuplicateEntry is renamed into NeutronDbObjectDuplicate
to make clear it is for handling db duplicate exceptions, in
the future we could generalize to a base NeutronObjectDuplicate class
if we need separate handling for other object backings (mem, keystore,
etc).

Change-Id: I6ec5883b3456ebc842f3f7bffd8cc924293f5766

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

index c4bb98f5672aa811b83aea28e35c9060088549a4..371fd896d1349600c59a5542c48980b283d40732 100644 (file)
@@ -13,6 +13,7 @@
 import abc
 
 from oslo_db import exception as obj_exc
+from oslo_utils import reflection
 from oslo_versionedobjects import base as obj_base
 import six
 
@@ -24,8 +25,16 @@ 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")
+class NeutronDbObjectDuplicateEntry(exceptions.Conflict):
+    message = _("Failed to create a duplicate %(object_type)s: "
+                "for attribute(s) %(attributes)s with value(s) %(values)s")
+
+    def __init__(self, object_class, db_exception):
+        super(NeutronDbObjectDuplicateEntry, self).__init__(
+            object_type=reflection.get_class_name(object_class,
+                                                  fully_qualified=False),
+            attributes=db_exception.columns,
+            values=db_exception.value)
 
 
 def get_updatable_fields(cls, fields):
@@ -139,8 +148,10 @@ class NeutronDbObject(NeutronObject):
         fields = self._get_changed_persistent_fields()
         try:
             db_obj = db_api.create_object(self._context, self.db_model, fields)
-        except obj_exc.DBDuplicateEntry:
-            raise NeutronObjectDuplicateEntry()
+        except obj_exc.DBDuplicateEntry as db_exc:
+            raise NeutronDbObjectDuplicateEntry(object_class=self.__class__,
+                                                db_exception=db_exc)
+
         self.from_db_object(db_obj)
 
     def update(self):
index 381ff8b29fc3f480eeab1b307d53e20e03d8bd1a..d447b37ae757469bd04f68bd020c03e8b52f3337 100644 (file)
@@ -215,7 +215,7 @@ class BaseObjectIfaceTestCase(_BaseObjectTestCase, test_base.BaseTestCase):
         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)
+            self.assertRaises(base.NeutronDbObjectDuplicateEntry, obj.create)
 
     @mock.patch.object(db_api, 'update_object')
     def test_update_no_changes(self, update_mock):