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
f0bd2ddb40
commit
6a5b3f4dd6
@ -442,11 +442,10 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
||||
{'ip_address': ip_address,
|
||||
'network_id': network_id,
|
||||
'subnet_id': subnet_id})
|
||||
alloc_qry = context.session.query(
|
||||
models_v2.IPAllocation).with_lockmode('update')
|
||||
alloc_qry.filter_by(network_id=network_id,
|
||||
ip_address=ip_address,
|
||||
subnet_id=subnet_id).delete()
|
||||
context.session.query(models_v2.IPAllocation).filter_by(
|
||||
network_id=network_id,
|
||||
ip_address=ip_address,
|
||||
subnet_id=subnet_id).delete()
|
||||
|
||||
@staticmethod
|
||||
def _generate_ip(context, subnets):
|
||||
@ -990,8 +989,10 @@ class NeutronDbPluginV2(neutron_plugin_base_v2.NeutronPluginBaseV2,
|
||||
with context.session.begin(subtransactions=True):
|
||||
network = self._get_network(context, id)
|
||||
|
||||
filter = {'network_id': [id]}
|
||||
ports = self.get_ports(context, filters=filter)
|
||||
filters = {'network_id': [id]}
|
||||
# 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
|
||||
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)
|
||||
# Check if any tenant owned ports are using this subnet
|
||||
allocated_qry = context.session.query(models_v2.IPAllocation)
|
||||
allocated_qry = allocated_qry.options(orm.joinedload('ports'))
|
||||
allocated = allocated_qry.filter_by(subnet_id=id)
|
||||
|
||||
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)
|
||||
allocated_qry = allocated_qry.join(models_v2.Port)
|
||||
allocated = allocated_qry.filter_by(
|
||||
network_id=subnet.network_id).with_lockmode('update')
|
||||
|
||||
# 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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user