Fix auto-deletion of ports and subnets in ML2
When a network is deleted, certain ports and any subnets referencing it are auto-deleted. The implementation of NeutronDBPluginV2.delete_network() does this at the DB level, so ML2's mechanism drivers were not being called. Ml2Plugin.delete_network() is changed to not use the base class's method, and to auto-delete ports and subnets by calling its own delete_port() and delete_subnet() methods outside of the transaction. A loop avoids race conditions with ports or subnets being asynchronously added to the network. Closes-Bug: 1230330 Change-Id: Icf21400c9938eec29d70da8497b9ef92642131e2
This commit is contained in:
parent
86feb8e4a8
commit
f69b25e73c
@ -368,17 +368,53 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
return [self._fields(net, fields) for net in nets]
|
return [self._fields(net, fields) for net in nets]
|
||||||
|
|
||||||
def delete_network(self, context, id):
|
def delete_network(self, context, id):
|
||||||
|
# REVISIT(rkukura) The super(Ml2Plugin, self).delete_network()
|
||||||
|
# function is not used because it auto-deletes ports and
|
||||||
|
# subnets from the DB without invoking the derived class's
|
||||||
|
# delete_port() or delete_subnet(), preventing mechanism
|
||||||
|
# drivers from being called. This approach should be revisited
|
||||||
|
# when the API layer is reworked during icehouse.
|
||||||
|
|
||||||
session = context.session
|
session = context.session
|
||||||
|
while True:
|
||||||
with session.begin(subtransactions=True):
|
with session.begin(subtransactions=True):
|
||||||
|
filter = {'network_id': [id]}
|
||||||
|
|
||||||
|
# Get ports to auto-delete.
|
||||||
|
ports = self.get_ports(context, filters=filter)
|
||||||
|
only_auto_del = all(p['device_owner']
|
||||||
|
in db_base_plugin_v2.
|
||||||
|
AUTO_DELETE_PORT_OWNERS
|
||||||
|
for p in ports)
|
||||||
|
if not only_auto_del:
|
||||||
|
raise exc.NetworkInUse(net_id=id)
|
||||||
|
|
||||||
|
# Get subnets to auto-delete.
|
||||||
|
subnets = self.get_subnets(context, filters=filter)
|
||||||
|
|
||||||
|
if not ports or subnets:
|
||||||
network = self.get_network(context, id)
|
network = self.get_network(context, id)
|
||||||
mech_context = driver_context.NetworkContext(self, context,
|
mech_context = driver_context.NetworkContext(self,
|
||||||
|
context,
|
||||||
network)
|
network)
|
||||||
self.mechanism_manager.delete_network_precommit(mech_context)
|
self.mechanism_manager.delete_network_precommit(
|
||||||
super(Ml2Plugin, self).delete_network(context, id)
|
mech_context)
|
||||||
|
|
||||||
|
record = self._get_network(context, id)
|
||||||
|
context.session.delete(record)
|
||||||
|
|
||||||
for segment in mech_context.network_segments:
|
for segment in mech_context.network_segments:
|
||||||
self.type_manager.release_segment(session, segment)
|
self.type_manager.release_segment(session, segment)
|
||||||
|
|
||||||
# The segment records are deleted via cascade from the
|
# The segment records are deleted via cascade from the
|
||||||
# network record, so explicit removal is not necessary.
|
# network record, so explicit removal is not necessary.
|
||||||
|
break
|
||||||
|
|
||||||
|
for port in ports:
|
||||||
|
self.delete_port(context, port['id'])
|
||||||
|
|
||||||
|
for subnet in subnets:
|
||||||
|
self.delete_subnet(context, subnet['id'])
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.mechanism_manager.delete_network_postcommit(mech_context)
|
self.mechanism_manager.delete_network_postcommit(mech_context)
|
||||||
|
Loading…
Reference in New Issue
Block a user