From b592d39d61392df01667de6b80b483bd04bb86a7 Mon Sep 17 00:00:00 2001 From: Eugene Nikanorov Date: Wed, 13 Aug 2014 15:10:45 +0400 Subject: [PATCH] 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 --- neutron/db/loadbalancer/loadbalancer_db.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/neutron/db/loadbalancer/loadbalancer_db.py b/neutron/db/loadbalancer/loadbalancer_db.py index b9ed1a5f17..1baffc1bcd 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):