summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChad Smith <chad.smith@canonical.com>2020-03-04 13:53:19 -0700
committerGitHub <noreply@github.com>2020-03-04 13:53:19 -0700
commit1d2dfc5d879dc905f440697c2b805c9485dda821 (patch)
treed65cbc78f93f47d57602508fc3403cd2fcb406e2
parentfa1abfec27050a4fb71cad950a17e42f9b43b478 (diff)
downloadvyos-cloud-init-1d2dfc5d879dc905f440697c2b805c9485dda821.tar.gz
vyos-cloud-init-1d2dfc5d879dc905f440697c2b805c9485dda821.zip
net: support network-config:disabled on the kernel commandline (#232)
Allow disabling cloud-init's network configuration via a plain-text kernel cmdline Cloud-init docs indicate that users can disable cloud-init networking via kernel command line parameter 'network-config=<YAML>'. This does not work unless the <YAML> payload base64 encoded. Document the base64 encoding requirement and add a plain-text value for disabling cloud-init network config: network-config=disabled Also: - Log an error and ignore any plain-text network-config payloads that are not specifically 'network-config=disabled'. - Log a warning if network-config kernel param is invalid yaml but do not raise an exception, allowing boot to continue and use fallback networking. LP: #1862702
-rwxr-xr-xcloudinit/net/cmdline.py34
-rw-r--r--doc/rtd/topics/network-config.rst22
-rw-r--r--tests/unittests/test_net.py17
3 files changed, 51 insertions, 22 deletions
diff --git a/cloudinit/net/cmdline.py b/cloudinit/net/cmdline.py
index 64e1c699..814ce411 100755
--- a/cloudinit/net/cmdline.py
+++ b/cloudinit/net/cmdline.py
@@ -10,6 +10,7 @@ import base64
import glob
import gzip
import io
+import logging
import os
from cloudinit import util
@@ -19,6 +20,8 @@ from . import read_sys_net_safe
_OPEN_ISCSI_INTERFACE_FILE = "/run/initramfs/open-iscsi.interface"
+KERNEL_CMDLINE_NETWORK_CONFIG_DISABLED = "disabled"
+
class InitramfsNetworkConfigSource(metaclass=abc.ABCMeta):
"""ABC for net config sources that read config written by initramfses"""
@@ -233,34 +236,35 @@ def read_initramfs_config():
return None
-def _decomp_gzip(blob, strict=True):
- # decompress blob. raise exception if not compressed unless strict=False.
+def _decomp_gzip(blob):
+ # decompress blob or return original blob
with io.BytesIO(blob) as iobuf:
gzfp = None
try:
gzfp = gzip.GzipFile(mode="rb", fileobj=iobuf)
return gzfp.read()
except IOError:
- if strict:
- raise
return blob
finally:
if gzfp:
gzfp.close()
-def _b64dgz(b64str, gzipped="try"):
- # decode a base64 string. If gzipped is true, transparently uncompresss
- # if gzipped is 'try', then try gunzip, returning the original on fail.
- try:
- blob = base64.b64decode(b64str)
- except TypeError:
- raise ValueError("Invalid base64 text: %s" % b64str)
+def _b64dgz(data):
+ """Decode a string base64 encoding, if gzipped, uncompress as well
- if not gzipped:
- return blob
+ :return: decompressed unencoded string of the data or empty string on
+ unencoded data.
+ """
+ try:
+ blob = base64.b64decode(data)
+ except (TypeError, ValueError):
+ logging.error(
+ "Expected base64 encoded kernel commandline parameter"
+ " network-config. Ignoring network-config=%s.", data)
+ return ''
- return _decomp_gzip(blob, strict=gzipped != "try")
+ return _decomp_gzip(blob)
def read_kernel_cmdline_config(cmdline=None):
@@ -273,6 +277,8 @@ def read_kernel_cmdline_config(cmdline=None):
if tok.startswith("network-config="):
data64 = tok.split("=", 1)[1]
if data64:
+ if data64 == KERNEL_CMDLINE_NETWORK_CONFIG_DISABLED:
+ return {"config": "disabled"}
return util.load_yaml(_b64dgz(data64))
return None
diff --git a/doc/rtd/topics/network-config.rst b/doc/rtd/topics/network-config.rst
index 1520ba9a..0144dfae 100644
--- a/doc/rtd/topics/network-config.rst
+++ b/doc/rtd/topics/network-config.rst
@@ -25,17 +25,23 @@ For example, OpenStack may provide network config in the MetaData Service.
**System Config**
-A ``network:`` entry in /etc/cloud/cloud.cfg.d/* configuration files.
+A ``network:`` entry in ``/etc/cloud/cloud.cfg.d/*`` configuration files.
**Kernel Command Line**
-``ip=`` or ``network-config=<YAML config string>``
+``ip=`` or ``network-config=<Base64 encoded YAML config string>``
User-data cannot change an instance's network configuration. In the absence
of network configuration in any of the above sources , `Cloud-init`_ will
write out a network configuration that will issue a DHCP request on a "first"
network interface.
+.. note::
+
+ The network-config value is expected to be a Base64 encoded YAML string in
+ :ref:`network_config_v1` or :ref:`network_config_v2` format. Optionally it
+ can be compressed with ``gzip`` prior to Base64 encoding.
+
Disabling Network Configuration
===============================
@@ -48,19 +54,19 @@ on other methods, such as embedded configuration or other customizations.
**Kernel Command Line**
-`Cloud-init`_ will check for a parameter ``network-config`` and the
-value is expected to be YAML string in the :ref:`network_config_v1` format.
-The YAML string may optionally be ``Base64`` encoded, and optionally
-compressed with ``gzip``.
+`Cloud-init`_ will check additionally check for the parameter
+``network-config=disabled`` which will automatically disable any network
+configuration.
Example disabling kernel command line entry: ::
- network-config={config: disabled}
+ network-config=disabled
**cloud config**
-In the combined cloud-init configuration dictionary. ::
+In the combined cloud-init configuration dictionary, merged from
+``/etc/cloud/cloud.cfg`` and ``/etc/cloud/cloud.cfg.d/*``::
network:
config: disabled
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index bedd05fe..e03857c4 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -4017,6 +4017,8 @@ class TestEniNetworkStateToEni(CiTestCase):
class TestCmdlineConfigParsing(CiTestCase):
+ with_logs = True
+
simple_cfg = {
'config': [{"type": "physical", "name": "eth0",
"mac_address": "c0:d6:9f:2c:e8:80",
@@ -4066,6 +4068,21 @@ class TestCmdlineConfigParsing(CiTestCase):
found = cmdline.read_kernel_cmdline_config(cmdline=raw_cmdline)
self.assertEqual(found, self.simple_cfg)
+ def test_cmdline_with_net_config_disabled(self):
+ raw_cmdline = 'ro network-config=disabled root=foo'
+ found = cmdline.read_kernel_cmdline_config(cmdline=raw_cmdline)
+ self.assertEqual(found, {'config': 'disabled'})
+
+ def test_cmdline_with_net_config_unencoded_logs_error(self):
+ """network-config cannot be unencoded besides 'disabled'."""
+ raw_cmdline = 'ro network-config={config:disabled} root=foo'
+ found = cmdline.read_kernel_cmdline_config(cmdline=raw_cmdline)
+ self.assertIsNone(found)
+ expected_log = (
+ 'ERROR: Expected base64 encoded kernel commandline parameter'
+ ' network-config. Ignoring network-config={config:disabled}.')
+ self.assertIn(expected_log, self.logs.getvalue())
+
def test_cmdline_with_b64_gz(self):
data = _gzip_data(json.dumps(self.simple_cfg).encode())
encoded_text = base64.b64encode(data).decode()