From efddb551adbf59394464ddd29e4ed80b23c0b25d Mon Sep 17 00:00:00 2001 From: Jon Maloy Date: Wed, 9 Aug 2023 19:29:43 +0000 Subject: [PATCH] * Wed Aug 09 2023 Jon Maloy - 23.1.1-9 - ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch [bz#2229460] - Resolves: bz#2229460 ([rhel-8.9] [RFE] Configure "ipv6.addr-gen-mode=eui64' as default in NetworkManager) --- ...default-IPv6-addr-gen-mode-for-all-i.patch | 293 ++++++++++++++++++ cloud-init.spec | 9 +- 2 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch diff --git a/ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch b/ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch new file mode 100644 index 0000000..2a5a2a1 --- /dev/null +++ b/ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch @@ -0,0 +1,293 @@ +From e9e49fc09636609ec5cf55984bee01784da52083 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Fri, 4 Aug 2023 08:58:26 +0530 +Subject: [PATCH] NM renderer: set default IPv6 addr-gen-mode for all + interfaces to eui64 (#4291) + +RH-Author: Ani Sinha +RH-MergeRequest: 107: NM renderer: set default IPv6 addr-gen-mode for all interfaces to eui64 (#4291) +RH-Bugzilla: 2229460 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/1] 2a8ed5a008d6fac5ab5263d94703a065ff3c192f (anisinha/rhel-cloud-init) + +By default, NetworkManager renderer in cloud-init does not set any specific +method for IPV6 addr-gen-mode in the keyfiles it writes. Hence, implicitly the +mode is set to `eui64` in the absence of any global addr-gen-mode option in +NetworkManager configuration. +Later when other interfaces get added via D-Bus API or by using nmcli commands +without explictly setting an addr-gen-mode, NM auto generates new profiles for +those interfaces with addr-gen-mode set to `stable-privacy`. This introduces +inconsistency of configurations between interfaces based on how they were +added. This can cause problems for the customers. + +In this change, cloud-init overrides NetworkManager's preferred default of +`stable-privacy` to use EUI64 using a drop in NetworkManager configuration +file. This setting can be overriden by using global-connection-defaults +setting in /etc/NetworkManager/NetworkManager.conf file. + +RHBZ: 2188388 + +Signed-off-by: Ani Sinha +(cherry picked from commit d41264cb4297a4b143a23f3677d33b81fbfc6e8e) + +Conflicts: + tests/unittests/test_net.py +--- + cloudinit/net/network_manager.py | 21 ++++++++ + tests/unittests/test_net.py | 91 +++++++++++++++++++++++++------- + 2 files changed, 94 insertions(+), 18 deletions(-) + +diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py +index ca216928..8047f796 100644 +--- a/cloudinit/net/network_manager.py ++++ b/cloudinit/net/network_manager.py +@@ -21,6 +21,15 @@ from cloudinit.net.network_state import NetworkState + NM_RUN_DIR = "/etc/NetworkManager" + NM_LIB_DIR = "/usr/lib/NetworkManager" + NM_CFG_FILE = "/etc/NetworkManager/NetworkManager.conf" ++NM_IPV6_ADDR_GEN_CONF = """# This is generated by cloud-init. Do not edit. ++# ++[.config] ++ enable=nm-version-min:1.40 ++[connection.30-cloud-init-ip6-addr-gen-mode] ++ # Select EUI64 to be used if the profile does not specify it. ++ ipv6.addr-gen-mode=0 ++ ++""" + LOG = logging.getLogger(__name__) + + +@@ -368,6 +377,12 @@ class Renderer(renderer.Renderer): + name = conn_filename(con_id, target) + util.write_file(name, conn.dump(), 0o600) + ++ # Select EUI64 to be used by default by NM for creating the address ++ # for use with RFC4862 IPv6 Stateless Address Autoconfiguration. ++ util.write_file( ++ cloud_init_nm_conf_filename(target), NM_IPV6_ADDR_GEN_CONF, 0o600 ++ ) ++ + + def conn_filename(con_id, target=None): + target_con_dir = subp.target_path(target, NM_RUN_DIR) +@@ -375,6 +390,12 @@ def conn_filename(con_id, target=None): + return f"{target_con_dir}/system-connections/{con_file}" + + ++def cloud_init_nm_conf_filename(target=None): ++ target_con_dir = subp.target_path(target, NM_RUN_DIR) ++ conf_file = "30-cloud-init-ip6-addr-gen-mode.conf" ++ return f"{target_con_dir}/conf.d/{conf_file}" ++ ++ + def available(target=None): + # TODO: Move `uses_systemd` to a more appropriate location + # It is imported here to avoid circular import +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index 6274f12d..aa4098b8 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -5628,9 +5628,25 @@ class TestNetworkManagerRendering(CiTestCase): + with_logs = True + + scripts_dir = "/etc/NetworkManager/system-connections" ++ conf_dir = "/etc/NetworkManager/conf.d" + + expected_name = "expected_network_manager" + ++ expected_conf_d = { ++ "30-cloud-init-ip6-addr-gen-mode.conf": textwrap.dedent( ++ """\ ++ # This is generated by cloud-init. Do not edit. ++ # ++ [.config] ++ enable=nm-version-min:1.40 ++ [connection.30-cloud-init-ip6-addr-gen-mode] ++ # Select EUI64 to be used if the profile does not specify it. ++ ipv6.addr-gen-mode=0 ++ ++ """ ++ ), ++ } ++ + def _get_renderer(self): + return network_manager.Renderer() + +@@ -5649,11 +5665,19 @@ class TestNetworkManagerRendering(CiTestCase): + renderer.render_network_state(ns, target=dir) + return dir2dict(dir) + +- def _compare_files_to_expected(self, expected, found): ++ def _compare_files_to_expected( ++ self, expected_scripts, expected_conf, found ++ ): + orig_maxdiff = self.maxDiff +- expected_d = dict( +- (os.path.join(self.scripts_dir, k), v) for k, v in expected.items() ++ conf_d = dict( ++ (os.path.join(self.conf_dir, k), v) ++ for k, v in expected_conf.items() ++ ) ++ scripts_d = dict( ++ (os.path.join(self.scripts_dir, k), v) ++ for k, v in expected_scripts.items() + ) ++ expected_d = {**conf_d, **scripts_d} + + try: + self.maxDiff = None +@@ -5714,6 +5738,7 @@ class TestNetworkManagerRendering(CiTestCase): + """ + ), + }, ++ self.expected_conf_d, + found, + ) + +@@ -5769,8 +5794,9 @@ class TestNetworkManagerRendering(CiTestCase): + gateway=10.0.2.2 + + """ +- ), ++ ) + }, ++ self.expected_conf_d, + found, + ) + +@@ -5806,33 +5832,44 @@ class TestNetworkManagerRendering(CiTestCase): + """ + ), + }, ++ self.expected_conf_d, + found, + ) + + def test_bond_config(self): + entry = NETWORK_CONFIGS["bond"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_vlan_config(self): + entry = NETWORK_CONFIGS["vlan"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_bridge_config(self): + entry = NETWORK_CONFIGS["bridge"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_manual_config(self): + entry = NETWORK_CONFIGS["manual"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_all_config(self): + entry = NETWORK_CONFIGS["all"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + self.assertNotIn( + "WARNING: Network config: ignoring eth0.101 device-level mtu", + self.logs.getvalue(), +@@ -5841,12 +5878,16 @@ class TestNetworkManagerRendering(CiTestCase): + def test_small_config(self): + entry = NETWORK_CONFIGS["small"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_v4_and_v6_static_config(self): + entry = NETWORK_CONFIGS["v4_and_v6_static"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + expected_msg = ( + "WARNING: Network config: ignoring iface0 device-level mtu:8999" + " because ipv4 subnet-level mtu:9000 provided." +@@ -5856,41 +5897,55 @@ class TestNetworkManagerRendering(CiTestCase): + def test_dhcpv6_only_config(self): + entry = NETWORK_CONFIGS["dhcpv6_only"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_simple_render_ipv6_slaac(self): + entry = NETWORK_CONFIGS["ipv6_slaac"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_dhcpv6_stateless_config(self): + entry = NETWORK_CONFIGS["dhcpv6_stateless"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_wakeonlan_disabled_config_v2(self): + entry = NETWORK_CONFIGS["wakeonlan_disabled"] + found = self._render_and_read( + network_config=yaml.load(entry["yaml_v2"]) + ) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_wakeonlan_enabled_config_v2(self): + entry = NETWORK_CONFIGS["wakeonlan_enabled"] + found = self._render_and_read( + network_config=yaml.load(entry["yaml_v2"]) + ) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_render_v4_and_v6(self): + entry = NETWORK_CONFIGS["v4_and_v6"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + def test_render_v6_and_v4(self): + entry = NETWORK_CONFIGS["v6_and_v4"] + found = self._render_and_read(network_config=yaml.load(entry["yaml"])) +- self._compare_files_to_expected(entry[self.expected_name], found) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + + @mock.patch( +-- +2.37.3 + diff --git a/cloud-init.spec b/cloud-init.spec index 007234a..91b0773 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -6,7 +6,7 @@ Name: cloud-init Version: 23.1.1 -Release: 8%{?dist} +Release: 9%{?dist} Summary: Cloud instance init scripts Group: System Environment/Base @@ -52,6 +52,8 @@ Patch25: ci-cosmetic-fix-tox-formatting.patch Patch28: ci-logging-keep-current-file-mode-of-log-file-if-its-st.patch # For bz#2223810 - [cloud-init] [RHEL8.9]There are warning logs if dev has more than one IPV6 address on ESXi Patch29: ci-DS-VMware-modify-a-few-log-level-4284.patch +# For bz#2229460 - [rhel-8.9] [RFE] Configure "ipv6.addr-gen-mode=eui64' as default in NetworkManager +Patch30: ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch BuildArch: noarch @@ -258,6 +260,11 @@ fi %config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf %changelog +* Wed Aug 09 2023 Jon Maloy - 23.1.1-9 +- ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch [bz#2229460] +- Resolves: bz#2229460 + ([rhel-8.9] [RFE] Configure "ipv6.addr-gen-mode=eui64' as default in NetworkManager) + * Thu Jul 27 2023 Camilla Conte - 23.1.1-8 - ci-DS-VMware-modify-a-few-log-level-4284.patch [bz#2223810] - Resolves: bz#2223810