cloud-init-dev team mailing list archive
-
cloud-init-dev team
-
Mailing list archive
-
Message #02944
[Merge] ~smoser/cloud-init:feature/curtin-centos8 into cloud-init:master
Scott Moser has proposed merging ~smoser/cloud-init:feature/curtin-centos8 into cloud-init:master.
Commit message:
sysconfig: use MACADDR on bonds/bridges to configure mac_address
Previously, sysconfig rendered HWADDR for all interface types, but
that value is only used to identify physical devices. Instead use
MACADDR to configure the MAC on virtual devices, like bonds and
bridges.
- Sort bond slave list to ensure consistent ordering in sysconfig
rendered files.
- Add unittests for sysconfig rendering of bonds/bridges with
mac_address
LP: #1701417
Requested reviews:
cloud-init commiters (cloud-init-dev)
Related bugs:
Bug #1701417 in cloud-init: "cloud-init fails to configure bonding on CentOS 7"
https://bugs.launchpad.net/cloud-init/+bug/1701417
For more details, see:
https://code.launchpad.net/~smoser/cloud-init/+git/cloud-init/+merge/327838
--
Your team cloud-init commiters is requested to review the proposed merge of ~smoser/cloud-init:feature/curtin-centos8 into cloud-init:master.
diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py
index c7df36c..8494e66 100644
--- a/cloudinit/net/sysconfig.py
+++ b/cloudinit/net/sysconfig.py
@@ -264,6 +264,9 @@ class Renderer(renderer.Renderer):
for (old_key, new_key) in [('mac_address', 'HWADDR'), ('mtu', 'MTU')]:
old_value = iface.get(old_key)
if old_value is not None:
+ # only set HWADDR on physical interfaces
+ if old_key == 'mac_address' and iface['type'] != 'physical':
+ continue
iface_cfg[new_key] = old_value
@classmethod
@@ -430,6 +433,9 @@ class Renderer(renderer.Renderer):
master_cfg['BONDING_MASTER'] = True
master_cfg.kind = 'bond'
+ if 'mac_address' in iface and iface.get('mac_address'):
+ iface_cfg['MACADDR'] = iface.get('mac_address')
+
iface_subnets = iface.get("subnets", [])
route_cfg = iface_cfg.routes
cls._render_subnets(iface_cfg, iface_subnets)
@@ -441,6 +447,7 @@ class Renderer(renderer.Renderer):
[slave_iface['name'] for slave_iface in
network_state.iter_interfaces(slave_filter)
if slave_iface['bond-master'] == iface_name])
+
for index, bond_slave in enumerate(bond_slaves):
slavestr = 'BONDING_SLAVE%s' % index
iface_cfg[slavestr] = bond_slave
@@ -499,6 +506,10 @@ class Renderer(renderer.Renderer):
for old_key, new_key in cls.bridge_opts_keys:
if old_key in iface:
iface_cfg[new_key] = iface[old_key]
+
+ if 'mac_address' in iface and iface.get('mac_address'):
+ iface_cfg['MACADDR'] = iface.get('mac_address')
+
# Is this the right key to get all the connected interfaces?
for bridged_iface_name in iface.get('bridge_ports', []):
# Ensure all bridged interfaces are correctly tagged
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index d15cd1f..38f11e7 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -422,6 +422,28 @@ NETWORK_CONFIGS = {
via: 65.61.151.37
set-name: eth99
""").rstrip(' '),
+ 'expected_sysconfig': {
+ 'ifcfg-eth1': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=eth1
+ HWADDR=cf:d6:af:48:e8:80
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no"""),
+ 'ifcfg-eth99': textwrap.dedent("""\
+ BOOTPROTO=dhcp
+ DEFROUTE=yes
+ DEVICE=eth99
+ GATEWAY=65.61.151.37
+ HWADDR=c0:d6:9f:2c:e8:80
+ IPADDR=192.168.21.3
+ NETMASK=255.255.255.0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no"""),
+ },
'yaml': textwrap.dedent("""
version: 1
config:
@@ -758,6 +780,118 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
- sacchromyces.maas
- brettanomyces.maas
""").rstrip(' '),
+ 'expected_sysconfig': {
+ 'ifcfg-bond0': textwrap.dedent("""\
+ BONDING_MASTER=yes
+ BONDING_OPTS="mode=active-backup """
+ """xmit_hash_policy=layer3+4 miimon=100"
+ BONDING_SLAVE0=eth1
+ BONDING_SLAVE1=eth2
+ BOOTPROTO=dhcp
+ DEVICE=bond0
+ DHCPV6C=yes
+ IPV6INIT=yes
+ MACADDR=aa:bb:cc:dd:ee:ff
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Bond
+ USERCTL=no"""),
+ 'ifcfg-bond0.200': textwrap.dedent("""\
+ BOOTPROTO=dhcp
+ DEVICE=bond0.200
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ PHYSDEV=bond0
+ TYPE=Ethernet
+ USERCTL=no
+ VLAN=yes"""),
+ 'ifcfg-br0': textwrap.dedent("""\
+ AGEING=250
+ BOOTPROTO=none
+ DEFROUTE=yes
+ DEVICE=br0
+ IPADDR=192.168.14.2
+ IPV6ADDR=2001:1::1/64
+ IPV6INIT=yes
+ IPV6_DEFAULTGW=2001:4800:78ff:1b::1
+ NETMASK=255.255.255.0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ PRIO=22
+ STP=off
+ TYPE=Bridge
+ USERCTL=no"""),
+ 'ifcfg-eth0': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=eth0
+ HWADDR=c0:d6:9f:2c:e8:80
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no"""),
+ 'ifcfg-eth0.101': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEFROUTE=yes
+ DEVICE=eth0.101
+ GATEWAY=192.168.0.1
+ IPADDR=192.168.0.2
+ IPADDR1=192.168.2.10
+ MTU=1500
+ NETMASK=255.255.255.0
+ NETMASK1=255.255.255.0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ PHYSDEV=eth0
+ TYPE=Ethernet
+ USERCTL=no
+ VLAN=yes"""),
+ 'ifcfg-eth1': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=eth1
+ HWADDR=aa:d6:9f:2c:e8:80
+ MASTER=bond0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ SLAVE=yes
+ TYPE=Ethernet
+ USERCTL=no"""),
+ 'ifcfg-eth2': textwrap.dedent("""\
+ BOOTPROTO=none
+ DEVICE=eth2
+ HWADDR=c0:bb:9f:2c:e8:80
+ MASTER=bond0
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ SLAVE=yes
+ TYPE=Ethernet
+ USERCTL=no"""),
+ 'ifcfg-eth3': textwrap.dedent("""\
+ BOOTPROTO=none
+ BRIDGE=br0
+ DEVICE=eth3
+ HWADDR=66:bb:9f:2c:e8:80
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no"""),
+ 'ifcfg-eth4': textwrap.dedent("""\
+ BOOTPROTO=none
+ BRIDGE=br0
+ DEVICE=eth4
+ HWADDR=98:bb:9f:2c:e8:80
+ NM_CONTROLLED=no
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no"""),
+ 'ifcfg-eth5': textwrap.dedent("""\
+ BOOTPROTO=dhcp
+ DEVICE=eth5
+ HWADDR=98:bb:9f:2c:e8:8a
+ NM_CONTROLLED=no
+ ONBOOT=no
+ TYPE=Ethernet
+ USERCTL=no""")
+ },
'yaml': textwrap.dedent("""
version: 1
config:
@@ -934,7 +1068,7 @@ pre-down route del -net 10.0.0.0 netmask 255.0.0.0 gw 11.0.0.1 metric 3 || true
DEFROUTE=yes
DEVICE=bond0
GATEWAY=192.168.0.1
- HWADDR=aa:bb:cc:dd:e8:ff
+ MACADDR=aa:bb:cc:dd:e8:ff
IPADDR=192.168.0.2
IPADDR1=192.168.1.2
IPV6ADDR=2001:1::1/92
@@ -2042,6 +2176,20 @@ class TestEniRoundTrip(CiTestCase):
entry['expected_eni'].splitlines(),
files['/etc/network/interfaces'].splitlines())
+ def testsimple_render_small(self):
+ entry = NETWORK_CONFIGS['small']
+ files = self._render_and_read(network_config=yaml.load(entry['yaml']))
+ self.assertEqual(
+ entry['expected_eni'].splitlines(),
+ files['/etc/network/interfaces'].splitlines())
+
+ def testsimple_render_all(self):
+ entry = NETWORK_CONFIGS['all']
+ files = self._render_and_read(network_config=yaml.load(entry['yaml']))
+ self.assertEqual(
+ entry['expected_eni'].splitlines(),
+ files['/etc/network/interfaces'].splitlines())
+
def test_routes_rendered(self):
# as reported in bug 1649652
conf = [