summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Harper <ryan.harper@canonical.com>2019-09-17 10:11:00 +0000
committerServer Team CI Bot <josh.powers+server-team-bot@canonical.com>2019-09-17 10:11:00 +0000
commit059d049c57cac02cdeaca832233a19712e0b4ded (patch)
tree9af213fb538f5c014a994b78681e9128fbf524e3
parent6f931795cc7c79033e6cc5c2f1be8de3e03a645b (diff)
downloadvyos-cloud-init-059d049c57cac02cdeaca832233a19712e0b4ded.tar.gz
vyos-cloud-init-059d049c57cac02cdeaca832233a19712e0b4ded.zip
net: add is_master check for filtering device list
Some network devices are transformed into a bond via kernel magic and do not have the 'bonding' sysfs attribute, but like a bond they have a duplicate MAC of other bond members. On Azure Advanced Networking SRIOV devices are auto bonded and will have the same MAC as the HyperV nic. We can detect this via the 'master' sysfs attribute in the device sysfs path and this patch adds this to the list of devices we ignore when enumerating device lists. LP: #1844191
-rw-r--r--cloudinit/net/__init__.py10
-rw-r--r--cloudinit/net/tests/test_init.py17
2 files changed, 25 insertions, 2 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index 0eb952fe..5de5c6de 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -109,6 +109,10 @@ def is_bond(devname):
return os.path.exists(sys_dev_path(devname, "bonding"))
+def has_master(devname):
+ return os.path.exists(sys_dev_path(devname, path="master"))
+
+
def is_netfailover(devname, driver=None):
""" netfailover driver uses 3 nics, master, primary and standby.
this returns True if the device is either the primary or standby
@@ -154,7 +158,7 @@ def is_netfail_master(devname, driver=None):
Return True if all of the above is True.
"""
- if os.path.exists(sys_dev_path(devname, path='master')):
+ if has_master(devname):
return False
if driver is None:
@@ -211,7 +215,7 @@ def is_netfail_standby(devname, driver=None):
Return True if all of the above is True.
"""
- if not os.path.exists(sys_dev_path(devname, path='master')):
+ if not has_master(devname):
return False
if driver is None:
@@ -786,6 +790,8 @@ def get_interfaces():
continue
if is_bond(name):
continue
+ if has_master(name):
+ continue
if is_netfailover(name):
continue
mac = get_interface_mac(name)
diff --git a/cloudinit/net/tests/test_init.py b/cloudinit/net/tests/test_init.py
index 7259dbe3..999db986 100644
--- a/cloudinit/net/tests/test_init.py
+++ b/cloudinit/net/tests/test_init.py
@@ -157,6 +157,12 @@ class TestReadSysNet(CiTestCase):
ensure_file(os.path.join(self.sysdir, 'eth0', 'bonding'))
self.assertTrue(net.is_bond('eth0'))
+ def test_has_master(self):
+ """has_master is True when /sys/net/devname/master exists."""
+ self.assertFalse(net.has_master('enP1s1'))
+ ensure_file(os.path.join(self.sysdir, 'enP1s1', 'master'))
+ self.assertTrue(net.has_master('enP1s1'))
+
def test_is_vlan(self):
"""is_vlan is True when /sys/net/devname/uevent has DEVTYPE=vlan."""
ensure_file(os.path.join(self.sysdir, 'eth0', 'uevent'))
@@ -424,6 +430,17 @@ class TestGetInterfaceMAC(CiTestCase):
expected = [('eth2', 'aa:bb:cc:aa:bb:cc', None, None)]
self.assertEqual(expected, net.get_interfaces())
+ def test_get_interfaces_by_mac_skips_master_devs(self):
+ """Ignore interfaces with a master device which would have dup mac."""
+ mac1 = mac2 = 'aa:bb:cc:aa:bb:cc'
+ write_file(os.path.join(self.sysdir, 'eth1', 'addr_assign_type'), '0')
+ write_file(os.path.join(self.sysdir, 'eth1', 'address'), mac1)
+ write_file(os.path.join(self.sysdir, 'eth1', 'master'), "blah")
+ write_file(os.path.join(self.sysdir, 'eth2', 'addr_assign_type'), '0')
+ write_file(os.path.join(self.sysdir, 'eth2', 'address'), mac2)
+ expected = [('eth2', mac2, None, None)]
+ self.assertEqual(expected, net.get_interfaces())
+
@mock.patch('cloudinit.net.is_netfailover')
def test_get_interfaces_by_mac_skips_netfailvoer(self, m_netfail):
"""Ignore interfaces if netfailover primary or standby."""