summaryrefslogtreecommitdiff
path: root/cloudinit
diff options
context:
space:
mode:
authorRyan Harper <ryan.harper@canonical.com>2019-10-24 20:16:47 +0000
committerServer Team CI Bot <josh.powers+server-team-bot@canonical.com>2019-10-24 20:16:47 +0000
commitf1c788e2bb7c86069d43a015267facfb8aefcdf0 (patch)
tree528ad995c0ee62b4cf5d24080faf1b8f17937256 /cloudinit
parent5bec6b0e2a2ce5fd03bb04f441536fc130e67997 (diff)
downloadvyos-cloud-init-f1c788e2bb7c86069d43a015267facfb8aefcdf0.tar.gz
vyos-cloud-init-f1c788e2bb7c86069d43a015267facfb8aefcdf0.zip
net/netplan: use ipv6-mtu key for specifying ipv6 mtu values
netplan introduced an 'info' subcommand which emits yaml describing implemented features that indicate new or changed fields and values in the yaml that it accepts. Previously, cloud-init emitted the key 'mtu6' for ipv6 MTU values. This is not correct and netplan will fail to parse these values. Netplan as of 0.98 supports both the info subcommand and the ipv6-mtu key. This branch modifies the netplan renderer to collect the netplan info output into a 'features' property which is a list of available feature flags which the renderer can use to modify its output. If the command is not available, no feature flags are set and cloud-init will render IPv6 MTU values just as MTU for the subnet.
Diffstat (limited to 'cloudinit')
-rwxr-xr-xcloudinit/cmd/devel/net_convert.py2
-rw-r--r--cloudinit/net/netplan.py35
2 files changed, 29 insertions, 8 deletions
diff --git a/cloudinit/cmd/devel/net_convert.py b/cloudinit/cmd/devel/net_convert.py
index 9b768304..2d27a76a 100755
--- a/cloudinit/cmd/devel/net_convert.py
+++ b/cloudinit/cmd/devel/net_convert.py
@@ -113,6 +113,8 @@ def handle_args(name, args):
config['postcmds'] = False
# trim leading slash
config['netplan_path'] = config['netplan_path'][1:]
+ # enable some netplan features
+ config['features'] = ['dhcp-use-domains', 'ipv6-mtu']
else:
r_cls = sysconfig.Renderer
config = distro.renderer_configs.get('sysconfig')
diff --git a/cloudinit/net/netplan.py b/cloudinit/net/netplan.py
index 54be1221..749d46f8 100644
--- a/cloudinit/net/netplan.py
+++ b/cloudinit/net/netplan.py
@@ -35,7 +35,7 @@ def _get_params_dict_by_match(config, match):
if key.startswith(match))
-def _extract_addresses(config, entry, ifname):
+def _extract_addresses(config, entry, ifname, features=None):
"""This method parse a cloudinit.net.network_state dictionary (config) and
maps netstate keys/values into a dictionary (entry) to represent
netplan yaml.
@@ -67,7 +67,7 @@ def _extract_addresses(config, entry, ifname):
'match': {'macaddress': '52:54:00:12:34:00'},
'mtu': 1501,
'address': ['192.168.1.2/24', '2001:4800:78ff:1b:be76:4eff:fe06:1000"],
- 'mtu6': 1480}
+ 'ipv6-mtu': 1480}
"""
@@ -80,6 +80,8 @@ def _extract_addresses(config, entry, ifname):
else:
return [obj, ]
+ if features is None:
+ features = []
addresses = []
routes = []
nameservers = []
@@ -109,8 +111,8 @@ def _extract_addresses(config, entry, ifname):
searchdomains += _listify(subnet.get('dns_search', []))
if 'mtu' in subnet:
mtukey = 'mtu'
- if subnet_is_ipv6(subnet):
- mtukey += '6'
+ if subnet_is_ipv6(subnet) and 'ipv6-mtu' in features:
+ mtukey = 'ipv6-mtu'
entry.update({mtukey: subnet.get('mtu')})
for route in subnet.get('routes', []):
to_net = "%s/%s" % (route.get('network'),
@@ -180,6 +182,7 @@ class Renderer(renderer.Renderer):
"""Renders network information in a /etc/netplan/network.yaml format."""
NETPLAN_GENERATE = ['netplan', 'generate']
+ NETPLAN_INFO = ['netplan', 'info']
def __init__(self, config=None):
if not config:
@@ -189,6 +192,22 @@ class Renderer(renderer.Renderer):
self.netplan_header = config.get('netplan_header', None)
self._postcmds = config.get('postcmds', False)
self.clean_default = config.get('clean_default', True)
+ self._features = config.get('features', None)
+
+ @property
+ def features(self):
+ if self._features is None:
+ try:
+ info_blob, _err = util.subp(self.NETPLAN_INFO, capture=True)
+ info = util.load_yaml(info_blob)
+ self._features = info['netplan.io']['features']
+ except util.ProcessExecutionError:
+ # if the info subcommand is not present then we don't have any
+ # new features
+ pass
+ except (TypeError, KeyError) as e:
+ LOG.debug('Failed to list features from netplan info: %s', e)
+ return self._features
def render_network_state(self, network_state, templates=None, target=None):
# check network state for version
@@ -272,7 +291,7 @@ class Renderer(renderer.Renderer):
else:
del eth['match']
del eth['set-name']
- _extract_addresses(ifcfg, eth, ifname)
+ _extract_addresses(ifcfg, eth, ifname, self.features)
ethernets.update({ifname: eth})
elif if_type == 'bond':
@@ -297,7 +316,7 @@ class Renderer(renderer.Renderer):
slave_interfaces = ifcfg.get('bond-slaves')
if slave_interfaces == 'none':
_extract_bond_slaves_by_name(interfaces, bond, ifname)
- _extract_addresses(ifcfg, bond, ifname)
+ _extract_addresses(ifcfg, bond, ifname, self.features)
bonds.update({ifname: bond})
elif if_type == 'bridge':
@@ -332,7 +351,7 @@ class Renderer(renderer.Renderer):
bridge.update({'parameters': br_config})
if ifcfg.get('mac_address'):
bridge['macaddress'] = ifcfg.get('mac_address').lower()
- _extract_addresses(ifcfg, bridge, ifname)
+ _extract_addresses(ifcfg, bridge, ifname, self.features)
bridges.update({ifname: bridge})
elif if_type == 'vlan':
@@ -344,7 +363,7 @@ class Renderer(renderer.Renderer):
macaddr = ifcfg.get('mac_address', None)
if macaddr is not None:
vlan['macaddress'] = macaddr.lower()
- _extract_addresses(ifcfg, vlan, ifname)
+ _extract_addresses(ifcfg, vlan, ifname, self.features)
vlans.update({ifname: vlan})
# inject global nameserver values under each all interface which