← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~daniel-thewatkins/cloud-init/+git/cloud-init:networking into cloud-init:master


Dan Watkins has proposed merging ~daniel-thewatkins/cloud-init/+git/cloud-init:networking into cloud-init:master.

Commit message:
stages: allow data sources to override network config source order

Currently, if a platform provides any network configuration via the
"cmdline" method (i.e. network-data=... on the kernel command line,
ip=... on the kernel command line, or iBFT config via /run/net-*.conf),
the value of the data source's network_config property is completely

This means that on platforms that use iSCSI boot (such as Oracle Compute
Infrastructure), there is no way for the data source to configure any
network interfaces other than those that have already been configured by
the initramfs.

This change allows data sources to specify the order in which network
configuration sources are considered.  Data sources that opt to use this
mechanism will be expected to consume the command line network data and
integrate it themselves.

(The generic merging of network configuration sources was considered,
but we concluded that the single use case we have presently (a) didn't
warrant the increased complexity, and (b) didn't give us a broad enough
view to be sure that our generic implementation would be sufficiently
generic.  This change in no way precludes a merging strategy in future.)

Requested reviews:
  Server Team CI bot (server-team-bot): continuous-integration
  cloud-init commiters (cloud-init-dev)

For more details, see:
Your team cloud-init commiters is requested to review the proposed merge of ~daniel-thewatkins/cloud-init/+git/cloud-init:networking into cloud-init:master.
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index e6966b3..ce4626b 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -153,6 +153,11 @@ class DataSource(object):
     # Track the discovered fallback nic for use in configuration generation.
     _fallback_interface = None
+    # The network configuration sources that should be considered for this data
+    # source.  (The first source in this list that provides network
+    # configuration will be used without considering any that follow.)
+    network_config_sources = ('cmdline', 'system_cfg', 'ds')
     # read_url_params
     url_max_wait = -1   # max_wait < 0 means do not wait
     url_timeout = 10    # timeout for each metadata url read attempt
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index da7d349..2498c69 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -630,18 +630,27 @@ class Init(object):
         if os.path.exists(disable_file):
             return (None, disable_file)
-        cmdline_cfg = ('cmdline', cmdline.read_kernel_cmdline_config())
-        dscfg = ('ds', None)
+        available_cfgs = {
+            'cmdline': cmdline.read_kernel_cmdline_config(),
+            'ds': None,
+            'system_cfg': self.cfg.get('network'),
+        }
         if self.datasource and hasattr(self.datasource, 'network_config'):
-            dscfg = ('ds', self.datasource.network_config)
-        sys_cfg = ('system_cfg', self.cfg.get('network'))
+            available_cfgs['ds'] = self.datasource.network_config
-        for loc, ncfg in (cmdline_cfg, sys_cfg, dscfg):
+        if self.datasource and hasattr(self.datasource,
+                                       'network_config_sources'):
+            order = self.datasource.network_config_sources
+        else:
+            order = sources.DataSource.network_config_sources
+        for cfg_source in order:
+            ncfg = available_cfgs[cfg_source]
             if net.is_disabled_cfg(ncfg):
-                LOG.debug("network config disabled by %s", loc)
-                return (None, loc)
+                LOG.debug("network config disabled by %s", cfg_source)
+                return (None, cfg_source)
             if ncfg:
-                return (ncfg, loc)
+                return (ncfg, cfg_source)
         return (self.distro.generate_fallback_config(), "fallback")
     def apply_network_config(self, bring_up):
diff --git a/cloudinit/tests/test_stages.py b/cloudinit/tests/test_stages.py
index 94b6b25..8f0be28 100644
--- a/cloudinit/tests/test_stages.py
+++ b/cloudinit/tests/test_stages.py
@@ -95,6 +95,23 @@ class TestInit(CiTestCase):
+    def test__find_networking_config_uses_datasrc_order(self, m_cmdline):
+        """find_networking_config should check sources in DS defined order"""
+        # cmdline, which would normally be preferred over other sources,
+        # disables networking; in this case, though, the DS moves cmdline later
+        # so its own config is preferred
+        m_cmdline.return_value = {'config': 'disabled'}
+        ds_net_cfg = {'config': {'needle': True}}
+        self.init.datasource = FakeDataSource(network_config=ds_net_cfg)
+        self.init.datasource.network_config_sources = [
+            'ds', 'system_cfg', 'cmdline']
+        self.assertEqual(
+            (ds_net_cfg, 'ds'),
+            self.init._find_networking_config())
+    @mock.patch('cloudinit.stages.cmdline.read_kernel_cmdline_config')
     def test_wb__find_networking_config_returns_kernel(self, m_cmdline):
         """find_networking_config returns kernel cmdline config if present."""
         expected_cfg = {'config': ['fakekernel']}