diff options
-rw-r--r-- | cloudinit/net/__init__.py | 3 | ||||
-rw-r--r-- | tests/unittests/test_net.py | 27 |
2 files changed, 22 insertions, 8 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index a072a8d6..8c6cd057 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -393,6 +393,7 @@ def get_interfaces_by_mac(): else: raise ret = {} + empty_mac = '00:00:00:00:00:00' for name in devs: if not interface_has_own_mac(name): continue @@ -404,6 +405,8 @@ def get_interfaces_by_mac(): # some devices may not have a mac (tun0) if not mac: continue + if mac == empty_mac and name != 'lo': + continue if mac in ret: raise RuntimeError( "duplicate mac found! both '%s' and '%s' have mac '%s'" % diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py index 68a0157a..8bd3f433 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -1542,24 +1542,24 @@ class TestNetRenderers(CiTestCase): class TestGetInterfacesByMac(CiTestCase): - _data = {'devices': ['enp0s1', 'enp0s2', 'bond1', 'bridge1', - 'bridge1-nic', 'tun0', 'bond1.101'], - 'bonds': ['bond1'], + _data = {'bonds': ['bond1'], 'bridges': ['bridge1'], 'vlans': ['bond1.101'], 'own_macs': ['enp0s1', 'enp0s2', 'bridge1-nic', 'bridge1', - 'bond1.101'], + 'bond1.101', 'lo'], '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', + 'lo': '00:00:00:00:00:00', + 'greptap0': '00:00:00:00:00:00', 'tun0': None}} data = {} def _se_get_devicelist(self): - return self.data['devices'] + return list(self.data['devices']) def _se_get_interface_mac(self, name): return self.data['macs'][name] @@ -1575,6 +1575,7 @@ class TestGetInterfacesByMac(CiTestCase): def _mock_setup(self): self.data = copy.deepcopy(self._data) + self.data['devices'] = set(list(self.data['macs'].keys())) mocks = ('get_devicelist', 'get_interface_mac', 'is_bridge', 'interface_has_own_mac', 'is_vlan') self.mocks = {} @@ -1602,7 +1603,7 @@ class TestGetInterfacesByMac(CiTestCase): [mock.call('enp0s1'), mock.call('bond1')], any_order=True) self.assertEqual( {'aa:aa:aa:aa:aa:01': 'enp0s1', 'aa:aa:aa:aa:aa:02': 'enp0s2', - 'aa:aa:aa:aa:aa:03': 'bridge1-nic'}, + 'aa:aa:aa:aa:aa:03': 'bridge1-nic', '00:00:00:00:00:00': 'lo'}, ret) def test_excludes_bridges(self): @@ -1611,7 +1612,7 @@ class TestGetInterfacesByMac(CiTestCase): # set everything other than 'b1' to be a bridge. # 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['devices'].add('b1') self.data['bonds'] = [] self.data['own_macs'] = self.data['devices'] self.data['bridges'] = [f for f in self.data['devices'] if f != "b1"] @@ -1628,7 +1629,7 @@ class TestGetInterfacesByMac(CiTestCase): # 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['devices'].add('b1') self.data['bonds'] = [] self.data['bridges'] = [] self.data['own_macs'] = self.data['devices'] @@ -1640,6 +1641,16 @@ class TestGetInterfacesByMac(CiTestCase): mock.call('b1')], any_order=True) + def test_duplicates_of_empty_mac_are_ok(self): + """Duplicate macs of 00:00:00:00:00:00 should be skipped.""" + self._mock_setup() + empty_mac = "00:00:00:00:00:00" + addnics = ('greptap1', 'lo', 'greptap2') + self.data['macs'].update(dict((k, empty_mac) for k in addnics)) + self.data['devices'].update(set(addnics)) + ret = net.get_interfaces_by_mac() + self.assertEqual('lo', ret[empty_mac]) + def _gzip_data(data): with io.BytesIO() as iobuf: |