From 921f203f4906a3b566f5a58471a55a4eedfc939c Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Mon, 4 Mar 2013 18:19:47 +0100 Subject: [PATCH] L3 port delete prevention: do not raise if no IP on port Bug #1104337 This patch alters the prevent_l3_port_deletion logic. PortInUse is raised only if the port has a device owner in (router_interface, router_gateway, floatingip) and an IP address. If no IP address is found on the port the port itself can be considered stale and therefore deleted as any association with l3 entities would be void. Change-Id: I9d711b2a9d2cbcc8be481f1751f51fe5b9f01327 --- quantum/db/l3_db.py | 13 +++++++++++-- quantum/tests/unit/test_l3_plugin.py | 17 +++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/quantum/db/l3_db.py b/quantum/db/l3_db.py index 506060fcb..514d7a691 100644 --- a/quantum/db/l3_db.py +++ b/quantum/db/l3_db.py @@ -740,8 +740,17 @@ class L3_NAT_db_mixin(l3.RouterPluginBase): if port_db['device_owner'] in [DEVICE_OWNER_ROUTER_INTF, DEVICE_OWNER_ROUTER_GW, DEVICE_OWNER_FLOATINGIP]: - raise l3.L3PortInUse(port_id=port_id, - device_owner=port_db['device_owner']) + # Raise port in use only if the port has IP addresses + # Otherwise it's a stale port that can be removed + fixed_ips = port_db['fixed_ips'].all() + if fixed_ips: + raise l3.L3PortInUse(port_id=port_id, + device_owner=port_db['device_owner']) + else: + LOG.debug(_("Port %(port_id)s has owner %(port_owner)s, but " + "no IP address, so it can be deleted"), + {'port_id': port_db['id'], + 'port_owner': port_db['device_owner']}) def disassociate_floatingips(self, context, port_id): with context.session.begin(subtransactions=True): diff --git a/quantum/tests/unit/test_l3_plugin.py b/quantum/tests/unit/test_l3_plugin.py index 8d7414d67..509ba8fc5 100644 --- a/quantum/tests/unit/test_l3_plugin.py +++ b/quantum/tests/unit/test_l3_plugin.py @@ -968,6 +968,23 @@ class L3NatDBTestCase(L3NatTestCaseBase): r['router']['id'], n['network']['id'], expected_code=exc.HTTPBadRequest.code) + def test_delete_unused_router_interface(self): + with self.network() as n: + with self.router() as r: + with self.subnet(network=n) as s: + res = self._create_port(self.fmt, + s['subnet']['network_id']) + p = self.deserialize(self.fmt, res) + self._router_interface_action('add', + r['router']['id'], + None, + p['port']['id']) + # The subnet here is deleted, and the port should have no IP + self._delete('ports', p['port']['id']) + # Verify the port has been deleted + self._show('ports', p['port']['id'], + expected_code=exc.HTTPNotFound.code) + def test_router_remove_interface_inuse_returns_409(self): with self.router() as r: with self.subnet() as s: -- 2.45.2