summaryrefslogtreecommitdiff
path: root/cloudinit/config
diff options
context:
space:
mode:
authorzsdc <taras@vyos.io>2024-05-16 03:12:08 +0300
committerzdc <zdc@users.noreply.github.com>2024-05-16 03:13:51 +0300
commit70304ff90d931265cb736ace692967242c9b9729 (patch)
tree02d5487084e01b9d2c5546d4dff2729938f64100 /cloudinit/config
parentfd8c12784127e3258762d0163455d595b427ea53 (diff)
downloadvyos-cloud-init-70304ff90d931265cb736ace692967242c9b9729.tar.gz
vyos-cloud-init-70304ff90d931265cb736ace692967242c9b9729.zip
ifupdown: T6038: Cleanup network config properly
Cloud-init in environments where Meta-data is available via network configures the main interface and keeps the config in `/etc/network/interfaces.d/`. This config later interferes with the VyOS configuration. To avoid the problem previously the code in the `cc_vyos.py` module was used, but this is not enough. The module is running only once during instance deployment. But Cloud-init will re-add the config file with each boot. There are two ways to solve this incompatibility (within Cloud-init) - disable network config or perform cleanup during each boot. Disabling network config is not correct in this context, because it blocks the ability to fetch Meta-data after the first boot, which in turn blocks the ability to run per-boot modules with an updated config. Therefore, the cleanup code was extracted to an independent `cc_vyos_ifupdown.py` module that performs proper cleanup with each boot.
Diffstat (limited to 'cloudinit/config')
-rw-r--r--cloudinit/config/cc_vyos.py32
-rw-r--r--cloudinit/config/cc_vyos_ifupdown.py62
2 files changed, 63 insertions, 31 deletions
diff --git a/cloudinit/config/cc_vyos.py b/cloudinit/config/cc_vyos.py
index 3195dcaa..9c9ac697 100644
--- a/cloudinit/config/cc_vyos.py
+++ b/cloudinit/config/cc_vyos.py
@@ -23,7 +23,7 @@
import re
import ipaddress
from pathlib import Path
-from subprocess import run, DEVNULL
+from subprocess import run
from uuid import uuid4
from cloudinit import log as logging
from cloudinit.ssh_util import AuthKeyLineParser
@@ -992,33 +992,6 @@ def set_config_hostname(config, hostname, fqdn):
logger.error("Failed to configure domain-name: {}".format(err))
-# cleanup network interface config file added by cloud-init
-def network_cleanup():
- logger.debug("Cleaning up network configuration applied by Cloud-Init")
- net_config_file = Path('/etc/network/interfaces.d/50-cloud-init')
- if net_config_file.exists():
- logger.debug(f"Configuration file {net_config_file} was found")
- try:
- # get a list of interfaces that need to be deconfigured
- configured_ifaces = run(
- ['ifquery', '-l', '-X', 'lo', '-i', net_config_file],
- capture_output=True).stdout.decode().splitlines()
- if configured_ifaces:
- for iface in configured_ifaces:
- logger.debug(f"Deconfiguring interface: {iface}")
- run(['ifdown', iface], stdout=DEVNULL)
- # delete the file
- net_config_file.unlink()
- logger.debug(f"Configuration file {net_config_file} was removed")
- except Exception as err:
- logger.error(f"Failed to cleanup network configuration: {err}")
-
- udev_rules_file = Path('/etc/udev/rules.d/70-persistent-net.rules')
- if udev_rules_file.exists():
- logger.debug(f"Configuration file {udev_rules_file} was removed")
- udev_rules_file.unlink()
-
-
# main config handler
def handle(name, cfg, cloud, log, _args):
logger.debug("Cloud-init config: {}".format(cfg))
@@ -1182,6 +1155,3 @@ def handle(name, cfg, cloud, log, _args):
logger.debug("Configuration file saved: {}".format(cfg_file_name))
except Exception as e:
logger.error("Failed to write configs into file {}: {}".format(cfg_file_name, e))
-
- # since we already have a config file, it is a time to clean up what Cloud-init may left
- network_cleanup()
diff --git a/cloudinit/config/cc_vyos_ifupdown.py b/cloudinit/config/cc_vyos_ifupdown.py
new file mode 100644
index 00000000..41457a1e
--- /dev/null
+++ b/cloudinit/config/cc_vyos_ifupdown.py
@@ -0,0 +1,62 @@
+# Copyright (C) 2024 VyOS Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# This module is used to cleanup ifupdown config that may be left by Cloud-init after its initialization.
+# This must be done during each boot to avoid interferring with VyOS CLI config.
+
+import logging
+from pathlib import Path
+from subprocess import run, DEVNULL
+from cloudinit.settings import PER_ALWAYS
+
+LOG = logging.getLogger(__name__)
+
+frequency = PER_ALWAYS
+
+
+# cleanup network interface config file added by cloud-init
+def network_cleanup() -> None:
+ LOG.debug("Cleaning up network configuration applied by Cloud-Init")
+ net_config_file = Path("/etc/network/interfaces.d/50-cloud-init")
+ if net_config_file.exists():
+ LOG.debug(f"Configuration file {net_config_file} was found")
+ try:
+ # get a list of interfaces that need to be deconfigured
+ configured_ifaces: list[str] = (
+ run(
+ ["ifquery", "-l", "-X", "lo", "-i", net_config_file],
+ capture_output=True,
+ )
+ .stdout.decode()
+ .splitlines()
+ )
+ if configured_ifaces:
+ for iface in configured_ifaces:
+ LOG.debug(f"Deconfiguring interface: {iface}")
+ run(["ifdown", iface], stdout=DEVNULL)
+ # delete the file
+ net_config_file.unlink()
+ LOG.debug(f"Configuration file {net_config_file} was removed")
+ except Exception as err:
+ LOG.error(f"Failed to cleanup network configuration: {err}")
+
+ udev_rules_file = Path("/etc/udev/rules.d/70-persistent-net.rules")
+ if udev_rules_file.exists():
+ LOG.debug(f"Configuration file {udev_rules_file} was removed")
+ udev_rules_file.unlink()
+
+
+def handle(*args) -> None:
+ LOG.debug('Running "cc_vyos_ifupdown" module')
+ network_cleanup()