|
|
69219a |
From b7b814bc0f4e7b63b50106d292e91f2c9555ad87 Mon Sep 17 00:00:00 2001
|
|
|
69219a |
From: Eduardo Otubo <otubo@redhat.com>
|
|
|
69219a |
Date: Mon, 4 May 2020 12:40:00 +0200
|
|
|
69219a |
Subject: [PATCH 3/6] azure/net: generate_fallback_nic emits network v2 config
|
|
|
69219a |
instead of v1
|
|
|
69219a |
|
|
|
69219a |
RH-Author: Eduardo Otubo <otubo@redhat.com>
|
|
|
69219a |
Message-id: <20200327152826.13343-4-otubo@redhat.com>
|
|
|
69219a |
Patchwork-id: 94460
|
|
|
69219a |
O-Subject: [RHEL-8.1.z/RHEL-8.2.z cloud-init PATCHv2 3/6] azure/net: generate_fallback_nic emits network v2 config instead of v1
|
|
|
69219a |
Bugzilla: 1811753
|
|
|
69219a |
RH-Acked-by: Cathy Avery <cavery@redhat.com>
|
|
|
69219a |
RH-Acked-by: Vitaly Kuznetsov <vkuznets@redhat.com>
|
|
|
69219a |
|
|
|
69219a |
commit 7f674256c1426ffc419fd6b13e66a58754d94939
|
|
|
69219a |
Author: Chad Smith <chad.smith@canonical.com>
|
|
|
69219a |
Date: Tue Aug 13 20:13:05 2019 +0000
|
|
|
69219a |
|
|
|
69219a |
azure/net: generate_fallback_nic emits network v2 config instead of v1
|
|
|
69219a |
|
|
|
69219a |
The function generate_fallback_config is used by Azure by default when
|
|
|
69219a |
not consuming IMDS configuration data. This function is also used by any
|
|
|
69219a |
datasource which does not implement it's own network config. This simple
|
|
|
69219a |
fallback configuration sets up dhcp on the most likely NIC. It will now
|
|
|
69219a |
emit network v2 instead of network v1.
|
|
|
69219a |
|
|
|
69219a |
This is a step toward moving all components talking in v2 and allows us
|
|
|
69219a |
to avoid costly conversions between v1 and v2 for newer distributions
|
|
|
69219a |
which rely on netplan.
|
|
|
69219a |
|
|
|
69219a |
Signed-off-by: Eduardo Otubo <otubo@redhat.com>
|
|
|
69219a |
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
69219a |
---
|
|
|
69219a |
cloudinit/net/__init__.py | 31 +++++---------
|
|
|
69219a |
cloudinit/net/network_state.py | 12 ++++--
|
|
|
69219a |
cloudinit/net/tests/test_init.py | 19 +++++----
|
|
|
69219a |
cloudinit/sources/DataSourceAzure.py | 7 +++-
|
|
|
69219a |
tests/unittests/test_datasource/test_azure.py | 59 ++++++++++++++++++++++++++-
|
|
|
69219a |
tests/unittests/test_net.py | 41 +++++++++++++++++--
|
|
|
69219a |
6 files changed, 130 insertions(+), 39 deletions(-)
|
|
|
69219a |
|
|
|
69219a |
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
|
|
|
69219a |
index 41659b1..b26a190 100644
|
|
|
69219a |
--- a/cloudinit/net/__init__.py
|
|
|
69219a |
+++ b/cloudinit/net/__init__.py
|
|
|
69219a |
@@ -268,32 +268,23 @@ def find_fallback_nic(blacklist_drivers=None):
|
|
|
69219a |
|
|
|
69219a |
|
|
|
69219a |
def generate_fallback_config(blacklist_drivers=None, config_driver=None):
|
|
|
69219a |
- """Determine which attached net dev is most likely to have a connection and
|
|
|
69219a |
- generate network state to run dhcp on that interface"""
|
|
|
69219a |
-
|
|
|
69219a |
+ """Generate network cfg v2 for dhcp on the NIC most likely connected."""
|
|
|
69219a |
if not config_driver:
|
|
|
69219a |
config_driver = False
|
|
|
69219a |
|
|
|
69219a |
target_name = find_fallback_nic(blacklist_drivers=blacklist_drivers)
|
|
|
69219a |
- if target_name:
|
|
|
69219a |
- target_mac = read_sys_net_safe(target_name, 'address')
|
|
|
69219a |
- nconf = {'config': [], 'version': 1}
|
|
|
69219a |
- cfg = {'type': 'physical', 'name': target_name,
|
|
|
69219a |
- 'mac_address': target_mac, 'subnets': [{'type': 'dhcp'}]}
|
|
|
69219a |
- # inject the device driver name, dev_id into config if enabled and
|
|
|
69219a |
- # device has a valid device driver value
|
|
|
69219a |
- if config_driver:
|
|
|
69219a |
- driver = device_driver(target_name)
|
|
|
69219a |
- if driver:
|
|
|
69219a |
- cfg['params'] = {
|
|
|
69219a |
- 'driver': driver,
|
|
|
69219a |
- 'device_id': device_devid(target_name),
|
|
|
69219a |
- }
|
|
|
69219a |
- nconf['config'].append(cfg)
|
|
|
69219a |
- return nconf
|
|
|
69219a |
- else:
|
|
|
69219a |
+ if not target_name:
|
|
|
69219a |
# can't read any interfaces addresses (or there are none); give up
|
|
|
69219a |
return None
|
|
|
69219a |
+ target_mac = read_sys_net_safe(target_name, 'address')
|
|
|
69219a |
+ cfg = {'dhcp4': True, 'set-name': target_name,
|
|
|
69219a |
+ 'match': {'macaddress': target_mac.lower()}}
|
|
|
69219a |
+ if config_driver:
|
|
|
69219a |
+ driver = device_driver(target_name)
|
|
|
69219a |
+ if driver:
|
|
|
69219a |
+ cfg['match']['driver'] = driver
|
|
|
69219a |
+ nconf = {'ethernets': {target_name: cfg}, 'version': 2}
|
|
|
69219a |
+ return nconf
|
|
|
69219a |
|
|
|
69219a |
|
|
|
69219a |
def apply_network_config_names(netcfg, strict_present=True, strict_busy=True):
|
|
|
69219a |
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
|
|
|
69219a |
index 4d19f56..71d3c0f 100644
|
|
|
69219a |
--- a/cloudinit/net/network_state.py
|
|
|
69219a |
+++ b/cloudinit/net/network_state.py
|
|
|
69219a |
@@ -596,6 +596,7 @@ class NetworkStateInterpreter(object):
|
|
|
69219a |
eno1:
|
|
|
69219a |
match:
|
|
|
69219a |
macaddress: 00:11:22:33:44:55
|
|
|
69219a |
+ driver: hv_netsvc
|
|
|
69219a |
wakeonlan: true
|
|
|
69219a |
dhcp4: true
|
|
|
69219a |
dhcp6: false
|
|
|
69219a |
@@ -631,15 +632,18 @@ class NetworkStateInterpreter(object):
|
|
|
69219a |
'type': 'physical',
|
|
|
69219a |
'name': cfg.get('set-name', eth),
|
|
|
69219a |
}
|
|
|
69219a |
- mac_address = cfg.get('match', {}).get('macaddress', None)
|
|
|
69219a |
+ match = cfg.get('match', {})
|
|
|
69219a |
+ mac_address = match.get('macaddress', None)
|
|
|
69219a |
if not mac_address:
|
|
|
69219a |
LOG.debug('NetworkState Version2: missing "macaddress" info '
|
|
|
69219a |
'in config entry: %s: %s', eth, str(cfg))
|
|
|
69219a |
- phy_cmd.update({'mac_address': mac_address})
|
|
|
69219a |
-
|
|
|
69219a |
+ phy_cmd['mac_address'] = mac_address
|
|
|
69219a |
+ driver = match.get('driver', None)
|
|
|
69219a |
+ if driver:
|
|
|
69219a |
+ phy_cmd['params'] = {'driver': driver}
|
|
|
69219a |
for key in ['mtu', 'match', 'wakeonlan']:
|
|
|
69219a |
if key in cfg:
|
|
|
69219a |
- phy_cmd.update({key: cfg.get(key)})
|
|
|
69219a |
+ phy_cmd[key] = cfg[key]
|
|
|
69219a |
|
|
|
69219a |
subnets = self._v2_to_v1_ipcfg(cfg)
|
|
|
69219a |
if len(subnets) > 0:
|
|
|
69219a |
diff --git a/cloudinit/net/tests/test_init.py b/cloudinit/net/tests/test_init.py
|
|
|
69219a |
index 5519867..5349176 100644
|
|
|
69219a |
--- a/cloudinit/net/tests/test_init.py
|
|
|
69219a |
+++ b/cloudinit/net/tests/test_init.py
|
|
|
69219a |
@@ -218,9 +218,9 @@ class TestGenerateFallbackConfig(CiTestCase):
|
|
|
69219a |
mac = 'aa:bb:cc:aa:bb:cc'
|
|
|
69219a |
write_file(os.path.join(self.sysdir, 'eth1', 'address'), mac)
|
|
|
69219a |
expected = {
|
|
|
69219a |
- 'config': [{'type': 'physical', 'mac_address': mac,
|
|
|
69219a |
- 'name': 'eth1', 'subnets': [{'type': 'dhcp'}]}],
|
|
|
69219a |
- 'version': 1}
|
|
|
69219a |
+ 'ethernets': {'eth1': {'match': {'macaddress': mac},
|
|
|
69219a |
+ 'dhcp4': True, 'set-name': 'eth1'}},
|
|
|
69219a |
+ 'version': 2}
|
|
|
69219a |
self.assertEqual(expected, net.generate_fallback_config())
|
|
|
69219a |
|
|
|
69219a |
def test_generate_fallback_finds_dormant_eth_with_mac(self):
|
|
|
69219a |
@@ -229,9 +229,9 @@ class TestGenerateFallbackConfig(CiTestCase):
|
|
|
69219a |
mac = 'aa:bb:cc:aa:bb:cc'
|
|
|
69219a |
write_file(os.path.join(self.sysdir, 'eth0', 'address'), mac)
|
|
|
69219a |
expected = {
|
|
|
69219a |
- 'config': [{'type': 'physical', 'mac_address': mac,
|
|
|
69219a |
- 'name': 'eth0', 'subnets': [{'type': 'dhcp'}]}],
|
|
|
69219a |
- 'version': 1}
|
|
|
69219a |
+ 'ethernets': {'eth0': {'match': {'macaddress': mac}, 'dhcp4': True,
|
|
|
69219a |
+ 'set-name': 'eth0'}},
|
|
|
69219a |
+ 'version': 2}
|
|
|
69219a |
self.assertEqual(expected, net.generate_fallback_config())
|
|
|
69219a |
|
|
|
69219a |
def test_generate_fallback_finds_eth_by_operstate(self):
|
|
|
69219a |
@@ -239,9 +239,10 @@ class TestGenerateFallbackConfig(CiTestCase):
|
|
|
69219a |
mac = 'aa:bb:cc:aa:bb:cc'
|
|
|
69219a |
write_file(os.path.join(self.sysdir, 'eth0', 'address'), mac)
|
|
|
69219a |
expected = {
|
|
|
69219a |
- 'config': [{'type': 'physical', 'mac_address': mac,
|
|
|
69219a |
- 'name': 'eth0', 'subnets': [{'type': 'dhcp'}]}],
|
|
|
69219a |
- 'version': 1}
|
|
|
69219a |
+ 'ethernets': {
|
|
|
69219a |
+ 'eth0': {'dhcp4': True, 'match': {'macaddress': mac},
|
|
|
69219a |
+ 'set-name': 'eth0'}},
|
|
|
69219a |
+ 'version': 2}
|
|
|
69219a |
valid_operstates = ['dormant', 'down', 'lowerlayerdown', 'unknown']
|
|
|
69219a |
for state in valid_operstates:
|
|
|
69219a |
write_file(os.path.join(self.sysdir, 'eth0', 'operstate'), state)
|
|
|
69219a |
diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py
|
|
|
69219a |
index 66bbe5e..8cb7e5c 100755
|
|
|
69219a |
--- a/cloudinit/sources/DataSourceAzure.py
|
|
|
69219a |
+++ b/cloudinit/sources/DataSourceAzure.py
|
|
|
69219a |
@@ -1242,7 +1242,7 @@ def parse_network_config(imds_metadata):
|
|
|
69219a |
privateIpv4 = addr4['privateIpAddress']
|
|
|
69219a |
if privateIpv4:
|
|
|
69219a |
if dev_config.get('dhcp4', False):
|
|
|
69219a |
- # Append static address config for nic > 1
|
|
|
69219a |
+ # Append static address config for ip > 1
|
|
|
69219a |
netPrefix = intf['ipv4']['subnet'][0].get(
|
|
|
69219a |
'prefix', '24')
|
|
|
69219a |
if not dev_config.get('addresses'):
|
|
|
69219a |
@@ -1252,6 +1252,11 @@ def parse_network_config(imds_metadata):
|
|
|
69219a |
ip=privateIpv4, prefix=netPrefix))
|
|
|
69219a |
else:
|
|
|
69219a |
dev_config['dhcp4'] = True
|
|
|
69219a |
+ # non-primary interfaces should have a higher
|
|
|
69219a |
+ # route-metric (cost) so default routes prefer
|
|
|
69219a |
+ # primary nic due to lower route-metric value
|
|
|
69219a |
+ dev_config['dhcp4-overrides'] = {
|
|
|
69219a |
+ 'route-metric': (idx + 1) * 100}
|
|
|
69219a |
for addr6 in intf['ipv6']['ipAddress']:
|
|
|
69219a |
privateIpv6 = addr6['privateIpAddress']
|
|
|
69219a |
if privateIpv6:
|
|
|
69219a |
diff --git a/tests/unittests/test_datasource/test_azure.py b/tests/unittests/test_datasource/test_azure.py
|
|
|
69219a |
index 1fb0565..f2ff967 100644
|
|
|
69219a |
--- a/tests/unittests/test_datasource/test_azure.py
|
|
|
69219a |
+++ b/tests/unittests/test_datasource/test_azure.py
|
|
|
69219a |
@@ -13,6 +13,7 @@ from cloudinit.tests.helpers import (
|
|
|
69219a |
HttprettyTestCase, CiTestCase, populate_dir, mock, wrap_and_call,
|
|
|
69219a |
ExitStack, PY26, SkipTest, resourceLocation)
|
|
|
69219a |
|
|
|
69219a |
+import copy
|
|
|
69219a |
import crypt
|
|
|
69219a |
import httpretty
|
|
|
69219a |
import json
|
|
|
69219a |
@@ -111,6 +112,26 @@ NETWORK_METADATA = {
|
|
|
69219a |
}
|
|
|
69219a |
}
|
|
|
69219a |
|
|
|
69219a |
+SECONDARY_INTERFACE = {
|
|
|
69219a |
+ "macAddress": "220D3A047598",
|
|
|
69219a |
+ "ipv6": {
|
|
|
69219a |
+ "ipAddress": []
|
|
|
69219a |
+ },
|
|
|
69219a |
+ "ipv4": {
|
|
|
69219a |
+ "subnet": [
|
|
|
69219a |
+ {
|
|
|
69219a |
+ "prefix": "24",
|
|
|
69219a |
+ "address": "10.0.1.0"
|
|
|
69219a |
+ }
|
|
|
69219a |
+ ],
|
|
|
69219a |
+ "ipAddress": [
|
|
|
69219a |
+ {
|
|
|
69219a |
+ "privateIpAddress": "10.0.1.5",
|
|
|
69219a |
+ }
|
|
|
69219a |
+ ]
|
|
|
69219a |
+ }
|
|
|
69219a |
+}
|
|
|
69219a |
+
|
|
|
69219a |
MOCKPATH = 'cloudinit.sources.DataSourceAzure.'
|
|
|
69219a |
|
|
|
69219a |
|
|
|
69219a |
@@ -632,8 +653,43 @@ fdescfs /dev/fd fdescfs rw 0 0
|
|
|
69219a |
'ethernets': {
|
|
|
69219a |
'eth0': {'set-name': 'eth0',
|
|
|
69219a |
'match': {'macaddress': '00:0d:3a:04:75:98'},
|
|
|
69219a |
- 'dhcp4': True}},
|
|
|
69219a |
+ 'dhcp4': True,
|
|
|
69219a |
+ 'dhcp4-overrides': {'route-metric': 100}}},
|
|
|
69219a |
+ 'version': 2}
|
|
|
69219a |
+ dsrc = self._get_ds(data)
|
|
|
69219a |
+ dsrc.get_data()
|
|
|
69219a |
+ self.assertEqual(expected_network_config, dsrc.network_config)
|
|
|
69219a |
+
|
|
|
69219a |
+ def test_network_config_set_from_imds_route_metric_for_secondary_nic(self):
|
|
|
69219a |
+ """Datasource.network_config adds route-metric to secondary nics."""
|
|
|
69219a |
+ sys_cfg = {'datasource': {'Azure': {'apply_network_config': True}}}
|
|
|
69219a |
+ odata = {}
|
|
|
69219a |
+ data = {'ovfcontent': construct_valid_ovf_env(data=odata),
|
|
|
69219a |
+ 'sys_cfg': sys_cfg}
|
|
|
69219a |
+ expected_network_config = {
|
|
|
69219a |
+ 'ethernets': {
|
|
|
69219a |
+ 'eth0': {'set-name': 'eth0',
|
|
|
69219a |
+ 'match': {'macaddress': '00:0d:3a:04:75:98'},
|
|
|
69219a |
+ 'dhcp4': True,
|
|
|
69219a |
+ 'dhcp4-overrides': {'route-metric': 100}},
|
|
|
69219a |
+ 'eth1': {'set-name': 'eth1',
|
|
|
69219a |
+ 'match': {'macaddress': '22:0d:3a:04:75:98'},
|
|
|
69219a |
+ 'dhcp4': True,
|
|
|
69219a |
+ 'dhcp4-overrides': {'route-metric': 200}},
|
|
|
69219a |
+ 'eth2': {'set-name': 'eth2',
|
|
|
69219a |
+ 'match': {'macaddress': '33:0d:3a:04:75:98'},
|
|
|
69219a |
+ 'dhcp4': True,
|
|
|
69219a |
+ 'dhcp4-overrides': {'route-metric': 300}}},
|
|
|
69219a |
'version': 2}
|
|
|
69219a |
+ imds_data = copy.deepcopy(NETWORK_METADATA)
|
|
|
69219a |
+ imds_data['network']['interface'].append(SECONDARY_INTERFACE)
|
|
|
69219a |
+ third_intf = copy.deepcopy(SECONDARY_INTERFACE)
|
|
|
69219a |
+ third_intf['macAddress'] = third_intf['macAddress'].replace('22', '33')
|
|
|
69219a |
+ third_intf['ipv4']['subnet'][0]['address'] = '10.0.2.0'
|
|
|
69219a |
+ third_intf['ipv4']['ipAddress'][0]['privateIpAddress'] = '10.0.2.6'
|
|
|
69219a |
+ imds_data['network']['interface'].append(third_intf)
|
|
|
69219a |
+
|
|
|
69219a |
+ self.m_get_metadata_from_imds.return_value = imds_data
|
|
|
69219a |
dsrc = self._get_ds(data)
|
|
|
69219a |
dsrc.get_data()
|
|
|
69219a |
self.assertEqual(expected_network_config, dsrc.network_config)
|
|
|
69219a |
@@ -936,6 +992,7 @@ fdescfs /dev/fd fdescfs rw 0 0
|
|
|
69219a |
expected_cfg = {
|
|
|
69219a |
'ethernets': {
|
|
|
69219a |
'eth0': {'dhcp4': True,
|
|
|
69219a |
+ 'dhcp4-overrides': {'route-metric': 100},
|
|
|
69219a |
'match': {'macaddress': '00:0d:3a:04:75:98'},
|
|
|
69219a |
'set-name': 'eth0'}},
|
|
|
69219a |
'version': 2}
|
|
|
69219a |
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
|
|
|
69219a |
index a975678..206de56 100644
|
|
|
69219a |
--- a/tests/unittests/test_net.py
|
|
|
69219a |
+++ b/tests/unittests/test_net.py
|
|
|
69219a |
@@ -1651,7 +1651,7 @@ DEFAULT_DEV_ATTRS = {
|
|
|
69219a |
"carrier": False,
|
|
|
69219a |
"dormant": False,
|
|
|
69219a |
"operstate": "down",
|
|
|
69219a |
- "address": "07-1C-C6-75-A4-BE",
|
|
|
69219a |
+ "address": "07-1c-c6-75-a4-be",
|
|
|
69219a |
"device/driver": None,
|
|
|
69219a |
"device/device": None,
|
|
|
69219a |
"name_assign_type": "4",
|
|
|
69219a |
@@ -1702,6 +1702,39 @@ class TestGenerateFallbackConfig(CiTestCase):
|
|
|
69219a |
@mock.patch("cloudinit.net.sys_dev_path")
|
|
|
69219a |
@mock.patch("cloudinit.net.read_sys_net")
|
|
|
69219a |
@mock.patch("cloudinit.net.get_devicelist")
|
|
|
69219a |
+ def test_device_driver_v2(self, mock_get_devicelist, mock_read_sys_net,
|
|
|
69219a |
+ mock_sys_dev_path):
|
|
|
69219a |
+ """Network configuration for generate_fallback_config is version 2."""
|
|
|
69219a |
+ devices = {
|
|
|
69219a |
+ 'eth0': {
|
|
|
69219a |
+ 'bridge': False, 'carrier': False, 'dormant': False,
|
|
|
69219a |
+ 'operstate': 'down', 'address': '00:11:22:33:44:55',
|
|
|
69219a |
+ 'device/driver': 'hv_netsvc', 'device/device': '0x3',
|
|
|
69219a |
+ 'name_assign_type': '4'},
|
|
|
69219a |
+ 'eth1': {
|
|
|
69219a |
+ 'bridge': False, 'carrier': False, 'dormant': False,
|
|
|
69219a |
+ 'operstate': 'down', 'address': '00:11:22:33:44:55',
|
|
|
69219a |
+ 'device/driver': 'mlx4_core', 'device/device': '0x7',
|
|
|
69219a |
+ 'name_assign_type': '4'},
|
|
|
69219a |
+
|
|
|
69219a |
+ }
|
|
|
69219a |
+
|
|
|
69219a |
+ tmp_dir = self.tmp_dir()
|
|
|
69219a |
+ _setup_test(tmp_dir, mock_get_devicelist,
|
|
|
69219a |
+ mock_read_sys_net, mock_sys_dev_path,
|
|
|
69219a |
+ dev_attrs=devices)
|
|
|
69219a |
+
|
|
|
69219a |
+ network_cfg = net.generate_fallback_config(config_driver=True)
|
|
|
69219a |
+ expected = {
|
|
|
69219a |
+ 'ethernets': {'eth0': {'dhcp4': True, 'set-name': 'eth0',
|
|
|
69219a |
+ 'match': {'macaddress': '00:11:22:33:44:55',
|
|
|
69219a |
+ 'driver': 'hv_netsvc'}}},
|
|
|
69219a |
+ 'version': 2}
|
|
|
69219a |
+ self.assertEqual(expected, network_cfg)
|
|
|
69219a |
+
|
|
|
69219a |
+ @mock.patch("cloudinit.net.sys_dev_path")
|
|
|
69219a |
+ @mock.patch("cloudinit.net.read_sys_net")
|
|
|
69219a |
+ @mock.patch("cloudinit.net.get_devicelist")
|
|
|
69219a |
def test_device_driver(self, mock_get_devicelist, mock_read_sys_net,
|
|
|
69219a |
mock_sys_dev_path):
|
|
|
69219a |
devices = {
|
|
|
69219a |
@@ -1981,7 +2014,7 @@ class TestRhelSysConfigRendering(CiTestCase):
|
|
|
69219a |
#
|
|
|
69219a |
BOOTPROTO=dhcp
|
|
|
69219a |
DEVICE=eth1000
|
|
|
69219a |
-HWADDR=07-1C-C6-75-A4-BE
|
|
|
69219a |
+HWADDR=07-1c-c6-75-a4-be
|
|
|
69219a |
ONBOOT=yes
|
|
|
69219a |
TYPE=Ethernet
|
|
|
69219a |
USERCTL=no
|
|
|
69219a |
@@ -2354,7 +2387,7 @@ class TestOpenSuseSysConfigRendering(CiTestCase):
|
|
|
69219a |
#
|
|
|
69219a |
BOOTPROTO=dhcp
|
|
|
69219a |
DEVICE=eth1000
|
|
|
69219a |
-HWADDR=07-1C-C6-75-A4-BE
|
|
|
69219a |
+HWADDR=07-1c-c6-75-a4-be
|
|
|
69219a |
NM_CONTROLLED=no
|
|
|
69219a |
ONBOOT=yes
|
|
|
69219a |
TYPE=Ethernet
|
|
|
69219a |
@@ -2728,13 +2761,13 @@ class TestNetplanNetRendering(CiTestCase):
|
|
|
69219a |
|
|
|
69219a |
expected = """
|
|
|
69219a |
network:
|
|
|
69219a |
- version: 2
|
|
|
69219a |
ethernets:
|
|
|
69219a |
eth1000:
|
|
|
69219a |
dhcp4: true
|
|
|
69219a |
match:
|
|
|
69219a |
macaddress: 07-1c-c6-75-a4-be
|
|
|
69219a |
set-name: eth1000
|
|
|
69219a |
+ version: 2
|
|
|
69219a |
"""
|
|
|
69219a |
self.assertEqual(expected.lstrip(), contents.lstrip())
|
|
|
69219a |
self.assertEqual(1, mock_clean_default.call_count)
|
|
|
69219a |
--
|
|
|
69219a |
1.8.3.1
|
|
|
69219a |
|