* 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:
parent
74b6471f2f
commit
efddb551ad
293
ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch
Normal file
293
ci-NM-renderer-set-default-IPv6-addr-gen-mode-for-all-i.patch
Normal 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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user