diff --git a/vmware_nsx/plugins/nsx_v3/plugin.py b/vmware_nsx/plugins/nsx_v3/plugin.py index 941386ecbd..46f55c721d 100644 --- a/vmware_nsx/plugins/nsx_v3/plugin.py +++ b/vmware_nsx/plugins/nsx_v3/plugin.py @@ -1465,12 +1465,16 @@ class NsxV3Plugin(addr_pair_db.AllowedAddressPairsMixin, port = self._get_port(context, port_id) if port.get('fixed_ips'): subnet_id = port['fixed_ips'][0]['subnet_id'] + self._confirm_router_interface_not_in_use( + context, router_id, subnet_id) if not (port['device_owner'] in const.ROUTER_INTERFACE_OWNERS and port['device_id'] == router_id): raise l3.RouterInterfaceNotFound(router_id=router_id, port_id=port_id) elif 'subnet_id' in interface_info: subnet_id = interface_info['subnet_id'] + self._confirm_router_interface_not_in_use( + context, router_id, subnet_id) subnet = self._get_subnet(context, subnet_id) rport_qry = context.session.query(models_v2.Port) ports = rport_qry.filter_by( diff --git a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py index bdae850602..228b92cab1 100644 --- a/vmware_nsx/tests/unit/nsx_v3/test_plugin.py +++ b/vmware_nsx/tests/unit/nsx_v3/test_plugin.py @@ -14,6 +14,7 @@ # limitations under the License. import mock import six +from webob import exc from neutron.api.v2 import attributes from neutron.common import constants @@ -380,6 +381,39 @@ class TestL3NatTestCase(L3NatTest, self._router_interface_action('remove', r1['router']['id'], s1['subnet']['id'], None) + def test_router_remove_interface_inuse_return_409(self): + with self.router() as r1,\ + self.subnet() as ext_subnet,\ + self.subnet(cidr='11.0.0.0/24') as s1: + self._set_net_external(ext_subnet['subnet']['network_id']) + self._router_interface_action( + 'add', r1['router']['id'], + s1['subnet']['id'], None) + self._add_external_gateway_to_router( + r1['router']['id'], + ext_subnet['subnet']['network_id']) + with self.port(subnet=s1,) as p: + fip_res = self._create_floatingip( + self.fmt, + ext_subnet['subnet']['network_id'], + subnet_id=ext_subnet['subnet']['id'], + port_id=p['port']['id']) + fip = self.deserialize(self.fmt, fip_res) + self._router_interface_action( + 'remove', + r1['router']['id'], + s1['subnet']['id'], + None, + expected_code=exc.HTTPConflict.code) + self._delete('floatingips', fip['floatingip']['id']) + self._remove_external_gateway_from_router( + r1['router']['id'], + ext_subnet['subnet']['network_id']) + self._router_interface_action('remove', + r1['router']['id'], + s1['subnet']['id'], + None) + def test_router_update_on_external_port(self): with self.router() as r: with self.subnet(cidr='10.0.1.0/24') as s: