Check if interface belongs to a Linux Bridge before removing

Checks if an interface belongs to a Linux Bridge before deleting
the interface and the bridge.

Change-Id: I03145681e0634ec52663a1ec4f54021e3325a6b1
Closes-Bug: #1736727
This commit is contained in:
Rodolfo Alonso Hernandez 2017-12-06 14:05:15 +00:00
parent 23c71e083a
commit 72b27d0e86
2 changed files with 30 additions and 3 deletions

View File

@ -107,6 +107,12 @@ def device_exists(device):
return os.path.exists('/sys/class/net/%s' % device)
def interface_in_bridge(bridge, device):
"""Check if an ethernet device belongs to a Linux Bridge."""
return os.path.exists('/sys/class/net/%(bridge)s/brif/%(device)s' %
{'bridge': bridge, 'device': device})
def _delete_net_dev(dev):
"""Delete a network device only if it exists."""
if device_exists(dev):
@ -172,7 +178,8 @@ def ensure_bridge(bridge):
@privsep.vif_plug.entrypoint
def delete_bridge(bridge, dev):
if device_exists(bridge):
processutils.execute('brctl', 'delif', bridge, dev)
if interface_in_bridge(bridge, dev):
processutils.execute('brctl', 'delif', bridge, dev)
processutils.execute('ip', 'link', 'set', bridge, 'down')
processutils.execute('brctl', 'delbr', bridge)

View File

@ -84,15 +84,20 @@ class LinuxNetTest(testtools.TestCase):
@mock.patch.object(processutils, "execute")
@mock.patch.object(linux_net, "device_exists", return_value=False)
def test_delete_bridge_none(self, mock_dev_exists, mock_execute):
@mock.patch.object(linux_net, "interface_in_bridge", return_value=False)
def test_delete_bridge_none(self, mock_interface_br, mock_dev_exists,
mock_execute,):
linux_net.delete_bridge("br0", "vnet1")
mock_execute.assert_not_called()
mock_dev_exists.assert_has_calls([mock.call("br0")])
mock_interface_br.assert_not_called()
@mock.patch.object(processutils, "execute")
@mock.patch.object(linux_net, "device_exists", return_value=True)
def test_delete_bridge_exists(self, mock_dev_exists, mock_execute):
@mock.patch.object(linux_net, "interface_in_bridge", return_value=True)
def test_delete_bridge_exists(self, mock_interface_br, mock_dev_exists,
mock_execute):
linux_net.delete_bridge("br0", "vnet1")
calls = [
@ -101,6 +106,21 @@ class LinuxNetTest(testtools.TestCase):
mock.call('brctl', 'delbr', 'br0')]
mock_execute.assert_has_calls(calls)
mock_dev_exists.assert_has_calls([mock.call("br0")])
mock_interface_br.assert_called_once_with("br0", "vnet1")
@mock.patch.object(processutils, "execute")
@mock.patch.object(linux_net, "device_exists", return_value=True)
@mock.patch.object(linux_net, "interface_in_bridge", return_value=False)
def test_delete_interface_not_present(self, mock_interface_br,
mock_dev_exists, mock_execute):
linux_net.delete_bridge("br0", "vnet1")
calls = [
mock.call('ip', 'link', 'set', 'br0', 'down'),
mock.call('brctl', 'delbr', 'br0')]
mock_execute.assert_has_calls(calls)
mock_dev_exists.assert_has_calls([mock.call("br0")])
mock_interface_br.assert_called_once_with("br0", "vnet1")
@mock.patch.object(processutils, "execute")
def test_add_bridge_port(self, mock_execute):