]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Fixes floating IP regression with multiple routers
authorKevin Fox <kevin@efox.cc>
Wed, 18 Feb 2015 22:01:49 +0000 (14:01 -0800)
committerKevin Benton <blak111@gmail.com>
Sat, 21 Mar 2015 00:44:10 +0000 (17:44 -0700)
During the refactor here:
Change-Id: I09e8a694cdff7f64a642a39b45cbd12422132806
Too much code was removed and caused floating ips to get miss assigned when
multiple routers with external networks in the same tenant are present. The
first router in the tenant was always being chosen. This patch adds back
some of the original code as well as a unit test.

Change-Id: I6f663cb1ce3e4a1340c415d13787a9855c4dcac2
Closes-Bug: 1422476

neutron/db/l3_db.py
neutron/tests/unit/test_l3_plugin.py

index 5d7d0178105e09005359542a71072a6d00496bc9..7bc1d2d0ef66c5148d0ad2e1bd0967dbd4123f7f 100644 (file)
@@ -716,10 +716,15 @@ class L3_NAT_dbonly_mixin(l3.RouterPluginBase):
             models_v2.IPAllocation.subnet_id == internal_subnet_id
         )
 
-        router_port = routerport_qry.first()
-
-        if router_port and router_port.router.gw_port:
-            return router_port.router.id
+        for router_port in routerport_qry:
+            router_id = router_port.router.id
+            router_gw_qry = context.session.query(models_v2.Port)
+            has_gw_port = router_gw_qry.filter_by(
+                network_id=external_network_id,
+                device_id=router_id,
+                device_owner=DEVICE_OWNER_ROUTER_GW).count()
+            if has_gw_port:
+                return router_id
 
         raise l3.ExternalGatewayForFloatingIPNotFound(
             subnet_id=internal_subnet_id,
index 56cba4177b50e1889db348e43018594c080bea20..639b276d7ee436843230c99f808628de51ecb750 100644 (file)
@@ -1998,6 +1998,50 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
                 self._delete('floatingips', fp2['floatingip']['id'])
                 self._delete('floatingips', fp3['floatingip']['id'])
 
+    def test_floatingip_multi_external_one_internal(self):
+        with contextlib.nested(self.subnet(cidr="10.0.0.0/24"),
+                               self.subnet(cidr="11.0.0.0/24"),
+                               self.subnet(cidr="12.0.0.0/24")
+                               ) as (exs1, exs2, ins1):
+            network_ex_id1 = exs1['subnet']['network_id']
+            network_ex_id2 = exs2['subnet']['network_id']
+            self._set_net_external(network_ex_id1)
+            self._set_net_external(network_ex_id2)
+
+            r2i_fixed_ips = [{'ip_address': '12.0.0.2'}]
+            with contextlib.nested(self.router(no_delete=True),
+                                   self.router(no_delete=True),
+                                   self.port(subnet=ins1,
+                                             fixed_ips=r2i_fixed_ips)
+                                   ) as (r1, r2, r2i_port):
+                self._add_external_gateway_to_router(
+                    r1['router']['id'],
+                    network_ex_id1)
+                self._router_interface_action('add', r1['router']['id'],
+                                              ins1['subnet']['id'],
+                                              None)
+                self._add_external_gateway_to_router(
+                    r2['router']['id'],
+                    network_ex_id2)
+                self._router_interface_action('add', r2['router']['id'],
+                                              None,
+                                              r2i_port['port']['id'])
+
+                with self.port(subnet=ins1,
+                               fixed_ips=[{'ip_address': '12.0.0.3'}]
+                               ) as private_port:
+
+                    fp1 = self._make_floatingip(self.fmt, network_ex_id1,
+                                            private_port['port']['id'],
+                                            floating_ip='10.0.0.3')
+                    fp2 = self._make_floatingip(self.fmt, network_ex_id2,
+                                            private_port['port']['id'],
+                                            floating_ip='11.0.0.3')
+                    self.assertEqual(fp1['floatingip']['router_id'],
+                                     r1['router']['id'])
+                    self.assertEqual(fp2['floatingip']['router_id'],
+                                     r2['router']['id'])
+
     def test_floatingip_delete_router_intf_with_subnet_id_returns_409(self):
         found = False
         with self.floatingip_with_assoc():