From 8cf7edf88b717868d1bd874adf81755650984c8a Mon Sep 17 00:00:00 2001 From: Miroslav Rezanina Date: Mon, 29 Apr 2024 03:29:13 -0400 Subject: [PATCH] * Mon Apr 29 2024 Miroslav Rezanina - 24.1.4-3 - ci-Fix-spec-file-post-install-script.patch [RHEL-33954] - ci-refactor-remove-dependency-on-netifaces-4634.patch [RHEL-34518] - ci-DS-VMware-Fix-ipv6-addr-converter-from-netinfo-to-ne.patch [RHEL-34518] - Resolves: RHEL-33954 ([RHEL-10] There is error message during cloud-init installation) - Resolves: RHEL-34518 (Remove dependency to netifcaces) --- ...v6-addr-converter-from-netinfo-to-ne.patch | 176 ++++++ ...-remove-dependency-on-netifaces-4634.patch | 544 ++++++++++++++++++ cloud-init.spec | 16 +- 3 files changed, 735 insertions(+), 1 deletion(-) create mode 100644 ci-DS-VMware-Fix-ipv6-addr-converter-from-netinfo-to-ne.patch create mode 100644 ci-refactor-remove-dependency-on-netifaces-4634.patch diff --git a/ci-DS-VMware-Fix-ipv6-addr-converter-from-netinfo-to-ne.patch b/ci-DS-VMware-Fix-ipv6-addr-converter-from-netinfo-to-ne.patch new file mode 100644 index 0000000..0e8c29e --- /dev/null +++ b/ci-DS-VMware-Fix-ipv6-addr-converter-from-netinfo-to-ne.patch @@ -0,0 +1,176 @@ +From 86930b77ad18aa8dbad8908ddad8852447db0242 Mon Sep 17 00:00:00 2001 +From: PengpengSun <40026211+PengpengSun@users.noreply.github.com> +Date: Tue, 12 Mar 2024 09:26:55 +0800 +Subject: [PATCH 3/3] DS VMware: Fix ipv6 addr converter from netinfo to + netifaces (#5029) + +RH-Author: Ani Sinha +RH-MergeRequest: 80: refactor: remove dependency on netifaces (#4634) +RH-Jira: RHEL-34518 +RH-Acked-by: xiachen +RH-Acked-by: Cathy Avery +RH-Commit: [2/2] d718522dec4c77dd153fb239d2d0a6bd9ef581a2 (anisinha/cloud-init) + +Found an issue when verifying PR 4634 on vSphere platform, +which is failing to convert ipv6 addr from netinfo format to +netifaces format due to 'bcast' is not existing in ipv6. + +This PR is fixing this by updating ipv4 converter function and +adding a new ipv6 converter function, also adding unit tests. + +(cherry picked from commit e544a0db82caee17ee19465f8689ce02e564286f) +Signed-off-by: Ani Sinha +--- + cloudinit/sources/DataSourceVMware.py | 45 ++++++++++++++++++++------ + tests/unittests/sources/test_vmware.py | 33 +++++++++++++++++++ + 2 files changed, 68 insertions(+), 10 deletions(-) + +diff --git a/cloudinit/sources/DataSourceVMware.py b/cloudinit/sources/DataSourceVMware.py +index 6ed6a6a5..888060c9 100644 +--- a/cloudinit/sources/DataSourceVMware.py ++++ b/cloudinit/sources/DataSourceVMware.py +@@ -859,19 +859,18 @@ def is_valid_ip_addr(val): + ) + + +-def convert_to_netifaces_format(addr): ++def convert_to_netifaces_ipv4_format(addr: dict) -> dict: + """ + Takes a cloudinit.netinfo formatted address and converts to netifaces + format, since this module was originally written with netifaces as the + network introspection module. +- netifaces format: ++ netifaces ipv4 format: + { + "broadcast": "10.15.255.255", + "netmask": "255.240.0.0", + "addr": "10.0.1.4" + } +- +- cloudinit.netinfo format: ++ cloudinit.netinfo ipv4 format: + { + "ip": "10.0.1.4", + "mask": "255.240.0.0", +@@ -879,10 +878,37 @@ def convert_to_netifaces_format(addr): + "scope": "global", + } + """ ++ if not addr.get("ip"): ++ return {} ++ return { ++ "broadcast": addr.get("bcast"), ++ "netmask": addr.get("mask"), ++ "addr": addr.get("ip"), ++ } ++ ++ ++def convert_to_netifaces_ipv6_format(addr: dict) -> dict: ++ """ ++ Takes a cloudinit.netinfo formatted address and converts to netifaces ++ format, since this module was originally written with netifaces as the ++ network introspection module. ++ netifaces ipv6 format: ++ { ++ "netmask": "ffff:ffff:ffff:ffff::/64", ++ "addr": "2001:db8:abcd:1234::1" ++ } ++ cloudinit.netinfo ipv6 format: ++ { ++ "ip": "2001:db8:abcd:1234::1/64", ++ "scope6": "global", ++ } ++ """ ++ if not addr.get("ip"): ++ return {} ++ ipv6 = ipaddress.IPv6Interface(addr.get("ip")) + return { +- "broadcast": addr["bcast"], +- "netmask": addr["mask"], +- "addr": addr["ip"], ++ "netmask": f"{ipv6.netmask}/{ipv6.network.prefixlen}", ++ "addr": str(ipv6.ip), + } + + +@@ -890,7 +916,6 @@ def get_host_info(): + """ + Returns host information such as the host name and network interfaces. + """ +- # TODO(look to promote netifices use up in cloud-init netinfo funcs) + host_info = { + "network": { + "interfaces": { +@@ -921,9 +946,9 @@ def get_host_info(): + af_inet4 = [] + af_inet6 = [] + for addr in ifaces[dev_name]["ipv4"]: +- af_inet4.append(convert_to_netifaces_format(addr)) ++ af_inet4.append(convert_to_netifaces_ipv4_format(addr)) + for addr in ifaces[dev_name]["ipv6"]: +- af_inet6.append(convert_to_netifaces_format(addr)) ++ af_inet6.append(convert_to_netifaces_ipv6_format(addr)) + + mac = ifaces[dev_name].get("hwaddr") + +diff --git a/tests/unittests/sources/test_vmware.py b/tests/unittests/sources/test_vmware.py +index 33193f89..cfeff6d5 100644 +--- a/tests/unittests/sources/test_vmware.py ++++ b/tests/unittests/sources/test_vmware.py +@@ -77,6 +77,11 @@ VMW_IPV4_NETDEV_ADDR = { + "mask": "255.255.255.0", + "scope": "global", + } ++VMW_IPV4_NETIFACES_ADDR = { ++ "broadcast": "10.85.130.255", ++ "netmask": "255.255.255.0", ++ "addr": "10.85.130.116", ++} + VMW_IPV6_ROUTEINFO = { + "destination": "::/0", + "flags": "UG", +@@ -88,6 +93,18 @@ VMW_IPV6_NETDEV_ADDR = { + "ip": "fd42:baa2:3dd:17a:216:3eff:fe16:db54/64", + "scope6": "global", + } ++VMW_IPV6_NETIFACES_ADDR = { ++ "netmask": "ffff:ffff:ffff:ffff::/64", ++ "addr": "fd42:baa2:3dd:17a:216:3eff:fe16:db54", ++} ++VMW_IPV6_NETDEV_PEER_ADDR = { ++ "ip": "fd42:baa2:3dd:17a:216:3eff:fe16:db54", ++ "scope6": "global", ++} ++VMW_IPV6_NETIFACES_PEER_ADDR = { ++ "netmask": "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/128", ++ "addr": "fd42:baa2:3dd:17a:216:3eff:fe16:db54", ++} + + + def generate_test_netdev_data(ipv4=None, ipv6=None): +@@ -147,6 +164,22 @@ class TestDataSourceVMware(CiTestCase): + ret = ds.get_data() + self.assertFalse(ret) + ++ def test_convert_to_netifaces_ipv4_format(self): ++ netifaces_format = DataSourceVMware.convert_to_netifaces_ipv4_format( ++ VMW_IPV4_NETDEV_ADDR ++ ) ++ self.assertEqual(netifaces_format, VMW_IPV4_NETIFACES_ADDR) ++ ++ def test_convert_to_netifaces_ipv6_format(self): ++ netifaces_format = DataSourceVMware.convert_to_netifaces_ipv6_format( ++ VMW_IPV6_NETDEV_ADDR ++ ) ++ self.assertEqual(netifaces_format, VMW_IPV6_NETIFACES_ADDR) ++ netifaces_format = DataSourceVMware.convert_to_netifaces_ipv6_format( ++ VMW_IPV6_NETDEV_PEER_ADDR ++ ) ++ self.assertEqual(netifaces_format, VMW_IPV6_NETIFACES_PEER_ADDR) ++ + @mock.patch("cloudinit.sources.DataSourceVMware.get_default_ip_addrs") + def test_get_host_info_ipv4(self, m_fn_ipaddr): + m_fn_ipaddr.return_value = ("10.10.10.1", None) +-- +2.39.3 + diff --git a/ci-refactor-remove-dependency-on-netifaces-4634.patch b/ci-refactor-remove-dependency-on-netifaces-4634.patch new file mode 100644 index 0000000..d59fb4e --- /dev/null +++ b/ci-refactor-remove-dependency-on-netifaces-4634.patch @@ -0,0 +1,544 @@ +From d5c2095abb4d22fc976ed3011679134c75bead99 Mon Sep 17 00:00:00 2001 +From: Cat Red +Date: Mon, 4 Mar 2024 21:38:14 -0500 +Subject: [PATCH 2/3] refactor: remove dependency on netifaces (#4634) + +RH-Author: Ani Sinha +RH-MergeRequest: 80: refactor: remove dependency on netifaces (#4634) +RH-Jira: RHEL-34518 +RH-Acked-by: xiachen +RH-Acked-by: Cathy Avery +RH-Commit: [1/2] e55e7a588301234f62dfaf36080fb5f95aa52b2f (anisinha/cloud-init) + +Upstream netifaces is no longer being maintained and is only +used by the VMWare data source. As such this commit +replaces the calls to netifaces with cloudinit's native netinfo. + +(cherry picked from commit 2ba7fdf0e1eb0bc597ceac8903695f67571fd873) +Signed-off-by: Ani Sinha +--- + cloudinit/sources/DataSourceVMware.py | 207 ++++++++++--------------- + pyproject.toml | 1 - + requirements.txt | 9 -- + tests/unittests/sources/test_vmware.py | 161 ++++++++++++++++++- + tools/build-on-netbsd | 1 - + tools/build-on-openbsd | 1 - + tox.ini | 1 - + 7 files changed, 239 insertions(+), 142 deletions(-) + +diff --git a/cloudinit/sources/DataSourceVMware.py b/cloudinit/sources/DataSourceVMware.py +index 2a91a307..6ed6a6a5 100644 +--- a/cloudinit/sources/DataSourceVMware.py ++++ b/cloudinit/sources/DataSourceVMware.py +@@ -16,51 +16,6 @@ multiple transports types, including: + * EnvVars + * GuestInfo + * IMC (Guest Customization) +- +-Netifaces (https://github.com/al45tair/netifaces) +- +- Please note this module relies on the netifaces project to introspect the +- runtime, network configuration of the host on which this datasource is +- running. This is in contrast to the rest of cloud-init which uses the +- cloudinit/netinfo module. +- +- The reasons for using netifaces include: +- +- * Netifaces is built in C and is more portable across multiple systems +- and more deterministic than shell exec'ing local network commands and +- parsing their output. +- +- * Netifaces provides a stable way to determine the view of the host's +- network after DHCP has brought the network online. Unlike most other +- datasources, this datasource still provides support for JINJA queries +- based on networking information even when the network is based on a +- DHCP lease. While this does not tie this datasource directly to +- netifaces, it does mean the ability to consistently obtain the +- correct information is paramount. +- +- * It is currently possible to execute this datasource on macOS +- (which many developers use today) to print the output of the +- get_host_info function. This function calls netifaces to obtain +- the same runtime network configuration that the datasource would +- persist to the local system's instance data. +- +- However, the netinfo module fails on macOS. The result is either a +- hung operation that requires a SIGINT to return control to the user, +- or, if brew is used to install iproute2mac, the ip commands are used +- but produce output the netinfo module is unable to parse. +- +- While macOS is not a target of cloud-init, this feature is quite +- useful when working on this datasource. +- +- For more information about this behavior, please see the following +- PR comment, https://bit.ly/3fG7OVh. +- +- The authors of this datasource are not opposed to moving away from +- netifaces. The goal may be to eventually do just that. This proviso was +- added to the top of this module as a way to remind future-us and others +- why netifaces was used in the first place in order to either smooth the +- transition away from netifaces or embrace it further up the cloud-init +- stack. + """ + + import collections +@@ -72,9 +27,7 @@ import os + import socket + import time + +-import netifaces +- +-from cloudinit import atomic_helper, dmi, log, net, sources, util ++from cloudinit import atomic_helper, dmi, log, net, netinfo, sources, util + from cloudinit.sources.helpers.vmware.imc import guestcust_util + from cloudinit.subp import ProcessExecutionError, subp, which + +@@ -814,91 +767,64 @@ def get_default_ip_addrs(): + addresses associated with the device used by the default route for a given + address. + """ +- # TODO(promote and use netifaces in cloudinit.net* modules) +- gateways = netifaces.gateways() +- if "default" not in gateways: +- return None, None +- +- default_gw = gateways["default"] +- if ( +- netifaces.AF_INET not in default_gw +- and netifaces.AF_INET6 not in default_gw +- ): +- return None, None + ++ # Get ipv4 and ipv6 interfaces associated with default routes ++ ipv4_if = None ++ ipv6_if = None ++ routes = netinfo.route_info() ++ for route in routes["ipv4"]: ++ if route["destination"] == "0.0.0.0": ++ ipv4_if = route["iface"] ++ break ++ for route in routes["ipv6"]: ++ if route["destination"] == "::/0": ++ ipv6_if = route["iface"] ++ break ++ ++ # Get ip address associated with default interface + ipv4 = None + ipv6 = None +- +- gw4 = default_gw.get(netifaces.AF_INET) +- if gw4: +- _, dev4 = gw4 +- addr4_fams = netifaces.ifaddresses(dev4) +- if addr4_fams: +- af_inet4 = addr4_fams.get(netifaces.AF_INET) +- if af_inet4: +- if len(af_inet4) > 1: +- LOG.debug( +- "device %s has more than one ipv4 address: %s", +- dev4, +- af_inet4, +- ) +- elif "addr" in af_inet4[0]: +- ipv4 = af_inet4[0]["addr"] +- +- # Try to get the default IPv6 address by first seeing if there is a default +- # IPv6 route. +- gw6 = default_gw.get(netifaces.AF_INET6) +- if gw6: +- _, dev6 = gw6 +- addr6_fams = netifaces.ifaddresses(dev6) +- if addr6_fams: +- af_inet6 = addr6_fams.get(netifaces.AF_INET6) +- if af_inet6: +- if len(af_inet6) > 1: +- LOG.debug( +- "device %s has more than one ipv6 address: %s", +- dev6, +- af_inet6, +- ) +- elif "addr" in af_inet6[0]: +- ipv6 = af_inet6[0]["addr"] ++ netdev = netinfo.netdev_info() ++ if ipv4_if in netdev: ++ addrs = netdev[ipv4_if]["ipv4"] ++ if len(addrs) > 1: ++ LOG.debug( ++ "device %s has more than one ipv4 address: %s", ipv4_if, addrs ++ ) ++ elif len(addrs) == 1 and "ip" in addrs[0]: ++ ipv4 = addrs[0]["ip"] ++ if ipv6_if in netdev: ++ addrs = netdev[ipv6_if]["ipv6"] ++ if len(addrs) > 1: ++ LOG.debug( ++ "device %s has more than one ipv6 address: %s", ipv6_if, addrs ++ ) ++ elif len(addrs) == 1 and "ip" in addrs[0]: ++ ipv6 = addrs[0]["ip"] + + # If there is a default IPv4 address but not IPv6, then see if there is a + # single IPv6 address associated with the same device associated with the + # default IPv4 address. +- if ipv4 and not ipv6: +- af_inet6 = addr4_fams.get(netifaces.AF_INET6) +- if af_inet6: +- if len(af_inet6) > 1: +- LOG.debug( +- "device %s has more than one ipv6 address: %s", +- dev4, +- af_inet6, +- ) +- elif "addr" in af_inet6[0]: +- ipv6 = af_inet6[0]["addr"] ++ if ipv4 is not None and ipv6 is None: ++ for dev_name in netdev: ++ for addr in netdev[dev_name]["ipv4"]: ++ if addr["ip"] == ipv4 and len(netdev[dev_name]["ipv6"]) == 1: ++ ipv6 = netdev[dev_name]["ipv6"][0]["ip"] ++ break + + # If there is a default IPv6 address but not IPv4, then see if there is a + # single IPv4 address associated with the same device associated with the + # default IPv6 address. +- if not ipv4 and ipv6: +- af_inet4 = addr6_fams.get(netifaces.AF_INET) +- if af_inet4: +- if len(af_inet4) > 1: +- LOG.debug( +- "device %s has more than one ipv4 address: %s", +- dev6, +- af_inet4, +- ) +- elif "addr" in af_inet4[0]: +- ipv4 = af_inet4[0]["addr"] ++ if ipv4 is None and ipv6 is not None: ++ for dev_name in netdev: ++ for addr in netdev[dev_name]["ipv6"]: ++ if addr["ip"] == ipv6 and len(netdev[dev_name]["ipv4"]) == 1: ++ ipv4 = netdev[dev_name]["ipv4"][0]["ip"] ++ break + + return ipv4, ipv6 + + +-# patched socket.getfqdn() - see https://bugs.python.org/issue5004 +- +- + def getfqdn(name=""): + """Get fully qualified domain name from name. + An empty argument is interpreted as meaning the local host. +@@ -933,6 +859,33 @@ def is_valid_ip_addr(val): + ) + + ++def convert_to_netifaces_format(addr): ++ """ ++ Takes a cloudinit.netinfo formatted address and converts to netifaces ++ format, since this module was originally written with netifaces as the ++ network introspection module. ++ netifaces format: ++ { ++ "broadcast": "10.15.255.255", ++ "netmask": "255.240.0.0", ++ "addr": "10.0.1.4" ++ } ++ ++ cloudinit.netinfo format: ++ { ++ "ip": "10.0.1.4", ++ "mask": "255.240.0.0", ++ "bcast": "10.15.255.255", ++ "scope": "global", ++ } ++ """ ++ return { ++ "broadcast": addr["bcast"], ++ "netmask": addr["mask"], ++ "addr": addr["ip"], ++ } ++ ++ + def get_host_info(): + """ + Returns host information such as the host name and network interfaces. +@@ -963,16 +916,16 @@ def get_host_info(): + by_ipv4 = host_info["network"]["interfaces"]["by-ipv4"] + by_ipv6 = host_info["network"]["interfaces"]["by-ipv6"] + +- ifaces = netifaces.interfaces() ++ ifaces = netinfo.netdev_info() + for dev_name in ifaces: +- addr_fams = netifaces.ifaddresses(dev_name) +- af_link = addr_fams.get(netifaces.AF_LINK) +- af_inet4 = addr_fams.get(netifaces.AF_INET) +- af_inet6 = addr_fams.get(netifaces.AF_INET6) +- +- mac = None +- if af_link and "addr" in af_link[0]: +- mac = af_link[0]["addr"] ++ af_inet4 = [] ++ af_inet6 = [] ++ for addr in ifaces[dev_name]["ipv4"]: ++ af_inet4.append(convert_to_netifaces_format(addr)) ++ for addr in ifaces[dev_name]["ipv6"]: ++ af_inet6.append(convert_to_netifaces_format(addr)) ++ ++ mac = ifaces[dev_name].get("hwaddr") + + # Do not bother recording localhost + if mac == "00:00:00:00:00:00": +diff --git a/pyproject.toml b/pyproject.toml +index 99854f39..6f8ccdd1 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -28,7 +28,6 @@ module = [ + "debconf", + "httplib", + "jsonpatch", +- "netifaces", + "paramiko.*", + "pip.*", + "pycloudlib.*", +diff --git a/requirements.txt b/requirements.txt +index edec46a7..eabd7a22 100644 +--- a/requirements.txt ++++ b/requirements.txt +@@ -29,12 +29,3 @@ jsonpatch + + # For validating cloud-config sections per schema definitions + jsonschema +- +-# Used by DataSourceVMware to inspect the host's network configuration during +-# the "setup()" function. +-# +-# This allows a host that uses DHCP to bring up the network during BootLocal +-# and still participate in instance-data by gathering the network in detail at +-# runtime and merge that information into the metadata and repersist that to +-# disk. +-netifaces>=0.10.4 +diff --git a/tests/unittests/sources/test_vmware.py b/tests/unittests/sources/test_vmware.py +index 585f4fbd..33193f89 100644 +--- a/tests/unittests/sources/test_vmware.py ++++ b/tests/unittests/sources/test_vmware.py +@@ -63,6 +63,45 @@ runcmd: + - echo "Hello, world." + """ + ++VMW_IPV4_ROUTEINFO = { ++ "destination": "0.0.0.0", ++ "flags": "G", ++ "gateway": "10.85.130.1", ++ "genmask": "0.0.0.0", ++ "iface": "eth0", ++ "metric": "50", ++} ++VMW_IPV4_NETDEV_ADDR = { ++ "bcast": "10.85.130.255", ++ "ip": "10.85.130.116", ++ "mask": "255.255.255.0", ++ "scope": "global", ++} ++VMW_IPV6_ROUTEINFO = { ++ "destination": "::/0", ++ "flags": "UG", ++ "gateway": "2001:67c:1562:8007::1", ++ "iface": "eth0", ++ "metric": "50", ++} ++VMW_IPV6_NETDEV_ADDR = { ++ "ip": "fd42:baa2:3dd:17a:216:3eff:fe16:db54/64", ++ "scope6": "global", ++} ++ ++ ++def generate_test_netdev_data(ipv4=None, ipv6=None): ++ ipv4 = ipv4 or [] ++ ipv6 = ipv6 or [] ++ return { ++ "eth0": { ++ "hwaddr": "00:16:3e:16:db:54", ++ "ipv4": ipv4, ++ "ipv6": ipv6, ++ "up": True, ++ }, ++ } ++ + + @pytest.fixture(autouse=True) + def common_patches(): +@@ -74,8 +113,8 @@ def common_patches(): + is_FreeBSD=mock.Mock(return_value=False), + ), + mock.patch( +- "cloudinit.sources.DataSourceVMware.netifaces.interfaces", +- return_value=[], ++ "cloudinit.netinfo.netdev_info", ++ return_value={}, + ), + mock.patch( + "cloudinit.sources.DataSourceVMware.getfqdn", +@@ -152,6 +191,124 @@ class TestDataSourceVMware(CiTestCase): + host_info[DataSourceVMware.LOCAL_IPV6] == "2001:db8::::::8888" + ) + ++ # TODO migrate this entire test suite to pytest then parameterize ++ @mock.patch("cloudinit.netinfo.route_info") ++ @mock.patch("cloudinit.netinfo.netdev_info") ++ def test_get_default_ip_addrs_ipv4only( ++ self, ++ m_netdev_info, ++ m_route_info, ++ ): ++ """Test get_default_ip_addrs use cases""" ++ m_route_info.return_value = { ++ "ipv4": [VMW_IPV4_ROUTEINFO], ++ "ipv6": [], ++ } ++ m_netdev_info.return_value = generate_test_netdev_data( ++ ipv4=[VMW_IPV4_NETDEV_ADDR] ++ ) ++ ipv4, ipv6 = DataSourceVMware.get_default_ip_addrs() ++ self.assertEqual(ipv4, "10.85.130.116") ++ self.assertEqual(ipv6, None) ++ ++ @mock.patch("cloudinit.netinfo.route_info") ++ @mock.patch("cloudinit.netinfo.netdev_info") ++ def test_get_default_ip_addrs_ipv6only( ++ self, ++ m_netdev_info, ++ m_route_info, ++ ): ++ m_route_info.return_value = { ++ "ipv4": [], ++ "ipv6": [VMW_IPV6_ROUTEINFO], ++ } ++ m_netdev_info.return_value = generate_test_netdev_data( ++ ipv6=[VMW_IPV6_NETDEV_ADDR] ++ ) ++ ipv4, ipv6 = DataSourceVMware.get_default_ip_addrs() ++ self.assertEqual(ipv4, None) ++ self.assertEqual(ipv6, "fd42:baa2:3dd:17a:216:3eff:fe16:db54/64") ++ ++ @mock.patch("cloudinit.netinfo.route_info") ++ @mock.patch("cloudinit.netinfo.netdev_info") ++ def test_get_default_ip_addrs_dualstack( ++ self, ++ m_netdev_info, ++ m_route_info, ++ ): ++ m_route_info.return_value = { ++ "ipv4": [VMW_IPV4_ROUTEINFO], ++ "ipv6": [VMW_IPV6_ROUTEINFO], ++ } ++ m_netdev_info.return_value = generate_test_netdev_data( ++ ipv4=[VMW_IPV4_NETDEV_ADDR], ++ ipv6=[VMW_IPV6_NETDEV_ADDR], ++ ) ++ ipv4, ipv6 = DataSourceVMware.get_default_ip_addrs() ++ self.assertEqual(ipv4, "10.85.130.116") ++ self.assertEqual(ipv6, "fd42:baa2:3dd:17a:216:3eff:fe16:db54/64") ++ ++ @mock.patch("cloudinit.netinfo.route_info") ++ @mock.patch("cloudinit.netinfo.netdev_info") ++ def test_get_default_ip_addrs_multiaddr( ++ self, ++ m_netdev_info, ++ m_route_info, ++ ): ++ m_route_info.return_value = { ++ "ipv4": [VMW_IPV4_ROUTEINFO], ++ "ipv6": [], ++ } ++ m_netdev_info.return_value = generate_test_netdev_data( ++ ipv4=[ ++ VMW_IPV4_NETDEV_ADDR, ++ { ++ "bcast": "10.85.131.255", ++ "ip": "10.85.131.117", ++ "mask": "255.255.255.0", ++ "scope": "global", ++ }, ++ ], ++ ipv6=[ ++ VMW_IPV6_NETDEV_ADDR, ++ { ++ "ip": "fe80::216:3eff:fe16:db54/64", ++ "scope6": "link", ++ }, ++ ], ++ ) ++ ipv4, ipv6 = DataSourceVMware.get_default_ip_addrs() ++ self.assertEqual(ipv4, None) ++ self.assertEqual(ipv6, None) ++ ++ @mock.patch("cloudinit.netinfo.route_info") ++ @mock.patch("cloudinit.netinfo.netdev_info") ++ def test_get_default_ip_addrs_nodefault( ++ self, ++ m_netdev_info, ++ m_route_info, ++ ): ++ m_route_info.return_value = { ++ "ipv4": [ ++ { ++ "destination": "185.125.188.0", ++ "flags": "G", ++ "gateway": "10.85.130.1", ++ "genmask": "0.0.0.255", ++ "iface": "eth0", ++ "metric": "50", ++ }, ++ ], ++ "ipv6": [], ++ } ++ m_netdev_info.return_value = generate_test_netdev_data( ++ ipv4=[VMW_IPV4_NETDEV_ADDR], ++ ipv6=[VMW_IPV6_NETDEV_ADDR], ++ ) ++ ipv4, ipv6 = DataSourceVMware.get_default_ip_addrs() ++ self.assertEqual(ipv4, None) ++ self.assertEqual(ipv6, None) ++ + @mock.patch("cloudinit.sources.DataSourceVMware.get_host_info") + def test_wait_on_network(self, m_fn): + metadata = { +diff --git a/tools/build-on-netbsd b/tools/build-on-netbsd +index 0d4eb58b..b743d591 100755 +--- a/tools/build-on-netbsd ++++ b/tools/build-on-netbsd +@@ -19,7 +19,6 @@ pkgs=" + ${py_prefix}-oauthlib + ${py_prefix}-requests + ${py_prefix}-setuptools +- ${py_prefix}-netifaces + ${py_prefix}-yaml + ${py_prefix}-jsonschema + sudo +diff --git a/tools/build-on-openbsd b/tools/build-on-openbsd +index 948ebeb8..09262aff 100755 +--- a/tools/build-on-openbsd ++++ b/tools/build-on-openbsd +@@ -16,7 +16,6 @@ pkgs=" + py3-configobj + py3-jinja2 + py3-jsonschema +- py3-netifaces + py3-oauthlib + py3-requests + py3-setuptools +diff --git a/tox.ini b/tox.ini +index 34b87d01..473e937c 100644 +--- a/tox.ini ++++ b/tox.ini +@@ -194,7 +194,6 @@ deps = + requests==2.18.4 + jsonpatch==1.16 + jsonschema==2.6.0 +- netifaces==0.10.4 + # test-requirements + pytest==3.3.2 + pytest-cov==2.5.1 +-- +2.39.3 + diff --git a/cloud-init.spec b/cloud-init.spec index dbc1f28..cdf3043 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -6,7 +6,7 @@ Name: cloud-init Version: 24.1.4 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Cloud instance init scripts License: Apache-2.0 OR GPL-3.0-only URL: https://github.com/canonical/cloud-init @@ -19,6 +19,10 @@ Patch3: 0003-Do-not-write-NM_CONTROLLED-no-in-generated-interface.patch Patch4: 0004-Setting-autoconnect-priority-setting-for-network-scr.patch Patch5: 0005-feat-Use-NetworkManager-renderer-by-default-in-RHEL-.patch Patch6: ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch +# For RHEL-34518 - Remove dependency to netifcaces +Patch7: ci-refactor-remove-dependency-on-netifaces-4634.patch +# For RHEL-34518 - Remove dependency to netifcaces +Patch8: ci-DS-VMware-Fix-ipv6-addr-converter-from-netinfo-to-ne.patch BuildArch: noarch @@ -163,6 +167,7 @@ elif [ $1 -eq 2 ]; then # there will be stale systemd config /bin/systemctl is-enabled cloud-config.service >/dev/null 2>&1 && /bin/systemctl reenable cloud-config.service >/dev/null 2>&1 || : +fi %preun %systemd_preun cloud-config.service cloud-config.target cloud-final.service cloud-init.service cloud-init.target cloud-init-local.service @@ -220,6 +225,15 @@ fi %changelog +* Mon Apr 29 2024 Miroslav Rezanina - 24.1.4-3 +- ci-Fix-spec-file-post-install-script.patch [RHEL-33954] +- ci-refactor-remove-dependency-on-netifaces-4634.patch [RHEL-34518] +- ci-DS-VMware-Fix-ipv6-addr-converter-from-netinfo-to-ne.patch [RHEL-34518] +- Resolves: RHEL-33954 + ([RHEL-10] There is error message during cloud-init installation) +- Resolves: RHEL-34518 + (Remove dependency to netifcaces) + * Tue Apr 23 2024 Miroslav Rezanina - 24.1.4-2 - ci-Remove-dependency-on-dhcp-client-ISC-DHCP-and-use-dh.patch [RHEL-26304] - ci-fix-Fall-back-to-cached-local-ds-if-no-valid-ds-foun.patch [RHEL-32854]