diff options
author | Scott Moser <smoser@ubuntu.com> | 2016-04-15 16:21:05 -0400 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2016-04-15 16:21:05 -0400 |
commit | b029dcefe1ed33be8ed80f2e376ca6874dfd64f7 (patch) | |
tree | 6ed7c2f73a8af96d4db8ef6702db47c573a58a56 | |
parent | 53f035122dffd5b821e29fe9af9a72276d9728b4 (diff) | |
parent | 8384076e77d8fa5e0f6f3639f2dddd33c64236b9 (diff) | |
download | vyos-cloud-init-b029dcefe1ed33be8ed80f2e376ca6874dfd64f7.tar.gz vyos-cloud-init-b029dcefe1ed33be8ed80f2e376ca6874dfd64f7.zip |
network: do not write interface as 'auto' from ip= on command line.
When ip= on the kernel command line defines the networking, set
those network devices to be manually controlled, instead of 'auto'.
The reason for this is that if they're marked as 'auto':
a.) a second attempt will be made to ifup them.
b.) they'll be brought down on shutdown
'b' is problematic on network root filesystem.
Also this picks up 2 changes from curtin's net module:
- 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.
LP: #1568637
-rw-r--r-- | cloudinit/net/__init__.py | 53 | ||||
-rw-r--r-- | tests/unittests/test_net.py | 4 |
2 files changed, 38 insertions, 19 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index a765b75a..31544fd8 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') @@ -508,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 ''' @@ -528,16 +549,19 @@ 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'] + iface['control'] = subnet.get('control', 'auto') if iface['mode'].endswith('6'): iface['inet'] += '6' elif iface['mode'] == 'static' and ":" in subnet['address']: @@ -545,28 +569,21 @@ def render_interfaces(network_state): if iface['mode'].startswith('dhcp'): iface['mode'] = 'dhcp' - if index == 0: - content += "iface {name} {inet} {mode}\n".format(**iface) - else: - 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) - for route in subnet.get('routes', []): - content += render_route(route, indent=" ") - content += "\n" 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) 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 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']}], |