]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Delete duplicate external devices in router namespace
authorCarl Baldwin <carl.baldwin@hp.com>
Thu, 27 Mar 2014 22:21:53 +0000 (22:21 +0000)
committerCarl Baldwin <carl.baldwin@hp.com>
Fri, 28 Mar 2014 15:56:55 +0000 (15:56 +0000)
When a router's gateway is removed during L3-agent restart, the agent
will fail to delete the old external device.  This device should be
identified and removed as soon as possible.

Change-Id: Ifd3e6ca009242138bea4a098e3fde258aeaa391e
Closes-Bug: #1298658

neutron/agent/l3_agent.py
neutron/tests/unit/test_l3_agent.py

index 27fa5fac53052cfde21f337d451ccdaf99580c13..469f73381cea6f621a4f594ca287c25b108ab77b 100644 (file)
@@ -414,12 +414,11 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
         prefixlen = netaddr.IPNetwork(port['subnet']['cidr']).prefixlen
         port['ip_cidr'] = "%s/%s" % (ips[0]['ip_address'], prefixlen)
 
-    def _get_existing_internal_devices(self, ri):
+    def _get_existing_devices(self, ri):
         ip_wrapper = ip_lib.IPWrapper(root_helper=self.root_helper,
                                       namespace=ri.ns_name())
         ip_devs = ip_wrapper.get_devices(exclude_loopback=True)
-        return [ip_dev.name for ip_dev in ip_devs if
-                ip_dev.name.startswith(INTERNAL_DEV_PREFIX)]
+        return [ip_dev.name for ip_dev in ip_devs]
 
     def process_router(self, ri):
         ri.iptables_manager.defer_apply_on()
@@ -443,7 +442,9 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
             self.internal_network_removed(ri, p['id'], p['ip_cidr'])
             ri.internal_ports.remove(p)
 
-        current_internal_devs = set(self._get_existing_internal_devices(ri))
+        existing_devices = self._get_existing_devices(ri)
+        current_internal_devs = set([n for n in existing_devices
+                                     if n.startswith(INTERNAL_DEV_PREFIX)])
         current_port_devs = set([self.get_internal_device_name(id) for
                                  id in current_port_ids])
         stale_devs = current_internal_devs - current_port_devs
@@ -471,6 +472,17 @@ class L3NATAgent(firewall_l3_agent.FWaaSL3AgentRpcCallback, manager.Manager):
             self.external_gateway_removed(ri, ri.ex_gw_port,
                                           interface_name, internal_cidrs)
 
+        stale_devs = [dev for dev in existing_devices
+                      if dev.startswith(EXTERNAL_DEV_PREFIX)
+                      and dev != interface_name]
+        for stale_dev in stale_devs:
+            LOG.debug(_('Deleting stale external router device: %s'),
+                      stale_dev)
+            self.driver.unplug(stale_dev,
+                               bridge=self.conf.external_network_bridge,
+                               namespace=ri.ns_name(),
+                               prefix=EXTERNAL_DEV_PREFIX)
+
         # Process static routes for router
         self.routes_updated(ri)
         # Process SNAT rules for external gateway
index 89250439ad57cdcae93b697af92893affe5ee219..d390ac29bd6e83161cd04a2f1cbbccedf1767384 100644 (file)
@@ -796,8 +796,7 @@ class TestBasicRouterOperations(base.BaseTestCase):
                          FakeDev('qr-b2c3d4e5-f6')]
         stale_devnames = [dev.name for dev in stale_devlist]
 
-        get_devices_return = [FakeDev('qg-a1b2c3d4-e5'),
-                              FakeDev('qg-b2c3d4e5-f6')]
+        get_devices_return = []
         get_devices_return.extend(stale_devlist)
         self.mock_ip.get_devices.return_value = get_devices_return
 
@@ -844,6 +843,33 @@ class TestBasicRouterOperations(base.BaseTestCase):
                      for stale_devname in stale_devnames]
             self.mock_driver.unplug.assert_has_calls(calls, any_order=True)
 
+    def test_process_router_delete_stale_external_devices(self):
+        class FakeDev(object):
+            def __init__(self, name):
+                self.name = name
+
+        agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
+        stale_devlist = [FakeDev('qg-a1b2c3d4-e5')]
+        stale_devnames = [dev.name for dev in stale_devlist]
+
+        router = self._prepare_router_data(enable_snat=True,
+                                           num_internal_ports=1)
+        del router['gw_port']
+        ri = l3_agent.RouterInfo(router['id'],
+                                 self.conf.root_helper,
+                                 self.conf.use_namespaces,
+                                 router=router)
+
+        self.mock_ip.get_devices.return_value = stale_devlist
+
+        agent.process_router(ri)
+
+        self.mock_driver.unplug.assert_called_with(
+            stale_devnames[0],
+            bridge="br-ex",
+            namespace=ri.ns_name(),
+            prefix=l3_agent.EXTERNAL_DEV_PREFIX)
+
     def test_routers_with_admin_state_down(self):
         agent = l3_agent.L3NATAgent(HOSTNAME, self.conf)
         self.plugin_api.get_external_network_id.return_value = None