summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri John Ledkov <xnox@ubuntu.com>2017-04-20 11:08:48 +0100
committerScott Moser <smoser@brickies.net>2017-04-20 14:56:52 -0400
commitdf4ca453520342a0541ab9202305858bf39d4f48 (patch)
tree0169443f30db2f99f336d5bf53c7d875b43541ea
parent169a7105a25a27ee894af63cd8b5bcc3ded6fd2e (diff)
downloadvyos-cloud-init-df4ca453520342a0541ab9202305858bf39d4f48.tar.gz
vyos-cloud-init-df4ca453520342a0541ab9202305858bf39d4f48.zip
net: kernel lies about vlans not stealing mac addresses, when they do
Introduce is_vlan function and call that when building dictionary of interfaces by mac address. LP: #1682871
-rw-r--r--cloudinit/net/__init__.py7
-rw-r--r--tests/unittests/test_net.py30
2 files changed, 34 insertions, 3 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index 346be5d3..a072a8d6 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -86,6 +86,11 @@ def is_bridge(devname):
return os.path.exists(sys_dev_path(devname, "bridge"))
+def is_vlan(devname):
+ uevent = str(read_sys_net_safe(devname, "uevent"))
+ return 'DEVTYPE=vlan' in uevent.splitlines()
+
+
def is_connected(devname):
# is_connected isn't really as simple as that. 2 is
# 'physically connected'. 3 is 'not connected'. but a wlan interface will
@@ -393,6 +398,8 @@ def get_interfaces_by_mac():
continue
if is_bridge(name):
continue
+ if is_vlan(name):
+ continue
mac = get_interface_mac(name)
# some devices may not have a mac (tun0)
if not mac:
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 9cc5e4ab..89e75369 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -1463,13 +1463,16 @@ class TestNetRenderers(CiTestCase):
class TestGetInterfacesByMac(CiTestCase):
_data = {'devices': ['enp0s1', 'enp0s2', 'bond1', 'bridge1',
- 'bridge1-nic', 'tun0'],
+ 'bridge1-nic', 'tun0', 'bond1.101'],
'bonds': ['bond1'],
'bridges': ['bridge1'],
- 'own_macs': ['enp0s1', 'enp0s2', 'bridge1-nic', 'bridge1'],
+ 'vlans': ['bond1.101'],
+ 'own_macs': ['enp0s1', 'enp0s2', 'bridge1-nic', 'bridge1',
+ 'bond1.101'],
'macs': {'enp0s1': 'aa:aa:aa:aa:aa:01',
'enp0s2': 'aa:aa:aa:aa:aa:02',
'bond1': 'aa:aa:aa:aa:aa:01',
+ 'bond1.101': 'aa:aa:aa:aa:aa:01',
'bridge1': 'aa:aa:aa:aa:aa:03',
'bridge1-nic': 'aa:aa:aa:aa:aa:03',
'tun0': None}}
@@ -1484,13 +1487,16 @@ class TestGetInterfacesByMac(CiTestCase):
def _se_is_bridge(self, name):
return name in self.data['bridges']
+ def _se_is_vlan(self, name):
+ return name in self.data['vlans']
+
def _se_interface_has_own_mac(self, name):
return name in self.data['own_macs']
def _mock_setup(self):
self.data = copy.deepcopy(self._data)
mocks = ('get_devicelist', 'get_interface_mac', 'is_bridge',
- 'interface_has_own_mac')
+ 'interface_has_own_mac', 'is_vlan')
self.mocks = {}
for n in mocks:
m = mock.patch('cloudinit.net.' + n,
@@ -1536,6 +1542,24 @@ class TestGetInterfacesByMac(CiTestCase):
mock.call('b1')],
any_order=True)
+ def test_excludes_vlans(self):
+ self._mock_setup()
+ # add a device 'b1', make all return they have their "own mac",
+ # set everything other than 'b1' to be a vlan.
+ # then expect b1 is the only thing left.
+ self.data['macs']['b1'] = 'aa:aa:aa:aa:aa:b1'
+ self.data['devices'].append('b1')
+ self.data['bonds'] = []
+ self.data['bridges'] = []
+ self.data['own_macs'] = self.data['devices']
+ self.data['vlans'] = [f for f in self.data['devices'] if f != "b1"]
+ ret = net.get_interfaces_by_mac()
+ self.assertEqual({'aa:aa:aa:aa:aa:b1': 'b1'}, ret)
+ self.mocks['is_vlan'].assert_has_calls(
+ [mock.call('bridge1'), mock.call('enp0s1'), mock.call('bond1'),
+ mock.call('b1')],
+ any_order=True)
+
def _gzip_data(data):
with io.BytesIO() as iobuf: