Chad Smith has proposed merging 
~chad.smith/cloud-init:feature/azure-to-network-v2 into cloud-init:master.

Commit message:
azure: provide fallback network config v2 for fallback nic

To enable Azure to send network v2, net.generate_fallback_config now
accepts a network_version param to specify whether version 1 or version
2 network configuration is desired. DataSourceAzure.network_config now
requests network_version=2 when generating fallback configuration.


This branch avoids moving generate_fallback_config to v2 exclusively because we 
first need NetworkState to be able to parse v2 as fallback config is passed 
directly into NetworkState.

Requested reviews:
  cloud-init commiters (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~chad.smith/cloud-init/+git/cloud-init/+merge/370970
-- 
Your team cloud-init commiters is requested to review the proposed merge of 
~chad.smith/cloud-init:feature/azure-to-network-v2 into cloud-init:master.
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index f3cec79..fa15b96 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -264,7 +264,8 @@ def find_fallback_nic(blacklist_drivers=None):
     return None
 
 
-def generate_fallback_config(blacklist_drivers=None, config_driver=None):
+def generate_fallback_config(
+        blacklist_drivers=None, config_driver=None, network_version=1):
     """Determine which attached net dev is most likely to have a connection and
        generate network state to run dhcp on that interface"""
 
@@ -272,25 +273,30 @@ def generate_fallback_config(blacklist_drivers=None, config_driver=None):
         config_driver = False
 
     target_name = find_fallback_nic(blacklist_drivers=blacklist_drivers)
-    if target_name:
-        target_mac = read_sys_net_safe(target_name, 'address')
+    if not target_name:
+        # can't read any interfaces addresses (or there are none); give up
+        return None
+    target_mac = read_sys_net_safe(target_name, 'address')
+    driver_params = {}
+    if config_driver:
+        driver = device_driver(target_name)
+        if driver:
+            driver_params = {'driver': driver,
+                             'device_id': device_devid(target_name)}
+    if network_version == 1:
+        # TODO(Drop network v1 once NetworkState parses v2)
         nconf = {'config': [], 'version': 1}
         cfg = {'type': 'physical', 'name': target_name,
                'mac_address': target_mac, 'subnets': [{'type': 'dhcp'}]}
-        # inject the device driver name, dev_id into config if enabled and
-        # device has a valid device driver value
-        if config_driver:
-            driver = device_driver(target_name)
-            if driver:
-                cfg['params'] = {
-                    'driver': driver,
-                    'device_id': device_devid(target_name),
-                }
+        if driver_params:
+            cfg['params'] = driver_params
         nconf['config'].append(cfg)
         return nconf
-    else:
-        # can't read any interfaces addresses (or there are none); give up
-        return None
+    cfg = {'dhcp4': True, 'set-name': target_name,
+           'match': {'macaddress': target_mac.lower()}}
+    cfg['match'].update(driver_params)
+    nconf = {'ethernets': {target_name: cfg}, 'version': 2}
+    return nconf
 
 
 def extract_physdevs(netcfg):
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index 0ca576b..1e6ead2 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -343,7 +343,6 @@ class NetworkStateInterpreter(object):
              ]
         }
         '''
-
         interfaces = self._network_state.get('interfaces', {})
         iface = interfaces.get(command['name'], {})
         for param, val in command.get('params', {}).items():
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
index d2fad9b..ab47507 100755
--- a/cloudinit/sources/DataSourceAzure.py
+++ b/cloudinit/sources/DataSourceAzure.py
@@ -1268,7 +1268,8 @@ def parse_network_config(imds_metadata):
             LOG.debug('Azure: generating fallback configuration')
             # generate a network config, blacklist picking mlx4_core devs
             netconfig = net.generate_fallback_config(
-                blacklist_drivers=blacklist, config_driver=True)
+                blacklist_drivers=blacklist, config_driver=True,
+                network_version=2)
             evt.description = "network config from fallback"
         return netconfig
 
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
index 2de2aea..3ed9e4e 100644
--- a/tests/unittests/test_datasource/test_azure.py
+++ b/tests/unittests/test_datasource/test_azure.py
@@ -997,7 +997,7 @@ scbus-1 on xpt0 bus 0
         netconfig = dsrc.network_config
         self.assertEqual(netconfig, fallback_config)
         mock_fallback.assert_called_with(blacklist_drivers=['mlx4_core'],
-                                         config_driver=True)
+                                         config_driver=True, network_version=2)
 
     @mock.patch('cloudinit.net.get_interface_mac')
     @mock.patch('cloudinit.net.get_devicelist')
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 1840ade..b579c51 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -2207,6 +2207,72 @@ class TestGenerateFallbackConfig(CiTestCase):
     @mock.patch("cloudinit.net.sys_dev_path")
     @mock.patch("cloudinit.net.read_sys_net")
     @mock.patch("cloudinit.net.get_devicelist")
+    def test_device_driver_v1(self, mock_get_devicelist, mock_read_sys_net,
+                              mock_sys_dev_path):
+        devices = {
+            'eth0': {
+                'bridge': False, 'carrier': False, 'dormant': False,
+                'operstate': 'down', 'address': '00:11:22:33:44:55',
+                'device/driver': 'hv_netsvc', 'device/device': '0x3',
+                'name_assign_type': '4'},
+            'eth1': {
+                'bridge': False, 'carrier': False, 'dormant': False,
+                'operstate': 'down', 'address': '00:11:22:33:44:55',
+                'device/driver': 'mlx4_core', 'device/device': '0x7',
+                'name_assign_type': '4'},
+
+        }
+
+        tmp_dir = self.tmp_dir()
+        _setup_test(tmp_dir, mock_get_devicelist,
+                    mock_read_sys_net, mock_sys_dev_path,
+                    dev_attrs=devices)
+
+        network_cfg = net.generate_fallback_config(config_driver=True)
+        expected = {'config': [
+            {'type': 'physical', 'name': 'eth0',
+             'mac_address': '00:11:22:33:44:55', 'subnets': [{'type': 'dhcp'}],
+             'params': {'driver': 'hv_netsvc', 'device_id': '0x3'}}],
+            'version': 1}
+        self.assertEqual(expected, network_cfg)
+
+    @mock.patch("cloudinit.net.sys_dev_path")
+    @mock.patch("cloudinit.net.read_sys_net")
+    @mock.patch("cloudinit.net.get_devicelist")
+    def test_device_driver_v2(self, mock_get_devicelist, mock_read_sys_net,
+                              mock_sys_dev_path):
+        devices = {
+            'eth0': {
+                'bridge': False, 'carrier': False, 'dormant': False,
+                'operstate': 'down', 'address': '00:11:22:33:44:55',
+                'device/driver': 'hv_netsvc', 'device/device': '0x3',
+                'name_assign_type': '4'},
+            'eth1': {
+                'bridge': False, 'carrier': False, 'dormant': False,
+                'operstate': 'down', 'address': '00:11:22:33:44:55',
+                'device/driver': 'mlx4_core', 'device/device': '0x7',
+                'name_assign_type': '4'},
+
+        }
+
+        tmp_dir = self.tmp_dir()
+        _setup_test(tmp_dir, mock_get_devicelist,
+                    mock_read_sys_net, mock_sys_dev_path,
+                    dev_attrs=devices)
+
+        network_cfg = net.generate_fallback_config(
+            config_driver=True, network_version=2)
+        expected = {
+            'ethernets': {'eth0': {'dhcp4': True, 'set-name': 'eth0',
+                                   'match': {'macaddress': '00:11:22:33:44:55',
+                                             'driver': 'hv_netsvc',
+                                             'device_id': '0x3'}}},
+            'version': 2}
+        self.assertEqual(expected, network_cfg)
+
+    @mock.patch("cloudinit.net.sys_dev_path")
+    @mock.patch("cloudinit.net.read_sys_net")
+    @mock.patch("cloudinit.net.get_devicelist")
     def test_device_driver(self, mock_get_devicelist, mock_read_sys_net,
                            mock_sys_dev_path):
         devices = {
_______________________________________________
Mailing list: https://launchpad.net/~cloud-init-dev
Post to     : cloud-init-dev@lists.launchpad.net
Unsubscribe : https://launchpad.net/~cloud-init-dev
More help   : https://help.launchpad.net/ListHelp

Reply via email to