diff options
author | Scott Moser <smoser@ubuntu.com> | 2016-03-23 11:00:37 -0400 |
---|---|---|
committer | Scott Moser <smoser@ubuntu.com> | 2016-03-23 11:00:37 -0400 |
commit | d32116c3468e5c394b56d078ceef86d416d83b3a (patch) | |
tree | 6c92d8bc5edfd9726106946bd57e9c8acc26f86a /cloudinit/net/__init__.py | |
parent | 6082a5b0c2b1a52ddbf63bfd80331f28f8cdc4fa (diff) | |
parent | 5b3cad36be8981cd12cffdf5c5e539b522404000 (diff) | |
download | vyos-cloud-init-d32116c3468e5c394b56d078ceef86d416d83b3a.tar.gz vyos-cloud-init-d32116c3468e5c394b56d078ceef86d416d83b3a.zip |
merge from trunk.net1
Diffstat (limited to 'cloudinit/net/__init__.py')
-rw-r--r-- | cloudinit/net/__init__.py | 131 |
1 files changed, 121 insertions, 10 deletions
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index e2dcaee7..0560fa45 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -29,6 +29,7 @@ from . import network_state LOG = logging.getLogger(__name__) SYS_CLASS_NET = "/sys/class/net/" +LINKS_FNAME_PREFIX = "etc/systemd/network/50-cloud-init-" NET_CONFIG_OPTIONS = [ "address", "netmask", "broadcast", "network", "metric", "gateway", @@ -46,6 +47,8 @@ NET_CONFIG_BRIDGE_OPTIONS = [ "bridge_hello", "bridge_maxage", "bridge_maxwait", "bridge_stp", ] +DEFAULT_PRIMARY_INTERFACE = 'eth0' + def sys_dev_path(devname, path=""): return SYS_CLASS_NET + devname + "/" + path @@ -510,18 +513,126 @@ def render_interfaces(network_state): return content -def render_network_state(target, network_state): - eni = 'etc/network/interfaces' - netrules = 'etc/udev/rules.d/70-persistent-net.rules' +def render_network_state(target, network_state, eni="etc/network/interfaces", + links_prefix=LINKS_FNAME_PREFIX, + netrules='etc/udev/rules.d/70-persistent-net.rules'): - eni = os.path.sep.join((target, eni,)) - util.ensure_dir(os.path.dirname(eni)) - with open(eni, 'w+') as f: + fpeni = os.path.sep.join((target, eni,)) + util.ensure_dir(os.path.dirname(fpeni)) + with open(fpeni, 'w+') as f: f.write(render_interfaces(network_state)) - netrules = os.path.sep.join((target, netrules,)) - util.ensure_dir(os.path.dirname(netrules)) - with open(netrules, 'w+') as f: - f.write(render_persistent_net(network_state)) + if netrules: + netrules = os.path.sep.join((target, netrules,)) + util.ensure_dir(os.path.dirname(netrules)) + with open(netrules, 'w+') as f: + f.write(render_persistent_net(network_state)) + + if links_prefix: + render_systemd_links(target, network_state, links_prefix) + + +def render_systemd_links(target, network_state, + links_prefix=LINKS_FNAME_PREFIX): + fp_prefix = os.path.sep.join((target, links_prefix)) + for f in glob.glob(fp_prefix + "*"): + os.unlink(f) + + interfaces = network_state.get('interfaces') + for iface in interfaces.values(): + if (iface['type'] == 'physical' and 'name' in iface and + 'mac_address' in iface): + fname = fp_prefix + iface['name'] + ".link" + with open(fname, "w") as fp: + fp.write("\n".join([ + "[Match]", + "MACAddress=" + iface['mac_address'], + "", + "[Link]", + "Name=" + iface['name'], + "" + ])) + + +def is_disabled_cfg(cfg): + if not cfg or not isinstance(cfg, dict): + return False + return cfg.get('config') == "disabled" + + +def generate_fallback_config(): + """Determine which attached net dev is most likely to have a connection and + generate network state to run dhcp on that interface""" + # by default use eth0 as primary interface + nconf = {'config': [], 'version': 1} + + # 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: + try: + sysfs_carrier = os.path.join(SYS_CLASS_NET, interface, 'carrier') + carrier = int(util.load_file(sysfs_carrier).strip()) + if carrier: + connected.append(interface) + continue + except OSError: + pass + # 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 + try: + 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 + except OSError: + pass + try: + 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 + except OSError: + pass + + # 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 DEFAULT_PRIMARY_INTERFACE in potential_interfaces: + name = DEFAULT_PRIMARY_INTERFACE + else: + name = sorted(potential_interfaces)[0] + + sysfs_mac = os.path.join(SYS_CLASS_NET, name, 'address') + mac = util.load_file(sysfs_mac).strip() + target_name = name + + nconf['config'].append( + {'type': 'physical', 'name': target_name, + 'mac_address': mac, 'subnets': [{'type': 'dhcp4'}]}) + return nconf + + +def read_kernel_cmdline_config(): + # FIXME: add implementation here + return None + # vi: ts=4 expandtab syntax=python |