From 14053fc79737f6ec6904021f3f6cdfd262c3b17e Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Fri, 15 Apr 2016 14:49:13 -0400 Subject: sync with curtin on render_interfaces This picks up newline cleanup and some bond fixes from curtin at rev 374. - Cleanup newline logic so we always have a clean '\n\n' between stanza - Add a unittest to validate bonding network config render, specifically when to emit auto $iface for dependent bond slaves. --- cloudinit/net/__init__.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'cloudinit/net/__init__.py') diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index a765b75a..7a6ec3a4 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -528,14 +528,16 @@ def render_interfaces(network_state): if len(value): content += " dns-{} {}\n".format(dnskey, " ".join(value)) - content += "\n" for iface in sorted(interfaces.values(), key=lambda k: (order[k['type']], k['name'])): - content += "auto {name}\n".format(**iface) + if content[-2:] != "\n\n": + content += "\n" subnets = iface.get('subnets', {}) if subnets: for index, subnet in zip(range(0, len(subnets)), subnets): + if content[-2:] != "\n\n": + content += "\n" iface['index'] = index iface['mode'] = subnet['type'] if iface['mode'].endswith('6'): @@ -546,27 +548,28 @@ def render_interfaces(network_state): iface['mode'] = 'dhcp' if index == 0: + if subnet['type'] != 'manual': + content += "auto {name}\n".format(**iface) content += "iface {name} {inet} {mode}\n".format(**iface) else: - content += "auto {name}:{index}\n".format(**iface) + if subnet['type'] != 'manual': + content += "auto {name}:{index}\n".format(**iface) content += \ "iface {name}:{index} {inet} {mode}\n".format(**iface) content += iface_add_subnet(iface, subnet) content += iface_add_attrs(iface) - for route in subnet.get('routes', []): - content += render_route(route, indent=" ") - content += "\n" else: + if 'bond-master' in iface: + content += "auto {name}\n".format(**iface) content += "iface {name} {inet} {mode}\n".format(**iface) content += iface_add_attrs(iface) - content += "\n" for route in network_state.get('routes'): content += render_route(route) # global replacements until v2 format - content = content.replace('mac_address', 'hwaddress ether') + content = content.replace('mac_address', 'hwaddress') return content -- cgit v1.2.3 From 5039a08032fc40c9c72afbef90184dbd1af10918 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Fri, 15 Apr 2016 15:13:07 -0400 Subject: support and render control=manual on initramfs network devices when reading the initramfs configurewd devices and turning them into network config, we change to not have 'auto' control (or allow=auto). The reason for this is that if the device was still up: a.) it would try to bring it up again (due to bug 1570142) b.) it would be brought down. 'b' is problematic if there is an iscsi or network root filesystem. Note, that ifupdown does now support 'no-auto-down' which means that the nic should not be brought down on 'ifdown -a'. LP: #1568637 --- cloudinit/net/__init__.py | 17 ++++++++++------- tests/unittests/test_net.py | 4 +++- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'cloudinit/net/__init__.py') diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index 7a6ec3a4..647c595b 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -350,7 +350,7 @@ def _klibc_to_config_entry(content, mac_addrs=None): # if no IPV4ADDR or IPV6ADDR, then go on. if pre + "ADDR" not in data: continue - subnet = {'type': proto} + subnet = {'type': proto, 'control': 'manual'} # these fields go right on the subnet for key in ('NETMASK', 'BROADCAST', 'GATEWAY'): @@ -444,12 +444,13 @@ def iface_add_subnet(iface, subnet): def iface_add_attrs(iface): content = "" ignore_map = [ - 'type', - 'name', + 'control', + 'index', 'inet', 'mode', - 'index', + 'name', 'subnets', + 'type', ] if iface['type'] not in ['bond', 'bridge', 'vlan']: ignore_map.append('mac_address') @@ -540,6 +541,7 @@ def render_interfaces(network_state): content += "\n" iface['index'] = index iface['mode'] = subnet['type'] + iface['control'] = subnet.get('control', 'auto') if iface['mode'].endswith('6'): iface['inet'] += '6' elif iface['mode'] == 'static' and ":" in subnet['address']: @@ -548,11 +550,11 @@ def render_interfaces(network_state): iface['mode'] = 'dhcp' if index == 0: - if subnet['type'] != 'manual': - content += "auto {name}\n".format(**iface) + if iface['control'] != 'manual': + content += "allow-{control} {name}\n".format(**iface) content += "iface {name} {inet} {mode}\n".format(**iface) else: - if subnet['type'] != 'manual': + if iface['control'] != 'manual': content += "auto {name}:{index}\n".format(**iface) content += \ "iface {name}:{index} {inet} {mode}\n".format(**iface) @@ -560,6 +562,7 @@ def render_interfaces(network_state): content += iface_add_subnet(iface, subnet) content += iface_add_attrs(iface) else: + # ifenslave docs say to auto the slave devices if 'bond-master' in iface: content += "auto {name}\n".format(**iface) content += "iface {name} {inet} {mode}\n".format(**iface) diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py index dfb31710..09235c4d 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -33,6 +33,7 @@ DHCP_EXPECTED_1 = { 'name': 'eth0', 'type': 'physical', 'subnets': [{'broadcast': '192.168.122.255', + 'control': 'manual', 'gateway': '192.168.122.1', 'dns_search': ['foo.com'], 'type': 'dhcp', @@ -59,7 +60,8 @@ DOMAINSEARCH='foo.com' STATIC_EXPECTED_1 = { 'name': 'eth1', 'type': 'physical', - 'subnets': [{'broadcast': '10.0.0.255', 'gateway': '10.0.0.1', + 'subnets': [{'broadcast': '10.0.0.255', 'control': 'manual', + 'gateway': '10.0.0.1', 'dns_search': ['foo.com'], 'type': 'static', 'netmask': '255.255.255.0', 'dns_nameservers': ['10.0.1.1']}], -- cgit v1.2.3 From 8384076e77d8fa5e0f6f3639f2dddd33c64236b9 Mon Sep 17 00:00:00 2001 From: Scott Moser Date: Fri, 15 Apr 2016 16:08:47 -0400 Subject: write 'allow-hotplug', but 'auto' for auto. --- cloudinit/net/__init__.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) (limited to 'cloudinit/net/__init__.py') diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index 647c595b..fa5a0033 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -509,6 +509,26 @@ def render_route(route, indent=""): return content +def iface_start_entry(iface, index): + fullname = iface['name'] + if index != 0: + fullname += ":%s" % index + + control = iface['control'] + if control == "auto": + cverb = "auto" + elif control in ("hotplug",): + cverb = "allow-" + control + else: + cverb = "# control-" + control + + subst = iface.copy() + subst.update({'fullname': fullname, 'cverb': cverb}) + + return ("{cverb} {fullname}\n" + "iface {fullname} {inet} {mode}\n").format(**subst) + + def render_interfaces(network_state): ''' Given state, emit etc/network/interfaces content ''' @@ -549,16 +569,7 @@ def render_interfaces(network_state): if iface['mode'].startswith('dhcp'): iface['mode'] = 'dhcp' - if index == 0: - if iface['control'] != 'manual': - content += "allow-{control} {name}\n".format(**iface) - content += "iface {name} {inet} {mode}\n".format(**iface) - else: - if iface['control'] != 'manual': - content += "auto {name}:{index}\n".format(**iface) - content += \ - "iface {name}:{index} {inet} {mode}\n".format(**iface) - + content += iface_start_entry(iface, index) content += iface_add_subnet(iface, subnet) content += iface_add_attrs(iface) else: -- cgit v1.2.3