diff options
author | zsdc <taras@vyos.io> | 2024-05-16 03:12:08 +0300 |
---|---|---|
committer | zsdc <taras@vyos.io> | 2024-05-16 03:16:32 +0300 |
commit | 02d7ea9908f726dc6a363f28942f4edb7d350340 (patch) | |
tree | 86e6661ac67d4ec939e0f9a45179809ae1a0adf7 /cloudinit | |
parent | fe56e399d4d95510a8837b9eb2045eda2316164c (diff) | |
download | vyos-cloud-init-02d7ea9908f726dc6a363f28942f4edb7d350340.tar.gz vyos-cloud-init-02d7ea9908f726dc6a363f28942f4edb7d350340.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')
-rw-r--r-- | cloudinit/config/cc_vyos.py | 32 | ||||
-rw-r--r-- | cloudinit/config/cc_vyos_ifupdown.py | 62 |
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() |