|
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)
|