Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 104 additions & 40 deletions cloudinit/net/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import logging
import os
import re
from typing import Any, Dict
from typing import Any, Dict, List, Optional

from cloudinit import subp, util
from cloudinit.net.network_state import mask_to_net_prefix
Expand Down Expand Up @@ -389,8 +389,23 @@ def is_disabled_cfg(cfg):
return cfg.get("config") == "disabled"


def find_fallback_nic(blacklist_drivers=None):
"""Return the name of the 'fallback' network device."""
def find_candidate_nics(blacklist_drivers: Optional[List] = None) -> List[str]:
"""Get the list of network interfaces viable for networking.

@return List of interfaces, sorted naturally.
"""
if util.is_FreeBSD() or util.is_DragonFlyBSD():
return find_candidate_nics_on_freebsd(blacklist_drivers)
elif util.is_NetBSD() or util.is_OpenBSD():
return find_candidate_nics_on_netbsd_or_openbsd(blacklist_drivers)
else:
return find_candidate_nics_on_linux(blacklist_drivers)


def find_fallback_nic(
blacklist_drivers: Optional[List] = None,
) -> Optional[str]:
"""Get the name of the 'fallback' network device."""
if util.is_FreeBSD() or util.is_DragonFlyBSD():
return find_fallback_nic_on_freebsd(blacklist_drivers)
elif util.is_NetBSD() or util.is_OpenBSD():
Expand All @@ -399,37 +414,73 @@ def find_fallback_nic(blacklist_drivers=None):
return find_fallback_nic_on_linux(blacklist_drivers)


def find_fallback_nic_on_netbsd_or_openbsd(blacklist_drivers=None):
values = list(
sorted(get_interfaces_by_mac().values(), key=natural_sort_key)
)
if values:
return values[0]
def find_candidate_nics_on_netbsd_or_openbsd(
blacklist_drivers: Optional[List] = None,
) -> List[str]:
"""Get the names of the candidate network devices on NetBSD/OpenBSD.

@param blacklist_drivers: currently ignored
@return list of sorted interfaces
"""
return sorted(get_interfaces_by_mac().values(), key=natural_sort_key)


def find_fallback_nic_on_freebsd(blacklist_drivers=None):
"""Return the name of the 'fallback' network device on FreeBSD.
def find_fallback_nic_on_netbsd_or_openbsd(
blacklist_drivers: Optional[List] = None,
) -> Optional[str]:
"""Get the 'fallback' network device name on NetBSD/OpenBSD.

@param blacklist_drivers: currently ignored
@return default interface, or None
"""
names = find_candidate_nics_on_netbsd_or_openbsd(blacklist_drivers)
if names:
return names[0]

return None


we'll use the first interface from ``ifconfig -l -u ether``
def find_candidate_nics_on_freebsd(
blacklist_drivers: Optional[List] = None,
) -> List[str]:
"""Get the names of the candidate network devices on FreeBSD.

@param blacklist_drivers: Currently ignored.
@return List of sorted interfaces.
"""
stdout, _stderr = subp.subp(["ifconfig", "-l", "-u", "ether"])
values = stdout.split()
if values:
return values[0]
return values

# On FreeBSD <= 10, 'ifconfig -l' ignores the interfaces with DOWN
# status
values = list(get_interfaces_by_mac().values())
values.sort()
if values:
return values[0]
return sorted(get_interfaces_by_mac().values(), key=natural_sort_key)


def find_fallback_nic_on_freebsd(
blacklist_drivers: Optional[List] = None,
) -> Optional[str]:
"""Get the 'fallback' network device name on FreeBSD.

@param blacklist_drivers: Currently ignored.
@return List of sorted interfaces.
"""
names = find_candidate_nics_on_freebsd(blacklist_drivers)
if names:
return names[0]

return None

def find_fallback_nic_on_linux(blacklist_drivers=None):
"""Return the name of the 'fallback' network device on Linux."""

def find_candidate_nics_on_linux(
blacklist_drivers: Optional[List] = None,
) -> List[str]:
"""Get the names of the candidate network devices on Linux.

@param blacklist_drivers: Filter out NICs with these drivers.
@return List of sorted interfaces.
"""
if not blacklist_drivers:
blacklist_drivers = []

Expand Down Expand Up @@ -464,6 +515,9 @@ def find_fallback_nic_on_linux(blacklist_drivers=None):
connected = []
possibly_connected = []
for interface in potential_interfaces:
if not read_sys_net_safe(interface, "address"):
# skip interfaces without MAC addresses
continue
if interface.startswith("veth"):
continue
if is_bridge(interface):
Expand Down Expand Up @@ -491,24 +545,34 @@ def find_fallback_nic_on_linux(blacklist_drivers=None):
possibly_connected.append(interface)
continue

# don't bother with interfaces that might not be connected if there are
# some that definitely are
if connected:
potential_interfaces = connected
else:
potential_interfaces = possibly_connected

# if eth0 exists use it above anything else, otherwise get the interface
# that we can read 'first' (using the sorted definition of first).
names = list(sorted(potential_interfaces, key=natural_sort_key))
if DEFAULT_PRIMARY_INTERFACE in names:
names.remove(DEFAULT_PRIMARY_INTERFACE)
names.insert(0, DEFAULT_PRIMARY_INTERFACE)

# pick the first that has a mac-address
for name in names:
if read_sys_net_safe(name, "address"):
return name
# Order the NICs:
# 1. DEFAULT_PRIMARY_INTERFACE, if connected.
# 2. Remaining connected interfaces, naturally sorted.
# 3. DEFAULT_PRIMARY_INTERFACE, if possibly connected.
# 4. Remaining possibly connected interfaces, naturally sorted.
sorted_interfaces = []
for interfaces in [connected, possibly_connected]:
interfaces = sorted(interfaces, key=natural_sort_key)
if DEFAULT_PRIMARY_INTERFACE in interfaces:
interfaces.remove(DEFAULT_PRIMARY_INTERFACE)
interfaces.insert(0, DEFAULT_PRIMARY_INTERFACE)
sorted_interfaces += interfaces

return sorted_interfaces


def find_fallback_nic_on_linux(
blacklist_drivers: Optional[List] = None,
) -> Optional[str]:
"""Get the 'fallback' network device name on Linux.

@param blacklist_drivers: Ignore devices with these drivers.
@return List of sorted interfaces.
"""
names = find_candidate_nics_on_linux(blacklist_drivers)
if names:
return names[0]

return None


Expand Down Expand Up @@ -872,7 +936,7 @@ def get_interfaces_by_mac(blacklist_drivers=None) -> dict:
)


def get_interfaces_by_mac_on_freebsd(blacklist_drivers=None) -> dict():
def get_interfaces_by_mac_on_freebsd(blacklist_drivers=None) -> dict:
(out, _) = subp.subp(["ifconfig", "-a", "ether"])

# flatten each interface block in a single line
Expand Down Expand Up @@ -900,7 +964,7 @@ def find_mac(flat_list):
return results


def get_interfaces_by_mac_on_netbsd(blacklist_drivers=None) -> dict():
def get_interfaces_by_mac_on_netbsd(blacklist_drivers=None) -> dict:
ret = {}
re_field_match = (
r"(?P<ifname>\w+).*address:\s"
Expand All @@ -916,7 +980,7 @@ def get_interfaces_by_mac_on_netbsd(blacklist_drivers=None) -> dict():
return ret


def get_interfaces_by_mac_on_openbsd(blacklist_drivers=None) -> dict():
def get_interfaces_by_mac_on_openbsd(blacklist_drivers=None) -> dict:
ret = {}
re_field_match = (
r"(?P<ifname>\w+).*lladdr\s"
Expand Down