summaryrefslogtreecommitdiff
path: root/cloudinit/net/__init__.py
diff options
context:
space:
mode:
authorScott Moser <smoser@ubuntu.com>2016-03-23 11:00:37 -0400
committerScott Moser <smoser@ubuntu.com>2016-03-23 11:00:37 -0400
commitd32116c3468e5c394b56d078ceef86d416d83b3a (patch)
tree6c92d8bc5edfd9726106946bd57e9c8acc26f86a /cloudinit/net/__init__.py
parent6082a5b0c2b1a52ddbf63bfd80331f28f8cdc4fa (diff)
parent5b3cad36be8981cd12cffdf5c5e539b522404000 (diff)
downloadvyos-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__.py131
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