Blame cloudinit/distros/networking.py

Packit Service 9bfd13
import abc
Packit Service 9bfd13
import logging
Packit Service 9bfd13
import os
Packit Service 9bfd13
Packit Service 9bfd13
from cloudinit import net, util
Packit Service 9bfd13
Packit Service 9bfd13
Packit Service 9bfd13
LOG = logging.getLogger(__name__)
Packit Service 9bfd13
Packit Service 9bfd13
Packit Service 9bfd13
# Type aliases (https://docs.python.org/3/library/typing.html#type-aliases),
Packit Service 9bfd13
# used to make the signatures of methods a little clearer
Packit Service 9bfd13
DeviceName = str
Packit Service 9bfd13
NetworkConfig = dict
Packit Service 9bfd13
Packit Service 9bfd13
Packit Service 9bfd13
class Networking(metaclass=abc.ABCMeta):
Packit Service 9bfd13
    """The root of the Networking hierarchy in cloud-init.
Packit Service 9bfd13
Packit Service 9bfd13
    This is part of an ongoing refactor in the cloud-init codebase, for more
Packit Service 9bfd13
    details see "``cloudinit.net`` -> ``cloudinit.distros.networking``
Packit Service 9bfd13
    Hierarchy" in HACKING.rst for full details.
Packit Service 9bfd13
    """
Packit Service 9bfd13
Packit Service 9bfd13
    def _get_current_rename_info(self) -> dict:
Packit Service 9bfd13
        return net._get_current_rename_info()
Packit Service 9bfd13
Packit Service 9bfd13
    def _rename_interfaces(self, renames: list, *, current_info=None) -> None:
Packit Service 9bfd13
        return net._rename_interfaces(renames, current_info=current_info)
Packit Service 9bfd13
Packit Service 9bfd13
    def apply_network_config_names(self, netcfg: NetworkConfig) -> None:
Packit Service 9bfd13
        return net.apply_network_config_names(netcfg)
Packit Service 9bfd13
Packit Service 9bfd13
    def device_devid(self, devname: DeviceName):
Packit Service 9bfd13
        return net.device_devid(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def device_driver(self, devname: DeviceName):
Packit Service 9bfd13
        return net.device_driver(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def extract_physdevs(self, netcfg: NetworkConfig) -> list:
Packit Service 9bfd13
        return net.extract_physdevs(netcfg)
Packit Service 9bfd13
Packit Service 9bfd13
    def find_fallback_nic(self, *, blacklist_drivers=None):
Packit Service 9bfd13
        return net.find_fallback_nic(blacklist_drivers=blacklist_drivers)
Packit Service 9bfd13
Packit Service 9bfd13
    def generate_fallback_config(
Packit Service 9bfd13
        self, *, blacklist_drivers=None, config_driver: bool = False
Packit Service 9bfd13
    ):
Packit Service 9bfd13
        return net.generate_fallback_config(
Packit Service 9bfd13
            blacklist_drivers=blacklist_drivers, config_driver=config_driver
Packit Service 9bfd13
        )
Packit Service 9bfd13
Packit Service 9bfd13
    def get_devicelist(self) -> list:
Packit Service 9bfd13
        return net.get_devicelist()
Packit Service 9bfd13
Packit Service 9bfd13
    def get_ib_hwaddrs_by_interface(self) -> dict:
Packit Service 9bfd13
        return net.get_ib_hwaddrs_by_interface()
Packit Service 9bfd13
Packit Service 9bfd13
    def get_ib_interface_hwaddr(
Packit Service 9bfd13
        self, devname: DeviceName, ethernet_format: bool
Packit Service 9bfd13
    ):
Packit Service 9bfd13
        return net.get_ib_interface_hwaddr(devname, ethernet_format)
Packit Service 9bfd13
Packit Service 9bfd13
    def get_interface_mac(self, devname: DeviceName):
Packit Service 9bfd13
        return net.get_interface_mac(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def get_interfaces(self) -> list:
Packit Service 9bfd13
        return net.get_interfaces()
Packit Service 9bfd13
Packit Service 9bfd13
    def get_interfaces_by_mac(self) -> dict:
Packit Service 9bfd13
        return net.get_interfaces_by_mac()
Packit Service 9bfd13
Packit Service 9bfd13
    def get_master(self, devname: DeviceName):
Packit Service 9bfd13
        return net.get_master(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def interface_has_own_mac(
Packit Service 9bfd13
        self, devname: DeviceName, *, strict: bool = False
Packit Service 9bfd13
    ) -> bool:
Packit Service 9bfd13
        return net.interface_has_own_mac(devname, strict=strict)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_bond(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_bond(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_bridge(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_bridge(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    @abc.abstractmethod
Packit Service 9bfd13
    def is_physical(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        """
Packit Service 9bfd13
        Is ``devname`` a physical network device?
Packit Service 9bfd13
Packit Service 9bfd13
        Examples of non-physical network devices: bonds, bridges, tunnels,
Packit Service 9bfd13
        loopback devices.
Packit Service 9bfd13
        """
Packit Service 9bfd13
Packit Service 9bfd13
    def is_renamed(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_renamed(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_up(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_up(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_vlan(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_vlan(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def master_is_bridge_or_bond(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.master_is_bridge_or_bond(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    @abc.abstractmethod
Packit Service 9bfd13
    def settle(self, *, exists=None) -> None:
Packit Service 9bfd13
        """Wait for device population in the system to complete.
Packit Service 9bfd13
Packit Service 9bfd13
        :param exists:
Packit Service 9bfd13
            An optional optimisation.  If given, only perform as much of the
Packit Service 9bfd13
            settle process as is required for the given DeviceName to be
Packit Service 9bfd13
            present in the system.  (This may include skipping the settle
Packit Service 9bfd13
            process entirely, if the device already exists.)
Packit Service 9bfd13
        :type exists: Optional[DeviceName]
Packit Service 9bfd13
        """
Packit Service 9bfd13
Packit Service 9bfd13
    def wait_for_physdevs(
Packit Service 9bfd13
        self, netcfg: NetworkConfig, *, strict: bool = True
Packit Service 9bfd13
    ) -> None:
Packit Service 9bfd13
        """Wait for all the physical devices in `netcfg` to exist on the system
Packit Service 9bfd13
Packit Service 9bfd13
        Specifically, this will call `self.settle` 5 times, and check after
Packit Service 9bfd13
        each one if the physical devices are now present in the system.
Packit Service 9bfd13
Packit Service 9bfd13
        :param netcfg:
Packit Service 9bfd13
            The NetworkConfig from which to extract physical devices to wait
Packit Service 9bfd13
            for.
Packit Service 9bfd13
        :param strict:
Packit Service 9bfd13
            Raise a `RuntimeError` if any physical devices are not present
Packit Service 9bfd13
            after waiting.
Packit Service 9bfd13
        """
Packit Service 9bfd13
        physdevs = self.extract_physdevs(netcfg)
Packit Service 9bfd13
Packit Service 9bfd13
        # set of expected iface names and mac addrs
Packit Service 9bfd13
        expected_ifaces = dict([(iface[0], iface[1]) for iface in physdevs])
Packit Service 9bfd13
        expected_macs = set(expected_ifaces.keys())
Packit Service 9bfd13
Packit Service 9bfd13
        # set of current macs
Packit Service 9bfd13
        present_macs = self.get_interfaces_by_mac().keys()
Packit Service 9bfd13
Packit Service 9bfd13
        # compare the set of expected mac address values to
Packit Service 9bfd13
        # the current macs present; we only check MAC as cloud-init
Packit Service 9bfd13
        # has not yet renamed interfaces and the netcfg may include
Packit Service 9bfd13
        # such renames.
Packit Service 9bfd13
        for _ in range(0, 5):
Packit Service 9bfd13
            if expected_macs.issubset(present_macs):
Packit Service 9bfd13
                LOG.debug("net: all expected physical devices present")
Packit Service 9bfd13
                return
Packit Service 9bfd13
Packit Service 9bfd13
            missing = expected_macs.difference(present_macs)
Packit Service 9bfd13
            LOG.debug("net: waiting for expected net devices: %s", missing)
Packit Service 9bfd13
            for mac in missing:
Packit Service 9bfd13
                # trigger a settle, unless this interface exists
Packit Service 9bfd13
                devname = expected_ifaces[mac]
Packit Service 9bfd13
                msg = "Waiting for settle or {} exists".format(devname)
Packit Service 9bfd13
                util.log_time(
Packit Service 9bfd13
                    LOG.debug,
Packit Service 9bfd13
                    msg,
Packit Service 9bfd13
                    func=self.settle,
Packit Service 9bfd13
                    kwargs={"exists": devname},
Packit Service 9bfd13
                )
Packit Service 9bfd13
Packit Service 9bfd13
            # update present_macs after settles
Packit Service 9bfd13
            present_macs = self.get_interfaces_by_mac().keys()
Packit Service 9bfd13
Packit Service 9bfd13
        msg = "Not all expected physical devices present: %s" % missing
Packit Service 9bfd13
        LOG.warning(msg)
Packit Service 9bfd13
        if strict:
Packit Service 9bfd13
            raise RuntimeError(msg)
Packit Service 9bfd13
Packit Service 9bfd13
Packit Service 9bfd13
class BSDNetworking(Networking):
Packit Service 9bfd13
    """Implementation of networking functionality shared across BSDs."""
Packit Service 9bfd13
Packit Service 9bfd13
    def is_physical(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        raise NotImplementedError()
Packit Service 9bfd13
Packit Service 9bfd13
    def settle(self, *, exists=None) -> None:
Packit Service 9bfd13
        """BSD has no equivalent to `udevadm settle`; noop."""
Packit Service 9bfd13
Packit Service 9bfd13
Packit Service 9bfd13
class LinuxNetworking(Networking):
Packit Service 9bfd13
    """Implementation of networking functionality common to Linux distros."""
Packit Service 9bfd13
Packit Service 9bfd13
    def get_dev_features(self, devname: DeviceName) -> str:
Packit Service 9bfd13
        return net.get_dev_features(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def has_netfail_standby_feature(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.has_netfail_standby_feature(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_netfailover(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_netfailover(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_netfail_master(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_netfail_master(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_netfail_primary(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_netfail_primary(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_netfail_standby(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return net.is_netfail_standby(devname)
Packit Service 9bfd13
Packit Service 9bfd13
    def is_physical(self, devname: DeviceName) -> bool:
Packit Service 9bfd13
        return os.path.exists(net.sys_dev_path(devname, "device"))
Packit Service 9bfd13
Packit Service 9bfd13
    def settle(self, *, exists=None) -> None:
Packit Service 9bfd13
        if exists is not None:
Packit Service 9bfd13
            exists = net.sys_dev_path(exists)
Packit Service 9bfd13
        util.udevadm_settle(exists=exists)