Catch DBReferenceError in IPAM and convert to SubnetNotFound

If a subnet is removed after lookup but before IP allocation
insert, we can end up getting a DBReferenceError in the IPAM
system. Since this can occur on any flush we force a flush
with a session context manager to get the DBReference error
in a desired spot (in multi-writer galera this is a deadlock
much later, which we retry). We then convert it to SubnetNotFound,
which is an expected exception.

Closes-Bug: #1623402
Change-Id: I65632b174f8692cd465c721e285526827842a740
This commit is contained in:
Kevin Benton 2016-09-13 20:23:42 -07:00
parent 33afa82517
commit a397792ff7

View File

@ -18,6 +18,7 @@ import random
import netaddr
from neutron_lib import exceptions as n_exc
from oslo_db import exception as db_exc
from oslo_log import log
from oslo_utils import uuidutils
@ -203,7 +204,16 @@ class NeutronDbSubnet(ipam_base.Subnet):
# Create IP allocation request object
# The only defined status at this stage is 'ALLOCATED'.
# More states will be available in the future - e.g.: RECYCLABLE
self.subnet_manager.create_allocation(session, ip_address)
try:
with session.begin(subtransactions=True):
# NOTE(kevinbenton): we use a subtransaction to force
# a flush here so we can capture DBReferenceErrors due
# to concurrent subnet deletions. (galera would deadlock
# later on final commit)
self.subnet_manager.create_allocation(session, ip_address)
except db_exc.DBReferenceError:
raise n_exc.SubnetNotFound(
subnet_id=self.subnet_manager.neutron_id)
return ip_address
def deallocate(self, address):