From: Eugene Nikanorov Date: Wed, 13 Aug 2014 11:10:45 +0000 (+0400) Subject: Reorder operations in create_vip X-Git-Url: https://review.fuel-infra.org/gitweb?a=commitdiff_plain;h=65de01dcb1c49271ad1e5067d8dfd206788086d4;p=openstack-build%2Fneutron-build.git Reorder operations in create_vip 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 --- diff --git a/neutron/db/loadbalancer/loadbalancer_db.py b/neutron/db/loadbalancer/loadbalancer_db.py index b9ed1a5f1..1baffc1bc 100644 --- a/neutron/db/loadbalancer/loadbalancer_db.py +++ b/neutron/db/loadbalancer/loadbalancer_db.py @@ -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):