diff options
author | James Falcon <james.falcon@canonical.com> | 2021-10-07 11:27:36 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-07 10:27:36 -0600 |
commit | 9c147e8341e287366790e60658f646cdcc59bef2 (patch) | |
tree | 7b4fe68c61d4e9630322e4903fc07f7e4b868cff /cloudinit | |
parent | 3d2bac8bf6d0c53f56e14cb2c15b0c695cf0a647 (diff) | |
download | vyos-cloud-init-9c147e8341e287366790e60658f646cdcc59bef2.tar.gz vyos-cloud-init-9c147e8341e287366790e60658f646cdcc59bef2.zip |
Allow disabling of network activation (SC-307) (#1048)
In #919 (81299de), we refactored some of the code used to bring up
networks across distros. Previously, the call to bring up network
interfaces during 'init' stage unintentionally resulted in a no-op
such that network interfaces were NEVER brought up by cloud-init, even
if new network interfaces were found after crawling the metadata.
The code was altered to bring up these discovered network interfaces.
On ubuntu, this results in a 'netplan apply' call during 'init' stage
for any ubuntu-based distro on a datasource that has a NETWORK
dependency. On GCE, this additional 'netplan apply' conflicts with the
google-guest-agent service, resulting in an instance that can no
be connected to.
This commit adds a 'disable_network_activation' option that can be
enabled in /etc/cloud.cfg to disable the activation of network
interfaces in 'init' stage.
LP: #1938299
Diffstat (limited to 'cloudinit')
-rw-r--r-- | cloudinit/cmd/main.py | 11 | ||||
-rw-r--r-- | cloudinit/cmd/tests/test_main.py | 23 | ||||
-rwxr-xr-x | cloudinit/distros/__init__.py | 3 |
3 files changed, 35 insertions, 2 deletions
diff --git a/cloudinit/cmd/main.py b/cloudinit/cmd/main.py index 1de1de99..63186d34 100644 --- a/cloudinit/cmd/main.py +++ b/cloudinit/cmd/main.py @@ -239,6 +239,12 @@ def purge_cache_on_python_version_change(init): util.write_file(python_version_path, current_python_version) +def _should_bring_up_interfaces(init, args): + if util.get_cfg_option_bool(init.cfg, 'disable_network_activation'): + return False + return not args.local + + def main_init(name, args): deps = [sources.DEP_FILESYSTEM, sources.DEP_NETWORK] if args.local: @@ -348,6 +354,7 @@ def main_init(name, args): util.del_file(os.path.join(path_helper.get_cpath("data"), "no-net")) # Stage 5 + bring_up_interfaces = _should_bring_up_interfaces(init, args) try: init.fetch(existing=existing) # if in network mode, and the datasource is local @@ -367,7 +374,7 @@ def main_init(name, args): util.logexc(LOG, ("No instance datasource found!" " Likely bad things to come!")) if not args.force: - init.apply_network_config(bring_up=not args.local) + init.apply_network_config(bring_up=bring_up_interfaces) LOG.debug("[%s] Exiting without datasource", mode) if mode == sources.DSMODE_LOCAL: return (None, []) @@ -388,7 +395,7 @@ def main_init(name, args): # dhcp clients to advertize this hostname to any DDNS services # LP: #1746455. _maybe_set_hostname(init, stage='local', retry_stage='network') - init.apply_network_config(bring_up=bool(mode != sources.DSMODE_LOCAL)) + init.apply_network_config(bring_up=bring_up_interfaces) if mode == sources.DSMODE_LOCAL: if init.datasource.dsmode != mode: diff --git a/cloudinit/cmd/tests/test_main.py b/cloudinit/cmd/tests/test_main.py index 1f5975b0..2e380848 100644 --- a/cloudinit/cmd/tests/test_main.py +++ b/cloudinit/cmd/tests/test_main.py @@ -4,6 +4,9 @@ from collections import namedtuple import copy import os from io import StringIO +from unittest import mock + +import pytest from cloudinit.cmd import main from cloudinit import safeyaml @@ -162,4 +165,24 @@ class TestMain(FilesystemMockingTestCase): for log in expected_logs: self.assertIn(log, self.stderr.getvalue()) + +class TestShouldBringUpInterfaces: + @pytest.mark.parametrize('cfg_disable,args_local,expected', [ + (True, True, False), + (True, False, False), + (False, True, False), + (False, False, True), + ]) + def test_should_bring_up_interfaces( + self, cfg_disable, args_local, expected + ): + init = mock.Mock() + init.cfg = {'disable_network_activation': cfg_disable} + + args = mock.Mock() + args.local = args_local + + result = main._should_bring_up_interfaces(init, args) + assert result == expected + # vi: ts=4 expandtab diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py index 63e78591..426a2cf4 100755 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py @@ -227,8 +227,11 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta): # Now try to bring them up if bring_up: + LOG.debug('Bringing up newly configured network interfaces') network_activator = activators.select_activator() network_activator.bring_up_all_interfaces(network_state) + else: + LOG.debug("Not bringing up newly configured network interfaces") return False def apply_network_config_names(self, netconfig): |