From 70304ff90d931265cb736ace692967242c9b9729 Mon Sep 17 00:00:00 2001 From: zsdc Date: Thu, 16 May 2024 03:12:08 +0300 Subject: 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. --- cloudinit/config/cc_vyos.py | 32 +------------------ cloudinit/config/cc_vyos_ifupdown.py | 62 ++++++++++++++++++++++++++++++++++++ config/cloud.cfg.d/10_vyos.cfg | 1 + 3 files changed, 64 insertions(+), 31 deletions(-) create mode 100644 cloudinit/config/cc_vyos_ifupdown.py 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 . + +# 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() diff --git a/config/cloud.cfg.d/10_vyos.cfg b/config/cloud.cfg.d/10_vyos.cfg index d4415126..f34e262a 100644 --- a/config/cloud.cfg.d/10_vyos.cfg +++ b/config/cloud.cfg.d/10_vyos.cfg @@ -19,6 +19,7 @@ cloud_init_modules: # The modules that run in the 'config' stage cloud_config_modules: + - vyos_ifupdown - vyos - write_files - vyos_userdata -- cgit v1.2.3