summaryrefslogtreecommitdiff
path: root/cloudinit/net
diff options
context:
space:
mode:
authorDaniel Watkins <daniel@daniel-watkins.co.uk>2019-08-22 21:07:16 +0000
committerServer Team CI Bot <josh.powers+server-team-bot@canonical.com>2019-08-22 21:07:16 +0000
commita3926bffc985e5d39056858f65259a4ac438c037 (patch)
tree9efddf56da59de445735f2cf512e12dd18f8a338 /cloudinit/net
parente6383719c1adccf20b5c21cfba1c5a2462d663a2 (diff)
downloadvyos-cloud-init-a3926bffc985e5d39056858f65259a4ac438c037.tar.gz
vyos-cloud-init-a3926bffc985e5d39056858f65259a4ac438c037.zip
net/cmdline: refactor to allow multiple initramfs network config sources
This refactors read_initramfs_config to support multiple different types of initramfs network configuration. It introduces an InitramfsNetworkConfigSource abstract base class. There is currently a single sub-class, KlibcNetworkConfigSource, which contains the logic which previously was directly within read_initramfs_config.
Diffstat (limited to 'cloudinit/net')
-rwxr-xr-xcloudinit/net/cmdline.py127
1 files changed, 95 insertions, 32 deletions
diff --git a/cloudinit/net/cmdline.py b/cloudinit/net/cmdline.py
index 556a10f3..55166ea8 100755
--- a/cloudinit/net/cmdline.py
+++ b/cloudinit/net/cmdline.py
@@ -5,20 +5,95 @@
#
# This file is part of cloud-init. See LICENSE file for license information.
+import abc
import base64
import glob
import gzip
import io
import os
-from . import get_devicelist
-from . import read_sys_net_safe
+import six
from cloudinit import util
+from . import get_devicelist
+from . import read_sys_net_safe
+
_OPEN_ISCSI_INTERFACE_FILE = "/run/initramfs/open-iscsi.interface"
+@six.add_metaclass(abc.ABCMeta)
+class InitramfsNetworkConfigSource(object):
+ """ABC for net config sources that read config written by initramfses"""
+
+ @abc.abstractmethod
+ def is_applicable(self):
+ # type: () -> bool
+ """Is this initramfs config source applicable to the current system?"""
+ pass
+
+ @abc.abstractmethod
+ def render_config(self):
+ # type: () -> dict
+ """Render a v1 network config from the initramfs configuration"""
+ pass
+
+
+class KlibcNetworkConfigSource(InitramfsNetworkConfigSource):
+ """InitramfsNetworkConfigSource for klibc initramfs (i.e. Debian/Ubuntu)
+
+ Has three parameters, but they are intended to make testing simpler, _not_
+ for use in production code. (This is indicated by the prepended
+ underscores.)
+ """
+
+ def __init__(self, _files=None, _mac_addrs=None, _cmdline=None):
+ self._files = _files
+ self._mac_addrs = _mac_addrs
+ self._cmdline = _cmdline
+
+ # Set defaults here, as they require computation that we don't want to
+ # do at method definition time
+ if self._files is None:
+ self._files = _get_klibc_net_cfg_files()
+ if self._cmdline is None:
+ self._cmdline = util.get_cmdline()
+ if self._mac_addrs is None:
+ self._mac_addrs = {}
+ for k in get_devicelist():
+ mac_addr = read_sys_net_safe(k, 'address')
+ if mac_addr:
+ self._mac_addrs[k] = mac_addr
+
+ def is_applicable(self):
+ # type: () -> bool
+ """
+ Return whether this system has klibc initramfs network config or not
+
+ Will return True if:
+ (a) klibc files exist in /run, AND
+ (b) either:
+ (i) ip= or ip6= are on the kernel cmdline, OR
+ (ii) an open-iscsi interface file is present in the system
+ """
+ if self._files:
+ if 'ip=' in self._cmdline or 'ip6=' in self._cmdline:
+ return True
+ if os.path.exists(_OPEN_ISCSI_INTERFACE_FILE):
+ # iBft can configure networking without ip=
+ return True
+ return False
+
+ def render_config(self):
+ # type: () -> dict
+ return config_from_klibc_net_cfg(
+ files=self._files, mac_addrs=self._mac_addrs,
+ )
+
+
+_INITRAMFS_CONFIG_SOURCES = [KlibcNetworkConfigSource]
+
+
def _klibc_to_config_entry(content, mac_addrs=None):
"""Convert a klibc written shell content file to a 'config' entry
When ip= is seen on the kernel command line in debian initramfs
@@ -137,6 +212,24 @@ def config_from_klibc_net_cfg(files=None, mac_addrs=None):
return {'config': entries, 'version': 1}
+def read_initramfs_config():
+ """
+ Return v1 network config for initramfs-configured networking (or None)
+
+ This will consider each _INITRAMFS_CONFIG_SOURCES entry in turn, and return
+ v1 network configuration for the first one that is applicable. If none are
+ applicable, return None.
+ """
+ for src_cls in _INITRAMFS_CONFIG_SOURCES:
+ cfg_source = src_cls()
+
+ if not cfg_source.is_applicable():
+ continue
+
+ return cfg_source.render_config()
+ return None
+
+
def _decomp_gzip(blob, strict=True):
# decompress blob. raise exception if not compressed unless strict=False.
with io.BytesIO(blob) as iobuf:
@@ -167,36 +260,6 @@ def _b64dgz(b64str, gzipped="try"):
return _decomp_gzip(blob, strict=gzipped != "try")
-def _is_initramfs_netconfig(files, cmdline):
- if files:
- if 'ip=' in cmdline or 'ip6=' in cmdline:
- return True
- if os.path.exists(_OPEN_ISCSI_INTERFACE_FILE):
- # iBft can configure networking without ip=
- return True
- return False
-
-
-def read_initramfs_config(files=None, mac_addrs=None, cmdline=None):
- if cmdline is None:
- cmdline = util.get_cmdline()
-
- if files is None:
- files = _get_klibc_net_cfg_files()
-
- if not _is_initramfs_netconfig(files, cmdline):
- return None
-
- if mac_addrs is None:
- mac_addrs = {}
- for k in get_devicelist():
- mac_addr = read_sys_net_safe(k, 'address')
- if mac_addr:
- mac_addrs[k] = mac_addr
-
- return config_from_klibc_net_cfg(files=files, mac_addrs=mac_addrs)
-
-
def read_kernel_cmdline_config(cmdline=None):
if cmdline is None:
cmdline = util.get_cmdline()