* Wed Aug 09 2023 Jon Maloy <jmaloy@redhat.com> - 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)
This commit is contained in:
Jon Maloy 2023-08-09 19:29:43 +00:00
parent 74b6471f2f
commit efddb551ad
2 changed files with 301 additions and 1 deletions

View File

@ -0,0 +1,293 @@
From e9e49fc09636609ec5cf55984bee01784da52083 Mon Sep 17 00:00:00 2001
From: Ani Sinha <anisinha@redhat.com>
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 <None>
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 <eesposit@redhat.com>
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
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 <anisinha@redhat.com>
(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

View File

@ -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 <jmaloy@redhat.com> - 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 <cconte@redhat.com> - 23.1.1-8
- ci-DS-VMware-modify-a-few-log-level-4284.patch [bz#2223810]
- Resolves: bz#2223810