Remove locking from network and subnet delete op
delete_subnet in Ml2 plugin instead of using SELECT FOR UPDATE deletes the IPAllocations that can be auto-deleted straight away. An exception is raised if there are ports that cannot be autodeleted. delete_network in ML2 plugin tries to delete all ports and subnets before performing the network deletion. No lock is needed here - if some other process modifies the Port or Subnet table, adding new items, the network deletion will fail because of a violation of a foreign key contraint. In that case the operation will be retried. Change-Id: Ib4e9441a95d6c80b92a43d55fdeb18d7b51a1cf3 Closes-bug: #1332917
This commit is contained in:
parent
99534786ab
commit
89c24012d0
@ -576,11 +576,6 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
session = context.session
|
session = context.session
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
# REVISIT(rkukura): Its not clear that
|
|
||||||
# with_lockmode('update') is really needed in this
|
|
||||||
# transaction, and if not, the semaphore can also be
|
|
||||||
# removed.
|
|
||||||
#
|
|
||||||
# REVISIT: Serialize this operation with a semaphore
|
# REVISIT: Serialize this operation with a semaphore
|
||||||
# to prevent deadlock waiting to acquire a DB lock
|
# to prevent deadlock waiting to acquire a DB lock
|
||||||
# held by another thread in the same process, leading
|
# held by another thread in the same process, leading
|
||||||
@ -592,13 +587,14 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
# Additionally, a rollback may not be enough to undo the
|
# Additionally, a rollback may not be enough to undo the
|
||||||
# deletion of a floating IP with certain L3 backends.
|
# deletion of a floating IP with certain L3 backends.
|
||||||
self._process_l3_delete(context, id)
|
self._process_l3_delete(context, id)
|
||||||
|
# Using query().with_lockmode isn't necessary. Foreign-key
|
||||||
|
# constraints prevent deletion if concurrent creation happens.
|
||||||
with contextlib.nested(lockutils.lock('db-access'),
|
with contextlib.nested(lockutils.lock('db-access'),
|
||||||
session.begin(subtransactions=True)):
|
session.begin(subtransactions=True)):
|
||||||
# Get ports to auto-delete.
|
# Get ports to auto-delete.
|
||||||
ports = (session.query(models_v2.Port).
|
ports = (session.query(models_v2.Port).
|
||||||
enable_eagerloads(False).
|
enable_eagerloads(False).
|
||||||
filter_by(network_id=id).
|
filter_by(network_id=id).all())
|
||||||
with_lockmode('update').all())
|
|
||||||
LOG.debug("Ports to auto-delete: %s", ports)
|
LOG.debug("Ports to auto-delete: %s", ports)
|
||||||
only_auto_del = all(p.device_owner
|
only_auto_del = all(p.device_owner
|
||||||
in db_base_plugin_v2.
|
in db_base_plugin_v2.
|
||||||
@ -611,8 +607,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
# Get subnets to auto-delete.
|
# Get subnets to auto-delete.
|
||||||
subnets = (session.query(models_v2.Subnet).
|
subnets = (session.query(models_v2.Subnet).
|
||||||
enable_eagerloads(False).
|
enable_eagerloads(False).
|
||||||
filter_by(network_id=id).
|
filter_by(network_id=id).all())
|
||||||
with_lockmode('update').all())
|
|
||||||
LOG.debug("Subnets to auto-delete: %s", subnets)
|
LOG.debug("Subnets to auto-delete: %s", subnets)
|
||||||
|
|
||||||
if not (ports or subnets):
|
if not (ports or subnets):
|
||||||
@ -722,20 +717,33 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
session.begin(subtransactions=True)):
|
session.begin(subtransactions=True)):
|
||||||
record = self._get_subnet(context, id)
|
record = self._get_subnet(context, id)
|
||||||
subnet = self._make_subnet_dict(record, None)
|
subnet = self._make_subnet_dict(record, None)
|
||||||
# Get ports to auto-deallocate
|
qry_allocated = (session.query(models_v2.IPAllocation).
|
||||||
allocated = (session.query(models_v2.IPAllocation).
|
filter_by(subnet_id=id).
|
||||||
filter_by(subnet_id=id).
|
join(models_v2.Port))
|
||||||
join(models_v2.Port).
|
is_ipv6_slaac_subnet = ipv6_utils.is_slaac_subnet(subnet)
|
||||||
filter_by(network_id=subnet['network_id']).
|
# Remove network owned ports, and delete IP allocations
|
||||||
with_lockmode('update').all())
|
# for IPv6 addresses which were automatically generated
|
||||||
|
# via SLAAC
|
||||||
|
if not is_ipv6_slaac_subnet:
|
||||||
|
qry_allocated = (
|
||||||
|
qry_allocated.filter(models_v2.Port.device_owner.
|
||||||
|
in_(db_base_plugin_v2.AUTO_DELETE_PORT_OWNERS)))
|
||||||
|
allocated = qry_allocated.all()
|
||||||
|
# Delete all the IPAllocation that can be auto-deleted
|
||||||
|
if allocated:
|
||||||
|
map(session.delete, allocated)
|
||||||
LOG.debug("Ports to auto-deallocate: %s", allocated)
|
LOG.debug("Ports to auto-deallocate: %s", allocated)
|
||||||
only_auto_del = ipv6_utils.is_slaac_subnet(subnet) or all(
|
# Check if there are tenant owned ports
|
||||||
not a.port_id or a.ports.device_owner in db_base_plugin_v2.
|
tenant_port = (session.query(models_v2.IPAllocation).
|
||||||
AUTO_DELETE_PORT_OWNERS for a in allocated)
|
filter_by(subnet_id=id).
|
||||||
if not only_auto_del:
|
join(models_v2.Port).
|
||||||
|
first())
|
||||||
|
if tenant_port:
|
||||||
LOG.debug("Tenant-owned ports exist")
|
LOG.debug("Tenant-owned ports exist")
|
||||||
raise exc.SubnetInUse(subnet_id=id)
|
raise exc.SubnetInUse(subnet_id=id)
|
||||||
|
|
||||||
|
# If allocated is None, then all the IPAllocation were
|
||||||
|
# correctly deleted during the previous pass.
|
||||||
if not allocated:
|
if not allocated:
|
||||||
mech_context = driver_context.SubnetContext(self, context,
|
mech_context = driver_context.SubnetContext(self, context,
|
||||||
subnet)
|
subnet)
|
||||||
@ -763,7 +771,6 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
LOG.exception(_LE("Exception deleting fixed_ip "
|
LOG.exception(_LE("Exception deleting fixed_ip "
|
||||||
"from port %s"), a.port_id)
|
"from port %s"), a.port_id)
|
||||||
session.delete(a)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.mechanism_manager.delete_subnet_postcommit(mech_context)
|
self.mechanism_manager.delete_subnet_postcommit(mech_context)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user