diff options
author | Wesley Wiedenmeier <wesley.wiedenmeier@gmail.com> | 2016-03-21 20:42:26 -0500 |
---|---|---|
committer | Wesley Wiedenmeier <wesley.wiedenmeier@gmail.com> | 2016-03-21 20:42:26 -0500 |
commit | bb58463474e334b8c8d1769101bd3afc48ebfef4 (patch) | |
tree | b15665917ee8e0eb69fb41ad58cbea56f8cfda3c /cloudinit/net | |
parent | 7a22e352b2f87636554d9787f60cd3168f3d77bc (diff) | |
download | vyos-cloud-init-bb58463474e334b8c8d1769101bd3afc48ebfef4.tar.gz vyos-cloud-init-bb58463474e334b8c8d1769101bd3afc48ebfef4.zip |
Added net.find_fallback_network_device() to find an appropriate device to dhcp
on in the event that no network configuration was provided to cloud-init
- Devices in /sys/class/net aside from loopback devices are scanned
- Each device is tested to determine if it has a carrier using
/sys/class/net/DEV/carrier, devices which do are preferred as they are most
likely connected to the outside world
- Devices which do not have a carrier but which might still be connected due
to being in a dormant or down state are used as fallbacks in case no
devices are found which have a carrier
- A network state dictionary is generated to be passed to
render_network_state to write ENI
- A systemd link file is generated that will rename the chosen device to eth0
Diffstat (limited to 'cloudinit/net')
-rw-r--r-- | cloudinit/net/__init__.py | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index 3cf99604..800ffe61 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -20,6 +20,8 @@ import errno import glob import os import re +import string +import textwrap from cloudinit import log as logging from cloudinit import util @@ -280,6 +282,87 @@ def parse_net_config(path): return ns +def find_fallback_network_device(): + """Determine which attached net dev is most likely to have a connection and + generate network state to run dhcp on that interface""" + ns = {'interfaces': {}, 'dns': {'search': [], 'nameservers': []}, + 'routes': []} + default_link_file = textwrap.dedent(""" + #cloud-init + [Match] + MACAddress={mac} + + [Link] + Name={name} + """) + + # get list of interfaces that could have connections + invalid_interfaces = set(['lo']) + potential_interfaces = set(os.listdir(SYS_CLASS_NET)) + potential_interfaces = potential_interfaces.difference(invalid_interfaces) + + # sort into interfaces with carrier, interfaces which could have carrier, + # and ignore interfaces that are definitely disconnected + connected = [] + possibly_connected = [] + for interface in potential_interfaces: + sysfs_carrier = os.path.join(SYS_CLASS_NET, interface, 'carrier') + carrier = int(util.load_file(sysfs_carrier).strip()) + if carrier: + connected.append(interface) + continue + # check if nic is dormant or down, as this may make a nick appear to + # not have a carrier even though it could acquire one when brought + # online by dhclient + sysfs_dormant = os.path.join(SYS_CLASS_NET, interface, 'dormant') + dormant = int(util.load_file(sysfs_dormant).strip()) + if dormant: + possibly_connected.append(interface) + continue + sysfs_operstate = os.path.join(SYS_CLASS_NET, interface, 'operstate') + operstate = util.load_file(sysfs_operstate).strip() + if operstate in ['dormant', 'down', 'lowerlayerdown', 'unknown']: + 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 there are no interfaces, give up + if not potential_interfaces: + return + + # if eth0 exists use it above anything else, otherwise get the interface + # that looks 'first' + if 'eth0' in potential_interfaces: + name = 'eth0' + else: + name = potential_interfaces.sort( + key=lambda x: int(x.strip(string.ascii_letters)))[0] + + sysfs_mac = os.path.join(SYS_CLASS_NET, name, 'address') + mac = util.load_file(sysfs_mac).strip() + + # generate net config for interface, rename interface to eth0 for backwards + # compatibility, and attempt both dhcp4 and dhcp6 + ns['interfaces']['eth0'] = { + 'mac_address': mac, 'name': 'eth0', 'type': 'physical', + 'mode': 'manual', 'inet': 'inet', + 'subnets': [{'type': 'dhcp4'}, {'type': 'dhcp6'}] + } + + # insert params into link file + link_file = default_link_file.format(name=name, mac=mac) + + syslink_name = "/etc/systemd/network/50-cloud-init-{}.link".format(name) + + return (ns, link_file, syslink_name) + + def render_persistent_net(network_state): ''' Given state, emit udev rules to map mac to ifname |