From 1e00041b0bcb83175760eb6347bb3eae55649328 Mon Sep 17 00:00:00 2001 From: mathieu-rohon Date: Thu, 15 Jan 2015 16:19:08 +0100 Subject: [PATCH] make delete_router send delete_port to core_plugin Have delete_router API call also delete the gateway port if needed. Currently, the db_base_plugin_v2 method is called, bypassing the core_plugin overload of this method. The consequence is that, in ML2, mechanism drivers are not aware of the port deletion. In this patch, tha gateway port is deleted through a common method. This method checks if floating IP and VPN are attached to the router, so those checks are removed from the delete_router method. Closes-Bug: #1361540 Change-Id: Iae98f3fe89126a76f16ed9c5230ce299a09ce8d8 --- neutron/db/l3_db.py | 28 ++++++++----------- neutron/plugins/bigswitch/l3_router_plugin.py | 4 --- neutron/plugins/vmware/plugins/base.py | 20 ++++++------- neutron/tests/unit/vmware/apiclient/fake.py | 2 +- 4 files changed, 23 insertions(+), 31 deletions(-) diff --git a/neutron/db/l3_db.py b/neutron/db/l3_db.py index 0ef0b89e5..c45df499f 100644 --- a/neutron/db/l3_db.py +++ b/neutron/db/l3_db.py @@ -395,11 +395,10 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase): return ip_address_change def _ensure_router_not_in_use(self, context, router_id): - admin_ctx = context.elevated() + """Ensure that no internal network interface is attached + to the router. + """ router = self._get_router(context, router_id) - if self.get_floatingips_count( - admin_ctx, filters={'router_id': [router_id]}): - raise l3.RouterInUse(router_id=router_id) device_owner = self._get_device_owner(context, router) if any(rp.port_type == device_owner for rp in router.attached_ports.all()): @@ -407,20 +406,17 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase): return router def delete_router(self, context, id): - with context.session.begin(subtransactions=True): - router = self._ensure_router_not_in_use(context, id) - #TODO(nati) Refactor here when we have router insertion model - vpnservice = manager.NeutronManager.get_service_plugins().get( - constants.VPN) - if vpnservice: - vpnservice.check_router_in_use(context, id) + #TODO(nati) Refactor here when we have router insertion model + router = self._ensure_router_not_in_use(context, id) + self._delete_current_gw_port(context, id, router, None, False) - router_ports = router.attached_ports.all() - # Set the router's gw_port to None to avoid a constraint violation. - router.gw_port = None - for rp in router_ports: - self._core_plugin._delete_port(context.elevated(), rp.port.id) + router_ports = router.attached_ports.all() + for rp in router_ports: + self._core_plugin.delete_port(context.elevated(), + rp.port.id, + l3_port_check=False) + with context.session.begin(subtransactions=True): context.session.delete(router) def get_router(self, context, id, fields=None): diff --git a/neutron/plugins/bigswitch/l3_router_plugin.py b/neutron/plugins/bigswitch/l3_router_plugin.py index ff5193d52..c96bbe5f2 100644 --- a/neutron/plugins/bigswitch/l3_router_plugin.py +++ b/neutron/plugins/bigswitch/l3_router_plugin.py @@ -28,7 +28,6 @@ from oslo.utils import excutils from neutron.api import extensions as neutron_extensions from neutron.common import exceptions from neutron.common import log -from neutron.common import utils from neutron.db import l3_db from neutron.extensions import l3 from neutron.i18n import _LE @@ -108,9 +107,6 @@ class L3RestProxy(cplugin.NeutronRestProxyV2Base, # return updated router return new_router - # NOTE(kevinbenton): workaround for eventlet/mysql deadlock. - # delete_router ends up calling _delete_port instead of delete_port. - @utils.synchronized('bsn-port-barrier') @put_context_in_serverpool @log.log def delete_router(self, context, router_id): diff --git a/neutron/plugins/vmware/plugins/base.py b/neutron/plugins/vmware/plugins/base.py index 4ca8ff118..53a5b46f6 100644 --- a/neutron/plugins/vmware/plugins/base.py +++ b/neutron/plugins/vmware/plugins/base.py @@ -645,10 +645,10 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin, @lockutils.synchronized('vmware', 'neutron-') def _nsx_delete_ext_gw_port(self, context, port_data): - lr_port = self._find_router_gw_port(context, port_data) # TODO(salvatore-orlando): Handle NSX resource # rollback when something goes not quite as expected try: + lr_port = self._find_router_gw_port(context, port_data) # Delete is actually never a real delete, otherwise the NSX # logical router will stop working router_id = port_data['device_id'] @@ -668,19 +668,19 @@ class NsxPluginV2(addr_pair_db.AllowedAddressPairsMixin, lr_port['uuid'], "L3GatewayAttachment", self.cluster.default_l3_gw_service_uuid) - - except api_exc.ResourceNotFound: - raise nsx_exc.NsxPluginException( - err_msg=_("Logical router resource %s not found " - "on NSX platform") % router_id) + LOG.debug("_nsx_delete_ext_gw_port completed on external network " + "%(ext_net_id)s, attached to NSX router:%(router_id)s", + {'ext_net_id': port_data['network_id'], + 'router_id': nsx_router_id}) + except n_exc.NotFound: + LOG.debug("Logical router resource %s not found " + "on NSX platform : the router may have " + "already been deleted", + port_data['device_id']) except api_exc.NsxApiException: raise nsx_exc.NsxPluginException( err_msg=_("Unable to update logical router" "on NSX Platform")) - LOG.debug("_nsx_delete_ext_gw_port completed on external network " - "%(ext_net_id)s, attached to NSX router:%(router_id)s", - {'ext_net_id': port_data['network_id'], - 'router_id': nsx_router_id}) def _nsx_create_l2_gw_port(self, context, port_data): """Create a switch port, and attach it to a L2 gateway attachment.""" diff --git a/neutron/tests/unit/vmware/apiclient/fake.py b/neutron/tests/unit/vmware/apiclient/fake.py index dfe48cb9e..0dbb69c6d 100644 --- a/neutron/tests/unit/vmware/apiclient/fake.py +++ b/neutron/tests/unit/vmware/apiclient/fake.py @@ -412,7 +412,7 @@ class FakeClient: def _lrouter_match(res_uuid): # verify that the router exist if parent_uuid and parent_uuid not in self._fake_lrouter_dict: - raise Exception(_("lrouter:%s not found") % parent_uuid) + raise api_exc.ResourceNotFound() if (not parent_uuid or res_dict[res_uuid].get('lr_uuid') == parent_uuid): return True -- 2.45.2