diff options
author | Dimitri John Ledkov <xnox@ubuntu.com> | 2017-04-20 11:08:48 +0100 |
---|---|---|
committer | Scott Moser <smoser@brickies.net> | 2017-04-20 14:56:52 -0400 |
commit | df4ca453520342a0541ab9202305858bf39d4f48 (patch) | |
tree | 0169443f30db2f99f336d5bf53c7d875b43541ea | |
parent | 169a7105a25a27ee894af63cd8b5bcc3ded6fd2e (diff) | |
download | vyos-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__.py | 7 | ||||
-rw-r--r-- | tests/unittests/test_net.py | 30 |
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: |