]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
fix l3-agent restart with last runtime fip for dvr
authorlzklibj <lzklibj@cn.ibm.com>
Sat, 21 Mar 2015 16:58:15 +0000 (09:58 -0700)
committerlzklibj <lzklibj@cn.ibm.com>
Sat, 25 Apr 2015 16:23:22 +0000 (00:23 +0800)
In DVR enabled environment, after we associated a floating
IP to a VM, when we restart L3-agent on the same compute
node, the L3-agent will miss to create rtr_fip_subnet for
router_info. The previous floating IP can still work, but
new associated floating IPs to VMs related to the same router
on this L3-agent will fail to configure and not work. This
patch will fix this.

The method create_dvr_fip_interfaces in dvr_router.py will
invoke fip_ns.create_rtr_2_fip_link, and the later one will
create rtr_fip_subnet, consider VMs related to the same router
will share the same rtr_fip_subnet, so processing here should
run only once for those VMs, once rtr_fip_subnet is created.
Current code will check dist_fip_count then decide to invoke
fip_ns.create_rtr_2_fip_link or not.

dist_fip_count should be zero if a router related VMs never
have been associated with any floating IPs before. But if a
router has floating IPs associated to its related VMs, after
it is restared, dist_fip_count will be non-zero, and this is
the point this patch try to fix. And for case rtr_fip_subnet
has been created, both dist_fip_count and is_fisrt will be
false, and fip_ns.create_rtr_2_fip_link will be no more need
to be invoked.

Change-Id: I3786eab86755a403991728ccb72d03f159ff8b63
Closes-Bug: 1434824

neutron/agent/l3/dvr_router.py
neutron/tests/unit/agent/l3/test_agent.py

index 4d2539ff44f7415399458a1f37f243e1b1ad2404..39a8d4b93954566e908ece62e568e0256cd102a7 100644 (file)
@@ -498,6 +498,7 @@ class DvrRouter(router.RouterInfo):
             ex_gw_port['network_id'])
         LOG.debug("FloatingIP agent gateway port received from the plugin: "
                   "%s", fip_agent_port)
+        is_first = False
         if floating_ips:
             is_first = self.fip_ns.subscribe(self.router_id)
             if is_first and fip_agent_port:
@@ -507,7 +508,7 @@ class DvrRouter(router.RouterInfo):
                     self.fip_ns.create_gateway_port(fip_agent_port)
 
         if self.fip_ns.agent_gateway_port and floating_ips:
-            if self.dist_fip_count == 0:
+            if self.dist_fip_count == 0 or is_first:
                 self.fip_ns.create_rtr_2_fip_link(self)
 
                 # kicks the FW Agent to add rules for the IR namespace if
index 0f0eb7f5f2d222aba10e2944468789211df6d0e4..1dca8ac124c3d0be48abe44a49fa89ef6d1c4913 100644 (file)
@@ -1200,6 +1200,7 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
         ri.fip_ns = agent.get_fip_ns(ext_gw_port['network_id'])
         ri.dist_fip_count = 0
         ri.fip_ns.subscribe = mock.Mock()
+        ri.fip_ns.agent_router_gateway = mock.Mock()
 
         with contextlib.nested(mock.patch.object(ri,
                                                  'get_floating_ips'),
@@ -1214,6 +1215,57 @@ class TestBasicRouterOperations(BasicRouterOperationsFramework):
             self.assertTrue(fips.called)
             self.assertEqual(ri.fip_ns.agent_gateway_port,
                              agent_gateway_port[0])
+            self.assertTrue(ri.rtr_fip_subnet)
+
+    def test_create_dvr_fip_interfaces_for_restart_l3agent_case(self):
+        fake_floatingips = {'floatingips': [
+            {'id': _uuid(),
+             'floating_ip_address': '20.0.0.3',
+             'fixed_ip_address': '192.168.0.1',
+             'floating_network_id': _uuid(),
+             'port_id': _uuid(),
+             'host': HOSTNAME}]}
+        agent_gateway_port = (
+            [{'fixed_ips': [
+                {'ip_address': '20.0.0.30',
+                 'prefixlen': 24,
+                 'subnet_id': 'subnet_id'}],
+             'subnets': [
+                 {'id': 'subnet_id',
+                  'gateway_ip': '20.0.0.1'}],
+             'id': _uuid(),
+             'network_id': 'fake_network_id',
+             'mac_address': 'ca:fe:de:ad:be:ef'}]
+        )
+
+        router = prepare_router_data(enable_snat=True)
+        router[l3_constants.FLOATINGIP_KEY] = fake_floatingips['floatingips']
+        router[l3_constants.FLOATINGIP_AGENT_INTF_KEY] = agent_gateway_port
+        router['distributed'] = True
+        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+        ri = dvr_router.DvrRouter(
+            agent, HOSTNAME, router['id'], router, **self.ri_kwargs)
+        ext_gw_port = ri.router.get('gw_port')
+        ri.fip_ns = agent.get_fip_ns(ext_gw_port['network_id'])
+        ri.fip_ns.subscribe = mock.Mock(return_value=True)
+        ri.fip_ns.agent_router_gateway = mock.Mock()
+        ri.rtr_fip_subnet = None
+        ri.dist_fip_count = 1
+
+        with contextlib.nested(mock.patch.object(
+                                   ri, 'get_floating_ips'),
+                               mock.patch.object(
+                                   ri, 'get_floating_agent_gw_interface')
+                               ) as (fips,
+                                     fip_gw_port):
+            fips.return_value = fake_floatingips
+            fip_gw_port.return_value = agent_gateway_port[0]
+            ri.create_dvr_fip_interfaces(ext_gw_port)
+            self.assertTrue(fip_gw_port.called)
+            self.assertTrue(fips.called)
+            self.assertEqual(ri.fip_ns.agent_gateway_port,
+                             agent_gateway_port[0])
+            self.assertTrue(ri.rtr_fip_subnet)
 
     def test_process_router_cent_floating_ip_add(self):
         fake_floatingips = {'floatingips': [