From ca00b0f1f8c8a40409328c595d44234bb61c24c4 Mon Sep 17 00:00:00 2001
From: Scott Moser <smoser@ubuntu.com>
Date: Tue, 22 Mar 2016 04:49:34 -0400
Subject: make NoCloud work for seeding network.

Tested now with the generated fallback config in an lxc container.
Had to change to return a config rather than a network state.

Also this makes nocloud look in nocloud-net's seed dir.
This way it will read the seed and clame the datasource but
not do anything other than apply networking and the init_modules early.

It is a change in behavior of the time that boothooks woudl run to do
this.  May need to change that back.
---
 cloudinit/net/__init__.py              | 20 +++++---------------
 cloudinit/sources/DataSourceNoCloud.py | 34 +++++++++++++++++++---------------
 cloudinit/stages.py                    |  1 +
 3 files changed, 25 insertions(+), 30 deletions(-)

diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index b45153f4..63fad2fa 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -448,11 +448,7 @@ 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
-             }
+    nconf = {'config': [], 'version': 1}
 
     # get list of interfaces that could have connections
     invalid_interfaces = set(['lo'])
@@ -506,21 +502,15 @@ def generate_fallback_config():
     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]
+        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
 
-    # 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'}]
-    }
-
+    nconf['config'].append(
+        {'type': 'physical', 'name': target_name,
+         'mac_address': mac, 'subnets': [{'type': 'dhcp4'}]})
     return nconf
 
 
diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py
index 538df7d9..bd04a6fe 100644
--- a/cloudinit/sources/DataSourceNoCloud.py
+++ b/cloudinit/sources/DataSourceNoCloud.py
@@ -36,7 +36,9 @@ class DataSourceNoCloud(sources.DataSource):
         self.dsmode = 'local'
         self.seed = None
         self.cmdline_id = "ds=nocloud"
-        self.seed_dir = os.path.join(paths.seed_dir, 'nocloud')
+        self.seed_dirs = [os.path.join(paths.seed_dir, 'nocloud'),
+                          os.path.join(paths.seed_dir, 'nocloud-net')]
+        self.seed_dir = None
         self.supported_seed_starts = ("/", "file://")
 
     def __str__(self):
@@ -67,15 +69,15 @@ class DataSourceNoCloud(sources.DataSource):
         pp2d_kwargs = {'required': ['user-data', 'meta-data'],
                        'optional': ['vendor-data', 'network-config']}
 
-        try:
-            seeded = util.pathprefix2dict(self.seed_dir, **pp2d_kwargs)
-            found.append(self.seed_dir)
-            LOG.debug("Using seeded data from %s", self.seed_dir)
-        except ValueError as e:
-            pass
-
-        if self.seed_dir in found:
-            mydata = _merge_new_seed(mydata, seeded)
+        for path in self.seed_dirs:
+            try:
+                seeded = util.pathprefix2dict(path, **pp2d_kwargs)
+                found.append(path)
+                LOG.debug("Using seeded data from %s", path)
+                mydata = _merge_new_seed(mydata, seeded)
+                break
+            except ValueError as e:
+                pass
 
         # If the datasource config had a 'seedfrom' entry, then that takes
         # precedence over a 'seedfrom' that was found in a filesystem
@@ -188,21 +190,19 @@ class DataSourceNoCloud(sources.DataSource):
         # if this is the local datasource or 'seedfrom' was used
         # and the source of the seed was self.dsmode.
         # Then see if there is network config to apply.
+        # note this is obsolete network-interfaces style seeding.
         if self.dsmode in ("local", seeded_network):
             if mydata['meta-data'].get('network-interfaces'):
                 LOG.debug("Updating network interfaces from %s", self)
                 self.distro.apply_network(
                     mydata['meta-data']['network-interfaces'])
-            elif mydata.get('network-config'):
-                LOG.debug("Updating network config from %s", self)
-                self.distro.apply_network_config(mydata['network-config'],
-                                                 bring_up=False)
 
         if mydata['meta-data']['dsmode'] == self.dsmode:
             self.seed = ",".join(found)
             self.metadata = mydata['meta-data']
             self.userdata_raw = mydata['user-data']
             self.vendordata_raw = mydata['vendor-data']
+            self._network_config = mydata['network-config']
             return True
 
         LOG.debug("%s: not claiming datasource, dsmode=%s", self,
@@ -222,6 +222,10 @@ class DataSourceNoCloud(sources.DataSource):
             return None
         return quick_id == current
 
+    @property
+    def network_config(self):
+        return self._network_config
+
 
 def _quick_read_instance_id(cmdline_id, dirs=None):
     if dirs is None:
@@ -312,7 +316,7 @@ class DataSourceNoCloudNet(DataSourceNoCloud):
         DataSourceNoCloud.__init__(self, sys_cfg, distro, paths)
         self.cmdline_id = "ds=nocloud-net"
         self.supported_seed_starts = ("http://", "https://", "ftp://")
-        self.seed_dir = os.path.join(paths.seed_dir, 'nocloud-net')
+        self.seed_dirs = [os.path.join(paths.seed_dir, 'nocloud-net')]
         self.dsmode = "net"
 
 
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index 8e681e29..73090025 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -589,6 +589,7 @@ class Init(object):
             LOG.info("network config is disabled")
             return
 
+        LOG.info("Applying configuration: %s", netcfg)
         return self.distro.apply_network_config(netcfg)
 
 
-- 
cgit v1.2.3