]> review.fuel-infra Code Review - openstack-build/neutron-build.git/commitdiff
Linuxbridge-agent: fix bridge deletion
authorNick <skywalker.nick@gmail.com>
Wed, 26 Aug 2015 10:16:14 +0000 (18:16 +0800)
committerArmando Migliaccio <armamig@gmail.com>
Mon, 31 Aug 2015 22:05:14 +0000 (22:05 +0000)
Make sure that linuxbridge agent doesn't delete
physical interfaces if they are specified in the
physical_interface_mappings.

Change-Id: I95e3c46b03ba2ae0872f5def47f26d4e8ea13094
Closes-Bug: #1334634

neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py
neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py

index 76592dc729ff556b7dfc857a9e78c1064cd3f0c7..47095c890e1ea4300b0dcf89234333142e0ad86c 100644 (file)
@@ -461,26 +461,25 @@ class LinuxBridgeManager(object):
 
     def delete_bridge(self, bridge_name):
         if ip_lib.device_exists(bridge_name):
+            physical_interfaces = set(self.interface_mappings.values())
             interfaces_on_bridge = self.get_interfaces_on_bridge(bridge_name)
             for interface in interfaces_on_bridge:
                 self.remove_interface(bridge_name, interface)
 
                 if interface.startswith(VXLAN_INTERFACE_PREFIX):
                     self.delete_interface(interface)
-                    continue
-
-                for physical_interface in self.interface_mappings.values():
-                    if (interface.startswith(physical_interface)):
-                        ips, gateway = self.get_interface_details(bridge_name)
-                        if ips:
-                            # This is a flat network or a VLAN interface that
-                            # was setup outside of neutron => return IP's from
-                            # bridge to interface
-                            self.update_interface_ip_details(interface,
-                                                             bridge_name,
-                                                             ips, gateway)
-                        elif physical_interface != interface:
-                            self.delete_interface(interface)
+                else:
+                    # Match the vlan/flat interface in the bridge.
+                    # If the bridge has an IP, it mean that this IP was moved
+                    # from the current interface, which also mean that this
+                    # interface was not created by the agent.
+                    ips, gateway = self.get_interface_details(bridge_name)
+                    if ips:
+                        self.update_interface_ip_details(interface,
+                                                         bridge_name,
+                                                         ips, gateway)
+                    elif interface not in physical_interfaces:
+                        self.delete_interface(interface)
 
             LOG.debug("Deleting bridge %s", bridge_name)
             bridge_device = bridge_lib.BridgeDevice(bridge_name)
index a48b513d9349a32775682806c485ec186f1db7e1..819ce6f591c6463991f0e5a79f73e7ba3b47b48b 100644 (file)
@@ -808,6 +808,23 @@ class TestLinuxBridgeManager(base.BaseTestCase):
             lbm.delete_bridge("br0")
             del_interface.assert_called_with("vxlan-1002")
 
+    def test_delete_bridge_with_physical_vlan(self):
+        self.lbm.interface_mappings.update({"physnet2": "eth1.4000"})
+        bridge_device = mock.Mock()
+        with mock.patch.object(ip_lib, "device_exists") as de_fn,\
+                mock.patch.object(self.lbm, "get_interfaces_on_bridge") as getif_fn,\
+                mock.patch.object(self.lbm, "remove_interface"),\
+                mock.patch.object(self.lbm, "get_interface_details") as if_det_fn,\
+                mock.patch.object(self.lbm, "delete_interface") as del_int,\
+                mock.patch.object(bridge_lib, "BridgeDevice",
+                                  return_value=bridge_device):
+            de_fn.return_value = True
+            getif_fn.return_value = ["eth1.1", "eth1.4000"]
+            if_det_fn.return_value = ([], None)
+            bridge_device.link.set_down.return_value = False
+            self.lbm.delete_bridge("br0")
+            del_int.assert_called_once_with("eth1.1")
+
     def test_remove_empty_bridges(self):
         self.lbm.network_map = {'net1': mock.Mock(), 'net2': mock.Mock()}