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
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()):
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):
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
# 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):
@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']
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."""
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