cloud-init/backport-Fix-network-v2-metric-rendering-4220.patch
2023-08-26 14:46:22 +08:00

389 lines
14 KiB
Diff

From c68305a91791e28031df8b9ebd33bfe7ffd7e75d Mon Sep 17 00:00:00 2001
From: James Falcon <james.falcon@canonical.com>
Date: Tue, 4 Jul 2023 07:00:22 -0500
Subject: [PATCH] Fix network v2 metric rendering (#4220)
Reference:https://github.com/canonical/cloud-init/commit/c68305a91791e28031df8b9ebd33bfe7ffd7e75d
Conflict:(1)change 'small' to 'small_v1'
(2)do not change TestNetworkManagerRendering.
(3)do not add "NM_CONTROLLED=no" in test because of cloud-init-20.4-nm-controlled.patch.
(4)format diffs.
Metric info was not being included in v2-based routes.
Fixes GH-4217
---
cloudinit/net/network_state.py | 4 +-
tests/unittests/test_net.py | 232 ++++++++++++++++++++++++++++++---
2 files changed, 216 insertions(+), 20 deletions(-)
diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py
index 4862bf9..ac44304 100644
--- a/cloudinit/net/network_state.py
+++ b/cloudinit/net/network_state.py
@@ -187,7 +187,6 @@ class NetworkState(object):
class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
-
initial_network_state = {
'interfaces': {},
'routes': [],
@@ -582,7 +581,6 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
self._handle_bond_bridge(command, cmd_type='bond')
def handle_bridges(self, command):
-
'''
v2_command = {
br0: {
@@ -815,7 +813,7 @@ class NetworkStateInterpreter(metaclass=CommandHandlerMeta):
routes = []
for route in cfg.get('routes', []):
routes.append(_normalize_route(
- {'destination': route.get('to'), 'gateway': route.get('via')}))
+ {'destination': route.get('to'), 'gateway': route.get('via'), "metric": route.get("metric"),}))
# v2 routes are bound to the interface, in v1 we add them under
# the first subnet since there isn't an equivalent interface level.
diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py
index 7cde102..764e1c7 100644
--- a/tests/unittests/test_net.py
+++ b/tests/unittests/test_net.py
@@ -818,7 +818,7 @@ iface eth1 inet static
""".lstrip()
NETWORK_CONFIGS = {
- 'small': {
+ 'small_v1': {
'expected_networkd_eth99': textwrap.dedent("""\
[Match]
Name=eth99
@@ -959,6 +959,164 @@ NETWORK_CONFIGS = {
- wark.maas
"""),
},
+ # We test a separate set of configs here because v2 doesn't support
+ # generic nameservers, so that aspect needs to be modified
+ "small_v2": {
+ "expected_networkd_eth99": textwrap.dedent(
+ """\
+ [Match]
+ Name=eth99
+ MACAddress=c0:d6:9f:2c:e8:80
+ [Address]
+ Address=192.168.21.3/24
+ [Network]
+ DHCP=ipv4
+ Domains=barley.maas sach.maas
+ DNS=8.8.8.8 8.8.4.4
+ [Route]
+ Gateway=65.61.151.37
+ Destination=0.0.0.0/0
+ Metric=10000
+ """
+ ).rstrip(" "),
+ "expected_networkd_eth1": textwrap.dedent(
+ """\
+ [Match]
+ Name=eth1
+ MACAddress=cf:d6:af:48:e8:80
+ [Network]
+ DHCP=no
+ """
+ ).rstrip(" "),
+ "expected_eni": textwrap.dedent(
+ """\
+ auto lo
+ iface lo inet loopback
+ dns-nameservers 8.8.8.8 8.8.4.4
+ dns-search wark.maas
+ iface eth1 inet manual
+ auto eth99
+ iface eth99 inet dhcp
+ # control-alias eth99
+ iface eth99 inet static
+ address 192.168.21.3/24
+ dns-nameservers 8.8.8.8 8.8.4.4
+ dns-search barley.maas sach.maas
+ post-up route add default gw 65.61.151.37 metric 10000 || true
+ pre-down route del default gw 65.61.151.37 metric 10000 || true
+ """
+ ).rstrip(" "),
+ "expected_sysconfig_opensuse": {
+ "ifcfg-eth1": textwrap.dedent(
+ """\
+ BOOTPROTO=static
+ LLADDR=cf:d6:af:48:e8:80
+ STARTMODE=auto"""
+ ),
+ "ifcfg-eth99": textwrap.dedent(
+ """\
+ BOOTPROTO=dhcp4
+ LLADDR=c0:d6:9f:2c:e8:80
+ IPADDR=192.168.21.3
+ NETMASK=255.255.255.0
+ STARTMODE=auto"""
+ ),
+ },
+ "expected_sysconfig_rhel": {
+ "ifcfg-eth1": textwrap.dedent(
+ """\
+ BOOTPROTO=none
+ DEVICE=eth1
+ HWADDR=cf:d6:af:48:e8:80
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no"""
+ ),
+ "ifcfg-eth99": textwrap.dedent(
+ """\
+ BOOTPROTO=dhcp
+ DEFROUTE=yes
+ DEVICE=eth99
+ DHCLIENT_SET_DEFAULT_ROUTE=yes
+ DNS1=8.8.8.8
+ DNS2=8.8.4.4
+ DOMAIN="barley.maas sach.maas"
+ GATEWAY=65.61.151.37
+ HWADDR=c0:d6:9f:2c:e8:80
+ IPADDR=192.168.21.3
+ NETMASK=255.255.255.0
+ METRIC=10000
+ ONBOOT=yes
+ TYPE=Ethernet
+ USERCTL=no"""
+ ),
+ },
+ "expected_network_manager": {
+ "cloud-init-eth1.nmconnection": textwrap.dedent(
+ """\
+ # Generated by cloud-init. Changes will be lost.
+ [connection]
+ id=cloud-init eth1
+ uuid=3c50eb47-7260-5a6d-801d-bd4f587d6b58
+ autoconnect-priority=120
+ type=ethernet
+ [user]
+ org.freedesktop.NetworkManager.origin=cloud-init
+ [ethernet]
+ mac-address=CF:D6:AF:48:E8:80
+ """
+ ),
+ "cloud-init-eth99.nmconnection": textwrap.dedent(
+ """\
+ # Generated by cloud-init. Changes will be lost.
+ [connection]
+ id=cloud-init eth99
+ uuid=b1b88000-1f03-5360-8377-1a2205efffb4
+ autoconnect-priority=120
+ type=ethernet
+ [user]
+ org.freedesktop.NetworkManager.origin=cloud-init
+ [ethernet]
+ mac-address=C0:D6:9F:2C:E8:80
+ [ipv4]
+ method=auto
+ may-fail=false
+ route1=0.0.0.0/0,65.61.151.37
+ address1=192.168.21.3/24
+ dns=8.8.8.8;8.8.4.4;
+ dns-search=barley.maas;sach.maas;
+ """
+ ),
+ },
+ "yaml": textwrap.dedent(
+ """
+ version: 2
+ ethernets:
+ eth1:
+ match:
+ macaddress: cf:d6:af:48:e8:80
+ set-name: eth1
+ eth99:
+ addresses:
+ - 192.168.21.3/24
+ dhcp4: true
+ match:
+ macaddress: c0:d6:9f:2c:e8:80
+ nameservers:
+ addresses:
+ - 8.8.8.8
+ - 8.8.4.4
+ search:
+ - barley.maas
+ - sach.maas
+ routes:
+ - metric: 10000
+ to: 0.0.0.0/0
+ via: 65.61.151.37
+ set-name: eth99
+ """
+ ),
+ },
'v4_and_v6': {
'expected_networkd': textwrap.dedent("""\
[Match]
@@ -2965,7 +3123,6 @@ iface eth1 inet dhcp
mock.Mock(return_value=False)
)
class TestRhelSysConfigRendering(CiTestCase):
-
with_logs = True
nm_cfg_file = "/etc/NetworkManager/NetworkManager.conf"
@@ -3286,8 +3443,14 @@ USERCTL=no
'WARNING: Network config: ignoring eth0.101 device-level mtu',
self.logs.getvalue())
- def test_small_config(self):
- entry = NETWORK_CONFIGS['small']
+ def test_small_config_v1(self):
+ entry = NETWORK_CONFIGS["small_v1"]
+ found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
+ self._compare_files_to_expected(entry[self.expected_name], found)
+ self._assert_headers(found)
+
+ def test_small_config_v2(self):
+ entry = NETWORK_CONFIGS["small_v2"]
found = self._render_and_read(network_config=yaml.load(entry['yaml']))
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)
@@ -3429,7 +3592,7 @@ USERCTL=no
self.assertTrue(os.path.exists(nm_cfg))
# render and read
- entry = NETWORK_CONFIGS['small']
+ entry = NETWORK_CONFIGS['small_v1']
found = self._render_and_read(network_config=yaml.load(entry['yaml']),
dir=render_dir)
self._compare_files_to_expected(entry[self.expected_name], found)
@@ -3450,7 +3613,7 @@ USERCTL=no
util.write_file(nm_cfg, '# test_check_ifcfg_rh\n[main]\nplugins=foo\n')
# render and read
- entry = NETWORK_CONFIGS['small']
+ entry = NETWORK_CONFIGS['small_v1']
found = self._render_and_read(network_config=yaml.load(entry['yaml']),
dir=render_dir)
self._compare_files_to_expected(entry[self.expected_name], found)
@@ -3476,7 +3639,7 @@ USERCTL=no
self.assertTrue(os.path.exists(nm_cfg))
# render and read
- entry = NETWORK_CONFIGS['small']
+ entry = NETWORK_CONFIGS['small_v1']
found = self._render_and_read(network_config=yaml.load(entry['yaml']),
dir=render_dir)
self._compare_files_to_expected(entry[self.expected_name], found)
@@ -3644,7 +3807,6 @@ USERCTL=no
mock.Mock(return_value=False)
)
class TestOpenSuseSysConfigRendering(CiTestCase):
-
with_logs = True
scripts_dir = '/etc/sysconfig/network'
@@ -3916,8 +4078,14 @@ STARTMODE=auto
'WARNING: Network config: ignoring eth0.101 device-level mtu',
self.logs.getvalue())
- def test_small_config(self):
- entry = NETWORK_CONFIGS['small']
+ def test_small_config_v1(self):
+ entry = NETWORK_CONFIGS["small_v1"]
+ found = self._render_and_read(network_config=yaml.load(entry["yaml"]))
+ self._compare_files_to_expected(entry[self.expected_name], found)
+ self._assert_headers(found)
+
+ def test_small_config_v2(self):
+ entry = NETWORK_CONFIGS["small_v1"]
found = self._render_and_read(network_config=yaml.load(entry['yaml']))
self._compare_files_to_expected(entry[self.expected_name], found)
self._assert_headers(found)
@@ -4539,7 +4707,6 @@ class TestReadInitramfsConfig(CiTestCase):
class TestNetplanRoundTrip(CiTestCase):
-
NETPLAN_INFO_OUT = textwrap.dedent("""
netplan.io:
features:
@@ -4596,7 +4763,7 @@ class TestNetplanRoundTrip(CiTestCase):
files['/etc/netplan/50-cloud-init.yaml'].splitlines())
def testsimple_render_small_netplan(self):
- entry = NETWORK_CONFIGS['small']
+ entry = NETWORK_CONFIGS['small_v1']
files = self._render_and_read(network_config=yaml.load(entry['yaml']))
self.assertEqual(
entry['expected_netplan'].splitlines(),
@@ -4781,8 +4948,17 @@ class TestEniRoundTrip(CiTestCase):
entry['expected_eni'].splitlines(),
files['/etc/network/interfaces'].splitlines())
- def testsimple_render_small(self):
- entry = NETWORK_CONFIGS['small']
+ def testsimple_render_small_v1(self):
+ entry = NETWORK_CONFIGS["small_v1"]
+ files = self._render_and_read(network_config=yaml.load(entry["yaml"]))
+ self.assertEqual(
+ entry["expected_eni"].splitlines(),
+ files["/etc/network/interfaces"].splitlines(),
+ )
+
+ @pytest.mark.xfail(reason="GH-4219")
+ def testsimple_render_small_v2(self):
+ entry = NETWORK_CONFIGS["small_v2"]
files = self._render_and_read(network_config=yaml.load(entry['yaml']))
self.assertEqual(
entry['expected_eni'].splitlines(),
@@ -5105,10 +5281,33 @@ class TestNetworkdRoundTrip(CiTestCase):
return dir2dict(dir)
@mock.patch("cloudinit.net.util.chownbyname", return_value=True)
- def testsimple_render_small_networkd(self, m_chown):
+ def testsimple_render_small_networkd_v1(self, m_chown):
+ nwk_fn1 = "/etc/systemd/network/10-cloud-init-eth99.network"
+ nwk_fn2 = "/etc/systemd/network/10-cloud-init-eth1.network"
+ entry = NETWORK_CONFIGS["small_v1"]
+ files = self._render_and_read(network_config=yaml.load(entry["yaml"]))
+
+ actual = files[nwk_fn1].splitlines()
+ actual = self.create_conf_dict(actual)
+
+ expected = entry["expected_networkd_eth99"].splitlines()
+ expected = self.create_conf_dict(expected)
+
+ self.compare_dicts(actual, expected)
+
+ actual = files[nwk_fn2].splitlines()
+ actual = self.create_conf_dict(actual)
+
+ expected = entry["expected_networkd_eth1"].splitlines()
+ expected = self.create_conf_dict(expected)
+
+ self.compare_dicts(actual, expected)
+
+ @mock.patch("cloudinit.net.util.chownbyname", return_value=True)
+ def testsimple_render_small_networkd_v2(self, m_chown):
nwk_fn1 = '/etc/systemd/network/10-cloud-init-eth99.network'
nwk_fn2 = '/etc/systemd/network/10-cloud-init-eth1.network'
- entry = NETWORK_CONFIGS['small']
+ entry = NETWORK_CONFIGS['small_v2']
files = self._render_and_read(network_config=yaml.load(entry['yaml']))
actual = files[nwk_fn1].splitlines()
@@ -5735,7 +5934,6 @@ class TestInterfacesSorting(CiTestCase):
mock.Mock(return_value=False)
)
class TestGetIBHwaddrsByInterface(CiTestCase):
-
_ib_addr = '80:00:00:28:fe:80:00:00:00:00:00:00:00:11:22:03:00:33:44:56'
_ib_addr_eth_format = '00:11:22:33:44:56'
_data = {'devices': ['enp0s1', 'enp0s2', 'bond1', 'bridge1',
--
2.33.0