Avoid dhcp agent race condition on subnet and network delete
Ensure that ports that are about to be deleted are 'selected for update'. By doing so, we avoid a race condition between subnet and network delete operations carried out by two separate server instances. A race caused by the dhcp agent deleting the DHCP port (caused by a subnet-delete event notification) can still occur and will be addressed in a subsequent patch. delete_subnet's way to delete ports has been tweaked to ensure that postgres db can handle the SELECT FOR UPDATE correctly. Partial-Bug:1197627 Change-Id: I5bd75a758395a2faeff9db35a03c42dfa8ae0eab
This commit is contained in:
parent
83965eb9f2
commit
8b20fb88f9
@ -442,9 +442,8 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
{'ip_address': ip_address,
|
{'ip_address': ip_address,
|
||||||
'network_id': network_id,
|
'network_id': network_id,
|
||||||
'subnet_id': subnet_id})
|
'subnet_id': subnet_id})
|
||||||
alloc_qry = context.session.query(
|
context.session.query(models_v2.IPAllocation).filter_by(
|
||||||
models_v2.IPAllocation).with_lockmode('update')
|
network_id=network_id,
|
||||||
alloc_qry.filter_by(network_id=network_id,
|
|
||||||
ip_address=ip_address,
|
ip_address=ip_address,
|
||||||
subnet_id=subnet_id).delete()
|
subnet_id=subnet_id).delete()
|
||||||
|
|
||||||
@ -990,8 +989,10 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
network = self._get_network(context, id)
|
network = self._get_network(context, id)
|
||||||
|
|
||||||
filter = {'network_id': [id]}
|
filters = {'network_id': [id]}
|
||||||
ports = self.get_ports(context, filters=filter)
|
# NOTE(armando-migliaccio): stick with base plugin
|
||||||
|
ports = self._get_ports_query(
|
||||||
|
context, filters=filters).with_lockmode('update')
|
||||||
|
|
||||||
# check if there are any tenant owned ports in-use
|
# check if there are any tenant owned ports in-use
|
||||||
only_auto_del = all(p['device_owner'] in AUTO_DELETE_PORT_OWNERS
|
only_auto_del = all(p['device_owner'] in AUTO_DELETE_PORT_OWNERS
|
||||||
@ -1266,17 +1267,17 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
|||||||
subnet = self._get_subnet(context, id)
|
subnet = self._get_subnet(context, id)
|
||||||
# Check if any tenant owned ports are using this subnet
|
# Check if any tenant owned ports are using this subnet
|
||||||
allocated_qry = context.session.query(models_v2.IPAllocation)
|
allocated_qry = context.session.query(models_v2.IPAllocation)
|
||||||
allocated_qry = allocated_qry.options(orm.joinedload('ports'))
|
allocated_qry = allocated_qry.join(models_v2.Port)
|
||||||
allocated = allocated_qry.filter_by(subnet_id=id)
|
allocated = allocated_qry.filter_by(
|
||||||
|
network_id=subnet.network_id).with_lockmode('update')
|
||||||
only_auto_del = all(not a.port_id or
|
|
||||||
a.ports.device_owner in AUTO_DELETE_PORT_OWNERS
|
|
||||||
for a in allocated)
|
|
||||||
if not only_auto_del:
|
|
||||||
raise q_exc.SubnetInUse(subnet_id=id)
|
|
||||||
|
|
||||||
# remove network owned ports
|
# remove network owned ports
|
||||||
allocated.delete()
|
for a in allocated:
|
||||||
|
if a.ports.device_owner in AUTO_DELETE_PORT_OWNERS:
|
||||||
|
NeutronDbPluginV2._delete_ip_allocation(
|
||||||
|
context, subnet.network_id, id, a.ip_address)
|
||||||
|
else:
|
||||||
|
raise q_exc.SubnetInUse(subnet_id=id)
|
||||||
|
|
||||||
context.session.delete(subnet)
|
context.session.delete(subnet)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user