]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Remove router binding with router-interface-delete
authorlzklibj <lzklibj@cn.ibm.com>
Wed, 11 Mar 2015 13:59:43 +0000 (06:59 -0700)
committerlzklibj <lzklibj@cn.ibm.com>
Thu, 12 Mar 2015 15:38:58 +0000 (08:38 -0700)
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
neutron/tests/unit/db/test_l3_dvr_db.py

index f507412dedffc320c4feead56c83576aecf4998b..c457109711c9d3dfedee95d5ca3c076b7e28a4cf 100644 (file)
@@ -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'],
index 2b7fab9355375b32abc20f05feee9ccbf71c8329..9f6dc01700a122696d2152db1ced2b9a64b047e9 100644 (file)
@@ -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)