summaryrefslogtreecommitdiff
path: root/cloudinit/net/__init__.py
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2016-06-03 14:18:38 -0400
committerScott Moser <smoser@ubuntu.com>2016-06-03 14:18:38 -0400
commitfe6919dcd37c6c1ecd371e5eb20b605ab20a6420 (patch)
treeef540fa8f50f147303235179675d2ebfd95c598c /cloudinit/net/__init__.py
parente2c2d70cde19211b18e5ec333e1cb0382d93f14d (diff)
downloadvyos-cloud-init-fe6919dcd37c6c1ecd371e5eb20b605ab20a6420.tar.gz
vyos-cloud-init-fe6919dcd37c6c1ecd371e5eb20b605ab20a6420.zip
improve how 'lo' is handled when rendering network state to interfaces
if you provide network state with a proper 'lo' entry, then when you render network interfaces you would get 2 entries. the additional one was because we add an 'lo' always and also because we had to put global 'dns' entries there. this fixes that duplicatation by handling lo specifically.
Diffstat (limited to 'cloudinit/net/__init__.py')
-rw-r--r--cloudinit/net/__init__.py105
1 files changed, 61 insertions, 44 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index f47053b2..0066561e 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -17,6 +17,7 @@
# along with Curtin. If not, see <http://www.gnu.org/licenses/>.
import base64
+import copy
import errno
import glob
import gzip
@@ -418,7 +419,7 @@ def render_persistent_net(network_state):
# TODO: switch valid_map based on mode inet/inet6
def iface_add_subnet(iface, subnet):
- content = ""
+ content = []
valid_map = [
'address',
'netmask',
@@ -437,14 +438,14 @@ def iface_add_subnet(iface, subnet):
value = " ".join(value)
if '_' in key:
key = key.replace('_', '-')
- content += " {} {}\n".format(key, value)
+ content.append(" {} {}".format(key, value))
return content
# TODO: switch to valid_map for attrs
def iface_add_attrs(iface):
- content = ""
+ content = []
ignore_map = [
'control',
'index',
@@ -461,7 +462,7 @@ def iface_add_attrs(iface):
if value and key not in ignore_map:
if type(value) == list:
value = " ".join(value)
- content += " {} {}\n".format(key, value)
+ content.append(" {} {}".format(key, value))
return content
@@ -481,10 +482,10 @@ def render_route(route, indent=""):
1. http://askubuntu.com/questions/168033/
how-to-set-static-routes-in-ubuntu-server
"""
- content = ""
+ content = []
up = indent + "post-up route add"
down = indent + "pre-down route del"
- eol = " || true\n"
+ eol = " || true"
mapping = {
'network': '-net',
'netmask': 'netmask',
@@ -493,20 +494,20 @@ def render_route(route, indent=""):
}
if route['network'] == '0.0.0.0' and route['netmask'] == '0.0.0.0':
default_gw = " default gw %s" % route['gateway']
- content += up + default_gw + eol
- content += down + default_gw + eol
+ content.append(up + default_gw + eol)
+ content.append(down + default_gw + eol)
elif route['network'] == '::' and route['netmask'] == 0:
# ipv6!
default_gw = " -A inet6 default gw %s" % route['gateway']
- content += up + default_gw + eol
- content += down + default_gw + eol
+ content.append(up + default_gw + eol)
+ content.append(down + default_gw + eol)
else:
route_line = ""
for k in ['network', 'netmask', 'gateway', 'metric']:
if k in route:
route_line += " %s %s" % (mapping[k], route[k])
- content += up + route_line + eol
- content += down + route_line + eol
+ content.append(up + route_line + eol)
+ content.append(down + route_line + eol)
return content
@@ -527,8 +528,38 @@ def iface_start_entry(iface, index):
subst = iface.copy()
subst.update({'fullname': fullname, 'cverb': cverb})
- return ("{cverb} {fullname}\n"
- "iface {fullname} {inet} {mode}\n").format(**subst)
+ if 'inet' not in subst:
+ print("bug....iface: %s" % iface)
+ return ["{cverb} {fullname}".format(**subst),
+ "iface {fullname} {inet} {mode}".format(**subst)]
+
+
+def _render_iface(iface):
+ lines = []
+ subnets = iface.get('subnets', {})
+ if subnets:
+ for index, subnet in zip(range(0, len(subnets)), subnets):
+ 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']:
+ iface['inet'] += '6'
+ if iface['mode'].startswith('dhcp'):
+ iface['mode'] = 'dhcp'
+
+ lines.extend(iface_start_entry(iface, index))
+ lines.extend(iface_add_subnet(iface, subnet))
+ lines.extend(iface_add_attrs(iface))
+ lines.append("")
+ else:
+ # ifenslave docs say to auto the slave devices
+ if 'bond-master' in iface:
+ lines.append("auto {name}".format(**iface))
+ lines.append("iface {name} {inet} {mode}".format(**iface))
+ lines.extend(iface_add_attrs(iface))
+ return lines
def render_interfaces(network_state):
@@ -546,44 +577,30 @@ def render_interfaces(network_state):
'bridge': 2,
'vlan': 3,
}
- content += "auto lo\niface lo inet loopback\n"
+
+ # handle 'lo' specifically as we need to insert the global dns entries
+ # there (as that is the only interface) that will be always up.
+ lo = {'name': 'lo', 'type': 'physical', 'inet': 'inet',
+ 'subnets': [{'type': 'loopback', 'control': 'auto'}]}
+ for iface in interfaces.values():
+ if iface.get('name') == "lo":
+ lo = copy.deepcopy(iface)
for dnskey, value in network_state.get('dns', {}).items():
if len(value):
- content += " dns-{} {}\n".format(dnskey, " ".join(value))
+ lo['subnets'][0]["dns_" + dnskey] = value
+
+ sections = [_render_iface(lo)]
for iface in sorted(interfaces.values(),
key=lambda k: (order[k['type']], k['name'])):
-
- 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']:
- iface['inet'] += '6'
- if iface['mode'].startswith('dhcp'):
- iface['mode'] = 'dhcp'
-
- content += iface_start_entry(iface, index)
- 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)
- content += iface_add_attrs(iface)
+ if iface.get('name') == "lo":
+ continue
+ sections.append(_render_iface(iface))
for route in network_state.get('routes'):
- content += render_route(route)
+ sections.append(render_route(route))
+ content = ''.join(['\n'.join(s) + '\n\n' for s in sections])
# global replacements until v2 format
content = content.replace('mac_address', 'hwaddress')
return content