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]
|
||||
|
||||
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
|
||||
with session.begin(subtransactions=True):
|
||||
network = self.get_network(context, id)
|
||||
mech_context = driver_context.NetworkContext(self, context,
|
||||
network)
|
||||
self.mechanism_manager.delete_network_precommit(mech_context)
|
||||
super(Ml2Plugin, self).delete_network(context, id)
|
||||
for segment in mech_context.network_segments:
|
||||
self.type_manager.release_segment(session, segment)
|
||||
# The segment records are deleted via cascade from the
|
||||
# network record, so explicit removal is not necessary.
|
||||
while 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)
|
||||
mech_context = driver_context.NetworkContext(self,
|
||||
context,
|
||||
network)
|
||||
self.mechanism_manager.delete_network_precommit(
|
||||
mech_context)
|
||||
|
||||
record = self._get_network(context, id)
|
||||
context.session.delete(record)
|
||||
|
||||
for segment in mech_context.network_segments:
|
||||
self.type_manager.release_segment(session, segment)
|
||||
|
||||
# The segment records are deleted via cascade from the
|
||||
# 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:
|
||||
self.mechanism_manager.delete_network_postcommit(mech_context)
|
||||
|
Loading…
Reference in New Issue
Block a user