]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Retry port status update on StaleDataError
authorKevin Benton <blak111@gmail.com>
Tue, 16 Jun 2015 06:10:09 +0000 (23:10 -0700)
committerKevin Benton <blak111@gmail.com>
Mon, 22 Jun 2015 03:14:42 +0000 (20:14 -0700)
During update_port_status, a port may be concurrently updated/deleted
by another process, which will result in a StaleDataError being
thrown. In the event it was an update, we want to retry to make sure
the port status is set to the desired state so third parties like Nova
get notified.

This patch uses the oslo_db wrap_db_retry decorator after converting
the StaleDataError into a RetryRequest that the decorator can catch.

Closes-Bug: #1465407
Change-Id: I0a9230d30f435ec3d48f033136e85c40ad489ef9

neutron/db/api.py
neutron/plugins/ml2/plugin.py

index 3a2752ae1bcc292bdb896f08e080adfad89ef549..0b68bd3310ad508d9e4983e5ddc3fadae0d5acc4 100644 (file)
 #    under the License.
 
 import contextlib
+import six
 
 from oslo_config import cfg
+from oslo_db import exception as os_db_exception
 from oslo_db.sqlalchemy import session
 from sqlalchemy import exc
+from sqlalchemy import orm
 
 
 _FACADE = None
@@ -64,3 +67,21 @@ def autonested_transaction(sess):
     finally:
         with session_context as tx:
             yield tx
+
+
+class convert_db_exception_to_retry(object):
+    """Converts other types of DB exceptions into RetryRequests."""
+
+    def __init__(self, stale_data=False):
+        self.to_catch = ()
+        if stale_data:
+            self.to_catch += (orm.exc.StaleDataError, )
+
+    def __call__(self, f):
+        @six.wraps(f)
+        def wrapper(*args, **kwargs):
+            try:
+                return f(*args, **kwargs)
+            except self.to_catch as e:
+                raise os_db_exception.RetryRequest(e)
+        return wrapper
index 2cf2ec80f4501c49416da146e443f0839038d7ed..00cd60a476d1526bbcc73592a7a1ccb138748324 100644 (file)
@@ -1376,7 +1376,9 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
         return self._bind_port_if_needed(port_context)
 
     @oslo_db_api.wrap_db_retry(max_retries=db_api.MAX_RETRIES,
-                               retry_on_deadlock=True)
+                               retry_on_deadlock=True,
+                               retry_on_request=True)
+    @db_api.convert_db_exception_to_retry(stale_data=True)
     def update_port_status(self, context, port_id, status, host=None,
                            network=None):
         """