From 300025b14cd6bfe5af096d40aaed90abf2716002 Mon Sep 17 00:00:00 2001 From: lzklibj Date: Wed, 11 Mar 2015 06:59:43 -0700 Subject: [PATCH] Remove router binding with router-interface-delete When "neutron router-interface-delete ROUTER subnet" command is executed to delete a router interface, it should check for dvr ports changing on nodes which have their l3-agent binded to the router. And if there is any node has no port related to the router, the binding to the L3-agent should be removed from the "RouterL3AgentBindings" table. This patch fixes the problem mentioned above. Closes-Bug: #1413630 Change-Id: I9e2b115079fa2c66c98b9c45386d139fdebf63e7 --- neutron/db/l3_dvr_db.py | 16 +++++++-- neutron/tests/unit/db/test_l3_dvr_db.py | 44 +++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/neutron/db/l3_dvr_db.py b/neutron/db/l3_dvr_db.py index f507412de..c45710971 100644 --- a/neutron/db/l3_dvr_db.py +++ b/neutron/db/l3_dvr_db.py @@ -333,9 +333,19 @@ class L3_NAT_with_dvr_db_mixin(l3_db.L3_NAT_db_mixin, port, subnet = self._remove_interface_by_subnet( context, router_id, subnet_id, device_owner) - if router.extra_attributes.distributed and router.gw_port: - self.delete_csnat_router_interface_ports( - context.elevated(), router, subnet_id=subnet_id) + if router.extra_attributes.distributed: + if router.gw_port: + self.delete_csnat_router_interface_ports( + context.elevated(), router, subnet_id=subnet_id) + plugin = manager.NeutronManager.get_service_plugins().get( + constants.L3_ROUTER_NAT) + l3_agents = plugin.get_l3_agents_hosting_routers(context, + [router_id]) + for l3_agent in l3_agents: + if not plugin.check_ports_exist_on_l3agent(context, l3_agent, + router_id): + plugin.remove_router_from_l3_agent( + context, l3_agent['id'], router_id) router_interface_info = self._make_router_interface_info( router_id, port['tenant_id'], port['id'], diff --git a/neutron/tests/unit/db/test_l3_dvr_db.py b/neutron/tests/unit/db/test_l3_dvr_db.py index 2b7fab935..9f6dc0170 100644 --- a/neutron/tests/unit/db/test_l3_dvr_db.py +++ b/neutron/tests/unit/db/test_l3_dvr_db.py @@ -22,6 +22,7 @@ from neutron.db import l3_dvr_db from neutron.extensions import l3 from neutron import manager from neutron.openstack.common import uuidutils +from neutron.plugins.common import constants as plugin_const from neutron.tests.unit import testlib_api _uuid = uuidutils.generate_uuid @@ -516,3 +517,46 @@ class L3DvrTestCase(testlib_api.SqlTestCase): self.mixin.check_router_has_no_vpnaas(mock.ANY, {'id': 'foo_id'}) vpn_plugin.check_router_in_use.assert_called_once_with( mock.ANY, 'foo_id') + + def test_remove_router_interface_delete_router_l3agent_binding(self): + interface_info = {'subnet_id': '123'} + router = mock.MagicMock() + router.extra_attributes.distributed = True + plugin = mock.MagicMock() + plugin.get_l3_agents_hosting_routers = mock.Mock( + return_value=[mock.MagicMock()]) + plugin.check_ports_exist_on_l3agent = mock.Mock( + return_value=False) + plugin.remove_router_from_l3_agent = mock.Mock( + return_value=None) + with contextlib.nested( + mock.patch.object(self.mixin, + '_get_router'), + mock.patch.object(self.mixin, + '_get_device_owner'), + mock.patch.object(self.mixin, + '_remove_interface_by_subnet'), + mock.patch.object(self.mixin, + 'delete_csnat_router_interface_ports'), + mock.patch.object(manager.NeutronManager, + 'get_service_plugins'), + mock.patch.object(self.mixin, + '_make_router_interface_info'), + mock.patch.object(self.mixin, + 'notify_router_interface_action'), + ) as (grtr, gdev, rmintf, delintf, gplugin, + mkintf, notify): + grtr.return_value = router + gdev.return_value = mock.Mock() + rmintf.return_value = (mock.MagicMock(), mock.Mock()) + mkintf.return_value = mock.Mock() + gplugin.return_value = {plugin_const.L3_ROUTER_NAT: plugin} + delintf.return_value = None + notify.return_value = None + + self.mixin.manager = manager + self.mixin.remove_router_interface( + self.ctx, mock.Mock(), interface_info) + self.assertTrue(plugin.get_l3_agents_hosting_routers.called) + self.assertTrue(plugin.check_ports_exist_on_l3agent.called) + self.assertTrue(plugin.remove_router_from_l3_agent.called) -- 2.45.2