Ensure metadata access network does not prevent router deletion

Bug 1152136

This patch checks if a metadata access network is still present when
removing a router in the NVP plugin. If yes, the network is detached
from the router and then destroyed, thus ensuring a safe completion of
the operation as well as removal of metadata access network resources.

Change-Id: Id8be6ec50ab4536f4ae9916dadaed56644597c7c
This commit is contained in:
Salvatore Orlando 2013-03-07 13:51:15 +01:00
parent 1955948570
commit 933088ac79
2 changed files with 15 additions and 8 deletions

View File

@ -1593,6 +1593,11 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
def delete_router(self, context, id): def delete_router(self, context, id):
with context.session.begin(subtransactions=True): with context.session.begin(subtransactions=True):
# Ensure metadata access network is detached and destroyed
# This will also destroy relevant objects on NVP platform.
# NOTE(salvatore-orlando): A failure in this operation will
# cause the router delete operation to fail too.
self._handle_metadata_access_network(context, id, do_create=False)
super(NvpPluginV2, self).delete_router(context, id) super(NvpPluginV2, self).delete_router(context, id)
# If removal is successful in Quantum it should be so on # If removal is successful in Quantum it should be so on
# the NVP platform too - otherwise the transaction should # the NVP platform too - otherwise the transaction should
@ -1779,6 +1784,7 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
results = nvplib.query_lswitch_lports( results = nvplib.query_lswitch_lports(
cluster, '*', relations="LogicalPortAttachment", cluster, '*', relations="LogicalPortAttachment",
filters={'tag': port_id, 'tag_scope': 'q_port_id'}) filters={'tag': port_id, 'tag_scope': 'q_port_id'})
lrouter_port_id = None
if len(results): if len(results):
lport = results[0] lport = results[0]
attachment_data = lport['_relations'].get('LogicalPortAttachment') attachment_data = lport['_relations'].get('LogicalPortAttachment')
@ -1799,11 +1805,8 @@ class NvpPluginV2(db_base_plugin_v2.QuantumDbPluginV2,
# to leverage validation performed in the base class # to leverage validation performed in the base class
if not lrouter_port_id: if not lrouter_port_id:
LOG.warning(_("Unable to find NVP logical router port for " LOG.warning(_("Unable to find NVP logical router port for "
"Quantum port id:%(q_port_id)s (NVP id: " "Quantum port id:%s. Was this port ever paired "
"%(nvp_port_id)s). Was this port " "with a logical router?"), port_id)
"ever paired with a logical router?"),
{'q_port_id': port_id,
'nvp_port_id': lport['uuid']})
return return
# Ensure the connection to the 'metadata access network' # Ensure the connection to the 'metadata access network'

View File

@ -113,7 +113,8 @@ class NvpMetadataAccess(object):
{'network': {'id': meta_net_id}}, {'network': {'id': meta_net_id}},
'network.delete.end') 'network.delete.end')
def _handle_metadata_access_network(self, context, router_id): def _handle_metadata_access_network(self, context, router_id,
do_create=True):
if not cfg.CONF.NVP.enable_metadata_access_network: if not cfg.CONF.NVP.enable_metadata_access_network:
LOG.debug(_("Metadata access network is disabled")) LOG.debug(_("Metadata access network is disabled"))
return return
@ -128,13 +129,16 @@ class NvpMetadataAccess(object):
'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF]} 'device_owner': [l3_db.DEVICE_OWNER_ROUTER_INTF]}
with ctx_elevated.session.begin(subtransactions=True): with ctx_elevated.session.begin(subtransactions=True):
ports = self.get_ports(ctx_elevated, filters=device_filter) ports = self.get_ports(ctx_elevated, filters=device_filter)
# Filter out ports without an IP (those are 'stale' router ports)
ports = [port for port in ports if port['fixed_ips']]
try: try:
if ports: if ports:
if not self._find_metadata_port(ctx_elevated, ports): if (do_create and
not self._find_metadata_port(ctx_elevated, ports)):
self._create_metadata_access_network(context, self._create_metadata_access_network(context,
router_id) router_id)
elif len(ports) == 1: elif len(ports) == 1:
# The only port left if the metadata port # The only port left is the metadata port
self._destroy_metadata_access_network(context, self._destroy_metadata_access_network(context,
router_id, router_id,
ports) ports)