]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Reorder operations in create_vip
authorEugene Nikanorov <enikanorov@mirantis.com>
Wed, 13 Aug 2014 11:10:45 +0000 (15:10 +0400)
committerEugene Nikanorov <enikanorov@mirantis.com>
Tue, 19 Aug 2014 01:32:44 +0000 (05:32 +0400)
Previously VIP's port creation was moved outside the transaction
to avoid deadlocks related to rpc calls.
It led to small chance of VIP being fetched by rpc code with
port being still None.

This patch reorders VIP association with the pool so it's done
only after port has been created.

This patch also leaves small possibility of uncaught exception in
case of pool being concurrently deleted in the process of VIP creation

Change-Id: I584558aecc92db4d19fb72b1d006868b840a4d8c
Closes-Bug: #1356227

neutron/db/loadbalancer/loadbalancer_db.py

index b9ed1a5f179b52d4a928552ccd5a61c0d6c8456d..1baffc1bcd12532c3458f27e1e90612dd8ee5d92 100644 (file)
@@ -232,7 +232,10 @@ class LoadBalancerPluginDb(loadbalancer.LoadBalancerPluginBase,
     ########################################################
     # VIP DB access
     def _make_vip_dict(self, vip, fields=None):
-        fixed_ip = (vip.port.fixed_ips or [{}])[0]
+        fixed_ip = {}
+        # it's possible that vip doesn't have created port yet
+        if vip.port:
+            fixed_ip = (vip.port.fixed_ips or [{}])[0]
 
         res = {'id': vip['id'],
                'tenant_id': vip['tenant_id'],
@@ -358,9 +361,6 @@ class LoadBalancerPluginDb(loadbalancer.LoadBalancerPluginBase,
                 if pool['status'] == constants.PENDING_DELETE:
                     raise loadbalancer.StateInvalid(state=pool['status'],
                                                     id=pool['id'])
-            else:
-                pool = None
-
             vip_db = Vip(id=uuidutils.generate_uuid(),
                          tenant_id=tenant_id,
                          name=v['name'],
@@ -386,8 +386,6 @@ class LoadBalancerPluginDb(loadbalancer.LoadBalancerPluginBase,
                 context.session.flush()
             except exception.DBDuplicateEntry:
                 raise loadbalancer.VipExists(pool_id=v['pool_id'])
-            if pool:
-                pool['vip_id'] = vip_db['id']
 
         try:
             # create a port to reserve address for IPAM
@@ -398,10 +396,18 @@ class LoadBalancerPluginDb(loadbalancer.LoadBalancerPluginBase,
             # catch any kind of exceptions
             with excutils.save_and_reraise_exception():
                 context.session.delete(vip_db)
-                if pool:
-                    pool['vip_id'] = None
                 context.session.flush()
 
+        if v['pool_id']:
+            # fetching pool again
+            pool = self._get_resource(context, Pool, v['pool_id'])
+            # (NOTE): we rely on the fact that pool didn't change between
+            # above block and here
+            vip_db['pool_id'] = v['pool_id']
+            pool['vip_id'] = vip_db['id']
+            # explicitly flush changes as we're outside any transaction
+            context.session.flush()
+
         return self._make_vip_dict(vip_db)
 
     def update_vip(self, context, id, vip):