summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2016-04-15 16:21:05 -0400
committerScott Moser <smoser@ubuntu.com>2016-04-15 16:21:05 -0400
commitb029dcefe1ed33be8ed80f2e376ca6874dfd64f7 (patch)
tree6ed7c2f73a8af96d4db8ef6702db47c573a58a56
parent53f035122dffd5b821e29fe9af9a72276d9728b4 (diff)
parent8384076e77d8fa5e0f6f3639f2dddd33c64236b9 (diff)
downloadvyos-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__.py53
-rw-r--r--tests/unittests/test_net.py4
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']}],