From 546a38fca6b5e9c389074c2365bf15b1071575ef Mon Sep 17 00:00:00 2001 From: rossella Date: Fri, 4 Apr 2014 13:13:31 +0000 Subject: [PATCH] Check if bridge exists and make sure it's UP in ensure_bridge Introduce _bridge_exists_and_ensure_up that checks if the bridge exists and if it's DOWN sets it UP Change-Id: Ide9d2bb04016cadb347b00cadbee7007e61bd01e Closes-bug: #1282741 --- .../agent/linuxbridge_neutron_agent.py | 20 ++++++++++++++++++- .../unit/linuxbridge/test_lb_neutron_agent.py | 12 ++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py b/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py index 9fe433289..962aba177 100755 --- a/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py +++ b/neutron/plugins/linuxbridge/agent/linuxbridge_neutron_agent.py @@ -279,10 +279,28 @@ class LinuxBridgeManager: src_device.addr.delete(ip_version=ip['ip_version'], cidr=ip['cidr']) + def _bridge_exists_and_ensure_up(self, bridge_name): + """Check if the bridge exists and make sure it is up.""" + br = ip_lib.IPDevice(bridge_name, self.root_helper) + try: + # If the device doesn't exist this will throw a RuntimeError + br.link.set_up() + except RuntimeError: + return False + return True + def ensure_bridge(self, bridge_name, interface=None, ips=None, gateway=None): """Create a bridge unless it already exists.""" - if not ip_lib.device_exists(bridge_name, root_helper=self.root_helper): + # _bridge_exists_and_ensure_up instead of device_exists is used here + # because there are cases where the bridge exists but it's not UP, + # for example: + # 1) A greenthread was executing this function and had not yet executed + # "ip link set bridge_name up" before eventlet switched to this + # thread running the same function + # 2) The Nova VIF driver was running concurrently and had just created + # the bridge, but had not yet put it UP + if not self._bridge_exists_and_ensure_up(bridge_name): LOG.debug(_("Starting bridge %(bridge_name)s for subinterface " "%(interface)s"), {'bridge_name': bridge_name, 'interface': interface}) diff --git a/neutron/tests/unit/linuxbridge/test_lb_neutron_agent.py b/neutron/tests/unit/linuxbridge/test_lb_neutron_agent.py index cc7cb334a..643dd850b 100644 --- a/neutron/tests/unit/linuxbridge/test_lb_neutron_agent.py +++ b/neutron/tests/unit/linuxbridge/test_lb_neutron_agent.py @@ -394,9 +394,19 @@ class TestLinuxBridgeManager(base.BaseTestCase): self.assertTrue(addgw_fn.called) self.assertTrue(delgw_fn.called) + def test_bridge_exists_and_ensure_up(self): + ip_lib_mock = mock.Mock() + with mock.patch.object(ip_lib, 'IPDevice', return_value=ip_lib_mock): + # device exists + self.assertTrue(self.lbm._bridge_exists_and_ensure_up("br0")) + self.assertTrue(ip_lib_mock.link.set_up.called) + # device doesn't exists + ip_lib_mock.link.set_up.side_effect = RuntimeError + self.assertFalse(self.lbm._bridge_exists_and_ensure_up("br0")) + def test_ensure_bridge(self): with contextlib.nested( - mock.patch.object(ip_lib, 'device_exists'), + mock.patch.object(self.lbm, '_bridge_exists_and_ensure_up'), mock.patch.object(utils, 'execute'), mock.patch.object(self.lbm, 'update_interface_ip_details'), mock.patch.object(self.lbm, 'interface_exists_on_bridge'), -- 2.45.2