diff options
| -rwxr-xr-x | bin/cloud-init | 4 | ||||
| -rw-r--r-- | cloudinit/distros/__init__.py | 2 | ||||
| -rw-r--r-- | cloudinit/net/__init__.py | 172 | ||||
| -rw-r--r-- | cloudinit/sources/__init__.py | 4 | ||||
| -rw-r--r-- | cloudinit/stages.py | 24 | 
5 files changed, 125 insertions, 81 deletions
| diff --git a/bin/cloud-init b/bin/cloud-init index 63aa765b..8875d2f6 100755 --- a/bin/cloud-init +++ b/bin/cloud-init @@ -263,6 +263,10 @@ def main_init(name, args):                  return (None, [])              else:                  return (None, ["No instance datasource found."]) + +    if args.local: +        init.apply_network_config() +      # Stage 6      iid = init.instancify()      LOG.debug("%s will now be targeting instance id: %s", name, iid) diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py index 74b484a7..418421b9 100644 --- a/cloudinit/distros/__init__.py +++ b/cloudinit/distros/__init__.py @@ -135,7 +135,7 @@ class Distro(object):              return self._bring_up_interfaces(dev_names)          return False -    def apply_network_config(self, netconfig, bring_up=True): +    def apply_network_config(self, netconfig, bring_up=False):          # Write it out          dev_names = self._write_network_config(netconfig)          # Now try to bring them up diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py index 36f07a02..b45153f4 100644 --- a/cloudinit/net/__init__.py +++ b/cloudinit/net/__init__.py @@ -283,86 +283,6 @@ def parse_net_config(path):      return ns -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': {'interfaces': {}, -                        'dns': {'search': [], 'nameservers': []}, 'routes': [] -                        }, -             '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: -        potential_interfaces.sort( -                key=lambda x: int(''.join(i for i in x if i in string.digits))) -        name = potential_interfaces[0] - -    sysfs_mac = os.path.join(SYS_CLASS_NET, name, 'address') -    mac = util.load_file(sysfs_mac).strip() -    target_name = name - -    # generate net config for interface -    nconf['config']['interfaces'][target_name] = { -        'mac_address': mac, 'name': target_name, 'type': 'physical', -        'mode': 'manual', 'inet': 'inet', -        'subnets': [{'type': 'dhcp4'}, {'type': 'dhcp6'}] -    } - -    return nconf - -  def render_persistent_net(network_state):      ''' Given state, emit udev rules to map          mac to ifname @@ -517,4 +437,96 @@ def render_network_state(target, network_state):      with open(netrules, 'w+') as f:          f.write(render_persistent_net(network_state)) + +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': {'interfaces': {}, +                        'dns': {'search': [], 'nameservers': []}, 'routes': [] +                        }, +             '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: +        potential_interfaces.sort( +                key=lambda x: int(''.join(i for i in x if i in string.digits))) +        name = potential_interfaces[0] + +    sysfs_mac = os.path.join(SYS_CLASS_NET, name, 'address') +    mac = util.load_file(sysfs_mac).strip() +    target_name = name + +    # generate net config for interface +    nconf['config']['interfaces'][target_name] = { +        'mac_address': mac, 'name': target_name, 'type': 'physical', +        'mode': 'manual', 'inet': 'inet', +        'subnets': [{'type': 'dhcp4'}, {'type': 'dhcp6'}] +    } + +    return nconf + + +def read_kernel_cmdline_config(): +    # FIXME: add implementation here +    return None + +  # vi: ts=4 expandtab syntax=python diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py index 28540a7b..c63464b2 100644 --- a/cloudinit/sources/__init__.py +++ b/cloudinit/sources/__init__.py @@ -221,6 +221,10 @@ class DataSource(object):          # quickly (local check only) if self.instance_id is still          return False +    @property +    def network_config(self): +        return None +  def normalize_pubkey_data(pubkey_data):      keys = [] diff --git a/cloudinit/stages.py b/cloudinit/stages.py index c230ec0d..8e681e29 100644 --- a/cloudinit/stages.py +++ b/cloudinit/stages.py @@ -43,6 +43,7 @@ from cloudinit import distros  from cloudinit import helpers  from cloudinit import importer  from cloudinit import log as logging +from cloudinit import net  from cloudinit import sources  from cloudinit import type_utils  from cloudinit import util @@ -567,6 +568,29 @@ class Init(object):          # Run the handlers          self._do_handlers(user_data_msg, c_handlers_list, frequency) +    def _find_networking_config(self): +        cmdline_cfg = ('cmdline', net.read_kernel_cmdline_config()) +        dscfg = ('ds', None) +        if self.datasource and hasattr(self.datasource, 'network_config'): +            dscfg = ('ds', self.datasource.network_config) +        sys_cfg = ('system_cfg', self.cfg.get('network')) + +        for loc, ncfg in (cmdline_cfg, dscfg, sys_cfg): +            if net.is_disabled_cfg(ncfg): +                LOG.debug("network config disabled by %s", loc) +                return None +            if ncfg: +                return ncfg +        return net.generate_fallback_config() + +    def apply_network_config(self): +        netcfg = self._find_networking_config() +        if netcfg is None: +            LOG.info("network config is disabled") +            return + +        return self.distro.apply_network_config(netcfg) +  class Modules(object):      def __init__(self, init, cfg_files=None, reporter=None): | 
