diff --git a/SOURCES/0041-enable-ec2_utils-to-stop-retrying-to-get-ec2-metadata.patch b/SOURCES/0041-enable-ec2_utils-to-stop-retrying-to-get-ec2-metadata.patch new file mode 100644 index 0000000..d691b94 --- /dev/null +++ b/SOURCES/0041-enable-ec2_utils-to-stop-retrying-to-get-ec2-metadata.patch @@ -0,0 +1,50 @@ +Enable ec2_utils to stop retrying to get ec2 metadata + +Signed-off-by: David Sloboda +Reviewed-by: Laurence Rochfort + +diff -ruN a/cloudinit/sources/helpers/openstack.py b/cloudinit/sources/helpers/openstack.py +--- a/cloudinit/sources/helpers/openstack.py 2018-04-02 12:51:20.053828637 -0700 ++++ b/cloudinit/sources/helpers/openstack.py 2018-04-02 12:33:20.000000000 -0700 +@@ -464,6 +464,16 @@ + + return results + ++def should_retry_cb(_request_args, cause): ++ try: ++ code = int(cause.code) ++ if code >= 400: ++ return False ++ except (TypeError, ValueError): ++ # Older versions of requests didn't have a code. ++ pass ++ return True ++ + + class MetadataReader(BaseReader): + def __init__(self, base_url, ssl_details=None, timeout=5, retries=5): +@@ -489,16 +499,6 @@ + return self._versions + + def _path_read(self, path, decode=False): +- def should_retry_cb(_request_args, cause): +- try: +- code = int(cause.code) +- if code >= 400: +- return False +- except (TypeError, ValueError): +- # Older versions of requests didn't have a code. +- pass +- return True +- + response = url_helper.readurl( + path, + retries=self.retries, +@@ -519,6 +519,7 @@ + ssl_details=self.ssl_details, + timeout=self.timeout, + retries=self.retries, ++ exception_cb=should_retry_cb, + ) + + diff --git a/SOURCES/0106-tests-unittests-add-a-new-unit-test-for-network-mana.patch b/SOURCES/0106-tests-unittests-add-a-new-unit-test-for-network-mana.patch new file mode 100644 index 0000000..2248cbf --- /dev/null +++ b/SOURCES/0106-tests-unittests-add-a-new-unit-test-for-network-mana.patch @@ -0,0 +1,136 @@ +From 37a6837813e418486af8cbef436ab82a8be3e3fa Mon Sep 17 00:00:00 2001 +From: Darren Archibald +Date: Fri, 23 Feb 2024 06:06:30 -0800 +Subject: [PATCH] tests/unittests: add a new unit test for network manager net + activator (#4672) + +Some changes in behavior in network manager net activator was brought in with +the commit +d1d5166895da ("net/nm: check for presence of ifcfg files when nm connection files are absent") + +This change adds some unit tests that exercizes network manager activator's +bring_up_interface() method that tests failure scenarios as well as cases +where an ifcfg file is used to bring the interface up. + +Signed-off-by: Ani Sinha +(cherry picked from commit bb474df78bfe45ea5f05907eb710e8d5de764fc8) +Signed-off-by: Darren Archibald +--- + tests/unittests/test_net_activators.py | 101 +++++++++++++++++++++++++ + 1 file changed, 101 insertions(+) + +diff --git a/tests/unittests/test_net_activators.py b/tests/unittests/test_net_activators.py +index 2a363ec..f95c8a7 100644 +--- a/tests/unittests/test_net_activators.py ++++ b/tests/unittests/test_net_activators.py +@@ -288,6 +288,107 @@ class TestActivatorsBringUp: + for call in m_subp.call_args_list: + assert call in expected_call_list + ++class TestNetworkManagerActivatorBringUp: ++ @patch("cloudinit.subp.subp", return_value=("", "")) ++ @patch( ++ "cloudinit.net.network_manager.available_nm_ifcfg_rh", ++ return_value=True, ++ ) ++ @patch("os.path.isfile") ++ @patch("os.path.exists", return_value=True) ++ def test_bring_up_interface_no_nm_conn( ++ self, m_exists, m_isfile, m_plugin, m_subp ++ ): ++ """ ++ There is no network manager connection file but ifcfg-rh plugin is ++ present and ifcfg interface config files are also present. In this ++ case, we should use ifcfg files. ++ """ ++ ++ def fake_isfile_no_nmconn(filename): ++ return False if filename.endswith(".nmconnection") else True ++ ++ m_isfile.side_effect = fake_isfile_no_nmconn ++ ++ expected_call_list = [ ++ ( ++ ( ++ [ ++ "nmcli", ++ "connection", ++ "load", ++ "".join( ++ [ ++ "/etc/sysconfig/network-scripts/ifcfg-eth0", ++ ] ++ ), ++ ], ++ ), ++ {}, ++ ), ++ ( ++ ( ++ [ ++ "nmcli", ++ "connection", ++ "up", ++ "filename", ++ "".join( ++ [ ++ "/etc/sysconfig/network-scripts/ifcfg-eth0", ++ ] ++ ), ++ ], ++ ), ++ {}, ++ ), ++ ] ++ ++ index = 0 ++ assert NetworkManagerActivator.bring_up_interface("eth0") ++ for call in m_subp.call_args_list: ++ assert call == expected_call_list[index] ++ index += 1 ++ ++ @patch("cloudinit.subp.subp", return_value=("", "")) ++ @patch( ++ "cloudinit.net.network_manager.available_nm_ifcfg_rh", ++ return_value=False, ++ ) ++ @patch("os.path.isfile") ++ @patch("os.path.exists", return_value=True) ++ def test_bring_up_interface_no_plugin_no_nm_conn( ++ self, m_exists, m_isfile, m_plugin, m_subp ++ ): ++ """ ++ The ifcfg-rh plugin is absent and nmconnection file is also ++ not present. In this case, we can't use ifcfg file and the ++ interface bring up should fail. ++ """ ++ ++ def fake_isfile_no_nmconn(filename): ++ return False if filename.endswith(".nmconnection") else True ++ ++ m_isfile.side_effect = fake_isfile_no_nmconn ++ assert not NetworkManagerActivator.bring_up_interface("eth0") ++ ++ @patch("cloudinit.subp.subp", return_value=("", "")) ++ @patch( ++ "cloudinit.net.network_manager.available_nm_ifcfg_rh", ++ return_value=True, ++ ) ++ @patch("os.path.isfile", return_value=False) ++ @patch("os.path.exists", return_value=True) ++ def test_bring_up_interface_no_conn_file( ++ self, m_exists, m_isfile, m_plugin, m_subp ++ ): ++ """ ++ Neither network manager connection files are present nor ++ ifcfg files are present. Even if ifcfg-rh plugin is present, ++ we can not bring up the interface. So bring_up_interface() ++ should fail. ++ """ ++ assert not NetworkManagerActivator.bring_up_interface("eth0") + + IF_UP_DOWN_BRING_DOWN_CALL_LIST: list = [ + ((["ifdown", "eth0"],), {}), +-- +2.31.1 + diff --git a/SOURCES/1010-orabug36958039-Removes-condition-specific-to-OL-for-write_files_def.patch b/SOURCES/1010-orabug36958039-Removes-condition-specific-to-OL-for-write_files_def.patch new file mode 100644 index 0000000..f72fbe8 --- /dev/null +++ b/SOURCES/1010-orabug36958039-Removes-condition-specific-to-OL-for-write_files_def.patch @@ -0,0 +1,31 @@ +From 4964e60ede9445e9891cf8501060ac2751a3ba5f Mon Sep 17 00:00:00 2001 +From: Sourav Sharma +Date: Fri, 22 Nov 2024 14:32:05 +0530 +Subject: [PATCH] Removes condition specific to OL for write_files_deferred + +Github-issue-link: https://github.com/oracle/oracle-linux/issues/156 + +Orabug: 36958039 + +Signed-off-by: Sourav Sharma +--- + config/cloud.cfg.tmpl | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl +index c756719..28ee581 100644 +--- a/config/cloud.cfg.tmpl ++++ b/config/cloud.cfg.tmpl +@@ -199,9 +199,7 @@ cloud_final_modules: + {% if variant in ["ubuntu", "unknown"] %} + - ubuntu_drivers + {% endif %} +-{% if variant not in ["ol"] %} + - write_files_deferred +-{% endif %} + - puppet + - chef + - ansible +-- +2.43.5 + diff --git a/SOURCES/ci-Deprecate-the-users-ssh-authorized-keys-property-516.patch b/SOURCES/ci-Deprecate-the-users-ssh-authorized-keys-property-516.patch new file mode 100644 index 0000000..6ded6b4 --- /dev/null +++ b/SOURCES/ci-Deprecate-the-users-ssh-authorized-keys-property-516.patch @@ -0,0 +1,108 @@ +From 808cd6f434a4ede1441cc1f5781abf59f53c4153 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Anders=20Bj=C3=B6rklund?= +Date: Mon, 22 Apr 2024 17:52:44 +0200 +Subject: [PATCH 1/3] Deprecate the users ssh-authorized-keys property (#5162) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Ani Sinha +RH-MergeRequest: 95: Deprecate the users ssh-authorized-keys property (#5162) +RH-Jira: RHEL-45262 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/3] 27d6f99519a28ae91037fe47f9ef654b7fbd6236 (anisinha/cloud-init) + +Deprecate the users ssh-authorized-keys property + +Signed-off-by: Anders F Björklund +(cherry picked from commit 5205b4dd74eb2168ebbeba56579b6f116a272937) +--- + .../schemas/schema-cloud-config-v1.json | 16 ++++++++++ + .../unittests/config/test_cc_users_groups.py | 30 +++++++++++++++++++ + tools/.github-cla-signers | 1 + + 3 files changed, 47 insertions(+) + +diff --git a/cloudinit/config/schemas/schema-cloud-config-v1.json b/cloudinit/config/schemas/schema-cloud-config-v1.json +index 8b10fe70..670ef4c2 100644 +--- a/cloudinit/config/schemas/schema-cloud-config-v1.json ++++ b/cloudinit/config/schemas/schema-cloud-config-v1.json +@@ -272,6 +272,22 @@ + }, + "minItems": 1 + }, ++ "ssh-authorized-keys": { ++ "allOf": [ ++ { ++ "type": "array", ++ "items": { ++ "type": "string" ++ }, ++ "minItems": 1 ++ }, ++ { ++ "deprecated": true, ++ "deprecated_version": "18.3", ++ "deprecated_description": "Use ``ssh_authorized_keys`` instead." ++ } ++ ] ++ }, + "ssh_import_id": { + "description": "List of SSH IDs to import for user. Can not be combined with ``ssh_redirect_user``.", + "type": "array", +diff --git a/tests/unittests/config/test_cc_users_groups.py b/tests/unittests/config/test_cc_users_groups.py +index 3300b77b..53e231e1 100644 +--- a/tests/unittests/config/test_cc_users_groups.py ++++ b/tests/unittests/config/test_cc_users_groups.py +@@ -503,6 +503,36 @@ class TestUsersGroupsSchema: + ), + True, + ), ++ ( ++ { ++ "users": [ ++ { ++ "name": "lima", ++ "uid": "1000", ++ "homedir": "/home/lima.linux", ++ "shell": "/bin/bash", ++ "sudo": "ALL=(ALL) NOPASSWD:ALL", ++ "lock_passwd": True, ++ "ssh-authorized-keys": ["ssh-ed25519 ..."], ++ } ++ ] ++ }, ++ pytest.raises( ++ SchemaValidationError, ++ match=( ++ "Cloud config schema deprecations: " ++ "users.0.ssh-authorized-keys: " ++ " Deprecated in version 18.3." ++ " Use ``ssh_authorized_keys`` instead." ++ ", " ++ "users.0.uid: " ++ " Changed in version 22.3." ++ " The use of ``string`` type is deprecated." ++ " Use an ``integer`` instead." ++ ), ++ ), ++ False, ++ ), + ], + ) + @skipUnlessJsonSchema() +diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers +index f4da0989..8b119025 100644 +--- a/tools/.github-cla-signers ++++ b/tools/.github-cla-signers +@@ -3,6 +3,7 @@ aciba90 + acourdavAkamai + ader1990 + adobley ++afbjorklund + ajmyyra + akutz + AlexBaranowski +-- +2.39.3 + diff --git a/SOURCES/ci-Fix-metric-setting-for-ifcfg-network-connections-for.patch b/SOURCES/ci-Fix-metric-setting-for-ifcfg-network-connections-for.patch new file mode 100644 index 0000000..6eb7ed9 --- /dev/null +++ b/SOURCES/ci-Fix-metric-setting-for-ifcfg-network-connections-for.patch @@ -0,0 +1,145 @@ +From 94c0cd9c656877250f7e5cfe05325a42bbdec182 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Fri, 4 Oct 2024 02:38:23 +0530 +Subject: [PATCH 1/2] Fix metric setting for ifcfg network connections for rhel + (#5777) + +RH-Author: xiachen +RH-MergeRequest: 145: Fix metric setting for ifcfg network connections for rhel (#5777) +RH-Jira: RHEL-65018 +RH-Acked-by: Ani Sinha +RH-Commit: [1/2] a18205f1ffa455a2ccd836ba6baa12b7da0afbde (xiachen/cloud-init) + +Most RHEL systems use Network manager to bring up manage network connections. +Network manager does not recognize "METRIC" option for network connections. +It uses IPV4_ROUTE_METRIC and IPV6_ROUTE_METRIC options. Please see +https://people.freedesktop.org/~lkundrak/nm-docs/nm-settings-ifcfg-rh.html + +This change ensures that cloud-init generates ifcfg network connection files +with IPV{4/6}_ROUTE_METRIC options that are compatible with RHEL and +network manager. + +Fixes GH-5776 + +(cherry picked from commit a399f4b0815234e3fe11255178c737902b2d243d) + +Signed-off-by: Amy Chen +--- + cloudinit/net/sysconfig.py | 21 ++++++++++++++++++--- + tests/unittests/test_net.py | 37 ++++++++++++++++++++----------------- + 2 files changed, 38 insertions(+), 20 deletions(-) + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index 7eb430ed1..b50a6a8a0 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -205,7 +205,7 @@ class Route(ConfigMap): + ) + metric_key = "METRIC" + index + if metric_key in self._conf: +- metric_value = str(self._conf["METRIC" + index]) ++ metric_value = str(self._conf[metric_key]) + buf.write( + "%s=%s\n" + % ("METRIC" + str(reindex), _quote_value(metric_value)) +@@ -549,7 +549,12 @@ class Renderer(renderer.Renderer): + subnet_type = subnet.get("type") + # metric may apply to both dhcp and static config + if "metric" in subnet: +- if flavor != "suse": ++ if flavor == "rhel": ++ if subnet_is_ipv6(subnet): ++ iface_cfg["IPV6_ROUTE_METRIC"] = subnet["metric"] ++ else: ++ iface_cfg["IPV4_ROUTE_METRIC"] = subnet["metric"] ++ elif flavor != "suse": + iface_cfg["METRIC"] = subnet["metric"] + if subnet_type in ["dhcp", "dhcp4"]: + # On SUSE distros 'DHCLIENT_SET_DEFAULT_ROUTE' is a global +@@ -656,7 +661,17 @@ class Renderer(renderer.Renderer): + iface_cfg["GATEWAY"] = route["gateway"] + route_cfg.has_set_default_ipv4 = True + if "metric" in route: +- iface_cfg["METRIC"] = route["metric"] ++ if flavor == "rhel": ++ if subnet_is_ipv6(subnet): ++ iface_cfg["IPV6_ROUTE_METRIC"] = route[ ++ "metric" ++ ] ++ else: ++ iface_cfg["IPV4_ROUTE_METRIC"] = route[ ++ "metric" ++ ] ++ else: ++ iface_cfg["METRIC"] = route["metric"] + + else: + # add default routes only to ifcfg files, not +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index 2d716f4b5..4673e4eaf 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -1345,7 +1345,7 @@ NETWORK_CONFIGS = { + HWADDR=c0:d6:9f:2c:e8:80 + IPADDR=192.168.21.3 + NETMASK=255.255.255.0 +- METRIC=10000 ++ IPV4_ROUTE_METRIC=10000 + ONBOOT=yes + TYPE=Ethernet + USERCTL=no""" +@@ -1521,7 +1521,7 @@ NETWORK_CONFIGS = { + HWADDR=c0:d6:9f:2c:e8:80 + IPADDR=192.168.21.3 + NETMASK=255.255.255.0 +- METRIC=10000 ++ IPV4_ROUTE_METRIC=10000 + ONBOOT=yes + TYPE=Ethernet + USERCTL=no""" +@@ -5725,24 +5725,27 @@ USERCTL=no + } + }, + } +- expected = { +- "ifcfg-eno1": textwrap.dedent( +- """\ +- AUTOCONNECT_PRIORITY=120 +- BOOTPROTO=dhcp +- DEVICE=eno1 +- HWADDR=07-1c-c6-75-a4-be +- METRIC=100 +- ONBOOT=yes +- TYPE=Ethernet +- USERCTL=no +- """ +- ), +- } + for dhcp_ver in ("dhcp4", "dhcp6"): ++ expected = { ++ "ifcfg-eno1": textwrap.dedent( ++ """\ ++ AUTOCONNECT_PRIORITY=120 ++ BOOTPROTO=dhcp ++ DEVICE=eno1 ++ HWADDR=07-1c-c6-75-a4-be ++ ONBOOT=yes ++ TYPE=Ethernet ++ USERCTL=no ++ """ ++ ), ++ } + v2data = copy.deepcopy(v2base) + if dhcp_ver == "dhcp6": +- expected["ifcfg-eno1"] += "IPV6INIT=yes\nDHCPV6C=yes\n" ++ expected[ ++ "ifcfg-eno1" ++ ] += "IPV6INIT=yes\nDHCPV6C=yes\nIPV6_ROUTE_METRIC=100\n" ++ else: ++ expected["ifcfg-eno1"] += "IPV4_ROUTE_METRIC=100\n" + v2data["ethernets"]["eno1"].update( + {dhcp_ver: True, "{0}-overrides".format(dhcp_ver): overrides} + ) +-- +2.39.3 + diff --git a/SOURCES/ci-Prevent-NM-from-handling-DNS-when-network-interfaces.patch b/SOURCES/ci-Prevent-NM-from-handling-DNS-when-network-interfaces.patch new file mode 100644 index 0000000..6ce4bf1 --- /dev/null +++ b/SOURCES/ci-Prevent-NM-from-handling-DNS-when-network-interfaces.patch @@ -0,0 +1,248 @@ +From 038a391b7016f16a7336d67965762a7dbf3ba662 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Tue, 5 Nov 2024 04:07:36 +0530 +Subject: [PATCH] Prevent NM from handling DNS when network interfaces have DNS + config (#5846) + +RH-Author: Ani Sinha +RH-MergeRequest: 150: Prevent NM from handling DNS when network interfaces have DNS config (#5846) +RH-Jira: RHEL-65778 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/1] b464ef219eba1a0c718dda5ed96b6f88e1273f99 + +In the change under PR #5401, we use global DNS configuration as well as +DNS and search domain information from interface config and use it to populate +/etc/resolv.conf. Therefore, if either or both global DNS/search domain config +is present along with per-interface DNS/search domain information, we should add +a network manager configuration to prevent network manager from manipulating +/etc/resolv.conf. +This is in addition to what we already do when only global DNS data is +configured. + +Fixes bug added in 1b8030e0 . + +Signed-off-by: Ani Sinha +(cherry picked from commit 2df49b652471999434f06d9d83ed9db8b4055895) +--- + cloudinit/net/sysconfig.py | 28 +++++-- + tests/unittests/test_net.py | 158 ++++++++++++++++++++++++++++++++++++ + 2 files changed, 181 insertions(+), 5 deletions(-) + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index e4a65187f..4898a2fd1 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -905,17 +905,35 @@ class Renderer(renderer.Renderer): + + @staticmethod + def _render_networkmanager_conf(network_state, templates=None): ++ iface_dns = False + content = networkmanager_conf.NetworkManagerConf("") +- +- # If DNS server information is provided, configure +- # NetworkManager to not manage dns, so that /etc/resolv.conf +- # does not get clobbered. ++ # check if there is interface specific DNS information configured ++ for iface in network_state.iter_interfaces(): ++ for subnet in iface["subnets"]: ++ if "dns_nameservers" in subnet or "dns_search" in subnet: ++ iface_dns = True ++ break ++ if ( ++ not iface_dns ++ and "dns" in iface ++ and (iface["dns"]["nameservers"] or iface["dns"]["search"]) ++ ): ++ iface_dns = True ++ break ++ ++ # If DNS server and/or dns search information is provided either ++ # globally or per interface basis, configure NetworkManager to ++ # not manage dns, so that /etc/resolv.conf does not get clobbered. + # This is not required for NetworkManager renderer as it + # does not write /etc/resolv.conf directly. DNS information is + # written to the interface keyfile and NetworkManager is then + # responsible for using the DNS information from the keyfile, + # including managing /etc/resolv.conf. +- if network_state.dns_nameservers: ++ if ( ++ network_state.dns_nameservers ++ or network_state.dns_searchdomains ++ or iface_dns ++ ): + content.set_section_keypair("main", "dns", "none") + + if len(content) == 0: +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index ddb45dc69..47b36d052 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -967,6 +967,164 @@ dns = none + ), + ], + }, ++ { ++ "in_data": { ++ "networks": [ ++ { ++ "network_id": "dacd568d-5be6-4786-91fe-750c374b78b4", ++ "type": "ipv4", ++ "netmask": "255.255.252.0", ++ "link": "eth0", ++ "routes": [ ++ { ++ "netmask": "0.0.0.0", ++ "network": "0.0.0.0", ++ "gateway": "172.19.3.254", ++ } ++ ], ++ "ip_address": "172.19.1.34", ++ "dns_search": ["example3.com"], ++ "dns_nameservers": ["172.19.0.12"], ++ "id": "network0", ++ } ++ ], ++ "links": [ ++ { ++ "ethernet_mac_address": "fa:16:3e:ed:9a:59", ++ "mtu": None, ++ "type": "physical", ++ "id": "eth0", ++ }, ++ ], ++ }, ++ "in_macs": { ++ "fa:16:3e:ed:9a:59": "eth0", ++ }, ++ "out_sysconfig_opensuse": [ ++ ( ++ "etc/sysconfig/network/ifcfg-eth0", ++ """ ++# Created by cloud-init automatically, do not edit. ++# ++BOOTPROTO=static ++IPADDR=172.19.1.34 ++LLADDR=fa:16:3e:ed:9a:59 ++NETMASK=255.255.252.0 ++STARTMODE=auto ++""".lstrip(), ++ ), ++ ( ++ "etc/resolv.conf", ++ """ ++; Created by cloud-init automatically, do not edit. ++; ++nameserver 172.19.0.12 ++search example3.com ++""".lstrip(), ++ ), ++ ( ++ "etc/NetworkManager/conf.d/99-cloud-init.conf", ++ """ ++# Created by cloud-init automatically, do not edit. ++# ++[main] ++dns = none ++""".lstrip(), ++ ), ++ ( ++ "etc/udev/rules.d/85-persistent-net-cloud-init.rules", ++ "".join( ++ [ ++ 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ', ++ 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n', ++ ] ++ ), ++ ), ++ ], ++ "out_sysconfig_rhel": [ ++ ( ++ "etc/sysconfig/network-scripts/ifcfg-eth0", ++ """ ++# Created by cloud-init automatically, do not edit. ++# ++AUTOCONNECT_PRIORITY=120 ++BOOTPROTO=none ++DEFROUTE=yes ++DEVICE=eth0 ++DNS1=172.19.0.12 ++DOMAIN=example3.com ++GATEWAY=172.19.3.254 ++HWADDR=fa:16:3e:ed:9a:59 ++IPADDR=172.19.1.34 ++NETMASK=255.255.252.0 ++ONBOOT=yes ++TYPE=Ethernet ++USERCTL=no ++""".lstrip(), ++ ), ++ ( ++ "etc/resolv.conf", ++ """ ++; Created by cloud-init automatically, do not edit. ++; ++nameserver 172.19.0.12 ++search example3.com ++""".lstrip(), ++ ), ++ ( ++ "etc/NetworkManager/conf.d/99-cloud-init.conf", ++ """ ++# Created by cloud-init automatically, do not edit. ++# ++[main] ++dns = none ++""".lstrip(), ++ ), ++ ( ++ "etc/udev/rules.d/70-persistent-net.rules", ++ "".join( ++ [ ++ 'SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ', ++ 'ATTR{address}=="fa:16:3e:ed:9a:59", NAME="eth0"\n', ++ ] ++ ), ++ ), ++ ], ++ "expected_network_manager": [ ++ ( ++ "".join( ++ [ ++ "etc/NetworkManager/system-connections", ++ "/cloud-init-eth0.nmconnection", ++ ] ++ ), ++ """ ++# Generated by cloud-init. Changes will be lost. ++ ++[connection] ++id=cloud-init eth0 ++uuid=1dd9a779-d327-56e1-8454-c65e2556c12c ++autoconnect-priority=120 ++type=ethernet ++ ++[user] ++org.freedesktop.NetworkManager.origin=cloud-init ++ ++[ethernet] ++mac-address=FA:16:3E:ED:9A:59 ++ ++[ipv4] ++method=manual ++may-fail=false ++address1=172.19.1.34/22 ++route1=0.0.0.0/0,172.19.3.254 ++dns=172.19.0.12; ++dns-search=example3.com; ++ ++""".lstrip(), ++ ), ++ ], ++ }, + { + "in_data": { + "services": [{"type": "dns", "address": "172.19.0.12"}], +-- +2.39.3 + diff --git a/SOURCES/ci-Revert-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-.patch b/SOURCES/ci-Revert-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-.patch new file mode 100644 index 0000000..a70513b --- /dev/null +++ b/SOURCES/ci-Revert-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-.patch @@ -0,0 +1,190 @@ +From 87db4f8680222d2579d0ffb5fe507231f88d8aa5 Mon Sep 17 00:00:00 2001 +From: PengpengSun <40026211+PengpengSun@users.noreply.github.com> +Date: Sat, 10 Aug 2024 03:32:40 +0800 +Subject: [PATCH] Revert "fix(vmware): Set IPv6 to dhcp when there is no IPv6 + addr (#5471)" (#5596) + +RH-Author: xiachen +RH-MergeRequest: 108: Revert "fix(vmware): Set IPv6 to dhcp when there is no IPv6 addr (#5471)" (#5596) +RH-Jira: RHEL-54373 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/1] 96cccfca3d29c95d9c491d5995b7aa96adec4621 (xiachen/cloud-init-centos) + +This reverts commit 2b6fe6403db769de14f7c7b7e4aa65f5bea8f3e0. + +When there is no IPv6 set to dhcp explicitly, NetworkManager keyfile +defaults to method=auto, may-fail=true. When there is Ipv6 set to dhcp +explictily, NetworkManager keyfile will be set to +method=auto, may-fail=false. The default settings are what we want, so +revert the previous change to keep IPv6 not set explicitly. + +(cherry picked from commit 65014b97420b41dcb6e7ea17c66bb2539f9b09fc) +Signed-off-by: Amy Chen +--- + .../sources/helpers/vmware/imc/config_nic.py | 2 +- + .../sources/vmware/test_vmware_config_file.py | 68 +++++-------------- + 2 files changed, 18 insertions(+), 52 deletions(-) + +diff --git a/cloudinit/sources/helpers/vmware/imc/config_nic.py b/cloudinit/sources/helpers/vmware/imc/config_nic.py +index 254518af..b07214a2 100644 +--- a/cloudinit/sources/helpers/vmware/imc/config_nic.py ++++ b/cloudinit/sources/helpers/vmware/imc/config_nic.py +@@ -207,7 +207,7 @@ class NicConfigurator: + """ + + if not nic.staticIpv6: +- return ([{"type": "dhcp6"}], []) ++ return ([], []) + + subnet_list = [] + # Static Ipv6 +diff --git a/tests/unittests/sources/vmware/test_vmware_config_file.py b/tests/unittests/sources/vmware/test_vmware_config_file.py +index 25d3b093..b53ea96c 100644 +--- a/tests/unittests/sources/vmware/test_vmware_config_file.py ++++ b/tests/unittests/sources/vmware/test_vmware_config_file.py +@@ -240,45 +240,27 @@ class TestVmwareConfigFile(CiTestCase): + elif cfg.get("name") == nic2.get("name"): + nic2.update(cfg) + +- # Test NIC1 + self.assertEqual("physical", nic1.get("type"), "type of NIC1") + self.assertEqual("NIC1", nic1.get("name"), "name of NIC1") + self.assertEqual( + "00:50:56:a6:8c:08", nic1.get("mac_address"), "mac address of NIC1" + ) + subnets = nic1.get("subnets") +- self.assertEqual(2, len(subnets), "number of subnets for NIC1") +- subnet_ipv4 = subnets[0] +- self.assertEqual( +- "dhcp", subnet_ipv4.get("type"), "Ipv4 DHCP type for NIC1" +- ) +- self.assertEqual( +- "auto", subnet_ipv4.get("control"), "NIC1 Control type" +- ) +- subnet_ipv6 = subnets[1] +- self.assertEqual( +- "dhcp6", subnet_ipv6.get("type"), "Ipv6 DHCP type for NIC1" +- ) ++ self.assertEqual(1, len(subnets), "number of subnets for NIC1") ++ subnet = subnets[0] ++ self.assertEqual("dhcp", subnet.get("type"), "DHCP type for NIC1") ++ self.assertEqual("auto", subnet.get("control"), "NIC1 Control type") + +- # Test NIC2 + self.assertEqual("physical", nic2.get("type"), "type of NIC2") + self.assertEqual("NIC2", nic2.get("name"), "name of NIC2") + self.assertEqual( + "00:50:56:a6:5a:de", nic2.get("mac_address"), "mac address of NIC2" + ) + subnets = nic2.get("subnets") +- self.assertEqual(2, len(subnets), "number of subnets for NIC2") +- subnet_ipv4 = subnets[0] +- self.assertEqual( +- "dhcp", subnet_ipv4.get("type"), "Ipv4 DHCP type for NIC2" +- ) +- self.assertEqual( +- "auto", subnet_ipv4.get("control"), "NIC2 Control type" +- ) +- subnet_ipv6 = subnets[1] +- self.assertEqual( +- "dhcp6", subnet_ipv6.get("type"), "Ipv6 DHCP type for NIC2" +- ) ++ self.assertEqual(1, len(subnets), "number of subnets for NIC2") ++ subnet = subnets[0] ++ self.assertEqual("dhcp", subnet.get("type"), "DHCP type for NIC2") ++ self.assertEqual("auto", subnet.get("control"), "NIC2 Control type") + + def test_get_nics_list_static(self): + """Tests if NicConfigurator properly calculates network subnets +@@ -303,7 +285,6 @@ class TestVmwareConfigFile(CiTestCase): + elif cfg.get("name") == nic2.get("name"): + nic2.update(cfg) + +- # Test NIC1 + self.assertEqual("physical", nic1.get("type"), "type of NIC1") + self.assertEqual("NIC1", nic1.get("name"), "name of NIC1") + self.assertEqual( +@@ -363,7 +344,6 @@ class TestVmwareConfigFile(CiTestCase): + else: + self.assertEqual(True, False, "invalid gateway %s" % (gateway)) + +- # Test NIC2 + self.assertEqual("physical", nic2.get("type"), "type of NIC2") + self.assertEqual("NIC2", nic2.get("name"), "name of NIC2") + self.assertEqual( +@@ -371,18 +351,16 @@ class TestVmwareConfigFile(CiTestCase): + ) + + subnets = nic2.get("subnets") +- self.assertEqual(2, len(subnets), "Number of subnets for NIC2") ++ self.assertEqual(1, len(subnets), "Number of subnets for NIC2") + +- subnet_ipv4 = subnets[0] +- self.assertEqual("static", subnet_ipv4.get("type"), "Subnet type") ++ subnet = subnets[0] ++ self.assertEqual("static", subnet.get("type"), "Subnet type") + self.assertEqual( +- "192.168.6.102", subnet_ipv4.get("address"), "Subnet address" ++ "192.168.6.102", subnet.get("address"), "Subnet address" + ) + self.assertEqual( +- "255.255.0.0", subnet_ipv4.get("netmask"), "Subnet netmask" ++ "255.255.0.0", subnet.get("netmask"), "Subnet netmask" + ) +- subnet_ipv6 = subnets[1] +- self.assertEqual("dhcp6", subnet_ipv6.get("type"), "Subnet type") + + def test_custom_script(self): + cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg") +@@ -469,10 +447,7 @@ class TestVmwareNetConfig(CiTestCase): + "type": "static", + "address": "10.20.87.154", + "netmask": "255.255.252.0", +- }, +- { +- "type": "dhcp6", +- }, ++ } + ], + } + ], +@@ -523,10 +498,7 @@ class TestVmwareNetConfig(CiTestCase): + "metric": 10000, + } + ], +- }, +- { +- "type": "dhcp6", +- }, ++ } + ], + } + ], +@@ -586,10 +558,7 @@ class TestVmwareNetConfig(CiTestCase): + "metric": 10000, + } + ], +- }, +- { +- "type": "dhcp6", +- }, ++ } + ], + } + ], +@@ -634,10 +603,7 @@ class TestVmwareNetConfig(CiTestCase): + "address": "10.20.87.154", + "netmask": "255.255.252.0", + "gateway": "10.20.87.253", +- }, +- { +- "type": "dhcp6", +- }, ++ } + ], + } + ], +-- +2.39.3 + diff --git a/SOURCES/ci-Support-metalink-in-yum-repository-config-5444.patch b/SOURCES/ci-Support-metalink-in-yum-repository-config-5444.patch new file mode 100644 index 0000000..c6a30a7 --- /dev/null +++ b/SOURCES/ci-Support-metalink-in-yum-repository-config-5444.patch @@ -0,0 +1,140 @@ +From 96b10adc942f5117e35584d28ba88071849e8e29 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 27 Jun 2024 18:38:22 +0530 +Subject: [PATCH 1/2] Support metalink in yum repository config (#5444) + +RH-Author: xiachen +RH-MergeRequest: 97: Support metalink in yum repository config (#5444) +RH-Jira: RHEL-44916 +RH-Acked-by: Ani Sinha +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Commit: [1/1] 4671fd3a3f6842f1f590d5a89a429facd0d8bb4d (xiachen/cloud-init-centos) + +'metalink' config can be specified instead or along with 'baseurl' in the yum +repository config. Add support for specifying metalink instead of 'baseurl'. + +Fixes GH-5359 + +Signed-off-by: Ani Sinha +Co-authored-by: Ben Gray +(cherry picked from commit 525026061404ef09baebb85631d9af3b0a4d8930) +--- + cloudinit/config/cc_yum_add_repo.py | 24 ++++++------ + doc/examples/cloud-config-yum-repo.txt | 3 +- + .../unittests/config/test_cc_yum_add_repo.py | 38 +++++++++++++++++++ + 3 files changed, 51 insertions(+), 14 deletions(-) + +diff --git a/cloudinit/config/cc_yum_add_repo.py b/cloudinit/config/cc_yum_add_repo.py +index 1ab5008f..4fd66250 100644 +--- a/cloudinit/config/cc_yum_add_repo.py ++++ b/cloudinit/config/cc_yum_add_repo.py +@@ -210,24 +210,22 @@ def handle(name: str, cfg: Config, cloud: Cloud, args: list) -> None: + n_repo_config[k] = v + repo_config = n_repo_config + missing_required = 0 +- for req_field in ["baseurl"]: ++ req_fields = ["baseurl", "metalink"] ++ for req_field in req_fields: + if req_field not in repo_config: +- LOG.warning( +- "Repository %s does not contain a %s" +- " configuration 'required' entry", +- repo_id, +- req_field, +- ) + missing_required += 1 +- if not missing_required: +- repo_configs[canon_repo_id] = repo_config +- repo_locations[canon_repo_id] = repo_fn_pth +- else: ++ ++ if missing_required == len(req_fields): + LOG.warning( +- "Repository %s is missing %s required fields, skipping!", ++ "Repository %s should contain atleast one of the" ++ " following configuration entries: %s, skipping!", + repo_id, +- missing_required, ++ ", ".join(req_fields), + ) ++ else: ++ repo_configs[canon_repo_id] = repo_config ++ repo_locations[canon_repo_id] = repo_fn_pth ++ + for (c_repo_id, path) in repo_locations.items(): + repo_blob = _format_repository_config( + c_repo_id, repo_configs.get(c_repo_id) +diff --git a/doc/examples/cloud-config-yum-repo.txt b/doc/examples/cloud-config-yum-repo.txt +index e8f2bbb4..6a4037e2 100644 +--- a/doc/examples/cloud-config-yum-repo.txt ++++ b/doc/examples/cloud-config-yum-repo.txt +@@ -11,8 +11,9 @@ yum_repos: + # Any repository configuration options + # See: man yum.conf + # +- # This one is required! ++ # At least one of 'baseurl' or 'metalink' is required! + baseurl: http://download.fedoraproject.org/pub/epel/testing/5/$basearch ++ metalink: https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch&infra=$infra&content=$contentdir + enabled: false + failovermethod: priority + gpgcheck: true +diff --git a/tests/unittests/config/test_cc_yum_add_repo.py b/tests/unittests/config/test_cc_yum_add_repo.py +index d2c2912f..1f27d1fb 100644 +--- a/tests/unittests/config/test_cc_yum_add_repo.py ++++ b/tests/unittests/config/test_cc_yum_add_repo.py +@@ -31,6 +31,7 @@ class TestConfig(helpers.FilesystemMockingTestCase): + "yum_repos": { + "epel-testing": { + "name": "Extra Packages for Enterprise Linux 5 - Testing", ++ # At least one of baseurl or metalink must be present. + # Missing this should cause the repo not to be written + # 'baseurl': 'http://blah.org/pub/epel/testing/5/$barch', + "enabled": False, +@@ -46,6 +47,43 @@ class TestConfig(helpers.FilesystemMockingTestCase): + IOError, util.load_file, "/etc/yum.repos.d/epel_testing.repo" + ) + ++ def test_metalink_config(self): ++ cfg = { ++ "yum_repos": { ++ "epel-testing": { ++ "name": "Extra Packages for Enterprise Linux 5 - Testing", ++ "metalink": "http://blah.org/pub/epel/testing/5/$basearch", ++ "enabled": False, ++ "gpgcheck": True, ++ "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL", ++ "failovermethod": "priority", ++ }, ++ }, ++ } ++ self.patchUtils(self.tmp) ++ self.patchOS(self.tmp) ++ cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) ++ contents = util.load_file("/etc/yum.repos.d/epel-testing.repo") ++ parser = configparser.ConfigParser() ++ parser.read_string(contents) ++ expected = { ++ "epel-testing": { ++ "name": "Extra Packages for Enterprise Linux 5 - Testing", ++ "failovermethod": "priority", ++ "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL", ++ "enabled": "0", ++ "metalink": "http://blah.org/pub/epel/testing/5/$basearch", ++ "gpgcheck": "1", ++ } ++ } ++ for section in expected: ++ self.assertTrue( ++ parser.has_section(section), ++ "Contains section {0}".format(section), ++ ) ++ for k, v in expected[section].items(): ++ self.assertEqual(parser.get(section, k), v) ++ + def test_write_config(self): + cfg = { + "yum_repos": { +-- +2.39.3 + diff --git a/SOURCES/ci-Support-setting-mirrorlist-in-yum-repository-config-.patch b/SOURCES/ci-Support-setting-mirrorlist-in-yum-repository-config-.patch new file mode 100644 index 0000000..ec67a9d --- /dev/null +++ b/SOURCES/ci-Support-setting-mirrorlist-in-yum-repository-config-.patch @@ -0,0 +1,145 @@ +From d27ac077dac3474fea3c7bb1a19afe50ecbcc64d Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 18 Jul 2024 13:36:39 +0530 +Subject: [PATCH 2/2] Support setting mirrorlist in yum repository config + (#5522) + +RH-Author: xiachen +RH-MergeRequest: 104: Support setting mirrorlist in yum repository config (#5522) +RH-Jira: RHEL-49674 +RH-Acked-by: Ani Sinha +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Commit: [1/1] 4605a0304c6bed6614990b7194465230afa79778 (xiachen/cloud-init-centos) + +'mirrorlist' config can be specified instead or along with 'baseurl' in the yum +repository config. Add support for specifying mirrorlist instead of 'baseurl'. + +Fixes GH-5520 +Signed-off-by: Ani Sinha +(cherry picked from commit 0b4084374440d2a5a9968129e0460a1a009d9830) +Signed-off-by: Amy Chen +--- + cloudinit/config/cc_yum_add_repo.py | 2 +- + .../schemas/schema-cloud-config-v1.json | 10 +++++ + doc/examples/cloud-config-yum-repo.txt | 3 +- + .../unittests/config/test_cc_yum_add_repo.py | 40 ++++++++++++++++++- + 4 files changed, 52 insertions(+), 3 deletions(-) + +diff --git a/cloudinit/config/cc_yum_add_repo.py b/cloudinit/config/cc_yum_add_repo.py +index 4fd66250..3870d24e 100644 +--- a/cloudinit/config/cc_yum_add_repo.py ++++ b/cloudinit/config/cc_yum_add_repo.py +@@ -210,7 +210,7 @@ def handle(name: str, cfg: Config, cloud: Cloud, args: list) -> None: + n_repo_config[k] = v + repo_config = n_repo_config + missing_required = 0 +- req_fields = ["baseurl", "metalink"] ++ req_fields = ["baseurl", "metalink", "mirrorlist"] + for req_field in req_fields: + if req_field not in repo_config: + missing_required += 1 +diff --git a/cloudinit/config/schemas/schema-cloud-config-v1.json b/cloudinit/config/schemas/schema-cloud-config-v1.json +index 4fb7fd93..c5f46f37 100644 +--- a/cloudinit/config/schemas/schema-cloud-config-v1.json ++++ b/cloudinit/config/schemas/schema-cloud-config-v1.json +@@ -3447,6 +3447,11 @@ + "format": "uri", + "description": "Specifies a URL to a metalink file for the repomd.xml" + }, ++ "mirrorlist": { ++ "type": "string", ++ "format": "uri", ++ "description": "Specifies a URL to a file containing a baseurls list" ++ }, + "name": { + "type": "string", + "description": "Optional human-readable name of the yum repo." +@@ -3484,6 +3489,11 @@ + "required": [ + "metalink" + ] ++ }, ++ { ++ "required": [ ++ "mirrorlist" ++ ] + } + ] + } +diff --git a/doc/examples/cloud-config-yum-repo.txt b/doc/examples/cloud-config-yum-repo.txt +index 6a4037e2..cee26677 100644 +--- a/doc/examples/cloud-config-yum-repo.txt ++++ b/doc/examples/cloud-config-yum-repo.txt +@@ -11,9 +11,10 @@ yum_repos: + # Any repository configuration options + # See: man yum.conf + # +- # At least one of 'baseurl' or 'metalink' is required! ++ # At least one of 'baseurl' or 'metalink' or 'mirrorlist' is required! + baseurl: http://download.fedoraproject.org/pub/epel/testing/5/$basearch + metalink: https://mirrors.fedoraproject.org/metalink?repo=epel-$releasever&arch=$basearch&infra=$infra&content=$contentdir ++ mirrorlist: https://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever& + enabled: false + failovermethod: priority + gpgcheck: true +diff --git a/tests/unittests/config/test_cc_yum_add_repo.py b/tests/unittests/config/test_cc_yum_add_repo.py +index 1f27d1fb..000792b4 100644 +--- a/tests/unittests/config/test_cc_yum_add_repo.py ++++ b/tests/unittests/config/test_cc_yum_add_repo.py +@@ -31,7 +31,8 @@ class TestConfig(helpers.FilesystemMockingTestCase): + "yum_repos": { + "epel-testing": { + "name": "Extra Packages for Enterprise Linux 5 - Testing", +- # At least one of baseurl or metalink must be present. ++ # At least one of baseurl or metalink or mirrorlist ++ # must be present. + # Missing this should cause the repo not to be written + # 'baseurl': 'http://blah.org/pub/epel/testing/5/$barch', + "enabled": False, +@@ -84,6 +85,43 @@ class TestConfig(helpers.FilesystemMockingTestCase): + for k, v in expected[section].items(): + self.assertEqual(parser.get(section, k), v) + ++ def test_mirrorlist_config(self): ++ cfg = { ++ "yum_repos": { ++ "epel-testing": { ++ "name": "Extra Packages for Enterprise Linux 5 - Testing", ++ "mirrorlist": "http://mirrors.blah.org/metalink?repo=rhel-$releasever", ++ "enabled": False, ++ "gpgcheck": True, ++ "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL", ++ "failovermethod": "priority", ++ }, ++ }, ++ } ++ self.patchUtils(self.tmp) ++ self.patchOS(self.tmp) ++ cc_yum_add_repo.handle("yum_add_repo", cfg, None, []) ++ contents = util.load_file("/etc/yum.repos.d/epel-testing.repo") ++ parser = configparser.ConfigParser() ++ parser.read_string(contents) ++ expected = { ++ "epel-testing": { ++ "name": "Extra Packages for Enterprise Linux 5 - Testing", ++ "failovermethod": "priority", ++ "gpgkey": "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL", ++ "enabled": "0", ++ "mirrorlist": "http://mirrors.blah.org/metalink?repo=rhel-$releasever", ++ "gpgcheck": "1", ++ } ++ } ++ for section in expected: ++ self.assertTrue( ++ parser.has_section(section), ++ "Contains section {0}".format(section), ++ ) ++ for k, v in expected[section].items(): ++ self.assertEqual(parser.get(section, k), v) ++ + def test_write_config(self): + cfg = { + "yum_repos": { +-- +2.39.3 + diff --git a/SOURCES/ci-Update-pylint-version-to-support-python-3.12-5338.patch b/SOURCES/ci-Update-pylint-version-to-support-python-3.12-5338.patch new file mode 100644 index 0000000..a9154e9 --- /dev/null +++ b/SOURCES/ci-Update-pylint-version-to-support-python-3.12-5338.patch @@ -0,0 +1,235 @@ +From c34f5c4275c3ef7bee9a99e87bf6e37c5886b160 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Wed, 29 May 2024 03:34:38 +0530 +Subject: [PATCH 6/6] Update pylint version to support python 3.12 (#5338) + +RH-Author: Ani Sinha +RH-MergeRequest: 92: Update pylint version to support python 3.12 +RH-Jira: RHEL-44598 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [3/3] d6185e0a126e1589260ee59709fe933b5a780b78 (anisinha/cloud-init) + +Fedora 39 and above comes with python version 3.12. When running `tox -e pylint` +on cloud-init, we may experience issue such as the one reported here: +https://github.com/pylint-dev/pylint/issues/8782 + +Minimum version of pylint required in order to support python 3.12 is 3.0.2. +Please see https://github.com/pylint-dev/astroid/issues/2201 . Upon further +experimentation, it is seen that we need minimum pylint version 3.2.0 for +cloud-init. Update tox.ini in order to use this pylint version. + +Signed-off-by: Ani Sinha +(cherry picked from commit 5ad609ffdf4bb76c5665e12e34e1867b72bd4435) + + Conflicts: + cloudinit/sources/DataSourceWSL.py (does not exist) + cloudinit/util.py (doc added upstream) +--- + cloudinit/config/cc_mounts.py | 4 ++++ + cloudinit/distros/bsd.py | 2 ++ + cloudinit/distros/netbsd.py | 2 +- + cloudinit/sources/DataSourceAzure.py | 2 +- + cloudinit/sources/DataSourceEc2.py | 3 ++- + cloudinit/sources/DataSourceLXD.py | 2 +- + tests/integration_tests/conftest.py | 6 +++--- + tests/integration_tests/util.py | 2 +- + tests/unittests/config/test_cc_ntp.py | 2 ++ + tests/unittests/sources/test_gce.py | 1 + + tests/unittests/test_util.py | 2 ++ + tox.ini | 2 +- + 12 files changed, 21 insertions(+), 9 deletions(-) + +diff --git a/cloudinit/config/cc_mounts.py b/cloudinit/config/cc_mounts.py +index 4efa2a29..d445b440 100644 +--- a/cloudinit/config/cc_mounts.py ++++ b/cloudinit/config/cc_mounts.py +@@ -304,6 +304,10 @@ def create_swapfile(fname: str, size: str) -> None: + "bs=1M", + "count=%s" % size, + ] ++ else: ++ raise subp.ProcessExecutionError( ++ "Missing dependency: 'dd' and 'fallocate' are not available" ++ ) + + try: + subp.subp(cmd, capture=True) +diff --git a/cloudinit/distros/bsd.py b/cloudinit/distros/bsd.py +index 761cf5c4..77e0385f 100644 +--- a/cloudinit/distros/bsd.py ++++ b/cloudinit/distros/bsd.py +@@ -120,6 +120,8 @@ class BSD(distros.Distro): + if not self.pkg_cmd_upgrade_prefix: + return + cmd = self.pkg_cmd_upgrade_prefix ++ else: ++ cmd = [] + + if args and isinstance(args, str): + cmd.append(args) +diff --git a/cloudinit/distros/netbsd.py b/cloudinit/distros/netbsd.py +index a5678907..b7f3f3d8 100644 +--- a/cloudinit/distros/netbsd.py ++++ b/cloudinit/distros/netbsd.py +@@ -12,7 +12,7 @@ import cloudinit.distros.bsd + from cloudinit import subp, util + + try: +- import crypt ++ import crypt # pylint: disable=W4901 + + salt = crypt.METHOD_BLOWFISH # pylint: disable=E1101 + blowfish_hash: Any = functools.partial( +diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py +index 11c14e20..eb0304c3 100644 +--- a/cloudinit/sources/DataSourceAzure.py ++++ b/cloudinit/sources/DataSourceAzure.py +@@ -51,7 +51,7 @@ from cloudinit.sources.helpers.azure import ( + from cloudinit.url_helper import UrlError + + try: +- import crypt ++ import crypt # pylint: disable=W4901 + + blowfish_hash: Any = functools.partial( + crypt.crypt, salt=f"$6${util.rand_str(strlen=16)}" +diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py +index 9e6bfbd1..384e4074 100644 +--- a/cloudinit/sources/DataSourceEc2.py ++++ b/cloudinit/sources/DataSourceEc2.py +@@ -312,6 +312,8 @@ class DataSourceEc2(sources.DataSource): + return None + + def wait_for_metadata_service(self): ++ urls = [] ++ start_time = 0 + mcfg = self.ds_cfg + + url_params = self.get_url_params() +@@ -345,7 +347,6 @@ class DataSourceEc2(sources.DataSource): + and self.cloud_name not in IDMSV2_SUPPORTED_CLOUD_PLATFORMS + ): + # if we can't get a token, use instance-id path +- urls = [] + url2base = {} + url_path = "{ver}/meta-data/instance-id".format( + ver=self.min_metadata_version +diff --git a/cloudinit/sources/DataSourceLXD.py b/cloudinit/sources/DataSourceLXD.py +index cd316101..4c95b907 100644 +--- a/cloudinit/sources/DataSourceLXD.py ++++ b/cloudinit/sources/DataSourceLXD.py +@@ -331,7 +331,7 @@ class MetaDataKeys(Flag): + CONFIG = auto() + DEVICES = auto() + META_DATA = auto() +- ALL = CONFIG | DEVICES | META_DATA ++ ALL = CONFIG | DEVICES | META_DATA # pylint: disable=E1131 + + + class _MetaDataReader: +diff --git a/tests/integration_tests/conftest.py b/tests/integration_tests/conftest.py +index fa729b7d..ec211a00 100644 +--- a/tests/integration_tests/conftest.py ++++ b/tests/integration_tests/conftest.py +@@ -241,7 +241,7 @@ def _client( + + + @pytest.fixture +-def client( ++def client( # pylint: disable=W0135 + request, fixture_utils, session_cloud, setup_image + ) -> Iterator[IntegrationInstance]: + """Provide a client that runs for every test.""" +@@ -250,7 +250,7 @@ def client( + + + @pytest.fixture(scope="module") +-def module_client( ++def module_client( # pylint: disable=W0135 + request, fixture_utils, session_cloud, setup_image + ) -> Iterator[IntegrationInstance]: + """Provide a client that runs once per module.""" +@@ -259,7 +259,7 @@ def module_client( + + + @pytest.fixture(scope="class") +-def class_client( ++def class_client( # pylint: disable=W0135 + request, fixture_utils, session_cloud, setup_image + ) -> Iterator[IntegrationInstance]: + """Provide a client that runs once per class.""" +diff --git a/tests/integration_tests/util.py b/tests/integration_tests/util.py +index 0a15203c..e26e466c 100644 +--- a/tests/integration_tests/util.py ++++ b/tests/integration_tests/util.py +@@ -182,7 +182,7 @@ def wait_for_cloud_init(client: IntegrationInstance, num_retries: int = 30): + except Exception as e: + last_exception = e + time.sleep(1) +- raise Exception( ++ raise Exception( # pylint: disable=W0719 + "cloud-init status did not return successfully." + ) from last_exception + +diff --git a/tests/unittests/config/test_cc_ntp.py b/tests/unittests/config/test_cc_ntp.py +index a9444ec5..c9ce5daa 100644 +--- a/tests/unittests/config/test_cc_ntp.py ++++ b/tests/unittests/config/test_cc_ntp.py +@@ -248,6 +248,7 @@ class TestNtp(FilesystemMockingTestCase): + ) + + def _get_expected_pools(self, pools, distro, client): ++ expected_pools = None + if client in ["ntp", "chrony"]: + if client == "ntp" and distro == "alpine": + # NTP for Alpine Linux is Busybox's ntp which does not +@@ -263,6 +264,7 @@ class TestNtp(FilesystemMockingTestCase): + return expected_pools + + def _get_expected_servers(self, servers, distro, client): ++ expected_servers = None + if client in ["ntp", "chrony"]: + if client == "ntp" and distro == "alpine": + # NTP for Alpine Linux is Busybox's ntp which only supports +diff --git a/tests/unittests/sources/test_gce.py b/tests/unittests/sources/test_gce.py +index c0b19d3c..30a50236 100644 +--- a/tests/unittests/sources/test_gce.py ++++ b/tests/unittests/sources/test_gce.py +@@ -101,6 +101,7 @@ class TestDataSourceGCE(test_helpers.ResponsesTestCase): + gce_meta = GCE_META + + def _request_callback(request): ++ recursive = False + url_path = urlparse(request.url).path + if url_path.startswith("/computeMetadata/v1/"): + path = url_path.split("/computeMetadata/v1/")[1:][0] +diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py +index 519ef63c..de1326d4 100644 +--- a/tests/unittests/test_util.py ++++ b/tests/unittests/test_util.py +@@ -1677,6 +1677,8 @@ class TestRedirectOutputPreexecFn: + args = (test_string, None) + elif request.param == "errfmt": + args = (None, test_string) ++ else: ++ args = (None, None) + with mock.patch(M_PATH + "subprocess.Popen") as m_popen: + util.redirect_output(*args) + +diff --git a/tox.ini b/tox.ini +index 5f01a9a8..5199ca13 100644 +--- a/tox.ini ++++ b/tox.ini +@@ -25,7 +25,7 @@ hypothesis==6.31.6 + hypothesis_jsonschema==0.20.1 + isort==5.10.1 + mypy==0.950 +-pylint==2.13.9 ++pylint==3.2.0 + pytest==7.0.1 + ruff==0.0.285 + types-jsonschema==4.4.2 +-- +2.39.3 + diff --git a/SOURCES/ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch b/SOURCES/ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch new file mode 100644 index 0000000..8a68c53 --- /dev/null +++ b/SOURCES/ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch @@ -0,0 +1,51 @@ +From 52c04e1a523a450dfce70bc441963eb6a026eb59 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 20 Jun 2024 11:18:40 +0530 +Subject: [PATCH 3/6] doc: update examples to reflect alternative ways to + provide `sudo` option (#5418) + +RH-Author: Ani Sinha +RH-MergeRequest: 90: fix(jsonschema): Add missing sudo definition (#5418) +RH-Jira: RHEL-44337 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [2/2] 62eac6d731cb725c32cd0beac0219ecc2b407198 (anisinha/cloud-init) + +For creating users and groups, it is possible to pass a `sudo` option to the +config file that accepts a sudo rule. The option can be a sudo rule string, +a list of sudo rule strings or `False` to explicitly deny sudo usage. Update +examples to show how a list of strings can be used with `sudo` option. + +Signed-off-by: Ani Sinha +(cherry picked from commit cbcb05349e35023ee6e81ccaf13e79adb8f65f63) +--- + doc/examples/cloud-config-user-groups.txt | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/doc/examples/cloud-config-user-groups.txt b/doc/examples/cloud-config-user-groups.txt +index 87fc52e8..56eb674f 100644 +--- a/doc/examples/cloud-config-user-groups.txt ++++ b/doc/examples/cloud-config-user-groups.txt +@@ -35,6 +35,10 @@ users: + lock_passwd: true + ssh_authorized_keys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSL7uWGj8cgWyIOaspgKdVy0cKJ+UTjfv7jBOjG2H/GN8bJVXy72XAvnhM0dUM+CCs8FOf0YlPX+Frvz2hKInrmRhZVwRSL129PasD12MlI3l44u6IwS1o/W86Q+tkQYEljtqDOo0a+cOsaZkvUNzUyEXUwz/lmYa6G4hMKZH4NBj7nbAAF96wsMCoyNwbWryBnDYUr6wMbjRR1J9Pw7Xh7WRC73wy4Va2YuOgbD3V/5ZrFPLbWZW/7TFXVrql04QVbyei4aiFR5n//GvoqwQDNe58LmbzX/xvxyKJYdny2zXmdAhMxbrpFQsfpkJ9E/H5w0yOdSvnWbUoG5xNGoOB csmith@fringe ++ - name: testuser ++ gecos: Mr. Test ++ homedir: /local/testdir ++ sudo: ["ALL=(ALL) NOPASSWD:ALL"] + - name: cloudy + gecos: Magic Cloud App Daemon User + inactive: '5' +@@ -100,6 +104,8 @@ users: + # + # Allow a user unrestricted sudo access. + # sudo: ALL=(ALL) NOPASSWD:ALL ++# or ++# sudo: ["ALL=(ALL) NOPASSWD:ALL"] + # + # Adding multiple sudo rule strings. + # sudo: +-- +2.39.3 + diff --git a/SOURCES/ci-docs-Add-deprecated-system_info-to-schema-5168.patch b/SOURCES/ci-docs-Add-deprecated-system_info-to-schema-5168.patch new file mode 100644 index 0000000..ad1ae0d --- /dev/null +++ b/SOURCES/ci-docs-Add-deprecated-system_info-to-schema-5168.patch @@ -0,0 +1,166 @@ +From c933187af44a5de1d6eafde5dcd48e8ac369cf34 Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Thu, 18 Apr 2024 20:21:14 -0500 +Subject: [PATCH 2/3] docs: Add deprecated system_info to schema (#5168) + +RH-Author: Ani Sinha +RH-MergeRequest: 95: Deprecate the users ssh-authorized-keys property (#5162) +RH-Jira: RHEL-45262 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [2/3] c4ea6f45ee0997e2f749c290fb8f2ceb8c05c691 (anisinha/cloud-init) + +In some cases, `system_info` can be passed via user data or vendor data +to override the system_info in /etc/cloud/cloud.cfg . While this +technically can work, this is a use case we no longer support and should +indicate that it is deprecated. + +Also remove/update examples. + +(cherry picked from commit 7c67f7732f04b41600934818f7d5bcb4d085ed7c) + +Conflicts: + cloudinit/config/schemas/schema-cloud-config-v1.json + - due to change fdefe08ad19cea5eb ("fix: Fix typos (#4850)") not + present in downstream. + doc/examples/cloud-config-user-groups.txt + - due to change 0aa17cd10bdd6 ("docs: set the home directory using homedir, not home (#5101)") + not present downstream. + tests/unittests/sources/test_vultr.py + - due to change 144782a838 ("test: Remove side effects from tests (#5074)") not present + downstream. +--- + .../schemas/schema-cloud-config-v1.json | 7 ++++++ + doc/examples/cloud-config-apt.txt | 23 ------------------- + doc/examples/cloud-config-user-groups.txt | 12 ++-------- + tests/data/user_data.1.txt | 10 -------- + tests/unittests/runs/test_merge_run.py | 16 ++++++++++++- + 5 files changed, 24 insertions(+), 44 deletions(-) + +diff --git a/cloudinit/config/schemas/schema-cloud-config-v1.json b/cloudinit/config/schemas/schema-cloud-config-v1.json +index 670ef4c2..97cf2b74 100644 +--- a/cloudinit/config/schemas/schema-cloud-config-v1.json ++++ b/cloudinit/config/schemas/schema-cloud-config-v1.json +@@ -513,6 +513,12 @@ + }, + "merge_type": { + "$ref": "#/$defs/merge_defintion" ++ }, ++ "system_info": { ++ "type": "object", ++ "description": "System and/or distro specific settings. This is not intended to be overridden by user data or vendor data.", ++ "deprecated": true, ++ "deprecated_version": "24.2" + } + } + }, +@@ -3905,6 +3911,7 @@ + "ssh_pwauth": {}, + "ssh_quiet_keygen": {}, + "swap": {}, ++ "system_info": {}, + "timezone": {}, + "ubuntu_advantage": {}, + "updates": {}, +diff --git a/doc/examples/cloud-config-apt.txt b/doc/examples/cloud-config-apt.txt +index dd6a0f6a..04968035 100644 +--- a/doc/examples/cloud-config-apt.txt ++++ b/doc/examples/cloud-config-apt.txt +@@ -8,29 +8,6 @@ + # Number: Set pipelining to some number (not recommended) + apt_pipelining: False + +-## apt config via system_info: +-# under the 'system_info', you can customize cloud-init's interaction +-# with apt. +-# system_info: +-# apt_get_command: [command, argument, argument] +-# apt_get_upgrade_subcommand: dist-upgrade +-# +-# apt_get_command: +-# To specify a different 'apt-get' command, set 'apt_get_command'. +-# This must be a list, and the subcommand (update, upgrade) is appended to it. +-# default is: +-# ['apt-get', '--option=Dpkg::Options::=--force-confold', +-# '--option=Dpkg::options::=--force-unsafe-io', '--assume-yes', '--quiet'] +-# +-# apt_get_upgrade_subcommand: "dist-upgrade" +-# Specify a different subcommand for 'upgrade. The default is 'dist-upgrade'. +-# This is the subcommand that is invoked for package_upgrade. +-# +-# apt_get_wrapper: +-# command: eatmydata +-# enabled: [True, False, "auto"] +-# +- + # Install additional packages on first boot + # + # Default: none +diff --git a/doc/examples/cloud-config-user-groups.txt b/doc/examples/cloud-config-user-groups.txt +index 56eb674f..2cafef88 100644 +--- a/doc/examples/cloud-config-user-groups.txt ++++ b/doc/examples/cloud-config-user-groups.txt +@@ -143,13 +143,5 @@ users: + # + # users[0] (the first user in users) overrides the user directive. + # +-# The 'default' user above references the distro's config: +-# system_info: +-# default_user: +-# name: Ubuntu +-# plain_text_passwd: 'ubuntu' +-# home: /home/ubuntu +-# shell: /bin/bash +-# lock_passwd: True +-# gecos: Ubuntu +-# groups: [adm, cdrom, dip, lxd, sudo] ++# The 'default' user above references the distro's config set in ++# /etc/cloud/cloud.cfg. +diff --git a/tests/data/user_data.1.txt b/tests/data/user_data.1.txt +index 4c4543de..a1b5aa60 100644 +--- a/tests/data/user_data.1.txt ++++ b/tests/data/user_data.1.txt +@@ -3,13 +3,3 @@ write_files: + - content: blah + path: /etc/blah.ini + permissions: 493 +- +-system_info: +- package_mirrors: +- - arches: [i386, amd64, blah] +- failsafe: +- primary: http://my.archive.mydomain.com/ubuntu +- security: http://my.security.mydomain.com/ubuntu +- search: +- primary: [] +- security: [] +diff --git a/tests/unittests/runs/test_merge_run.py b/tests/unittests/runs/test_merge_run.py +index afc256ec..251c5ae5 100644 +--- a/tests/unittests/runs/test_merge_run.py ++++ b/tests/unittests/runs/test_merge_run.py +@@ -22,7 +22,21 @@ class TestMergeRun(helpers.FilesystemMockingTestCase): + cfg = { + "datasource_list": ["None"], + "cloud_init_modules": ["write_files"], +- "system_info": {"paths": {"run_dir": new_root}}, ++ "system_info": { ++ "paths": {"run_dir": new_root}, ++ "package_mirrors": [ ++ { ++ "arches": ["i386", "amd64", "blah"], ++ "failsafe": { ++ "primary": "http://my.archive.mydomain.com/ubuntu", ++ "security": ( ++ "http://my.security.mydomain.com/ubuntu" ++ ), ++ }, ++ "search": {"primary": [], "security": []}, ++ }, ++ ], ++ }, + } + ud = helpers.readResource("user_data.1.txt") + cloud_cfg = safeyaml.dumps(cfg) +-- +2.39.3 + diff --git a/SOURCES/ci-fix-Add-subnet-ipv4-ipv6-to-network-schema-5191.patch b/SOURCES/ci-fix-Add-subnet-ipv4-ipv6-to-network-schema-5191.patch new file mode 100644 index 0000000..4c75da5 --- /dev/null +++ b/SOURCES/ci-fix-Add-subnet-ipv4-ipv6-to-network-schema-5191.patch @@ -0,0 +1,45 @@ +From 6a61ce0f0cde11551bfe92835d0b33c7b1022b68 Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Thu, 18 Apr 2024 20:27:27 -0500 +Subject: [PATCH] fix: Add subnet ipv4/ipv6 to network schema (#5191) + +RH-Author: Ani Sinha +RH-MergeRequest: 109: fix: Add subnet ipv4/ipv6 to network schema (#5191) +RH-Jira: RHEL-54686 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Cathy Avery +RH-Commit: [1/1] 83692fac8f9af1831970091bdf7c43d0e59f314c (anisinha/cloud-init) + +These are used by our openstack network_data.json parsing code and +get used by the sysconfig renderer. + +Fixes GH-4911 + +(cherry picked from commit 0b1ca174095e3ad685e6d6649bb08aafb19a95b9) +Signed-off-by: Ani Sinha +--- + cloudinit/config/schemas/schema-network-config-v1.json | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/cloudinit/config/schemas/schema-network-config-v1.json b/cloudinit/config/schemas/schema-network-config-v1.json +index 64c492a4..f485c784 100644 +--- a/cloudinit/config/schemas/schema-network-config-v1.json ++++ b/cloudinit/config/schemas/schema-network-config-v1.json +@@ -523,6 +523,14 @@ + "items": { + "$ref": "#/$defs/anyOf_type_route" + } ++ }, ++ "ipv4": { ++ "type": "boolean", ++ "description": "Indicate if the subnet is IPv4. If not specified, it will be inferred from the subnet type or address. This exists for compatibility with OpenStack's ``network_data.json`` when rendered through sysconfig." ++ }, ++ "ipv6": { ++ "type": "boolean", ++ "description": "Indicate if the subnet is IPv6. If not specified, it will be inferred from the subnet type or address. This is exists for compatibility with OpenStack's ``network_data.json`` when rendered through sysconfig." + } + } + }, +-- +2.39.3 + diff --git a/SOURCES/ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch b/SOURCES/ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch new file mode 100644 index 0000000..68d5884 --- /dev/null +++ b/SOURCES/ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch @@ -0,0 +1,73 @@ +From 8ead44cb39f7726a695aa21a34820f6d40270829 Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Mon, 12 Feb 2024 14:48:01 -0600 +Subject: [PATCH 5/6] fix: Address TIOBE abstract interpretation issues (#4866) + +RH-Author: Ani Sinha +RH-MergeRequest: 92: Update pylint version to support python 3.12 +RH-Jira: RHEL-44598 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [2/3] 3ca11206fa159ab45b2db21e78c4cfaf358b1e01 (anisinha/cloud-init) + +These involve operations on possibly null variables or impossible logic. + +(cherry picked from commit 5e7ef1032a12267a9a518358fbf89da0a88ddb99) +--- + cloudinit/config/cc_lxd.py | 2 +- + cloudinit/distros/parsers/ifconfig.py | 6 ++++++ + cloudinit/util.py | 1 + + 3 files changed, 8 insertions(+), 1 deletion(-) + +diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py +index cb9fc4f3..9f267b4c 100644 +--- a/cloudinit/config/cc_lxd.py ++++ b/cloudinit/config/cc_lxd.py +@@ -432,7 +432,7 @@ def bridge_to_cmd(bridge_cfg): + % (bridge_cfg.get("ipv6_address"), bridge_cfg.get("ipv6_netmask")) + ) + +- if bridge_cfg.get("ipv6_nat", "false") == "true": ++ if bridge_cfg.get("ipv6_nat") == "true": + cmd_create.append("ipv6.nat=true") + + else: +diff --git a/cloudinit/distros/parsers/ifconfig.py b/cloudinit/distros/parsers/ifconfig.py +index 516b5eb5..d671df1f 100644 +--- a/cloudinit/distros/parsers/ifconfig.py ++++ b/cloudinit/distros/parsers/ifconfig.py +@@ -102,6 +102,7 @@ class Ifconfig: + """ + ifindex = 0 + ifs_by_mac = defaultdict(list) ++ dev = None + for line in text.splitlines(): + if len(line) == 0: + continue +@@ -119,6 +120,11 @@ class Ifconfig: + dev.index = ifindex + self._ifs_by_name[curif] = dev + ++ if not dev: ++ # This shouldn't happen with normal ifconfig output, but ++ # if it does, ensure we don't Traceback ++ continue ++ + toks = line.lower().strip().split() + + if len(toks) > 1 and toks[1].startswith("flags="): +diff --git a/cloudinit/util.py b/cloudinit/util.py +index 3295735c..5f787c5c 100644 +--- a/cloudinit/util.py ++++ b/cloudinit/util.py +@@ -1417,6 +1417,7 @@ def find_devs_with_netbsd( + devlist = [] + label = None + _type = None ++ mscdlabel_out = "" + if criteria: + if criteria.startswith("LABEL="): + label = criteria.lstrip("LABEL=") +-- +2.39.3 + diff --git a/SOURCES/ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch b/SOURCES/ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch new file mode 100644 index 0000000..fc9bd8c --- /dev/null +++ b/SOURCES/ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch @@ -0,0 +1,246 @@ +From 914ac26ebd889b1f5cbb13d55fc011e92fc213c6 Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Thu, 18 Jul 2024 09:04:54 -0400 +Subject: [PATCH 1/2] fix: Clean cache if no datasource fallback (#5499) + +RH-Author: Ani Sinha +RH-MergeRequest: 103: fix: Clean cache if no datasource fallback (#5499) +RH-Jira: RHEL-49736 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Commit: [1/1] 37eacd97f5e60fae2f71d401c528d508d3db517e (anisinha/cloud-init) + +9929a00 added the ability to used a cached datasource when none is +found. This was supposed to be per-datasource, but the lack of cache +cleaning got applied universally. This commit makes it so cache will be +cleaned as it was before if fallback isn't implemented in datasource. + +Fixes GH-5486 + +(cherry picked from commit 550c685c98551f65c30832b186fe091721b48477) +Signed-off-by: Ani Sinha +--- + cloudinit/stages.py | 1 + + .../assets/DataSourceNoCacheNetworkOnly.py | 23 ++++ + .../assets/DataSourceNoCacheWithFallback.py | 29 +++++ + .../datasources/test_caching.py | 115 ++++++++++++++++++ + tests/integration_tests/instances.py | 4 +- + 5 files changed, 171 insertions(+), 1 deletion(-) + create mode 100644 tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py + create mode 100644 tests/integration_tests/assets/DataSourceNoCacheWithFallback.py + create mode 100644 tests/integration_tests/datasources/test_caching.py + +diff --git a/cloudinit/stages.py b/cloudinit/stages.py +index 0b795624..ace94c9a 100644 +--- a/cloudinit/stages.py ++++ b/cloudinit/stages.py +@@ -378,6 +378,7 @@ class Init: + ds, + ) + else: ++ util.del_file(self.paths.instance_link) + raise e + self.datasource = ds + # Ensure we adjust our path members datasource +diff --git a/tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py b/tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py +new file mode 100644 +index 00000000..54a7bab3 +--- /dev/null ++++ b/tests/integration_tests/assets/DataSourceNoCacheNetworkOnly.py +@@ -0,0 +1,23 @@ ++import logging ++ ++from cloudinit import sources ++ ++LOG = logging.getLogger(__name__) ++ ++ ++class DataSourceNoCacheNetworkOnly(sources.DataSource): ++ def _get_data(self): ++ LOG.debug("TEST _get_data called") ++ return True ++ ++ ++datasources = [ ++ ( ++ DataSourceNoCacheNetworkOnly, ++ (sources.DEP_FILESYSTEM, sources.DEP_NETWORK), ++ ), ++] ++ ++ ++def get_datasource_list(depends): ++ return sources.list_from_depends(depends, datasources) +diff --git a/tests/integration_tests/assets/DataSourceNoCacheWithFallback.py b/tests/integration_tests/assets/DataSourceNoCacheWithFallback.py +new file mode 100644 +index 00000000..fdfc473f +--- /dev/null ++++ b/tests/integration_tests/assets/DataSourceNoCacheWithFallback.py +@@ -0,0 +1,29 @@ ++import logging ++import os ++ ++from cloudinit import sources ++ ++LOG = logging.getLogger(__name__) ++ ++ ++class DataSourceNoCacheWithFallback(sources.DataSource): ++ def _get_data(self): ++ if os.path.exists("/ci-test-firstboot"): ++ LOG.debug("TEST _get_data called") ++ return True ++ return False ++ ++ def check_if_fallback_is_allowed(self): ++ return True ++ ++ ++datasources = [ ++ ( ++ DataSourceNoCacheWithFallback, ++ (sources.DEP_FILESYSTEM,), ++ ), ++] ++ ++ ++def get_datasource_list(depends): ++ return sources.list_from_depends(depends, datasources) +diff --git a/tests/integration_tests/datasources/test_caching.py b/tests/integration_tests/datasources/test_caching.py +new file mode 100644 +index 00000000..33e4b671 +--- /dev/null ++++ b/tests/integration_tests/datasources/test_caching.py +@@ -0,0 +1,115 @@ ++import pytest ++ ++from tests.integration_tests import releases, util ++from tests.integration_tests.instances import IntegrationInstance ++ ++ ++def setup_custom_datasource(client: IntegrationInstance, datasource_name: str): ++ client.write_to_file( ++ "/etc/cloud/cloud.cfg.d/99-imds.cfg", ++ f"datasource_list: [ {datasource_name}, None ]\n" ++ "datasource_pkg_list: [ cisources ]", ++ ) ++ assert client.execute( ++ "mkdir -p /usr/lib/python3/dist-packages/cisources" ++ ) ++ client.push_file( ++ util.ASSETS_DIR / f"DataSource{datasource_name}.py", ++ "/usr/lib/python3/dist-packages/cisources/" ++ f"DataSource{datasource_name}.py", ++ ) ++ ++ ++def verify_no_cache_boot(client: IntegrationInstance): ++ log = client.read_from_file("/var/log/cloud-init.log") ++ util.verify_ordered_items_in_text( ++ [ ++ "No local datasource found", ++ "running 'init'", ++ "no cache found", ++ "Detected platform", ++ "TEST _get_data called", ++ ], ++ text=log, ++ ) ++ util.verify_clean_boot(client) ++ ++ ++@pytest.mark.skipif( ++ not releases.IS_UBUNTU, ++ reason="hardcoded dist-packages directory", ++) ++def test_no_cache_network_only(client: IntegrationInstance): ++ """Test cache removal per boot. GH-5486 ++ ++ This tests the CloudStack password reset use case. The expectation is: ++ - Metadata is fetched in network timeframe only ++ - Because `check_instance_id` is not defined, no cached datasource ++ is found in the init-local phase, but the cache is used in the ++ remaining phases due to existance of /run/cloud-init/.instance-id ++ - Because `check_if_fallback_is_allowed` is not defined, cloud-init ++ does NOT fall back to the pickled datasource, and will ++ instead delete the cache during the init-local phase ++ - Metadata is therefore fetched every boot in the network phase ++ """ ++ setup_custom_datasource(client, "NoCacheNetworkOnly") ++ ++ # Run cloud-init as if first boot ++ assert client.execute("cloud-init clean --logs") ++ client.restart() ++ ++ verify_no_cache_boot(client) ++ ++ # Clear the log without clean and run cloud-init for subsequent boot ++ assert client.execute("echo '' > /var/log/cloud-init.log") ++ client.restart() ++ ++ verify_no_cache_boot(client) ++ ++ ++@pytest.mark.skipif( ++ not releases.IS_UBUNTU, ++ reason="hardcoded dist-packages directory", ++) ++def test_no_cache_with_fallback(client: IntegrationInstance): ++ """Test we use fallback when defined and no cache available.""" ++ setup_custom_datasource(client, "NoCacheWithFallback") ++ ++ # Run cloud-init as if first boot ++ assert client.execute("cloud-init clean --logs") ++ # Used by custom datasource ++ client.execute("touch /ci-test-firstboot") ++ client.restart() ++ ++ log = client.read_from_file("/var/log/cloud-init.log") ++ util.verify_ordered_items_in_text( ++ [ ++ "no cache found", ++ "Detected platform", ++ "TEST _get_data called", ++ "running 'init'", ++ "restored from cache with run check", ++ "running 'modules:config'", ++ ], ++ text=log, ++ ) ++ util.verify_clean_boot(client) ++ ++ # Clear the log without clean and run cloud-init for subsequent boot ++ assert client.execute("echo '' > /var/log/cloud-init.log") ++ client.execute("rm /ci-test-firstboot") ++ client.restart() ++ ++ log = client.read_from_file("/var/log/cloud-init.log") ++ util.verify_ordered_items_in_text( ++ [ ++ "cache invalid in datasource", ++ "Detected platform", ++ "Restored fallback datasource from checked cache", ++ "running 'init'", ++ "restored from cache with run check", ++ "running 'modules:config'", ++ ], ++ text=log, ++ ) ++ util.verify_clean_boot(client) +diff --git a/tests/integration_tests/instances.py b/tests/integration_tests/instances.py +index 3fc6558a..23c0dc98 100644 +--- a/tests/integration_tests/instances.py ++++ b/tests/integration_tests/instances.py +@@ -88,7 +88,9 @@ class IntegrationInstance: + # First push to a temporary directory because of permissions issues + tmp_path = _get_tmp_path() + self.instance.push_file(str(local_path), tmp_path) +- assert self.execute("mv {} {}".format(tmp_path, str(remote_path))).ok ++ assert self.execute( ++ "mv {} {}".format(tmp_path, str(remote_path)) ++ ), f"Failed to push {tmp_path} to {remote_path}" + + def read_from_file(self, remote_path) -> str: + result = self.execute("cat {}".format(remote_path)) +-- +2.39.3 + diff --git a/SOURCES/ci-fix-Render-bridges-correctly-for-v2-on-sysconfig-wit.patch b/SOURCES/ci-fix-Render-bridges-correctly-for-v2-on-sysconfig-wit.patch new file mode 100644 index 0000000..b2e69b6 --- /dev/null +++ b/SOURCES/ci-fix-Render-bridges-correctly-for-v2-on-sysconfig-wit.patch @@ -0,0 +1,306 @@ +From 1df31428c87f08c790c300ba402318378cea8d65 Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Thu, 10 Oct 2024 23:19:28 -0500 +Subject: [PATCH 1/2] fix: Render bridges correctly for v2 on sysconfig with + set-name (#5674) + +RH-Author: xiachen +RH-MergeRequest: 147: fix: Render bridges correctly for v2 on sysconfig with set-name (#5674) +RH-Jira: RHEL-65021 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Ani Sinha +RH-Commit: [1/2] 7f7fce173ee9a3ba719fc36580fbce813c5bfbd0 (xiachen/cloud-init) + +When listing interfaces in v2 format, we should expect to be able to +reference other interfaces using the name in the configuration, not +the name the interface will eventually take. This was broken when +using `set-name`. + +To fix this, we now store the configuration id alongside the eventual +name, and reference that instead of the name. + +Fixes GH-5574 + +(cherry picked from commit a8f69409e5cebf43767d3bb54fbad7ced1e8fc7b) +Signed-off-by: Amy Chen +--- + cloudinit/net/eni.py | 6 +++ + cloudinit/net/network_state.py | 30 ++++------- + cloudinit/net/sysconfig.py | 24 ++++++--- + tests/unittests/test_net.py | 96 ++++++++++++++++++++++++++++++++++ + 4 files changed, 128 insertions(+), 28 deletions(-) + +diff --git a/cloudinit/net/eni.py b/cloudinit/net/eni.py +index 486fa22dc..ac0306d6a 100644 +--- a/cloudinit/net/eni.py ++++ b/cloudinit/net/eni.py +@@ -5,6 +5,7 @@ import glob + import logging + import os + import re ++from contextlib import suppress + from typing import Optional + + from cloudinit import subp, util +@@ -421,6 +422,11 @@ class Renderer(renderer.Renderer): + return content + + def _render_iface(self, iface, render_hwaddress=False): ++ iface = copy.deepcopy(iface) ++ ++ # Remove irrelevant keys ++ with suppress(KeyError): ++ iface.pop("config_id") + sections = [] + subnets = iface.get("subnets", {}) + accept_ra = iface.pop("accept-ra", None) +diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py +index 14c57cdcc..226421bd0 100644 +--- a/cloudinit/net/network_state.py ++++ b/cloudinit/net/network_state.py +@@ -411,6 +411,7 @@ class NetworkStateInterpreter: + wakeonlan = util.is_true(wakeonlan) + iface.update( + { ++ "config_id": command.get("config_id"), + "name": command.get("name"), + "type": command.get("type"), + "mac_address": command.get("mac_address"), +@@ -424,7 +425,8 @@ class NetworkStateInterpreter: + "wakeonlan": wakeonlan, + } + ) +- self._network_state["interfaces"].update({command.get("name"): iface}) ++ iface_key = command.get("config_id", command.get("name")) ++ self._network_state["interfaces"].update({iface_key: iface}) + self.dump_network_state() + + @ensure_command_keys(["name", "vlan_id", "vlan_link"]) +@@ -712,6 +714,7 @@ class NetworkStateInterpreter: + + for eth, cfg in command.items(): + phy_cmd = { ++ "config_id": eth, + "type": "physical", + } + match = cfg.get("match", {}) +@@ -800,28 +803,15 @@ class NetworkStateInterpreter: + def _v2_common(self, cfg) -> None: + LOG.debug("v2_common: handling config:\n%s", cfg) + for iface, dev_cfg in cfg.items(): +- if "set-name" in dev_cfg: +- set_name_iface = dev_cfg.get("set-name") +- if set_name_iface: +- iface = set_name_iface + if "nameservers" in dev_cfg: +- search = dev_cfg.get("nameservers").get("search", []) +- dns = dev_cfg.get("nameservers").get("addresses", []) ++ search = dev_cfg.get("nameservers").get("search") ++ dns = dev_cfg.get("nameservers").get("addresses") + name_cmd = {"type": "nameserver"} +- if len(search) > 0: +- name_cmd.update({"search": search}) +- if len(dns) > 0: +- name_cmd.update({"address": dns}) ++ if search: ++ name_cmd["search"] = search ++ if dns: ++ name_cmd["address"] = dns + self.handle_nameserver(name_cmd) +- +- mac_address: Optional[str] = dev_cfg.get("match", {}).get( +- "macaddress" +- ) +- if mac_address: +- real_if_name = find_interface_name_from_mac(mac_address) +- if real_if_name: +- iface = real_if_name +- + self._handle_individual_nameserver(name_cmd, iface) + + def _handle_bond_bridge(self, command, cmd_type=None): +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index b50a6a8a0..e4a65187f 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -6,7 +6,7 @@ import io + import logging + import os + import re +-from typing import Mapping, Optional ++from typing import Dict, Optional + + from cloudinit import subp, util + from cloudinit.distros.parsers import networkmanager_conf, resolv_conf +@@ -721,7 +721,7 @@ class Renderer(renderer.Renderer): + ): + physical_filter = renderer.filter_by_physical + for iface in network_state.iter_interfaces(physical_filter): +- iface_name = iface["name"] ++ iface_name = iface.get("config_id") or iface["name"] + iface_subnets = iface.get("subnets", []) + iface_cfg = iface_contents[iface_name] + route_cfg = iface_cfg.routes +@@ -924,7 +924,9 @@ class Renderer(renderer.Renderer): + return out + + @classmethod +- def _render_bridge_interfaces(cls, network_state, iface_contents, flavor): ++ def _render_bridge_interfaces( ++ cls, network_state: NetworkState, iface_contents, flavor ++ ): + bridge_key_map = { + old_k: new_k + for old_k, new_k in cls.cfg_key_maps[flavor].items() +@@ -1005,23 +1007,29 @@ class Renderer(renderer.Renderer): + + @classmethod + def _render_sysconfig( +- cls, base_sysconf_dir, network_state, flavor, templates=None ++ cls, ++ base_sysconf_dir, ++ network_state: NetworkState, ++ flavor, ++ templates=None, + ): + """Given state, return /etc/sysconfig files + contents""" + if not templates: + templates = cls.templates +- iface_contents: Mapping[str, NetInterface] = {} ++ iface_contents: Dict[str, NetInterface] = {} + for iface in network_state.iter_interfaces(): + if iface["type"] == "loopback": + continue +- iface_name = iface["name"] +- iface_cfg = NetInterface(iface_name, base_sysconf_dir, templates) ++ config_id: str = iface.get("config_id") or iface["name"] ++ iface_cfg = NetInterface( ++ iface["name"], base_sysconf_dir, templates ++ ) + if flavor == "suse": + iface_cfg.drop("DEVICE") + # If type detection fails it is considered a bug in SUSE + iface_cfg.drop("TYPE") + cls._render_iface_shared(iface, iface_cfg, flavor) +- iface_contents[iface_name] = iface_cfg ++ iface_contents[config_id] = iface_cfg + cls._render_physical_interfaces(network_state, iface_contents, flavor) + cls._render_bond_interfaces(network_state, iface_contents, flavor) + cls._render_vlan_interfaces(network_state, iface_contents, flavor) +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index 4673e4eaf..004da81ab 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -4489,6 +4489,95 @@ iface bond0 inet6 static + """ + ), + }, ++ "v2-bridges-set-name": { ++ "yaml": textwrap.dedent( ++ """\ ++ version: 2 ++ ethernets: ++ baremetalport: ++ match: ++ macaddress: 52:54:00:bd:8f:cb ++ set-name: baremetal0 ++ provisioningport: ++ match: ++ macaddress: 52:54:00:25:ae:12 ++ set-name: provisioning0 ++ bridges: ++ baremetal: ++ addresses: ++ - fc00:1:1::2/64 ++ interfaces: ++ - baremetalport ++ provisioning: ++ addresses: ++ - fc00:1:2::2/64 ++ interfaces: ++ - provisioningport ++ """ ++ ), ++ "expected_sysconfig_rhel": { ++ "ifcfg-baremetal": textwrap.dedent( ++ """\ ++ # Created by cloud-init automatically, do not edit. ++ # ++ AUTOCONNECT_PRIORITY=120 ++ BOOTPROTO=none ++ DEVICE=baremetal ++ IPV6ADDR=fc00:1:1::2/64 ++ IPV6INIT=yes ++ IPV6_AUTOCONF=no ++ IPV6_FORCE_ACCEPT_RA=no ++ ONBOOT=yes ++ TYPE=Bridge ++ USERCTL=no ++ """ ++ ), ++ "ifcfg-baremetal0": textwrap.dedent( ++ """\ ++ # Created by cloud-init automatically, do not edit. ++ # ++ AUTOCONNECT_PRIORITY=120 ++ BOOTPROTO=none ++ BRIDGE=baremetal ++ DEVICE=baremetal0 ++ HWADDR=52:54:00:bd:8f:cb ++ ONBOOT=yes ++ TYPE=Ethernet ++ USERCTL=no ++ """ ++ ), ++ "ifcfg-provisioning": textwrap.dedent( ++ """\ ++ # Created by cloud-init automatically, do not edit. ++ # ++ AUTOCONNECT_PRIORITY=120 ++ BOOTPROTO=none ++ DEVICE=provisioning ++ IPV6ADDR=fc00:1:2::2/64 ++ IPV6INIT=yes ++ IPV6_AUTOCONF=no ++ IPV6_FORCE_ACCEPT_RA=no ++ ONBOOT=yes ++ TYPE=Bridge ++ USERCTL=no ++ """ ++ ), ++ "ifcfg-provisioning0": textwrap.dedent( ++ """\ ++ # Created by cloud-init automatically, do not edit. ++ # ++ AUTOCONNECT_PRIORITY=120 ++ BOOTPROTO=none ++ BRIDGE=provisioning ++ DEVICE=provisioning0 ++ HWADDR=52:54:00:25:ae:12 ++ ONBOOT=yes ++ TYPE=Ethernet ++ USERCTL=no ++ """ ++ ), ++ }, ++ }, + } + + +@@ -5558,6 +5647,13 @@ USERCTL=no + self._compare_files_to_expected(entry[self.expected_name], found) + self._assert_headers(found) + ++ def test_bridges_set_name_config(self): ++ entry = NETWORK_CONFIGS["v2-bridges-set-name"] ++ 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_netplan_dhcp_false_disable_dhcp_in_state(self): + """netplan config with dhcp[46]: False should not add dhcp in state""" + net_config = yaml.load(NETPLAN_DHCP_FALSE) +-- +2.39.3 + diff --git a/SOURCES/ci-fix-Render-v2-bridges-correctly-on-network-manager-w.patch b/SOURCES/ci-fix-Render-v2-bridges-correctly-on-network-manager-w.patch new file mode 100644 index 0000000..5ebc106 --- /dev/null +++ b/SOURCES/ci-fix-Render-v2-bridges-correctly-on-network-manager-w.patch @@ -0,0 +1,160 @@ +From 58904df7d689df6e3d1d4ddf47b5cb5a267006da Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Fri, 11 Oct 2024 13:58:19 -0500 +Subject: [PATCH 2/2] fix: Render v2 bridges correctly on network-manager with + set-name (#5740) + +RH-Author: xiachen +RH-MergeRequest: 147: fix: Render bridges correctly for v2 on sysconfig with set-name (#5674) +RH-Jira: RHEL-65021 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Ani Sinha +RH-Commit: [2/2] e101d8ff06a379752958a3eb19d209bcb7d1e0ed (xiachen/cloud-init) + +Similar to the recent sysconfig fix, ensure bridges render correctly +for configs that contain `set-name`. + +Fixes GH-5717 + +(cherry picked from commit 9554338e6ecf49c66324cc637eaf0fa7bf10e407) +Signed-off-by: Amy Chen +--- + cloudinit/net/network_manager.py | 6 +- + tests/unittests/test_net.py | 94 ++++++++++++++++++++++++++++++++ + 2 files changed, 98 insertions(+), 2 deletions(-) + +diff --git a/cloudinit/net/network_manager.py b/cloudinit/net/network_manager.py +index 0ba210b74..f50fafa39 100644 +--- a/cloudinit/net/network_manager.py ++++ b/cloudinit/net/network_manager.py +@@ -464,11 +464,13 @@ class Renderer(renderer.Renderer): + # interfaces that have UUIDs that can be linked to from related + # interfaces + for iface in network_state.iter_interfaces(): +- self.connections[iface["name"]] = NMConnection(iface["name"]) ++ conn_key = iface.get("config_id") or iface["name"] ++ self.connections[conn_key] = NMConnection(iface["name"]) + + # Now render the actual interface configuration + for iface in network_state.iter_interfaces(): +- conn = self.connections[iface["name"]] ++ conn_key = iface.get("config_id") or iface["name"] ++ conn = self.connections[conn_key] + conn.render_interface(iface, network_state, self) + + # And finally write the files +diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py +index 004da81ab..ddb45dc69 100644 +--- a/tests/unittests/test_net.py ++++ b/tests/unittests/test_net.py +@@ -4577,6 +4577,94 @@ iface bond0 inet6 static + """ + ), + }, ++ "expected_network_manager": { ++ "cloud-init-baremetal.nmconnection": textwrap.dedent( ++ """\ ++ # Generated by cloud-init. Changes will be lost. ++ ++ [connection] ++ id=cloud-init baremetal ++ uuid=e63eed9a-cd1c-55de-8d5e-1e80b756a482 ++ autoconnect-priority=120 ++ type=bridge ++ interface-name=baremetal ++ ++ [user] ++ org.freedesktop.NetworkManager.origin=cloud-init ++ ++ [bridge] ++ ++ [ipv6] ++ method=manual ++ may-fail=false ++ address1=fc00:1:1::2/64 ++ ++ """ ++ ), ++ "cloud-init-baremetalport.nmconnection": textwrap.dedent( ++ """\ ++ # Generated by cloud-init. Changes will be lost. ++ ++ [connection] ++ id=cloud-init baremetal0 ++ uuid=8e326690-51d6-5157-ab84-e4e822b06503 ++ autoconnect-priority=120 ++ type=ethernet ++ slave-type=bridge ++ master=e63eed9a-cd1c-55de-8d5e-1e80b756a482 ++ ++ [user] ++ org.freedesktop.NetworkManager.origin=cloud-init ++ ++ [ethernet] ++ mac-address=52:54:00:BD:8F:CB ++ ++ """ ++ ), ++ "cloud-init-provisioning.nmconnection": textwrap.dedent( ++ """\ ++ # Generated by cloud-init. Changes will be lost. ++ ++ [connection] ++ id=cloud-init provisioning ++ uuid=e5bd3f1a-cdcc-55d3-a6d8-88f1ba73bd0e ++ autoconnect-priority=120 ++ type=bridge ++ interface-name=provisioning ++ ++ [user] ++ org.freedesktop.NetworkManager.origin=cloud-init ++ ++ [bridge] ++ ++ [ipv6] ++ method=manual ++ may-fail=false ++ address1=fc00:1:2::2/64 ++ ++ """ ++ ), ++ "cloud-init-provisioningport.nmconnection": textwrap.dedent( ++ """\ ++ # Generated by cloud-init. Changes will be lost. ++ ++ [connection] ++ id=cloud-init provisioning0 ++ uuid=d79b7b70-e9df-596f-ace7-89537db45684 ++ autoconnect-priority=120 ++ type=ethernet ++ slave-type=bridge ++ master=e5bd3f1a-cdcc-55d3-a6d8-88f1ba73bd0e ++ ++ [user] ++ org.freedesktop.NetworkManager.origin=cloud-init ++ ++ [ethernet] ++ mac-address=52:54:00:25:AE:12 ++ ++ """ ++ ), ++ }, + }, + } + +@@ -6722,6 +6810,12 @@ class TestNetworkManagerRendering(CiTestCase): + entry[self.expected_name], self.expected_conf_d, found + ) + ++ def test_v2_bridges_set_name(self): ++ entry = NETWORK_CONFIGS["v2-bridges-set-name"] ++ found = self._render_and_read(network_config=yaml.load(entry["yaml"])) ++ self._compare_files_to_expected( ++ entry[self.expected_name], self.expected_conf_d, found ++ ) + + @mock.patch( + "cloudinit.net.is_openvswitch_internal_interface", +-- +2.39.3 + diff --git a/SOURCES/ci-fix-add-schema-rules-for-baseurl-and-metalink-in-yum.patch b/SOURCES/ci-fix-add-schema-rules-for-baseurl-and-metalink-in-yum.patch new file mode 100644 index 0000000..775f9c6 --- /dev/null +++ b/SOURCES/ci-fix-add-schema-rules-for-baseurl-and-metalink-in-yum.patch @@ -0,0 +1,66 @@ +From ed3c05af60c0d50a4576a63c8638e148e58ebf06 Mon Sep 17 00:00:00 2001 +From: Ani Sinha +Date: Thu, 11 Jul 2024 00:49:58 +0530 +Subject: [PATCH] fix: add schema rules for 'baseurl' and 'metalink' in yum + repo config (#5501) + +RH-Author: Ani Sinha +RH-MergeRequest: 101: fix: add schema rules for 'baseurl' and 'metalink' in yum repo config (#5501) +RH-Jira: RHEL-46873 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: xiachen +RH-Commit: [1/1] df01c93fde517e66ce71a66f80ee54d3ed504906 (anisinha/cloud-init) + +At least one of (or both) 'baseurl' or 'metalink' should be provided for yum +repository specification. Add schema changes to enforce it. Without this, +with just 'metalink' property set, one would get the schema validator error + +\--- +Error: Cloud config schema errors: yum_repos.epel-release: 'baseurl' is a required property +\--- + +Signed-off-by: Ani Sinha +(cherry picked from commit 7d35664ef8b85840f92f18cc48187f7284d227bc) +--- + .../config/schemas/schema-cloud-config-v1.json | 18 ++++++++++++++++-- + 1 file changed, 16 insertions(+), 2 deletions(-) + +diff --git a/cloudinit/config/schemas/schema-cloud-config-v1.json b/cloudinit/config/schemas/schema-cloud-config-v1.json +index 03e723e2..4fb7fd93 100644 +--- a/cloudinit/config/schemas/schema-cloud-config-v1.json ++++ b/cloudinit/config/schemas/schema-cloud-config-v1.json +@@ -3442,6 +3442,11 @@ + "format": "uri", + "description": "URL to the directory where the yum repository's 'repodata' directory lives" + }, ++ "metalink": { ++ "type": "string", ++ "format": "uri", ++ "description": "Specifies a URL to a metalink file for the repomd.xml" ++ }, + "name": { + "type": "string", + "description": "Optional human-readable name of the yum repo." +@@ -3469,8 +3474,17 @@ + "description": "Any supported yum repository configuration options will be written to the yum repo config file. See: man yum.conf" + } + }, +- "required": [ +- "baseurl" ++ "anyOf": [ ++ { ++ "required": [ ++ "baseurl" ++ ] ++ }, ++ { ++ "required": [ ++ "metalink" ++ ] ++ } + ] + } + } +-- +2.39.3 + diff --git a/SOURCES/ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch b/SOURCES/ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch new file mode 100644 index 0000000..b7eb978 --- /dev/null +++ b/SOURCES/ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch @@ -0,0 +1,132 @@ +From 2b74b0eb94edfd7caa42bc0d8affc37311ba041b Mon Sep 17 00:00:00 2001 +From: Brett Holman +Date: Wed, 3 Jan 2024 09:11:21 -0700 +Subject: [PATCH 4/6] fix(dhcp): Guard against FileNotFoundError and NameError + exceptions + +RH-Author: Ani Sinha +RH-MergeRequest: 92: Update pylint version to support python 3.12 +RH-Jira: RHEL-44598 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/3] 730b8de9ceb2c380d3b15573d83691ab95a1487e (anisinha/cloud-init) + +(cherry picked from commit 53eb8555e091474803b724700815adc09aa84f05) +--- + cloudinit/net/dhcp.py | 20 ++++++++++------ + tests/unittests/net/test_dhcp.py | 40 ++++++++++++++++++++++++++++++++ + 2 files changed, 53 insertions(+), 7 deletions(-) + +diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py +index 07c13390..a0aee98c 100644 +--- a/cloudinit/net/dhcp.py ++++ b/cloudinit/net/dhcp.py +@@ -5,15 +5,15 @@ + # This file is part of cloud-init. See LICENSE file for license information. + + import abc +-import contextlib + import glob + import logging + import os + import re + import signal + import time ++from contextlib import suppress + from io import StringIO +-from typing import Any, Dict, List ++from typing import Any, Dict, List, Optional + + import configobj + +@@ -268,7 +268,7 @@ class IscDhclient(DhcpClient): + + # this function waits for these files to exist, clean previous runs + # to avoid false positive in wait_for_files +- with contextlib.suppress(FileNotFoundError): ++ with suppress(FileNotFoundError): + os.remove(pid_file) + os.remove(lease_file) + +@@ -514,9 +514,15 @@ class IscDhclient(DhcpClient): + return latest_file + + @staticmethod +- def parse_dhcp_server_from_lease_file(lease_file): +- with open(lease_file, "r") as fd: +- for line in fd: ++ def parse_dhcp_server_from_lease_file(lease_file) -> Optional[str]: ++ """Parse a lease file for the dhcp server address ++ ++ @param lease_file: Name of a file to be parsed ++ @return: An address if found, or None ++ """ ++ latest_address = None ++ with suppress(FileNotFoundError), open(lease_file, "r") as file: ++ for line in file: + if "dhcp-server-identifier" in line: + words = line.strip(" ;\r\n").split(" ") + if len(words) > 2: +@@ -561,7 +567,7 @@ class Udhcpc(DhcpClient): + + tmp_dir = temp_utils.get_tmp_ancestor(needs_exe=True) + lease_file = os.path.join(tmp_dir, interface + ".lease.json") +- with contextlib.suppress(FileNotFoundError): ++ with suppress(FileNotFoundError): + os.remove(lease_file) + + # udhcpc needs the interface up to send initial discovery packets +diff --git a/tests/unittests/net/test_dhcp.py b/tests/unittests/net/test_dhcp.py +index a7b62312..8ec96eef 100644 +--- a/tests/unittests/net/test_dhcp.py ++++ b/tests/unittests/net/test_dhcp.py +@@ -32,6 +32,46 @@ LEASE_F = "/run/dhclient.lease" + DHCLIENT = "/sbin/dhclient" + + ++@pytest.mark.parametrize( ++ "server_address,lease_file_content", ++ ( ++ pytest.param(None, None, id="no_server_addr_on_absent_lease_file"), ++ pytest.param(None, "", id="no_server_addr_on_empty_lease_file"), ++ pytest.param( ++ None, ++ "lease {\n fixed-address: 10.1.2.3;\n}\n", ++ id="no_server_addr_when_no_server_ident", ++ ), ++ pytest.param( ++ "10.4.5.6", ++ "lease {\n fixed-address: 10.1.2.3;\n" ++ " option dhcp-server-identifier 10.4.5.6;\n" ++ " option dhcp-renewal-time 1800;\n}\n", ++ id="server_addr_found_when_server_ident_present", ++ ), ++ ), ++) ++class TestParseDHCPServerFromLeaseFile: ++ def test_find_server_address_when_present( ++ self, server_address, lease_file_content, tmp_path ++ ): ++ """Test that we return None in the case of no file or file contains no ++ server address, otherwise return the address. ++ """ ++ lease_file = tmp_path / "dhcp.leases" ++ if server_address: ++ if lease_file_content: ++ lease_file.write_text(lease_file_content) ++ assert ( ++ server_address ++ == IscDhclient.parse_dhcp_server_from_lease_file(lease_file) ++ ) ++ else: ++ assert not IscDhclient.parse_dhcp_server_from_lease_file( ++ lease_file ++ ) ++ ++ + class TestParseDHCPLeasesFile(CiTestCase): + def test_parse_empty_lease_file_errors(self): + """parse_dhcp_lease_file errors when file content is empty.""" +-- +2.39.3 + diff --git a/SOURCES/ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch b/SOURCES/ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch new file mode 100644 index 0000000..221d24f --- /dev/null +++ b/SOURCES/ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch @@ -0,0 +1,53 @@ +From b7fddab36d805099639358736dab474d2924906b Mon Sep 17 00:00:00 2001 +From: Brett Holman +Date: Wed, 19 Jun 2024 17:07:56 -0600 +Subject: [PATCH 2/6] fix(jsonschema): Add missing sudo definition (#5418) + +RH-Author: Ani Sinha +RH-MergeRequest: 90: fix(jsonschema): Add missing sudo definition (#5418) +RH-Jira: RHEL-44337 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [1/2] 9e56c7ab35744c6530c8cef2f122ffdcc0480d29 (anisinha/cloud-init) + +This configuration: + +``` +users: + - name: osadmin + lock_passwd: false + sudo: ["ALL=(ALL) NOPASSWD:ALL"] +``` + +Is valid syntax but is missing from the jsonschema definition. + +Fixes GH-5399 + +(cherry picked from commit b533fa51acb850ed754e2b1925e276ff8e5f3507) +--- + cloudinit/config/schemas/schema-cloud-config-v1.json | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/cloudinit/config/schemas/schema-cloud-config-v1.json b/cloudinit/config/schemas/schema-cloud-config-v1.json +index a553c52c..8b10fe70 100644 +--- a/cloudinit/config/schemas/schema-cloud-config-v1.json ++++ b/cloudinit/config/schemas/schema-cloud-config-v1.json +@@ -299,6 +299,15 @@ + ], + "description": "Sudo rule to use or false. Absence of a sudo value or ``null`` will result in no sudo rules added for this user." + }, ++ { ++ "type": "array", ++ "items": { ++ "type": [ ++ "string", ++ "null" ++ ] ++ } ++ }, + { + "type": "boolean", + "changed": true, +-- +2.39.3 + diff --git a/SOURCES/ci-fix-nocloud-smbios-datasource-definition.patch b/SOURCES/ci-fix-nocloud-smbios-datasource-definition.patch new file mode 100644 index 0000000..4d0cec6 --- /dev/null +++ b/SOURCES/ci-fix-nocloud-smbios-datasource-definition.patch @@ -0,0 +1,103 @@ +From 75e658591f6187f73eb0baa3291bde01db62cc5e Mon Sep 17 00:00:00 2001 +From: Brett Holman +Date: Fri, 23 Feb 2024 11:16:15 -0700 +Subject: [PATCH] fix(nocloud): smbios datasource definition + +RH-Author: Ani Sinha +RH-MergeRequest: 154: fix(nocloud): smbios datasource definition +RH-Jira: RHEL-79774 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Jon Maloy +RH-Commit: [1/1] 3ce501f6167ffafcb6dea7df37589d348039a371 + +deprecate nocloud-net name + +(cherry picked from commit 66b5ce9d5f94c0c6625972fdfdca3796d365b069) +--- + cloudinit/sources/DataSourceNoCloud.py | 39 ++++++++++++++++++++++---- + cloudinit/sources/__init__.py | 11 +++++--- + 2 files changed, 41 insertions(+), 9 deletions(-) + +diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py +index 55a16638..7581f0a5 100644 +--- a/cloudinit/sources/DataSourceNoCloud.py ++++ b/cloudinit/sources/DataSourceNoCloud.py +@@ -11,6 +11,7 @@ + import errno + import logging + import os ++from functools import partial + + from cloudinit import dmi, sources, util + from cloudinit.net import eni +@@ -368,12 +369,40 @@ class DataSourceNoCloudNet(DataSourceNoCloud): + self.supported_seed_starts = ("http://", "https://") + + def ds_detect(self): +- """NoCloud requires "nocloud-net" as the way to specify +- seeding from an http(s) address. This diverges from all other +- datasources in that it does a kernel commandline match on something +- other than the datasource dsname for only DEP_NETWORK. ++ """Check dmi and kernel commandline for dsname ++ ++ NoCloud historically used "nocloud-net" as its dsname ++ for network timeframe (DEP_NETWORK), which supports http(s) urls. ++ For backwards compatiblity, check for that dsname. + """ +- return "nocloud-net" == sources.parse_cmdline() ++ log_deprecated = partial( ++ util.deprecate, ++ deprecated="The 'nocloud-net' datasource name", ++ deprecated_version="24.1", ++ extra_message=( ++ "Use 'nocloud' instead, which uses the seedfrom protocol" ++ "scheme (http// or file://) to decide how to run." ++ ), ++ ) ++ ++ if "nocloud-net" == sources.parse_cmdline(): ++ log_deprecated() ++ return True ++ ++ serial = sources.parse_cmdline_or_dmi( ++ dmi.read_dmi_data("system-serial-number") or "" ++ ).lower() ++ ++ if serial in (self.dsname.lower(), "nocloud-net"): ++ LOG.debug( ++ "Machine is configured by dmi serial number to run on " ++ "single datasource %s.", ++ self, ++ ) ++ if serial == "nocloud-net": ++ log_deprecated() ++ return True ++ return False + + + # Used to match classes to dependencies +diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py +index 453801be..e89af3d0 100644 +--- a/cloudinit/sources/__init__.py ++++ b/cloudinit/sources/__init__.py +@@ -1198,10 +1198,13 @@ def parse_cmdline() -> str: + """Check if command line argument for this datasource was passed + Passing by command line overrides runtime datasource detection + """ +- cmdline = util.get_cmdline() +- ds_parse_0 = re.search(r"ds=([^\s;]+)", cmdline) +- ds_parse_1 = re.search(r"ci\.ds=([^\s;]+)", cmdline) +- ds_parse_2 = re.search(r"ci\.datasource=([^\s;]+)", cmdline) ++ return parse_cmdline_or_dmi(util.get_cmdline()) ++ ++ ++def parse_cmdline_or_dmi(input: str) -> str: ++ ds_parse_0 = re.search(r"(?:^|\s)ds=([^\s;]+)", input) ++ ds_parse_1 = re.search(r"(?:^|\s)ci\.ds=([^\s;]+)", input) ++ ds_parse_2 = re.search(r"(?:^|\s)ci\.datasource=([^\s;]+)", input) + ds = ds_parse_0 or ds_parse_1 or ds_parse_2 + deprecated = ds_parse_1 or ds_parse_2 + if deprecated: +-- +2.48.1 + diff --git a/SOURCES/ci-fix-python3.13-Fix-import-error-for-passlib-on-Pytho.patch b/SOURCES/ci-fix-python3.13-Fix-import-error-for-passlib-on-Pytho.patch new file mode 100644 index 0000000..7d1f1de --- /dev/null +++ b/SOURCES/ci-fix-python3.13-Fix-import-error-for-passlib-on-Pytho.patch @@ -0,0 +1,34 @@ +From e6e7c274235d924fde752b228f68ec5773e39029 Mon Sep 17 00:00:00 2001 +From: Brett Holman +Date: Tue, 5 Dec 2023 16:40:03 -0700 +Subject: [PATCH 2/2] fix(python3.13): Fix import error for passlib on Python + 3.13 (#4669) + +RH-Author: xiachen +RH-MergeRequest: 145: Fix metric setting for ifcfg network connections for rhel (#5777) +RH-Jira: RHEL-65018 +RH-Acked-by: Ani Sinha +RH-Commit: [2/2] 226ae26a9f903774cb36f8f72b89071ba4545a66 (xiachen/cloud-init) + +(cherry picked from commit 09b70436b3a0aae1fe24fdde6e8cdd7ee98d9c15) +Signed-off-by: Amy Chen +--- + cloudinit/sources/DataSourceAzure.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py +index eb0304c3d..939210100 100644 +--- a/cloudinit/sources/DataSourceAzure.py ++++ b/cloudinit/sources/DataSourceAzure.py +@@ -58,7 +58,7 @@ try: + ) + except (ImportError, AttributeError): + try: +- import passlib ++ import passlib.hash + + blowfish_hash = passlib.hash.sha512_crypt.hash + except ImportError: +-- +2.39.3 + diff --git a/SOURCES/ci-fix-schema-permit-deprecated-hyphenated-keys-under-u.patch b/SOURCES/ci-fix-schema-permit-deprecated-hyphenated-keys-under-u.patch new file mode 100644 index 0000000..82723c2 --- /dev/null +++ b/SOURCES/ci-fix-schema-permit-deprecated-hyphenated-keys-under-u.patch @@ -0,0 +1,412 @@ +From ce69cd178d9c05827db1ca1654de82dc3f9f521e Mon Sep 17 00:00:00 2001 +From: Chad Smith +Date: Thu, 27 Jun 2024 18:12:31 -0600 +Subject: [PATCH 3/3] fix(schema): permit deprecated hyphenated keys under + users key (#5456) + +RH-Author: Ani Sinha +RH-MergeRequest: 95: Deprecate the users ssh-authorized-keys property (#5162) +RH-Jira: RHEL-45262 +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Acked-by: Miroslav Rezanina +RH-Commit: [3/3] 76804599a9166796dc52bab2031a706993ad2e3c (anisinha/cloud-init) + +Both hyphenated and underscore delimited key names are permitted +by cloudinit/distros/ug_util.py#L114 due to magic replacement +of key names. + +Since this is still valid json schema, add the necessary hyphenated +aliases for all users/groups keys. Because the goal in the future is +to only support one config key for a given configuraion option, add +deprecated keys to those schema definitions. + +Also drop the description key from the deprecates lock-passwd schema +key. + +Any deprecated schema key which provides a suggested replacement should +not provide duplicated key descriptions as the preferred replacement +will provided the necessary context. + +Fixes GH-5454 + +(cherry picked from commit b3618d44a37ae6345f0c3d935b77ae0ae9dd1c92) +--- + .../schemas/schema-cloud-config-v1.json | 103 +++++++++++++----- + tests/unittests/config/test_cc_grub_dpkg.py | 4 +- + .../test_cc_package_update_upgrade_install.py | 11 +- + .../unittests/config/test_cc_users_groups.py | 33 +++--- + tests/unittests/config/test_schema.py | 15 ++- + 5 files changed, 108 insertions(+), 58 deletions(-) + +diff --git a/cloudinit/config/schemas/schema-cloud-config-v1.json b/cloudinit/config/schemas/schema-cloud-config-v1.json +index 97cf2b74..03e723e2 100644 +--- a/cloudinit/config/schemas/schema-cloud-config-v1.json ++++ b/cloudinit/config/schemas/schema-cloud-config-v1.json +@@ -178,9 +178,9 @@ + "patternProperties": { + "^.+$": { + "label": "", +- "description": "When providing an object for users.groups the ```` keys are the groups to add this user to", + "deprecated": true, + "deprecated_version": "23.1", ++ "deprecated_description": "The use of ``object`` type is deprecated. Use ``string`` or ``array`` of ``string`` instead.", + "type": [ + "null" + ], +@@ -203,9 +203,7 @@ + "type": "string" + }, + "lock-passwd": { +- "default": true, + "type": "boolean", +- "description": "Default: ``true``", + "deprecated": true, + "deprecated_version": "22.3", + "deprecated_description": "Use ``lock_passwd`` instead." +@@ -215,16 +213,34 @@ + "description": "Disable password login. Default: ``true``", + "type": "boolean" + }, ++ "no-create-home": { ++ "type": "boolean", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``no_create_home`` instead." ++ }, + "no_create_home": { + "default": false, + "description": "Do not create home directory. Default: ``false``", + "type": "boolean" + }, ++ "no-log-init": { ++ "type": "boolean", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``no_log_init`` instead." ++ }, + "no_log_init": { + "default": false, + "description": "Do not initialize lastlog and faillog for user. Default: ``false``", + "type": "boolean" + }, ++ "no-user-group": { ++ "type": "boolean", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``no_user_group`` instead." ++ }, + "no_user_group": { + "default": false, + "description": "Do not create group named after user. Default: ``false``", +@@ -234,24 +250,54 @@ + "description": "Hash of user password applied when user does not exist. This will NOT be applied if the user already exists. To generate this hash, run: mkpasswd --method=SHA-512 --rounds=4096. **Note:** While hashed password is better than plain text, using ``passwd`` in user-data represents a security risk as user-data could be accessible by third-parties depending on your cloud platform.", + "type": "string" + }, ++ "hashed-passwd": { ++ "type": "string", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``hashed_passwd`` instead." ++ }, + "hashed_passwd": { + "description": "Hash of user password to be applied. This will be applied even if the user is pre-existing. To generate this hash, run: mkpasswd --method=SHA-512 --rounds=4096. **Note:** While ``hashed_password`` is better than ``plain_text_passwd``, using ``passwd`` in user-data represents a security risk as user-data could be accessible by third-parties depending on your cloud platform.", + "type": "string" + }, ++ "plain-text-passwd": { ++ "type": "string", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``plain_text_passwd`` instead." ++ }, + "plain_text_passwd": { + "description": "Clear text of user password to be applied. This will be applied even if the user is pre-existing. There are many more secure options than using plain text passwords, such as ``ssh_import_id`` or ``hashed_passwd``. Do not use this in production as user-data and your password can be exposed.", + "type": "string" + }, ++ "create-groups": { ++ "type": "boolean", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``create_groups`` instead." ++ }, + "create_groups": { + "default": true, + "description": "Boolean set ``false`` to disable creation of specified user ``groups``. Default: ``true``.", + "type": "boolean" + }, ++ "primary-group": { ++ "type": "string", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``primary_group`` instead." ++ }, + "primary_group": { + "default": "````", + "description": "Primary group for user. Default: ````", + "type": "string" + }, ++ "selinux-user": { ++ "type": "string", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``selinux_user`` instead." ++ }, + "selinux_user": { + "description": "SELinux user for user's login. Default to default SELinux user.", + "type": "string" +@@ -273,20 +319,24 @@ + "minItems": 1 + }, + "ssh-authorized-keys": { +- "allOf": [ +- { +- "type": "array", +- "items": { +- "type": "string" +- }, +- "minItems": 1 +- }, +- { +- "deprecated": true, +- "deprecated_version": "18.3", +- "deprecated_description": "Use ``ssh_authorized_keys`` instead." +- } +- ] ++ "type": "array", ++ "items": { ++ "type": "string" ++ }, ++ "minItems": 1, ++ "deprecated": true, ++ "deprecated_version": "18.3", ++ "deprecated_description": "Use ``ssh_authorized_keys`` instead." ++ }, ++ "ssh-import-id": { ++ "type": "array", ++ "items": { ++ "type": "string" ++ }, ++ "minItems": 1, ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``ssh_import_id`` instead." + }, + "ssh_import_id": { + "description": "List of SSH IDs to import for user. Can not be combined with ``ssh_redirect_user``.", +@@ -296,6 +346,12 @@ + }, + "minItems": 1 + }, ++ "ssh-redirect-user": { ++ "type": "boolean", ++ "deprecated": true, ++ "deprecated_version": "24.2", ++ "deprecated_description": "Use ``ssh_redirect_user`` instead." ++ }, + "ssh_redirect_user": { + "type": "boolean", + "default": false, +@@ -398,7 +454,6 @@ + "properties": { + "remove-defaults": { + "type": "boolean", +- "default": false, + "deprecated": true, + "deprecated_version": "22.3", + "deprecated_description": "Use ``remove_defaults`` instead." +@@ -516,9 +571,9 @@ + }, + "system_info": { + "type": "object", +- "description": "System and/or distro specific settings. This is not intended to be overridden by user data or vendor data.", + "deprecated": true, +- "deprecated_version": "24.2" ++ "deprecated_version": "24.2", ++ "deprecated_description": "System and/or distro specific settings. This is not intended to be overridden by user data or vendor data." + } + } + }, +@@ -1483,7 +1538,6 @@ + }, + "grub-dpkg": { + "type": "object", +- "description": "An alias for ``grub_dpkg``", + "deprecated": true, + "deprecated_version": "22.2", + "deprecated_description": "Use ``grub_dpkg`` instead." +@@ -2082,24 +2136,18 @@ + }, + "apt_update": { + "type": "boolean", +- "default": false, +- "description": "Default: ``false``.", + "deprecated": true, + "deprecated_version": "22.2", + "deprecated_description": "Use ``package_update`` instead." + }, + "apt_upgrade": { + "type": "boolean", +- "default": false, +- "description": "Default: ``false``.", + "deprecated": true, + "deprecated_version": "22.2", + "deprecated_description": "Use ``package_upgrade`` instead." + }, + "apt_reboot_if_required": { + "type": "boolean", +- "default": false, +- "description": "Default: ``false``.", + "deprecated": true, + "deprecated_version": "22.2", + "deprecated_description": "Use ``package_reboot_if_required`` instead." +@@ -2798,7 +2846,6 @@ + } + ], + "minItems": 1, +- "description": "List of ``username:password`` pairs. Each user will have the corresponding password set. A password can be randomly generated by specifying ``RANDOM`` or ``R`` as a user's password. A hashed password, created by a tool like ``mkpasswd``, can be specified. A regex (``r'\\$(1|2a|2y|5|6)(\\$.+){2}'``) is used to determine if a password value should be treated as a hash.", + "deprecated": true, + "deprecated_version": "22.2", + "deprecated_description": "Use ``users`` instead." +diff --git a/tests/unittests/config/test_cc_grub_dpkg.py b/tests/unittests/config/test_cc_grub_dpkg.py +index b4bd48df..36ef7fd9 100644 +--- a/tests/unittests/config/test_cc_grub_dpkg.py ++++ b/tests/unittests/config/test_cc_grub_dpkg.py +@@ -300,8 +300,8 @@ class TestGrubDpkgSchema: + pytest.raises( + SchemaValidationError, + match=( +- "Cloud config schema deprecations: grub-dpkg: An alias" +- " for ``grub_dpkg`` Deprecated in version 22.2. Use " ++ "Cloud config schema deprecations: grub-dpkg:" ++ " Deprecated in version 22.2. Use " + "``grub_dpkg`` instead." + ), + ), +diff --git a/tests/unittests/config/test_cc_package_update_upgrade_install.py b/tests/unittests/config/test_cc_package_update_upgrade_install.py +index 9ba7f178..734dbc53 100644 +--- a/tests/unittests/config/test_cc_package_update_upgrade_install.py ++++ b/tests/unittests/config/test_cc_package_update_upgrade_install.py +@@ -192,16 +192,16 @@ class TestPackageUpdateUpgradeSchema: + ( + {"apt_update": False}, + ( +- "Cloud config schema deprecations: apt_update: " +- "Default: ``false``. Deprecated in version 22.2. " ++ "Cloud config schema deprecations: apt_update: " ++ "Deprecated in version 22.2. " + "Use ``package_update`` instead." + ), + ), + ( + {"apt_upgrade": False}, + ( +- "Cloud config schema deprecations: apt_upgrade: " +- "Default: ``false``. Deprecated in version 22.2. " ++ "Cloud config schema deprecations: apt_upgrade: " ++ "Deprecated in version 22.2. " + "Use ``package_upgrade`` instead." + ), + ), +@@ -209,8 +209,7 @@ class TestPackageUpdateUpgradeSchema: + {"apt_reboot_if_required": False}, + ( + "Cloud config schema deprecations: " +- "apt_reboot_if_required: Default: ``false``. " +- "Deprecated in version 22.2. Use " ++ "apt_reboot_if_required: Deprecated in version 22.2. Use " + "``package_reboot_if_required`` instead." + ), + ), +diff --git a/tests/unittests/config/test_cc_users_groups.py b/tests/unittests/config/test_cc_users_groups.py +index 53e231e1..4ca67f77 100644 +--- a/tests/unittests/config/test_cc_users_groups.py ++++ b/tests/unittests/config/test_cc_users_groups.py +@@ -371,9 +371,20 @@ class TestUsersGroupsSchema: + SchemaValidationError, + match=( + "Cloud config schema deprecations: " +- "users.0.lock-passwd: Default: ``true`` " +- "Deprecated in version 22.3. Use " +- "``lock_passwd`` instead." ++ "users.0.lock-passwd: Deprecated in version 22.3." ++ " Use ``lock_passwd`` instead." ++ ), ++ ), ++ False, ++ ), ++ ( ++ {"users": [{"name": "bbsw", "no-create-home": True}]}, ++ pytest.raises( ++ SchemaValidationError, ++ match=( ++ "Cloud config schema deprecations: " ++ "users.0.no-create-home: Deprecated in version 24.2." ++ " Use ``no_create_home`` instead." + ), + ), + False, +@@ -394,13 +405,10 @@ class TestUsersGroupsSchema: + SchemaValidationError, + match=( + "Cloud config schema deprecations: " +- "users.0.groups.adm: When providing an object " +- "for users.groups the ```` keys " +- "are the groups to add this user to Deprecated" +- " in version 23.1., users.0.groups.sudo: When " +- "providing an object for users.groups the " +- "```` keys are the groups to add " +- "this user to Deprecated in version 23.1." ++ "users.0.groups.adm: Deprecated in version 23.1. " ++ "The use of ``object`` type is deprecated. Use " ++ "``string`` or ``array`` of ``string`` instead., " ++ "users.0.groups.sudo: Deprecated in version 23.1." + ), + ), + False, +@@ -456,10 +464,7 @@ class TestUsersGroupsSchema: + SchemaValidationError, + match=( + "Cloud config schema deprecations: " +- "user.groups.sbuild: When providing an object " +- "for users.groups the ```` keys " +- "are the groups to add this user to Deprecated" +- " in version 23.1." ++ "user.groups.sbuild: Deprecated in version 23.1." + ), + ), + False, +diff --git a/tests/unittests/config/test_schema.py b/tests/unittests/config/test_schema.py +index 52667332..8208affc 100644 +--- a/tests/unittests/config/test_schema.py ++++ b/tests/unittests/config/test_schema.py +@@ -2251,9 +2251,9 @@ class TestHandleSchemaArgs: + apt_reboot_if_required: true # D3 + + # Deprecations: ------------- +- # D1: Default: ``false``. Deprecated in version 22.2. Use ``package_update`` instead. +- # D2: Default: ``false``. Deprecated in version 22.2. Use ``package_upgrade`` instead. +- # D3: Default: ``false``. Deprecated in version 22.2. Use ``package_reboot_if_required`` instead. ++ # D1: Deprecated in version 22.2. Use ``package_update`` instead. ++ # D2: Deprecated in version 22.2. Use ``package_upgrade`` instead. ++ # D3: Deprecated in version 22.2. Use ``package_reboot_if_required`` instead. + + Valid schema {cfg_file} + """ # noqa: E501 +@@ -2264,11 +2264,10 @@ class TestHandleSchemaArgs: + dedent( + """\ + Cloud config schema deprecations: \ +-apt_reboot_if_required: Default: ``false``. Deprecated in version 22.2.\ +- Use ``package_reboot_if_required`` instead., apt_update: Default: \ +-``false``. Deprecated in version 22.2. Use ``package_update`` instead.,\ +- apt_upgrade: Default: ``false``. Deprecated in version 22.2. Use \ +-``package_upgrade`` instead.\ ++apt_reboot_if_required: Deprecated in version 22.2. Use\ ++ ``package_reboot_if_required`` instead., apt_update: Deprecated in version\ ++ 22.2. Use ``package_update`` instead., apt_upgrade: Deprecated in version\ ++ 22.2. Use ``package_upgrade`` instead.\ + Valid schema {cfg_file} + """ # noqa: E501 + ), +-- +2.39.3 + diff --git a/SOURCES/ci-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-IPv6-ad.patch b/SOURCES/ci-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-IPv6-ad.patch new file mode 100644 index 0000000..615e767 --- /dev/null +++ b/SOURCES/ci-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-IPv6-ad.patch @@ -0,0 +1,185 @@ +From 9ee9fe608b906fe4e523cbf7fbe4539f0322ba2f Mon Sep 17 00:00:00 2001 +From: PengpengSun <40026211+PengpengSun@users.noreply.github.com> +Date: Thu, 4 Jul 2024 04:06:39 +0800 +Subject: [PATCH 2/2] fix(vmware): Set IPv6 to dhcp when there is no IPv6 addr + (#5471) + +RH-Author: xiachen +RH-MergeRequest: 99: fix(vmware): Set IPv6 to dhcp when there is no IPv6 addr (#5471) +RH-Jira: RHEL-46194 +RH-Acked-by: Ani Sinha +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Commit: [1/1] fbae24c7e7f48239200eaf457d260203fb550845 (xiachen/cloud-init-centos) + +When there is no IPv6 addr given in the customization configuration, +we shall set IPv6 type to dhcp6, then customized Linux network will be +set to dhcp IPv6 explicitly. + +(cherry picked from commit 2b6fe6403db769de14f7c7b7e4aa65f5bea8f3e0) +--- + .../sources/helpers/vmware/imc/config_nic.py | 2 +- + .../sources/vmware/test_vmware_config_file.py | 68 ++++++++++++++----- + 2 files changed, 52 insertions(+), 18 deletions(-) + +diff --git a/cloudinit/sources/helpers/vmware/imc/config_nic.py b/cloudinit/sources/helpers/vmware/imc/config_nic.py +index b07214a2..254518af 100644 +--- a/cloudinit/sources/helpers/vmware/imc/config_nic.py ++++ b/cloudinit/sources/helpers/vmware/imc/config_nic.py +@@ -207,7 +207,7 @@ class NicConfigurator: + """ + + if not nic.staticIpv6: +- return ([], []) ++ return ([{"type": "dhcp6"}], []) + + subnet_list = [] + # Static Ipv6 +diff --git a/tests/unittests/sources/vmware/test_vmware_config_file.py b/tests/unittests/sources/vmware/test_vmware_config_file.py +index b53ea96c..25d3b093 100644 +--- a/tests/unittests/sources/vmware/test_vmware_config_file.py ++++ b/tests/unittests/sources/vmware/test_vmware_config_file.py +@@ -240,27 +240,45 @@ class TestVmwareConfigFile(CiTestCase): + elif cfg.get("name") == nic2.get("name"): + nic2.update(cfg) + ++ # Test NIC1 + self.assertEqual("physical", nic1.get("type"), "type of NIC1") + self.assertEqual("NIC1", nic1.get("name"), "name of NIC1") + self.assertEqual( + "00:50:56:a6:8c:08", nic1.get("mac_address"), "mac address of NIC1" + ) + subnets = nic1.get("subnets") +- self.assertEqual(1, len(subnets), "number of subnets for NIC1") +- subnet = subnets[0] +- self.assertEqual("dhcp", subnet.get("type"), "DHCP type for NIC1") +- self.assertEqual("auto", subnet.get("control"), "NIC1 Control type") ++ self.assertEqual(2, len(subnets), "number of subnets for NIC1") ++ subnet_ipv4 = subnets[0] ++ self.assertEqual( ++ "dhcp", subnet_ipv4.get("type"), "Ipv4 DHCP type for NIC1" ++ ) ++ self.assertEqual( ++ "auto", subnet_ipv4.get("control"), "NIC1 Control type" ++ ) ++ subnet_ipv6 = subnets[1] ++ self.assertEqual( ++ "dhcp6", subnet_ipv6.get("type"), "Ipv6 DHCP type for NIC1" ++ ) + ++ # Test NIC2 + self.assertEqual("physical", nic2.get("type"), "type of NIC2") + self.assertEqual("NIC2", nic2.get("name"), "name of NIC2") + self.assertEqual( + "00:50:56:a6:5a:de", nic2.get("mac_address"), "mac address of NIC2" + ) + subnets = nic2.get("subnets") +- self.assertEqual(1, len(subnets), "number of subnets for NIC2") +- subnet = subnets[0] +- self.assertEqual("dhcp", subnet.get("type"), "DHCP type for NIC2") +- self.assertEqual("auto", subnet.get("control"), "NIC2 Control type") ++ self.assertEqual(2, len(subnets), "number of subnets for NIC2") ++ subnet_ipv4 = subnets[0] ++ self.assertEqual( ++ "dhcp", subnet_ipv4.get("type"), "Ipv4 DHCP type for NIC2" ++ ) ++ self.assertEqual( ++ "auto", subnet_ipv4.get("control"), "NIC2 Control type" ++ ) ++ subnet_ipv6 = subnets[1] ++ self.assertEqual( ++ "dhcp6", subnet_ipv6.get("type"), "Ipv6 DHCP type for NIC2" ++ ) + + def test_get_nics_list_static(self): + """Tests if NicConfigurator properly calculates network subnets +@@ -285,6 +303,7 @@ class TestVmwareConfigFile(CiTestCase): + elif cfg.get("name") == nic2.get("name"): + nic2.update(cfg) + ++ # Test NIC1 + self.assertEqual("physical", nic1.get("type"), "type of NIC1") + self.assertEqual("NIC1", nic1.get("name"), "name of NIC1") + self.assertEqual( +@@ -344,6 +363,7 @@ class TestVmwareConfigFile(CiTestCase): + else: + self.assertEqual(True, False, "invalid gateway %s" % (gateway)) + ++ # Test NIC2 + self.assertEqual("physical", nic2.get("type"), "type of NIC2") + self.assertEqual("NIC2", nic2.get("name"), "name of NIC2") + self.assertEqual( +@@ -351,16 +371,18 @@ class TestVmwareConfigFile(CiTestCase): + ) + + subnets = nic2.get("subnets") +- self.assertEqual(1, len(subnets), "Number of subnets for NIC2") ++ self.assertEqual(2, len(subnets), "Number of subnets for NIC2") + +- subnet = subnets[0] +- self.assertEqual("static", subnet.get("type"), "Subnet type") ++ subnet_ipv4 = subnets[0] ++ self.assertEqual("static", subnet_ipv4.get("type"), "Subnet type") + self.assertEqual( +- "192.168.6.102", subnet.get("address"), "Subnet address" ++ "192.168.6.102", subnet_ipv4.get("address"), "Subnet address" + ) + self.assertEqual( +- "255.255.0.0", subnet.get("netmask"), "Subnet netmask" ++ "255.255.0.0", subnet_ipv4.get("netmask"), "Subnet netmask" + ) ++ subnet_ipv6 = subnets[1] ++ self.assertEqual("dhcp6", subnet_ipv6.get("type"), "Subnet type") + + def test_custom_script(self): + cf = ConfigFile("tests/data/vmware/cust-dhcp-2nic.cfg") +@@ -447,7 +469,10 @@ class TestVmwareNetConfig(CiTestCase): + "type": "static", + "address": "10.20.87.154", + "netmask": "255.255.252.0", +- } ++ }, ++ { ++ "type": "dhcp6", ++ }, + ], + } + ], +@@ -498,7 +523,10 @@ class TestVmwareNetConfig(CiTestCase): + "metric": 10000, + } + ], +- } ++ }, ++ { ++ "type": "dhcp6", ++ }, + ], + } + ], +@@ -558,7 +586,10 @@ class TestVmwareNetConfig(CiTestCase): + "metric": 10000, + } + ], +- } ++ }, ++ { ++ "type": "dhcp6", ++ }, + ], + } + ], +@@ -603,7 +634,10 @@ class TestVmwareNetConfig(CiTestCase): + "address": "10.20.87.154", + "netmask": "255.255.252.0", + "gateway": "10.20.87.253", +- } ++ }, ++ { ++ "type": "dhcp6", ++ }, + ], + } + ], +-- +2.39.3 + diff --git a/SOURCES/ci-refactor-Ensure-internal-DNS-state-same-for-v1-and-v.patch b/SOURCES/ci-refactor-Ensure-internal-DNS-state-same-for-v1-and-v.patch new file mode 100644 index 0000000..cf33e50 --- /dev/null +++ b/SOURCES/ci-refactor-Ensure-internal-DNS-state-same-for-v1-and-v.patch @@ -0,0 +1,91 @@ +From 9a3c16dc89d2813c90df2e57e71ae5df704083be Mon Sep 17 00:00:00 2001 +From: James Falcon +Date: Tue, 9 Jan 2024 10:32:12 -0600 +Subject: [PATCH] refactor: Ensure internal DNS state same for v1 and v2 + (#4756) + +RH-Author: Ani Sinha +RH-MergeRequest: 152: refactor: Ensure internal DNS state same for v1 and v2 (#4756) +RH-Jira: RHEL-68409 +RH-Acked-by: xiachen +RH-Acked-by: Emanuele Giuseppe Esposito +RH-Commit: [1/1] f006996f7b418103ffaf73ff9ded5b5d149bedf6 + +When defining interface-level DNS on the network state, v1 uses the +"nameservers" key whereas v2 was using an "addresses" key. +This commit updates the v2 parsing to set the key as "nameservers". + +Also update networkd renderer as this was only renderer using the v2 +"addresses" key. + +(cherry picked from commit 436e6f5ce3fbb8b391a2158538873644058904e6) +Signed-off-by: Ani Sinha +--- + cloudinit/net/network_state.py | 2 +- + cloudinit/net/networkd.py | 13 ++++--------- + tests/unittests/net/test_network_state.py | 5 ++++- + 3 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/cloudinit/net/network_state.py b/cloudinit/net/network_state.py +index 226421bd0..82c3bf894 100644 +--- a/cloudinit/net/network_state.py ++++ b/cloudinit/net/network_state.py +@@ -336,7 +336,7 @@ class NetworkStateInterpreter: + if iface: + nameservers, search = dns + iface["dns"] = { +- "addresses": nameservers, ++ "nameservers": nameservers, + "search": search, + } + +diff --git a/cloudinit/net/networkd.py b/cloudinit/net/networkd.py +index 0978849c8..29f466eda 100644 +--- a/cloudinit/net/networkd.py ++++ b/cloudinit/net/networkd.py +@@ -221,12 +221,6 @@ class Renderer(renderer.Renderer): + def parse_dns(self, iface, cfg: CfgParser, ns: NetworkState): + sec = "Network" + +- dns_cfg_map = { +- "search": "Domains", +- "nameservers": "DNS", +- "addresses": "DNS", +- } +- + dns = iface.get("dns") + if not dns and ns.version == 1: + dns = { +@@ -236,9 +230,10 @@ class Renderer(renderer.Renderer): + elif not dns and ns.version == 2: + return + +- for k, v in dns_cfg_map.items(): +- if k in dns and dns[k]: +- cfg.update_section(sec, v, " ".join(dns[k])) ++ if dns.get("search"): ++ cfg.update_section(sec, "Domains", " ".join(dns["search"])) ++ if dns.get("nameservers"): ++ cfg.update_section(sec, "DNS", " ".join(dns["nameservers"])) + + def parse_dhcp_overrides(self, cfg: CfgParser, device, dhcp, version): + dhcp_config_maps = { +diff --git a/tests/unittests/net/test_network_state.py b/tests/unittests/net/test_network_state.py +index 7d304ca3a..74a6bb34c 100644 +--- a/tests/unittests/net/test_network_state.py ++++ b/tests/unittests/net/test_network_state.py +@@ -258,7 +258,10 @@ class TestNetworkStateParseNameservers: + # If an interface was specified, DNS should be part of the interface + for iface in config.iter_interfaces(): + if iface["name"] == "eth1": +- assert iface["dns"]["addresses"] == ["192.168.1.1", "8.8.8.8"] ++ assert iface["dns"]["nameservers"] == [ ++ "192.168.1.1", ++ "8.8.8.8", ++ ] + assert iface["dns"]["search"] == ["spam.local"] + else: + assert "dns" not in iface +-- +2.39.3 + diff --git a/SOURCES/ignore-enslaved-interface.patch b/SOURCES/ignore-enslaved-interface.patch new file mode 100644 index 0000000..cfefbe4 --- /dev/null +++ b/SOURCES/ignore-enslaved-interface.patch @@ -0,0 +1,44 @@ +From e7aba0f0ccd6f023667f41385f25044a94428ed3 Mon Sep 17 00:00:00 2001 +From: Darren Archibald +Date: Fri, 23 Feb 2024 05:56:06 -0800 +Subject: [PATCH] ignore enslaved interface + + Changes to ignore all enslaved interfaces. + https://jira.oci.oraclecorp.com/browse/LINUX-1947 + + Orabug: 30092148 + + Signed-off-by: Si-Wei Liu + Signed-off-by: Darren Archibald +--- + cloudinit/net/__init__.py | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py +index c0888f5..b093796 100644 +--- a/cloudinit/net/__init__.py ++++ b/cloudinit/net/__init__.py +@@ -335,6 +335,10 @@ def is_netfail_standby(devname, driver=None): + return True + + ++def is_slave(devname): ++ return os.path.exists(sys_dev_path(devname, "master")) ++ ++ + def is_renamed(devname): + """ + /* interface name assignment types (sysfs name_assign_type attribute) */ +@@ -1054,6 +1058,9 @@ def get_interfaces( + if is_bridge(name): + filtered_logger("Ignoring bridge interface: %s", name) + continue ++ if is_slave(name): ++ filtered_logger("Ignoring bridge interface: %s", name) ++ continue + if filter_vlan and is_vlan(name): + continue + if is_bond(name): +-- +2.31.1 + diff --git a/SOURCES/ol-sysconfig-add-Oracle-Linux-variant-to-known-distros.patch b/SOURCES/ol-sysconfig-add-Oracle-Linux-variant-to-known-distros.patch new file mode 100644 index 0000000..c8b89d8 --- /dev/null +++ b/SOURCES/ol-sysconfig-add-Oracle-Linux-variant-to-known-distros.patch @@ -0,0 +1,26 @@ +From 8735577c8a683407e94abed0cfccc3aacbb9aa47 Mon Sep 17 00:00:00 2001 +From: Si-Wei Liu +Date: Wed, 10 Jun 2020 20:59:29 -0400 +Subject: [PATCH] sysconfig: add Oracle Linux variant to known distros + +otherwise anything sysconfig breaks on Oracle Linux. + +JIRA: https://jira.oci.oraclecorp.com/browse/LINUX-6128 + +Signed-off-by: Si-Wei Liu +--- + cloudinit/net/sysconfig.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py +index e94590f..55b7db5 100644 +--- a/cloudinit/net/sysconfig.py ++++ b/cloudinit/net/sysconfig.py +@@ -35,6 +35,7 @@ + "suse", + "TencentOS", + "virtuozzo", ++ "ol", + ] + + diff --git a/SOURCES/orabug29956753-DataSourceOracle-_is_iscsi_root-not-working-with-dra.patch b/SOURCES/orabug29956753-DataSourceOracle-_is_iscsi_root-not-working-with-dra.patch new file mode 100644 index 0000000..4443391 --- /dev/null +++ b/SOURCES/orabug29956753-DataSourceOracle-_is_iscsi_root-not-working-with-dra.patch @@ -0,0 +1,81 @@ +From 8eff3fdfd9ed477bead953deec3599c93409a415 Mon Sep 17 00:00:00 2001 +From: Darren Archibald +Date: Fri, 23 Feb 2024 05:33:05 -0800 +Subject: [PATCH] DataSourceOracle: _is_iscsi_root() not working with dracut + based initramfs + +The _is_iscsi_root() implementation in Oracle datasource today only works +with initramfs-tools on Debian/Ubuntu systems, where initramfs-tools specific +files e.g. /run/net{,6}-*.conf are examined to identify initramfs initiated +network configuration. This partial implementation works with OCI Oracle +Linux (OL) images by chance as the "network-config=..." option in the boot +line happens to satisfy the corresponding network-config conditional +branch (which itself is insufficient in checking disabled network-config) in +cmdline.read_kernel_cmdline_config, and eventually renders _is_iscsi_root() +return true for OL images all across. Apparently this shouldn't be the +case for VM instance with PV boot. + +The fix involved is to identify dracut based initramfs config files for +network boot, and also ibft as how it does for initramfs-tools based +initramfs on Ubuntu. + +Orabug: 29956753 + +Signed-off-by: Si-Wei Liu +Signed-off-by: Darren Archibald +--- + cloudinit/sources/DataSourceOracle.py | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +diff --git a/cloudinit/sources/DataSourceOracle.py b/cloudinit/sources/DataSourceOracle.py +index 07247d7..afae393 100644 +--- a/cloudinit/sources/DataSourceOracle.py ++++ b/cloudinit/sources/DataSourceOracle.py +@@ -14,6 +14,8 @@ Notes: + """ + + import base64 ++import glob ++import os + import ipaddress + import logging + from collections import namedtuple +@@ -31,6 +33,11 @@ from cloudinit.url_helper import UrlError, readurl + + LOG = logging.getLogger(__name__) + ++DRACUT_TMP_PATH='/var/run/initramfs' ++DRACUT_OLDTMP_PATH='/dev/.initramfs' ++DRACUT_NET_IFACES='net.ifaces' ++DRACUT_IBFT_PATTERN='net.*.has_ibft_config' ++ + BUILTIN_DS_CONFIG = { + # Don't use IMDS to configure secondary NICs by default + "configure_secondary_nics": False, +@@ -200,9 +207,22 @@ class DataSourceOracle(sources.DataSource): + def get_public_ssh_keys(self): + return sources.normalize_pubkey_data(self.metadata.get("public_keys")) + ++ def _is_dracut_netconfig(): ++ for net_ifaces_path in ( ++ DRACUT_TMP_PATH + '/' + DRACUT_NET_IFACES, ++ DRACUT_OLDTMP_PATH + '/' + DRACUT_NET_IFACES): ++ if os.path.exists(net_ifaces_path): ++ return True ++ ++ if glob.glob(DRACUT_TMP_PATH + '/' + DRACUT_IBFT_PATTERN) + \ ++ glob.glob(DRACUT_OLDTMP_PATH + '/' + DRACUT_IBFT_PATTERN): ++ return True ++ ++ return False ++ + def _is_iscsi_root(self) -> bool: + """Return whether we are on a iscsi machine.""" +- return self._network_config_source.is_applicable() ++ return self._network_config_source.is_applicable() or _is_dracut_netconfig() + + def _get_iscsi_config(self) -> dict: + return self._network_config_source.render_config() +-- +2.31.1 + diff --git a/SOURCES/orabug30435672-003-cloud-init-collect-logs.patch b/SOURCES/orabug30435672-003-cloud-init-collect-logs.patch new file mode 100644 index 0000000..1ba0aad --- /dev/null +++ b/SOURCES/orabug30435672-003-cloud-init-collect-logs.patch @@ -0,0 +1,78 @@ +From 51cdd87ad861d5d47c212258bf00402a4dec2198 Mon Sep 17 00:00:00 2001 +From: Darren Archibald +Date: Fri, 23 Feb 2024 06:17:54 -0800 +Subject: [PATCH] Update cloud-init collect-logs for Oracle Linux + +Updating the code to collect triage logs with OL distro specic methods. + +Orabug: 30435672 + +Signed-off-by: Vijay Balakrishna +Reviewed-by: Si-Wei Liu +Acked-by: Joe Kennedy +Reviewed-by: Laurence Rochfort +--- + cloudinit/cmd/devel/logs.py | 26 ++++++++++++++++---------- + cloudinit/util.py | 1 + + 2 files changed, 17 insertions(+), 10 deletions(-) + +diff --git a/cloudinit/cmd/devel/logs.py b/cloudinit/cmd/devel/logs.py +index 8312218..85d976a 100755 +--- a/cloudinit/cmd/devel/logs.py ++++ b/cloudinit/cmd/devel/logs.py +@@ -19,7 +19,7 @@ from cloudinit.cmd.devel import read_cfg_paths + from cloudinit.helpers import Paths + from cloudinit.subp import ProcessExecutionError, subp + from cloudinit.temp_utils import tempdir +-from cloudinit.util import chdir, copy, ensure_dir, write_file ++from cloudinit.util import chdir, copy, ensure_dir, write_file, system_info + + CLOUDINIT_LOGS = ["/var/log/cloud-init.log", "/var/log/cloud-init-output.log"] + CLOUDINIT_RUN_DIR = "/run/cloud-init" +@@ -219,15 +219,21 @@ def collect_logs(tarfile, include_userdata: bool, verbosity=0): + msg="cloud-init --version", + verbosity=verbosity, + ) +- dpkg_ver = _write_command_output_to_file( +- cmd=["dpkg-query", "--show", "-f=${Version}\n", "cloud-init"], +- filename=os.path.join(log_dir, "dpkg-version"), +- msg="dpkg version", +- verbosity=verbosity, +- ) +- if not version: +- version = dpkg_ver if dpkg_ver else "not-available" +- print("version: ", version) ++ if system_info()['variant'] == "ol": ++ rpm_ver = _write_command_output_to_file( ++ ['rpm', '-q', '--queryformat', ++ "[%{VERSION}-%{RELEASE}.%{ARCH}]\n", 'cloud-init'], ++ os.path.join(log_dir, 'rpm-version'), ++ "rpm version", verbosity) ++ if not version: ++ version = rpm_ver if rpm_ver else "not-available" ++ else: ++ dpkg_ver = _write_command_output_to_file( ++ ['dpkg-query', '--show', "-f=${Version}\n", 'cloud-init'], ++ os.path.join(log_dir, 'dpkg-version'), ++ "dpkg version", verbosity) ++ if not version: ++ version = dpkg_ver if dpkg_ver else "not-available" + _debug("collected cloud-init version: %s\n" % version, 1, verbosity) + _stream_command_output_to_file( + cmd=["dmesg"], +diff --git a/cloudinit/util.py b/cloudinit/util.py +index 3295735..db7bb97 100644 +--- a/cloudinit/util.py ++++ b/cloudinit/util.py +@@ -660,6 +660,7 @@ def _get_variant(info): + "suse", + "tencentos", + "virtuozzo", ++ "ol", + ): + variant = linux_dist + elif linux_dist in ("ubuntu", "linuxmint", "mint"): +-- +2.31.1 + diff --git a/SOURCES/orabug30435672-004-ol-cloud-config.patch b/SOURCES/orabug30435672-004-ol-cloud-config.patch new file mode 100644 index 0000000..5958b77 --- /dev/null +++ b/SOURCES/orabug30435672-004-ol-cloud-config.patch @@ -0,0 +1,112 @@ +From 250aa45f74e29b95f81b24811c972369605bd24e Mon Sep 17 00:00:00 2001 +From: Vijay Balakrishna +Date: Tue, 5 Nov 2019 16:00:21 -0500 +Subject: [PATCH] Add static cloud.cfg file for OL7. + +Adding OL specific cloud.cfg file to enable updates cloud-init +config file independently, adding newly verified ntp module. + +Orabug: 30435672 + +Signed-off-by: Vijay Balakrishna +Signed-off-by: Si-Wei Liu +Acked-by: Joe Kennedy +Reviewed-by: Laurence Rochfort + +--- + ol/README.ol | 6 ++++++ + ol/cloud.cfg | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 75 insertions(+) + create mode 100644 ol/README.ol + create mode 100644 ol/cloud.cfg + +diff --git a/ol/README.ol b/ol/README.ol +new file mode 100644 +index 0000000..f59d559 +--- /dev/null ++++ b/ol/README.ol +@@ -0,0 +1,6 @@ ++The following cloud-init modules are currently unsupported on this OS: ++ - apt_update_upgrade ('apt_update', 'apt_upgrade', 'apt_mirror', 'apt_preserve_sources_list', 'apt_old_mirror', 'apt_sources', 'debconf_selections', 'packages' options) ++ - byobu ('byobu_by_default' option) ++ - chef ++ - grub_dpkg ++ - rh_subscription +diff --git a/ol/cloud.cfg b/ol/cloud.cfg +new file mode 100644 +index 0000000..2ee1fb3 +--- /dev/null ++++ b/ol/cloud.cfg +@@ -0,0 +1,69 @@ ++users: ++ - default ++ ++disable_root: 1 ++ssh_pwauth: 0 ++ ++mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2'] ++resize_rootfs_tmp: /dev ++ssh_deletekeys: 0 ++ssh_genkeytypes: ~ ++syslog_fix_perms: ~ ++disable_vmware_customization: false ++ ++cloud_init_modules: ++ - disk_setup ++ - migrator ++ - bootcmd ++ - write-files ++ - growpart ++ - resizefs ++ - set_hostname ++ - update_hostname ++ - update_etc_hosts ++ - rsyslog ++ - users-groups ++ - ssh ++ ++cloud_config_modules: ++ - mounts ++ - locale ++ - set-passwords ++ - ntp ++ - yum-add-repo ++ - package-update-upgrade-install ++ - timezone ++ - puppet ++ - chef ++ - salt-minion ++ - mcollective ++ - disable-ec2-metadata ++ - runcmd ++ ++cloud_final_modules: ++ - rightscale_userdata ++ - scripts-per-once ++ - scripts-per-boot ++ - scripts-per-instance ++ - scripts-user ++ - ssh-authkey-fingerprints ++ - keys-to-console ++ - phone-home ++ - final-message ++ - power-state-change ++ ++system_info: ++ default_user: ++ name: cloud-user ++ lock_passwd: true ++ gecos: Cloud User ++ groups: [adm, systemd-journal] ++ sudo: ["ALL=(ALL) NOPASSWD:ALL"] ++ shell: /bin/bash ++ distro: rhel ++ paths: ++ cloud_dir: /var/lib/cloud ++ templates_dir: /etc/cloud/templates ++ ssh_svcname: sshd ++ ++# vim:syntax=yaml +-- +1.8.3.1 + diff --git a/SOURCES/orabug30435672-006-cc_spacewalk.py.patch b/SOURCES/orabug30435672-006-cc_spacewalk.py.patch new file mode 100644 index 0000000..1feb434 --- /dev/null +++ b/SOURCES/orabug30435672-006-cc_spacewalk.py.patch @@ -0,0 +1,57 @@ +From 2b92e042bb8a4510abec38fcfc302d8de1e28f37 Mon Sep 17 00:00:00 2001 +From: Darren Archibald +Date: Fri, 23 Feb 2024 06:55:32 -0800 +Subject: [PATCH] spacewalk: fix CA cert file path for Oracle Linux + +Update the CA cert file that is available in Oracle Linux to register with ULN. + +Orabug: 30435672 + +Signed-off-by: Si-Wei Liu +Signed-off-by: Vijay Balakrishna +Acked-by: Joe Kennedy +Reviewed-by: Laurence Rochfort +Signed-off-by: Darren Archibald +--- + cloudinit/config/cc_spacewalk.py | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/cloudinit/config/cc_spacewalk.py b/cloudinit/config/cc_spacewalk.py +index 08514f2..7248cce 100644 +--- a/cloudinit/config/cc_spacewalk.py ++++ b/cloudinit/config/cc_spacewalk.py +@@ -4,7 +4,7 @@ + import logging + from textwrap import dedent + +-from cloudinit import subp ++from cloudinit import subp, util + from cloudinit.cloud import Cloud + from cloudinit.config import Config + from cloudinit.config.schema import MetaSchema, get_meta_doc +@@ -47,6 +47,7 @@ LOG = logging.getLogger(__name__) + distros = ["redhat", "fedora"] + required_packages = ["rhn-setup"] + def_ca_cert_path = "/usr/share/rhn/RHN-ORG-TRUSTED-SSL-CERT" ++ol_ca_cert_path = "/usr/share/rhn/ULN-CA-CERT" + + + def is_registered(): +@@ -100,9 +101,14 @@ def handle(name: str, cfg: Config, cloud: Cloud, args: list) -> None: + # Need to have this installed before further things will work. + cloud.distro.install_packages(required_packages) + if not is_registered(): ++ if util.system_info()['variant'] == "ol": ++ cert = ol_ca_cert_path ++ else: ++ cert = def_ca_cert_path + do_register( + spacewalk_server, + cloud.datasource.get_hostname(fqdn=True).hostname, ++ ca_cert_path=cert, + proxy=cfg.get("proxy"), + activation_key=cfg.get("activation_key"), + ) +-- +2.31.1 + diff --git a/SOURCES/orabug32183938-009-missing-sshd-services.patch b/SOURCES/orabug32183938-009-missing-sshd-services.patch new file mode 100644 index 0000000..4bacda5 --- /dev/null +++ b/SOURCES/orabug32183938-009-missing-sshd-services.patch @@ -0,0 +1,30 @@ +cloud-init service file is missing sshd required services +Orabug: 32183938 + +in the systemd sshd-keygen.target file, the following services are listed: +[Unit] +Wants=sshd-keygen@rsa.service +Wants=sshd-keygen@ecdsa.service +Wants=sshd-keygen@ed25519.service + +Need to add the following to the cloud-init service file: +Before=sshd-keygen@rsa.service +Before=sshd-keygen@ecdsa.service +Before=sshd-keygen@ed25519.service + +Signed-off-by: Isaac Chen + +diff -up cloud-init-19.4/systemd/cloud-init.service.tmpl.orig cloud-init-19.4/systemd/cloud-init.service.tmpl +--- cloud-init-19.4/systemd/cloud-init.service.tmpl.orig 2020-12-10 13:03:19.978023730 -0800 ++++ cloud-init-19.4/systemd/cloud-init.service.tmpl 2020-12-10 13:07:35.791879370 -0800 +@@ -21,7 +21,9 @@ After=wicked.service + After=dbus.service + {% endif %} + Before=network-online.target +-Before=sshd-keygen.service ++Before=sshd-keygen@rsa.service ++Before=sshd-keygen@ecdsa.service ++Before=sshd-keygen@ed25519.service + Before=sshd.service + {% if variant in ["ubuntu", "unknown", "debian"] %} + Before=sysinit.target diff --git a/SOURCES/orabug32183938-010-missing-sshd-services-in-rhel-systemd.patch b/SOURCES/orabug32183938-010-missing-sshd-services-in-rhel-systemd.patch new file mode 100644 index 0000000..7cb4fb0 --- /dev/null +++ b/SOURCES/orabug32183938-010-missing-sshd-services-in-rhel-systemd.patch @@ -0,0 +1,22 @@ +cloud-init service file is missing sshd required services +Orabug: 32183938 + +This patch is the supplement of patch orabug32183938-009, where changes +to cloud-init.service also need to be added to files in rhel/systemd. + +Signed-off-by: Isaac Chen + +diff -up cloud-init-19.4/systemd/cloud-init.service.tmpl.orig cloud-init-19.4/systemd/cloud-init.service.tmpl +--- cloud-init-19.4/systemd/cloud-init.service.tmpl.orig 2020-12-11 19:59:37.331277979 -0800 ++++ cloud-init-19.4/systemd/cloud-init.service.tmpl 2020-12-11 20:00:38.867459043 -0800 +@@ -5,7 +5,9 @@ + DefaultDependencies=no + {% endif %} + Wants=cloud-init-local.service +-Wants=sshd-keygen.service ++Wants=sshd-keygen@rsa.service ++Wants=sshd-keygen@ecdsa.service ++Wants=sshd-keygen@ed25519.service + Wants=sshd.service + After=cloud-init-local.service + After=systemd-networkd-wait-online.service diff --git a/SOURCES/orabug34845400-Add-Oracle-to-distro-detection-logic-in-cloud.cfg.tm.patch b/SOURCES/orabug34845400-Add-Oracle-to-distro-detection-logic-in-cloud.cfg.tm.patch new file mode 100644 index 0000000..8d56c9b --- /dev/null +++ b/SOURCES/orabug34845400-Add-Oracle-to-distro-detection-logic-in-cloud.cfg.tm.patch @@ -0,0 +1,354 @@ +From e921be03f802ee154ed1ddf044e276b23af0d2b6 Mon Sep 17 00:00:00 2001 +From: Darren Archibald +Date: Fri, 23 Feb 2024 07:52:25 -0800 +Subject: [PATCH] Add Oracle to distro detection logic in cloud.cfg.tmpl + +Oracle Linux is being detected as "ol" variant by cloud-init. +This patch adds "ol" to the list of supported variants, and applies needed settings to it. +You can notice that variant "ol" is being set as distro "rhel" in a couple of places, +that is expected as this designated that base distro for "ol" is "rhel" ( which is true ) + +The main reason for this change is that cloud-init package dropped hardcoded configs that set OL as rhel +and to make cloud-init behave on OL systems as expected we need to add "ol" designation to supported list. + +Orabug: 34845400 +Signed-off-by: Alex Burmashev +Signed-off-by: Darren Archibald +--- + cloudinit/distros/__init__.py | 1 + + cloudinit/sources/DataSourceRbxCloud.py | 2 +- + config/cloud.cfg.tmpl | 33 ++++++++++++++++++------- + systemd/cloud-config.service.tmpl | 4 +++ + systemd/cloud-final.service.tmpl | 4 ++- + systemd/cloud-init-local.service.tmpl | 12 ++++++--- + systemd/cloud-init.service.tmpl | 8 ++++-- + tests/unittests/test_util.py | 1 + + 8 files changed, 48 insertions(+), 17 deletions(-) + +diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py +index 79e2623..8f1381b 100644 +--- a/cloudinit/distros/__init__.py ++++ b/cloudinit/distros/__init__.py +@@ -78,6 +78,7 @@ OSFAMILIES = { + "rhel", + "rocky", + "virtuozzo", ++ "ol", + ], + "suse": [ + "opensuse", +diff --git a/cloudinit/sources/DataSourceRbxCloud.py b/cloudinit/sources/DataSourceRbxCloud.py +index 9214f1b..5379132 100644 +--- a/cloudinit/sources/DataSourceRbxCloud.py ++++ b/cloudinit/sources/DataSourceRbxCloud.py +@@ -60,7 +60,7 @@ def _sub_arp(cmd): + + def gratuitous_arp(items, distro): + source_param = "-S" +- if distro.name in ["fedora", "centos", "rhel"]: ++ if distro.name in ["fedora", "centos", "rhel", "ol"]: + source_param = "-s" + for item in items: + try: +diff --git a/config/cloud.cfg.tmpl b/config/cloud.cfg.tmpl +@@ -39,7 +39,7 @@ + - name: root + lock_passwd: false + {% else %} +- - default ++ - default + {% endif %} + + {% if variant == "photon" %} +@@ -58,9 +58,9 @@ + {% endif %} + + {%- if variant in ["alpine", "amazon", "fedora", "OpenCloudOS", "openeuler", +- "openmandriva", "photon", "TencentOS"] or is_rhel %} ++ "openmandriva", "photon", "TencentOS", "ol"] or is_rhel %} + +-{% if is_rhel %} ++{% if variant in ["ol"] or is_rhel %} + mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service,_netdev', '0', '2'] + {% else %} + mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2'] +@@ -101,7 +101,7 @@ + + {% endif -%} + +-{% if is_rhel %} ++{% if variant in ["ol"] or is_rhel %} + # Default redhat settings: + ssh_deletekeys: true + ssh_genkeytypes: ['rsa', 'ecdsa', 'ed25519'] +@@ -149,9 +149,9 @@ + {% if variant == "ubuntu" %} + - ubuntu_autoinstall + {% endif %} +-{% if variant not in ["photon"] %} ++{% if variant not in ["photon", "ol"] %} + - ssh_import_id +-{% if not is_rhel %} ++{% if variant not in ["ol"] or is_rhel %} + - keyboard + {% endif %} + - locale +@@ -167,18 +167,20 @@ + - ubuntu_advantage + {% endif %} + {% elif variant in ["fedora", "mariner", "openeuler", "openmandriva", +- "photon"] or is_rhel %} ++ "photon", "ol"] or is_rhel %} + {% if is_rhel %} + - rh_subscription + {% endif %} +-{% if variant not in ["mariner", "photon"] %} ++{% if variant not in ["mariner", "photon", "ol"] %} + - spacewalk + {% endif %} + - yum_add_repo + {% elif variant == "suse" %} + - zypper_add_repo + {% endif %} ++{% if variant not in ["ol"] %} + - ntp ++{% endif %} + - timezone + - disable_ec2_metadata + - runcmd +@@ -197,13 +199,17 @@ + {% if variant in ["ubuntu", "unknown"] %} + - ubuntu_drivers + {% endif %} ++{% if variant not in ["ol"] %} + - write_files_deferred ++{% endif %} + - puppet + - chef + - ansible + - mcollective + - salt_minion ++{% if variant not in ["ol"] %} + - reset_rmc ++{% endif %} + - rightscale_userdata + - scripts_vendor + - scripts_per_once +@@ -212,7 +218,9 @@ + - scripts_user + - ssh_authkey_fingerprints + - keys_to_console ++{% if variant not in ["ol"] %} + - install_hotplug ++{% endif %} + - phone_home + - final_message + - power_state_change +@@ -224,8 +232,10 @@ + {% if variant in ["alpine", "amazon", "arch", "debian", "fedora", "freebsd", + "gentoo", "mariner", "netbsd", "openbsd", "OpenCloudOS", + "openeuler", "openmandriva", "photon", "suse", "TencentOS", +- "ubuntu"] or is_rhel %} ++ "ubuntu", "centos", "rhel"] %} + distro: {{ variant }} ++{% elif variant == "ol" %} ++ distro: rhel + {% elif variant == "dragonfly" %} + distro: dragonflybsd + {% else %} +@@ -234,7 +244,9 @@ + {% endif %} + # Default user name + that default users groups (if added/used) + default_user: +-{% if variant in usernames %} ++{% if variant == "ol" %} ++ name: cloud-user ++{% elif variant in usernames %} + name: {{ usernames[variant] }} + {% else %} + name: {{ variant }} +@@ -245,7 +257,12 @@ + or is_bsd or is_rhel %} + lock_passwd: True + {% endif %} +-{% if variant in gecos %} ++{% if variant == "ol" %} ++ lock_passwd: true ++{% endif %} ++{% if variant == "ol" %} ++ gecos: Cloud User ++{% elif variant in gecos %} + gecos: {{ gecos[variant] }} + {% else %} + gecos: {{ variant }} Cloud User +@@ -254,7 +271,7 @@ + groups: [{{ groups[variant] }}] + {% elif is_bsd %} + groups: [wheel] +-{% elif is_rhel %} ++{% elif variant in ["ol"] or is_rhel %} + groups: [adm, systemd-journal] + {% else %} + groups: [wheel, adm, systemd-journal] +@@ -321,7 +338,7 @@ + {% endif %} + {% if variant in ["alpine", "amazon", "arch", "debian", "fedora", "gentoo", + "mariner", "OpenCloudOS", "openeuler", "openmandriva", +- "photon", "suse", "TencentOS", "ubuntu", "unknown"] ++ "photon", "suse", "TencentOS", "ubuntu", "unknown", "ol"] + or is_rhel %} + # Other config here will be given to the distro class and/or path classes + paths: +@@ -365,6 +382,6 @@ + ssh_svcname: ssh + {% elif variant in ["alpine", "amazon", "arch", "fedora", "gentoo", + "mariner", "OpenCloudOS", "openeuler", "openmandriva", +- "photon", "suse", "TencentOS"] or is_rhel %} ++ "photon", "suse", "TencentOS", "ol"] or is_rhel %} + ssh_svcname: sshd + {% endif %} +diff --git a/systemd/cloud-config.service.tmpl b/systemd/cloud-config.service.tmpl +index 31d9d98..8222c7c 100644 +--- a/systemd/cloud-config.service.tmpl ++++ b/systemd/cloud-config.service.tmpl +@@ -2,11 +2,15 @@ + [Unit] + Description=Apply the settings specified in cloud-config + After=network-online.target cloud-config.target ++{% if variant not in "ol" %} + After=snapd.seeded.service ++{% endif %} + Before=systemd-user-sessions.service + Wants=network-online.target cloud-config.target ++{% if variant in ["rhel", "ol"] %} + ConditionPathExists=!/etc/cloud/cloud-init.disabled + ConditionKernelCommandLine=!cloud-init=disabled ++{% endif %} + ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled + + [Service] +diff --git a/systemd/cloud-final.service.tmpl b/systemd/cloud-final.service.tmpl +index bcf8b00..f84c687 100644 +--- a/systemd/cloud-final.service.tmpl ++++ b/systemd/cloud-final.service.tmpl +@@ -7,8 +7,10 @@ After=multi-user.target + Before=apt-daily.service + {% endif %} + Wants=network-online.target cloud-config.service ++{% if variant in ["rhel", "ol"] %} + ConditionPathExists=!/etc/cloud/cloud-init.disabled + ConditionKernelCommandLine=!cloud-init=disabled ++{% endif %} + ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled + + +@@ -18,7 +20,7 @@ ExecStart=/usr/bin/cloud-init modules --mode=final + RemainAfterExit=yes + TimeoutSec=0 + KillMode=process +-{% if variant == "rhel" %} ++{% if variant in ["rhel", "ol"] %} + # Restart NetworkManager if it is present and running. + ExecStartPost=/bin/sh -c 'u=NetworkManager.service; \ + out=$(systemctl show --property=SubState $u) || exit; \ +diff --git a/systemd/cloud-init-local.service.tmpl b/systemd/cloud-init-local.service.tmpl +index 3a1ca7f..4750c36 100644 +--- a/systemd/cloud-init-local.service.tmpl ++++ b/systemd/cloud-init-local.service.tmpl +@@ -1,23 +1,25 @@ + ## template:jinja + [Unit] + Description=Initial cloud-init job (pre-networking) +-{% if variant in ["ubuntu", "unknown", "debian", "rhel" ] %} ++{% if variant in ["ubuntu", "unknown", "debian", "rhel", "ol" ] %} + DefaultDependencies=no + {% endif %} + Wants=network-pre.target ++{% if variant not in ["ol"] %} + After=hv_kvp_daemon.service ++{% endif %} + After=systemd-remount-fs.service +-{% if variant == "rhel" %} ++{% if variant in ["rhel", "ol"] %} + Requires=dbus.socket + After=dbus.socket + {% endif %} + Before=NetworkManager.service +-{% if variant == "rhel" %} ++{% if variant in ["rhel", "ol"] %} + Before=network.service + {% endif %} + Before=network-pre.target + Before=shutdown.target +-{% if variant == "rhel" %} ++{% if variant in ["rhel", "ol"] %} + Before=firewalld.target + Conflicts=shutdown.target + {% endif %} +@@ -26,8 +28,10 @@ Before=sysinit.target + Conflicts=shutdown.target + {% endif %} + RequiresMountsFor=/var/lib/cloud ++{% if variant in ["rhel", "ol"] %} + ConditionPathExists=!/etc/cloud/cloud-init.disabled + ConditionKernelCommandLine=!cloud-init=disabled ++{% endif %} + ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled + + [Service] +diff --git a/systemd/cloud-init.service.tmpl b/systemd/cloud-init.service.tmpl +index 90d45f2..2e1ce48 100644 +--- a/systemd/cloud-init.service.tmpl ++++ b/systemd/cloud-init.service.tmpl +@@ -1,7 +1,7 @@ + ## template:jinja + [Unit] + Description=Initial cloud-init job (metadata service crawler) +-{% if variant not in ["photon", "rhel"] %} ++{% if variant not in ["photon", "rhel", "ol"] %} + DefaultDependencies=no + {% endif %} + Wants=cloud-init-local.service +@@ -10,13 +10,15 @@ Wants=sshd-keygen@ecdsa.service + Wants=sshd-keygen@ed25519.service + Wants=sshd.service + After=cloud-init-local.service ++{% if variant not in ["ol"] %} + After=systemd-networkd-wait-online.service ++{% endif %} + {% if variant in ["ubuntu", "unknown", "debian"] %} + After=networking.service + {% endif %} + {% if variant in ["almalinux", "centos", "cloudlinux", "eurolinux", "fedora", + "miraclelinux", "openeuler", "OpenCloudOS", "openmandriva", "rhel", "rocky", +- "suse", "TencentOS", "virtuozzo"] %} ++ "suse", "TencentOS", "virtuozzo", "ol"] %} + + After=network.service + After=NetworkManager.service +@@ -42,8 +44,10 @@ Conflicts=shutdown.target + Before=shutdown.target + Conflicts=shutdown.target + {% endif %} ++{% if variant in ["rhel", "ol"] %} + ConditionPathExists=!/etc/cloud/cloud-init.disabled + ConditionKernelCommandLine=!cloud-init=disabled ++{% endif %} + ConditionEnvironment=!KERNEL_CMDLINE=cloud-init=disabled + + [Service] +diff --git a/tests/unittests/test_util.py b/tests/unittests/test_util.py +index 519ef63..323e7f6 100644 +--- a/tests/unittests/test_util.py ++++ b/tests/unittests/test_util.py +@@ -1311,6 +1311,7 @@ class TestGetVariant: + ({"system": "linux", "dist": ("sles",)}, "suse"), + ({"system": "linux", "dist": ("sle_hpc",)}, "suse"), + ({"system": "linux", "dist": ("my_distro",)}, "linux"), ++ ({"system": "linux", "dist": ("ol",)}, "ol"), + ({"system": "Windows", "dist": ("dontcare",)}, "windows"), + ({"system": "Darwin", "dist": ("dontcare",)}, "darwin"), + ({"system": "Freebsd", "dist": ("dontcare",)}, "freebsd"), +-- +2.31.1 + diff --git a/SOURCES/orabug35329883-Increase-retry-value-and-add-timeout-for-OCI.patch b/SOURCES/orabug35329883-Increase-retry-value-and-add-timeout-for-OCI.patch new file mode 100644 index 0000000..099a8cc --- /dev/null +++ b/SOURCES/orabug35329883-Increase-retry-value-and-add-timeout-for-OCI.patch @@ -0,0 +1,30 @@ +From ae1b843c7ab8b173ef2ffd9ea02842d1d4455e64 Mon Sep 17 00:00:00 2001 +From: Alexander Burmashev +Date: Fri, 5 May 2023 03:15:06 -0700 +Subject: [PATCH] Increase retry value and add timeout for OCI + +To be sure there are no failures, and accomodate to current behaviour on some supoported shapes it is needed to set +increased values for retries and timeout. + +Orabug: 35329883 + +Signed-off-by: Alex Burmashev +--- + cloudinit/sources/DataSourceOracle.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/cloudinit/sources/DataSourceOracle.py b/cloudinit/sources/DataSourceOracle.py +--- a/cloudinit/sources/DataSourceOracle.py 2023-10-03 22:09:18.480515323 +0000 ++++ b/cloudinit/sources/DataSourceOracle.py 2023-10-03 22:21:31.155006874 +0000 +@@ -364,11 +364,12 @@ + return asset_tag == CHASSIS_ASSET_TAG + + +-def _fetch(metadata_version: int, path: str, retries: int = 2) -> dict: ++def _fetch(metadata_version: int, path: str, retries: int = 9) -> dict: + return readurl( + url=METADATA_PATTERN.format(version=metadata_version, path=path), + headers=V2_HEADERS if metadata_version > 1 else None, + retries=retries, ++ timeout=20, + )._response.json() diff --git a/SOURCES/orabug35950168-DataSourceOracle-network-getdata-updates.patch b/SOURCES/orabug35950168-DataSourceOracle-network-getdata-updates.patch new file mode 100644 index 0000000..b540576 --- /dev/null +++ b/SOURCES/orabug35950168-DataSourceOracle-network-getdata-updates.patch @@ -0,0 +1,140 @@ +From 6a81b1e0970f37246276009c844baca860f3f913 Mon Sep 17 00:00:00 2001 +From: Darren Archibald +Date: Fri, 23 Feb 2024 08:04:44 -0800 +Subject: [PATCH] DataSourceOracle network getdata updates + +Orabug: 35950168 + +Signed-off-by: Darren Archibald +--- + cloudinit/sources/DataSourceOracle.py | 78 +++++++++++++-------------- + 1 file changed, 39 insertions(+), 39 deletions(-) + +diff -git a/cloudinit/sources/DataSourceOracle.py b/cloudinit/sources/DataSourceOracle.py +--- a/cloudinit/sources/DataSourceOracle.py 2024-04-03 15:54:08.713716247 -0700 ++++ b/cloudinit/sources/DataSourceOracle.py 2024-04-03 15:53:35.426718593 -0700 +@@ -20,6 +20,7 @@ + import logging + from collections import namedtuple + from typing import Optional, Tuple ++from contextlib import suppress as noop + + from cloudinit import atomic_helper, dmi, net, sources, util + from cloudinit.distros.networking import NetworkConfig +@@ -37,6 +38,7 @@ + DRACUT_OLDTMP_PATH='/dev/.initramfs' + DRACUT_NET_IFACES='net.ifaces' + DRACUT_IBFT_PATTERN='net.*.has_ibft_config' ++ISCSI_IBFT_PATH='/sys/firmware/acpi/tables/iBFT' + + BUILTIN_DS_CONFIG = { + # Don't use IMDS to configure secondary NICs by default +@@ -129,7 +131,7 @@ + sources.NetworkConfigSource.INITRAMFS, + ) + +- _network_config: dict = {"config": [], "version": 1} ++ _network_config = sources.UNSET + + def __init__(self, sys_cfg, *args, **kwargs): + super(DataSourceOracle, self).__init__(sys_cfg, *args, **kwargs) +@@ -155,14 +157,16 @@ + + self.system_uuid = _read_system_uuid() + +- network_context = ephemeral.EphemeralDHCPv4( +- self.distro, +- iface=net.find_fallback_nic(), +- connectivity_url_data={ +- "url": METADATA_PATTERN.format(version=2, path="instance"), +- "headers": V2_HEADERS, +- }, +- ) ++ network_context = noop() ++ if not self._is_iscsi_root(): ++ network_context = ephemeral.EphemeralDHCPv4( ++ self.distro, ++ iface=net.find_fallback_nic(), ++ connectivity_url_data={ ++ "url": METADATA_PATTERN.format(version=2, path="instance"), ++ "headers": V2_HEADERS, ++ }, ++ ) + fetch_primary_nic = not self._is_iscsi_root() + fetch_secondary_nics = self.ds_cfg.get( + "configure_secondary_nics", +@@ -222,7 +226,7 @@ + + def _is_iscsi_root(self) -> bool: + """Return whether we are on a iscsi machine.""" +- return self._network_config_source.is_applicable() or _is_dracut_netconfig() ++ return self._network_config_source.is_applicable() or bool(os.path.exists(ISCSI_IBFT_PATH)) + + def _get_iscsi_config(self) -> dict: + return self._network_config_source.render_config() +@@ -237,39 +241,36 @@ + + If none is present, then we fall back to fallback configuration. + """ +- if self._has_network_config(): +- return self._network_config +- + set_primary = False +- # this is v1 +- if self._is_iscsi_root(): +- self._network_config = self._get_iscsi_config() +- if not self._has_network_config(): +- LOG.warning( +- "Could not obtain network configuration from initramfs. " +- "Falling back to IMDS." +- ) +- set_primary = True + +- set_secondary = self.ds_cfg.get( +- "configure_secondary_nics", +- BUILTIN_DS_CONFIG["configure_secondary_nics"], +- ) +- if set_primary or set_secondary: +- try: +- # Mutate self._network_config to include primary and/or +- # secondary VNICs +- self._add_network_config_from_opc_imds(set_primary) +- except Exception: +- util.logexc( +- LOG, +- "Failed to parse IMDS network configuration!", ++ if self._network_config == sources.UNSET: ++ # this is v1 ++ self._network_config = cmdline.read_initramfs_config() ++ ++ if not self._network_config: ++ self._network_config = self.distro.generate_fallback_config() ++ set_primary = True ++ ++ set_secondary = self.ds_cfg.get( ++ "configure_secondary_nics", ++ BUILTIN_DS_CONFIG["configure_secondary_nics"], + ) + +- # we need to verify that the nic selected is not a netfail over +- # device and, if it is a netfail master, then we need to avoid +- # emitting any match by mac +- _ensure_netfailover_safe(self._network_config) ++ if set_primary or set_secondary: ++ try: ++ # Mutate self._network_config to include primary and/or ++ # secondary VNICs ++ self._add_network_config_from_opc_imds(set_primary) ++ except Exception: ++ util.logexc( ++ LOG, ++ "Failed to parse IMDS network configuration!", ++ ) ++ ++ # we need to verify that the nic selected is not a netfail over ++ # device and, if it is a netfail master, then we need to avoid ++ # emitting any match by mac ++ _ensure_netfailover_safe(self._network_config) + + return self._network_config + diff --git a/SPECS/cloud-init.spec b/SPECS/cloud-init.spec index 26dc8fa..1fd8287 100644 --- a/SPECS/cloud-init.spec +++ b/SPECS/cloud-init.spec @@ -1,43 +1,103 @@ -Name: cloud-init -Version: 23.4 -Release: 7%{?dist}.5 -Summary: Cloud instance init scripts -License: ASL 2.0 or GPLv3 -URL: http://launchpad.net/cloud-init -Source0: https://github.com/canonical/cloud-init/archive/refs/tags/%{version}.tar.gz -Source1: cloud-init-tmpfiles.conf +Name: cloud-init +Version: 23.4 +Release: 19.0.2%{?dist}.5 +Summary: Cloud instance init scripts +License: ASL 2.0 or GPLv3 +URL: http://launchpad.net/cloud-init +Source0: https://github.com/canonical/cloud-init/archive/refs/tags/%{version}.tar.gz +Source1: cloud-init-tmpfiles.conf # Source-git patches -Patch1: 0001-Add-initial-redhat-changes.patch -Patch2: 0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch -Patch3: 0003-Setting-autoconnect-priority-setting-for-network-scr.patch -Patch4: 0004-net-network_manager-do-not-set-may-fail-to-False-for.patch -Patch5: 0005-net-allow-dhcp6-configuration-from-generate_fallback.patch -Patch6: 0006-net-nm-check-for-presence-of-ifcfg-files-when-nm-con.patch -Patch7: 0007-test-jsonschema-Pin-jsonschema-version-4781.patch -Patch8: 0008-fix-clean-stop-warning-when-running-clean-command-47.patch +Patch1: 0001-Add-initial-redhat-changes.patch +Patch2: 0002-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch +Patch3: 0003-Setting-autoconnect-priority-setting-for-network-scr.patch +Patch4: 0004-net-network_manager-do-not-set-may-fail-to-False-for.patch +Patch5: 0005-net-allow-dhcp6-configuration-from-generate_fallback.patch +Patch6: 0006-net-nm-check-for-presence-of-ifcfg-files-when-nm-con.patch +Patch7: 0007-test-jsonschema-Pin-jsonschema-version-4781.patch +Patch8: 0008-fix-clean-stop-warning-when-running-clean-command-47.patch # For RHEL-22255 - [Azure][RHEL-9] cloud-init-23.4 cannot read "- Azure" datasource_list format -Patch9: ci-Revert-Use-grep-for-faster-parsing-of-cloud-config-i.patch -Patch10: ci-Pin-pythes-8.0.0.patch +Patch9: ci-Revert-Use-grep-for-faster-parsing-of-cloud-config-i.patch +Patch10: ci-Pin-pythes-8.0.0.patch # For RHEL-21324 - [rhel-9] The schema WARNING info for network-config.json is not suitable in cloud-init-23.4 -Patch11: ci-fix-Add-types-to-network-v1-schema-4841.patch +Patch11: ci-fix-Add-types-to-network-v1-schema-4841.patch # For RHEL-28549 - [RHEL 9.4] cloud-init 23.4 returns 2 on recoverable errors instead of 0 -Patch12: ci-Retain-exit-code-in-cloud-init-status-for-recoverabl.patch +Patch12: ci-Retain-exit-code-in-cloud-init-status-for-recoverabl.patch # For RHEL-20964 - [rhel-9]cloud-init fails to configure DNS/search domains for network-config v1 -Patch13: ci-fix-Correct-v2-NetworkManager-route-rendering-4637.patch +Patch13: ci-fix-Correct-v2-NetworkManager-route-rendering-4637.patch # For RHEL-20964 - [rhel-9]cloud-init fails to configure DNS/search domains for network-config v1 -Patch14: ci-feat-apply-global-DNS-to-interfaces-in-network-manag.patch +Patch14: ci-feat-apply-global-DNS-to-interfaces-in-network-manag.patch # For RHEL-29709 - Suggest to backport patch ff40d1a to undeprecate 'network' in schema route definition -Patch15: ci-fix-Undeprecate-network-in-schema-route-definition-5.patch +Patch15: ci-fix-Undeprecate-network-in-schema-route-definition-5.patch # For RHEL-32846 - [cloud-init][ESXi]VMware datasource resets on every boot causing it to lose network configuration [rhel-9] -Patch16: ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch +Patch16: ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch # For RHEL-36255 - [rhel-9.5] DataSourceNoCloudNet not configurable via config files -Patch17: ci-fix-Always-use-single-datasource-if-specified-5098.patch +Patch17: ci-fix-Always-use-single-datasource-if-specified-5098.patch # For RHEL-40217 - [Cloud-init] CloudstackDataSource cannot work with NetworkManager -Patch18: ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch +Patch18: ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch # For RHEL-17961 - [RHEL-9] cloud-init fails to configure DNS search domains -Patch19: ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch +Patch19: ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch +# For RHEL-44337 - [rhel-9] fix `SUDO` configuration schema for users and groups +Patch20: ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch +# For RHEL-44337 - [rhel-9] fix `SUDO` configuration schema for users and groups +Patch21: ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch +# For RHEL-44598 - fix pylint error and support python 3.12 +Patch22: ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch +# For RHEL-44598 - fix pylint error and support python 3.12 +Patch23: ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch +# For RHEL-44598 - fix pylint error and support python 3.12 +Patch24: ci-Update-pylint-version-to-support-python-3.12-5338.patch +# For RHEL-45262 - Deprecate the users ssh-authorized-keys property and permit deprecated hyphenated keys under users key +Patch25: ci-Deprecate-the-users-ssh-authorized-keys-property-516.patch +# For RHEL-45262 - Deprecate the users ssh-authorized-keys property and permit deprecated hyphenated keys under users key +Patch26: ci-docs-Add-deprecated-system_info-to-schema-5168.patch +# For RHEL-45262 - Deprecate the users ssh-authorized-keys property and permit deprecated hyphenated keys under users key +Patch27: ci-fix-schema-permit-deprecated-hyphenated-keys-under-u.patch +# For RHEL-44916 - [RFE] Support metalink in yum repository config +Patch28: ci-Support-metalink-in-yum-repository-config-5444.patch +# For RHEL-46194 - [RHEL-9] It leaves the ipv6 networking config as blank in NM keyfile when config dhcp ipv6 with customization spec +Patch29: ci-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-IPv6-ad.patch +# For RHEL-46873 - Suggest to update schema to support metalink +Patch30: ci-fix-add-schema-rules-for-baseurl-and-metalink-in-yum.patch +# For RHEL-49736 - [Cloud-init] [RHEL-9] Password reset feature broken with CloudstackDataSource +Patch31: ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch +# For RHEL-49674 - Support setting mirrorlist in yum repository config +Patch32: ci-Support-setting-mirrorlist-in-yum-repository-config-.patch +# For RHEL-54373 - [RHEL9]Revert "fix(vmware): Set IPv6 to dhcp when there is no IPv6 addr (#5471)" +Patch33: ci-Revert-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-.patch +# For RHEL-54686 - [RHEL-9.5] cloud-init schema validation fails. +Patch34: ci-fix-Add-subnet-ipv4-ipv6-to-network-schema-5191.patch +# For RHEL-65018 - Configuring metric for default gateway is not working [rhel-9.5.z] +Patch35: ci-Fix-metric-setting-for-ifcfg-network-connections-for.patch +# For RHEL-65018 - Configuring metric for default gateway is not working [rhel-9.5.z] +Patch36: ci-fix-python3.13-Fix-import-error-for-passlib-on-Pytho.patch +# For RHEL-65021 - NoCloud - network_config bridges incorrectly configured [rhel-9.5.z] +Patch37: ci-fix-Render-bridges-correctly-for-v2-on-sysconfig-wit.patch +# For RHEL-65021 - NoCloud - network_config bridges incorrectly configured [rhel-9.5.z] +Patch38: ci-fix-Render-v2-bridges-correctly-on-network-manager-w.patch +# For RHEL-65778 - [RHEL-9] Prevent NM from handling DNS when network interfaces have DNS config [rhel-9.5.z] +Patch39: ci-Prevent-NM-from-handling-DNS-when-network-interfaces.patch +# For RHEL-68409 - cloud-init fails to configure DNS and search domain [rhel-9.5.z] +Patch40: ci-refactor-Ensure-internal-DNS-state-same-for-v1-and-v.patch +# For RHEL-79774 - [RHEL 9] Backport support for smbios datasource definition [rhel-9.5.z] +Patch41: ci-fix-nocloud-smbios-datasource-definition.patch +Patch100: 0041-enable-ec2_utils-to-stop-retrying-to-get-ec2-metadata.patch +Patch101: orabug29956753-DataSourceOracle-_is_iscsi_root-not-working-with-dra.patch +Patch102: ignore-enslaved-interface.patch +Patch103: ol-sysconfig-add-Oracle-Linux-variant-to-known-distros.patch +Patch104: 0106-tests-unittests-add-a-new-unit-test-for-network-mana.patch + +# Oracle patches +Patch1001: orabug30435672-003-cloud-init-collect-logs.patch +Patch1002: orabug30435672-004-ol-cloud-config.patch +Patch1003: orabug30435672-006-cc_spacewalk.py.patch +Patch1005: orabug32183938-009-missing-sshd-services.patch +Patch1006: orabug32183938-010-missing-sshd-services-in-rhel-systemd.patch +Patch1007: orabug34845400-Add-Oracle-to-distro-detection-logic-in-cloud.cfg.tm.patch +Patch1008: orabug35329883-Increase-retry-value-and-add-timeout-for-OCI.patch +Patch1009: orabug35950168-DataSourceOracle-network-getdata-updates.patch +Patch1010: 1010-orabug36958039-Removes-condition-specific-to-OL-for-write_files_def.patch BuildArch: noarch @@ -47,48 +107,46 @@ BuildRequires: python3-setuptools BuildRequires: systemd # For tests -BuildRequires: iproute -BuildRequires: python3-configobj +BuildRequires: iproute +BuildRequires: python3-configobj # https://bugzilla.redhat.com/show_bug.cgi?id=1695953 -BuildRequires: python3-distro -# https://bugzilla.redhat.com/show_bug.cgi?id=1417029 -BuildRequires: python3-httpretty >= 0.8.14-2 -BuildRequires: python3-jinja2 -BuildRequires: python3-jsonpatch -BuildRequires: python3-oauthlib -BuildRequires: python3-prettytable -BuildRequires: python3-pyserial -BuildRequires: python3-PyYAML -BuildRequires: python3-requests -BuildRequires: python3-six +BuildRequires: python3-distro +BuildRequires: python3-jinja2 +BuildRequires: python3-jsonpatch +BuildRequires: python3-oauthlib +BuildRequires: python3-prettytable +BuildRequires: python3-pyserial +BuildRequires: python3-PyYAML +BuildRequires: python3-requests +BuildRequires: python3-six # dnf is needed to make cc_ntp unit tests work # https://bugs.launchpad.net/cloud-init/+bug/1721573 -BuildRequires: /usr/bin/dnf +BuildRequires: /usr/bin/dnf -Requires: e2fsprogs -Requires: iproute -Requires: libselinux-python3 -Requires: policycoreutils-python3 -Requires: procps -Requires: python3-configobj +Requires: e2fsprogs +Requires: iproute +Requires: libselinux-python3 +Requires: policycoreutils-python3 +Requires: procps +Requires: python3-configobj # https://bugzilla.redhat.com/show_bug.cgi?id=1695953 -Requires: python3-distro -Requires: python3-jinja2 -Requires: python3-jsonpatch -Requires: python3-oauthlib -Requires: python3-prettytable -Requires: python3-pyserial -Requires: python3-PyYAML -Requires: python3-requests -Requires: python3-six -Requires: shadow-utils -Requires: util-linux -Requires: xfsprogs -Requires: dhcp-client +Requires: python3-distro +Requires: python3-jinja2 +Requires: python3-jsonpatch +Requires: python3-oauthlib +Requires: python3-prettytable +Requires: python3-pyserial +Requires: python3-PyYAML +Requires: python3-requests +Requires: python3-six +Requires: shadow-utils +Requires: util-linux +Requires: xfsprogs +Requires: dhcp-client # https://bugzilla.redhat.com/show_bug.cgi?id=2032524 -Requires: gdisk -Requires: openssl -Requires: python3-netifaces +Requires: gdisk +Requires: openssl +Requires: python3-netifaces %{?systemd_requires} @@ -254,23 +312,130 @@ fi %config(noreplace) %{_sysconfdir}/rsyslog.d/21-cloudinit.conf %changelog -* Mon Jun 17 2024 Miroslav Rezanina - 23.4-7.5 +* Tue Mar 18 2025 Darren Archibald - 23.4-19.0.2.el9_5.5 +- Fixes regression in cloud-init-23.4-19.0.1 with module cc_write_files_deferred [Orabug: 36958039] +- NetworkManagerActivator brings up interface failed when using sysconfig renderer [RHEL-18981] +- Fix Oracle Datasource network and getdata methods for OCI OL [Orabug: 35950168] +- Increase retry value and add timeout for OCI [Orabug: 35329883] +- Fix log file permission [Orabug: 35302969] +- Update detection logic for OL distros in config template [Orabug: 34845400] +- Added missing services in rhel/systemd/cloud-init.service [Orabug: 32183938] +- Added missing services in cloud-init.service.tmpl for sshd [Orabug: 32183938] +- Forward port applicable cloud-init 18.4-2.0.3 changes to cloud-init-18-5 [Orabug: 30435672] +- limit permissions [Orabug: 31352433] +- Changes to ignore all enslaved interfaces [Orabug: 30092148] +- Make Oracle datasource detect dracut based config files [Orabug: 29956753] +- add modified version of enable-ec2_utils-to-stop-retrying-to-get-ec2-metadata.patch: + 1. Enable ec2_utils.py having a way to stop retrying to get ec2 metadata + 2. Apply stop retrying to get ec2 metadata to helper/openstack.py MetadataReader + Resolves: Oracle-Bug:41660 (Bugzilla) +- added OL to list of known distros +Resolves: rhbz#1427280 +Resolves: rhbz#1427280 + +* Tue Mar 18 2025 Release Engineering - 23.4.0.2 +- Apply OpenELA fixes + +* Mon Feb 24 2025 Jon Maloy - 23.4-19.el9_5.5 +- ci-fix-nocloud-smbios-datasource-definition.patch [RHEL-79774] +- Resolves: RHEL-79774 + ([RHEL 9] Backport support for smbios datasource definition [rhel-9.5.z]) + +* Wed Nov 27 2024 Miroslav Rezanina - 23.4-19.el9_5.4 +- ci-refactor-Ensure-internal-DNS-state-same-for-v1-and-v.patch [RHEL-68409] +- Resolves: RHEL-68409 + (cloud-init fails to configure DNS and search domain [rhel-9.5.z]) + +* Mon Nov 18 2024 Miroslav Rezanina - 23.4-19.el9_5.3 +- ci-Prevent-NM-from-handling-DNS-when-network-interfaces.patch [RHEL-65778] +- Resolves: RHEL-65778 + ([RHEL-9] Prevent NM from handling DNS when network interfaces have DNS config [rhel-9.5.z]) + +* Wed Nov 06 2024 Miroslav Rezanina - 23.4-19.el9_5.2 +- ci-fix-Render-bridges-correctly-for-v2-on-sysconfig-wit.patch [RHEL-65021] +- ci-fix-Render-v2-bridges-correctly-on-network-manager-w.patch [RHEL-65021] +- Resolves: RHEL-65021 + (NoCloud - network_config bridges incorrectly configured [rhel-9.5.z]) + +* Thu Oct 31 2024 Miroslav Rezanina - 23.4-19.el9_5.1 +- ci-Fix-metric-setting-for-ifcfg-network-connections-for.patch [RHEL-65018] +- ci-fix-python3.13-Fix-import-error-for-passlib-on-Pytho.patch [RHEL-65018] +- Resolves: RHEL-65018 + (Configuring metric for default gateway is not working [rhel-9.5.z]) + +* Mon Aug 26 2024 Miroslav Rezanina - 23.4-19 +- ci-fix-Add-subnet-ipv4-ipv6-to-network-schema-5191.patch [RHEL-54686] +- Resolves: RHEL-54686 + ([RHEL-9.5] cloud-init schema validation fails.) + +* Mon Aug 19 2024 Miroslav Rezanina - 23.4-18 +- ci-Revert-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-.patch [RHEL-54373] +- Resolves: RHEL-54373 + ([RHEL9]Revert "fix(vmware): Set IPv6 to dhcp when there is no IPv6 addr (#5471)") + +* Thu Jul 25 2024 Miroslav Rezanina - 23.4-17 +- ci-fix-Clean-cache-if-no-datasource-fallback-5499.patch [RHEL-49736] +- ci-Support-setting-mirrorlist-in-yum-repository-config-.patch [RHEL-49674] +- Resolves: RHEL-49736 + ([Cloud-init] [RHEL-9] Password reset feature broken with CloudstackDataSource) +- Resolves: RHEL-49674 + (Support setting mirrorlist in yum repository config) + +* Fri Jul 12 2024 Miroslav Rezanina - 23.4-16 +- ci-fix-add-schema-rules-for-baseurl-and-metalink-in-yum.patch [RHEL-46873] +- Resolves: RHEL-46873 + (Suggest to update schema to support metalink) + +* Mon Jul 08 2024 Miroslav Rezanina - 23.4-15 +- ci-Support-metalink-in-yum-repository-config-5444.patch [RHEL-44916] +- ci-fix-vmware-Set-IPv6-to-dhcp-when-there-is-no-IPv6-ad.patch [RHEL-46194] +- Resolves: RHEL-44916 + ([RFE] Support metalink in yum repository config) +- Resolves: RHEL-46194 + ([RHEL-9] It leaves the ipv6 networking config as blank in NM keyfile when config dhcp ipv6 with customization spec) + +* Mon Jul 01 2024 Miroslav Rezanina - 23.4-14 +- ci-Deprecate-the-users-ssh-authorized-keys-property-516.patch [RHEL-45262] +- ci-docs-Add-deprecated-system_info-to-schema-5168.patch [RHEL-45262] +- ci-fix-schema-permit-deprecated-hyphenated-keys-under-u.patch [RHEL-45262] +- Resolves: RHEL-45262 + (Deprecate the users ssh-authorized-keys property and permit deprecated hyphenated keys under users key) + +* Tue Jun 25 2024 Miroslav Rezanina - 23.4-13 +- ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch [RHEL-17961] +- ci-fix-jsonschema-Add-missing-sudo-definition-5418.patch [RHEL-44337] +- ci-doc-update-examples-to-reflect-alternative-ways-to-p.patch [RHEL-44337] +- ci-fix-dhcp-Guard-against-FileNotFoundError-and-NameErr.patch [RHEL-44598] +- ci-fix-Address-TIOBE-abstract-interpretation-issues-486.patch [RHEL-44598] +- ci-Update-pylint-version-to-support-python-3.12-5338.patch [RHEL-44598] +- Resolves: RHEL-17961 + ([RHEL-9] cloud-init fails to configure DNS search domains) +- Resolves: RHEL-44337 + ([rhel-9] fix `SUDO` configuration schema for users and groups) +- Resolves: RHEL-44598 + (fix pylint error and support python 3.12) + +* Mon Jun 17 2024 Miroslav Rezanina - 23.4-12 - ci-fix-cloudstack-Use-parsed-lease-file-for-virtual-rou.patch [RHEL-40217] - Resolves: RHEL-40217 ([Cloud-init] CloudstackDataSource cannot work with NetworkManager) -- ci-feat-sysconfig-Add-DNS-from-interface-config-to-reso.patch [RHEL-17961] -* Thu May 16 2024 Miroslav Rezanina - 23.4-7.3 +* Thu May 16 2024 Miroslav Rezanina - 23.4-11 - ci-fix-Always-use-single-datasource-if-specified-5098.patch [RHEL-36255] - Resolves: RHEL-36255 ([rhel-9.5] DataSourceNoCloudNet not configurable via config files) -* Mon Apr 22 2024 Miroslav Rezanina - 23.4-7.2 +* Mon Apr 29 2024 Miroslav Rezanina - 23.4-10 +- ci-Remove-dependency-on-python3-httpretty.patch [RHEL-33973] +- Resolves: RHEL-33973 + ([RFE] Remove dependency on python3-httpretty) + +* Mon Apr 22 2024 Miroslav Rezanina - 23.4-9 - ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch [RHEL-32846] - Resolves: RHEL-32846 ([cloud-init][ESXi]VMware datasource resets on every boot causing it to lose network configuration [rhel-9]) -* Mon Apr 08 2024 Miroslav Rezanina - 23.4-7.1 +* Mon Apr 08 2024 Miroslav Rezanina - 23.4-8 - ci-fix-Correct-v2-NetworkManager-route-rendering-4637.patch [RHEL-20964] - ci-feat-apply-global-DNS-to-interfaces-in-network-manag.patch [RHEL-20964] - ci-fix-Undeprecate-network-in-schema-route-definition-5.patch [RHEL-29709] @@ -692,7 +857,7 @@ fi * Thu Apr 13 2017 Charalampos Stratakis 0.7.9-4 - Import to RHEL 7 -Resolves: rhbz#1427280 +Resolves: rhbz#1427280 * Tue Mar 07 2017 Lars Kellogg-Stedman 0.7.9-3 - fixes for network config generation