From 1ec34b7d0d38324053996394be90d6fdecfed3ef Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 26 Aug 2015 18:16:14 +0800 Subject: [PATCH] Linuxbridge-agent: fix bridge deletion 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 --- .../agent/linuxbridge_neutron_agent.py | 27 +++++++++---------- .../agent/test_linuxbridge_neutron_agent.py | 17 ++++++++++++ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py index 76592dc72..47095c890 100644 --- a/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py +++ b/neutron/plugins/ml2/drivers/linuxbridge/agent/linuxbridge_neutron_agent.py @@ -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) diff --git a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py index a48b513d9..819ce6f59 100644 --- a/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py +++ b/neutron/tests/unit/plugins/ml2/drivers/linuxbridge/agent/test_linuxbridge_neutron_agent.py @@ -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()} -- 2.45.2