summaryrefslogtreecommitdiffstats
path: root/pkgs/tools/virtualization/cloud-init
diff options
context:
space:
mode:
authorJean-François Roche <jfroche@pyxel.be>2023-06-19 17:18:36 +0200
committerJean-François Roche <jfroche@pyxel.be>2023-06-19 18:09:18 +0200
commit67f5018fe6f71a704c1606da8d2eb2af917972e3 (patch)
tree436efb8a9a97964bf42e69945bd5b1dafe44b610 /pkgs/tools/virtualization/cloud-init
parent619d9c7bb70aea398bb3f7b820932ce849ca9e10 (diff)
cloud-init: 23.1.2 -> 23.2
Keep support for udhcpc (waiting for upstream PR: https://github.com/canonical/cloud-init/pull/4190). Vultr patch has been merged upstream (https://github.com/canonical/cloud-init/pull/2151).
Diffstat (limited to 'pkgs/tools/virtualization/cloud-init')
-rw-r--r--pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch16
-rw-r--r--pkgs/tools/virtualization/cloud-init/0002-Add-Udhcpc-support.patch453
-rw-r--r--pkgs/tools/virtualization/cloud-init/0003-vultr-remove-check_route-check.patch110
-rw-r--r--pkgs/tools/virtualization/cloud-init/default.nix8
4 files changed, 340 insertions, 247 deletions
diff --git a/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch b/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch
index f79e3dda8497..f26690bacb70 100644
--- a/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch
+++ b/pkgs/tools/virtualization/cloud-init/0001-add-nixos-support.patch
@@ -12,10 +12,10 @@ index b82852e1..c998b21e 100644
LOG = logging.getLogger(__name__)
diff --git a/cloudinit/distros/nixos.py b/cloudinit/distros/nixos.py
new file mode 100644
-index 00000000..d53d2a61
+index 00000000..d53d2a62
--- /dev/null
+++ b/cloudinit/distros/nixos.py
-@@ -0,0 +1,103 @@
+@@ -0,0 +1,109 @@
+# vi: ts=4 expandtab
+#
+# Copyright (C) 2012 Canonical Ltd.
@@ -47,6 +47,7 @@ index 00000000..d53d2a61
+from cloudinit import atomic_helper
+
+from cloudinit.distros.parsers.hostname import HostnameConf
++from cloudinit.net import dhcp
+
+LOG = logging.getLogger(__name__)
+
@@ -61,6 +62,11 @@ index 00000000..d53d2a61
+ self.usr_lib_exec = os.path.join(os.path.dirname(__file__),
+ "../../../../../libexec")
+ self.osfamily = 'nixos'
++ self.dhcp_client_priority = [
++ dhcp.Udhcpc,
++ dhcp.IscDhclient,
++ dhcp.Dhcpcd,
++ ]
+
+ def _select_hostname(self, hostname, fqdn):
+ # Prefer the short hostname over the long
@@ -112,10 +118,10 @@ index 00000000..d53d2a61
+ raise NotImplementedError()
+
+ def package_command(self, command, args=None, pkgs=None):
-+ raise NotImplementedError()
++ pass
+
+ def set_timezone(self, tz):
-+ raise NotImplementedError()
++ pass
+
+ def update_package_sources(self):
-+ raise NotImplementedError()
++ pass
diff --git a/pkgs/tools/virtualization/cloud-init/0002-Add-Udhcpc-support.patch b/pkgs/tools/virtualization/cloud-init/0002-Add-Udhcpc-support.patch
index ef1694837691..0df3f27a2c40 100644
--- a/pkgs/tools/virtualization/cloud-init/0002-Add-Udhcpc-support.patch
+++ b/pkgs/tools/virtualization/cloud-init/0002-Add-Udhcpc-support.patch
@@ -1,15 +1,56 @@
-diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py
-index a9a1c980..2d83089b 100644
---- a/cloudinit/net/dhcp.py
-+++ b/cloudinit/net/dhcp.py
-@@ -14,12 +14,48 @@ from io import StringIO
+From 53260ce3bd70a0852d3e0d5569474214cea0ec0c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Roche?= <jfroche@pyxel.be>
+Date: Mon, 19 Jun 2023 15:56:46 +0200
+Subject: [PATCH] net/dhcp: add udhcpc support
+
+The currently used dhcp client, dhclient, is coming from the unmaintained package, isc-dhcp-client (refer https://www.isc.org/dhcp/) which ended support in 2022.
+
+This change introduce support for the dhcp client, udhcpc, from the busybox project. Busybox advantages are that it is available across many distributions and comes with lightweight executables.
+---
+ cloudinit/distros/__init__.py | 8 +-
+ cloudinit/net/dhcp.py | 129 ++++++++++++++++++++++-
+ tests/unittests/net/test_dhcp.py | 175 ++++++++++++++++++++++++++++++-
+ tools/.github-cla-signers | 1 +
+ 4 files changed, 309 insertions(+), 4 deletions(-)
+
+diff --git a/cloudinit/distros/__init__.py b/cloudinit/distros/__init__.py
+index ec148939..0fab8945 100644
+--- a/cloudinit/distros/__init__.py
++++ b/cloudinit/distros/__init__.py
+@@ -110,14 +110,18 @@ class Distro(persistence.CloudInitPickleMixin, metaclass=abc.ABCMeta):
+ resolve_conf_fn = "/etc/resolv.conf"
- import configobj
+ osfamily: str
+- dhcp_client_priority = [dhcp.IscDhclient, dhcp.Dhcpcd]
++ dhcp_client_priority = [dhcp.IscDhclient, dhcp.Dhcpcd, dhcp.Udhcpc]
--from cloudinit import subp, util
-+from cloudinit import subp, util, temp_utils
- from cloudinit.net import find_fallback_nic, get_devicelist
+ def __init__(self, name, cfg, paths):
+ self._paths = paths
+ self._cfg = cfg
+ self.name = name
+ self.networking: Networking = self.networking_cls()
+- self.dhcp_client_priority = [dhcp.IscDhclient, dhcp.Dhcpcd]
++ self.dhcp_client_priority = [
++ dhcp.IscDhclient,
++ dhcp.Dhcpcd,
++ dhcp.Udhcpc,
++ ]
+ def _unpickle(self, ci_pkl_version: int) -> None:
+ """Perform deserialization fixes for Distro."""
+diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py
+index 6c8c2f54..f5586cea 100644
+--- a/cloudinit/net/dhcp.py
++++ b/cloudinit/net/dhcp.py
+@@ -21,6 +21,7 @@ from cloudinit import subp, temp_utils, util
+ from cloudinit.net import (
+ find_fallback_nic,
+ get_devicelist,
++ get_ib_interface_hwaddr,
+ get_interface_mac,
+ is_ib_interface,
+ )
+@@ -28,6 +29,37 @@ from cloudinit.net import (
LOG = logging.getLogger(__name__)
NETWORKD_LEASES_DIR = "/run/systemd/netif/leases"
@@ -17,9 +58,7 @@ index a9a1c980..2d83089b 100644
+log() {
+ echo "udhcpc[$PPID]" "$interface: $2"
+}
-+
+[ -z "$1" ] && echo "Error: should be called from udhcpc" && exit 1
-+
+case $1 in
+ bound|renew)
+ cat <<JSON > "$LEASE_FILE"
@@ -32,17 +71,14 @@ index a9a1c980..2d83089b 100644
+}
+JSON
+ ;;
-+
+ deconfig)
+ log err "Not supported"
+ exit 1
+ ;;
-+
+ leasefail | nak)
+ log err "configuration failed: $1: $message"
+ exit 1
+ ;;
-+
+ *)
+ echo "$0: Unknown udhcpc command: $1" >&2
+ exit 1
@@ -52,134 +88,199 @@ index a9a1c980..2d83089b 100644
class NoDHCPLeaseError(Exception):
-@@ -43,12 +79,14 @@ class NoDHCPLeaseMissingDhclientError(NoDHCPLeaseError):
+@@ -50,6 +82,10 @@ class NoDHCPLeaseMissingDhclientError(NoDHCPLeaseError):
+ """Raised when unable to find dhclient."""
- def maybe_perform_dhcp_discovery(nic=None, dhcp_log_func=None, tmp_dir=None):
-- """Perform dhcp discovery if nic valid and dhclient command exists.
-+ """Perform dhcp discovery if nic valid and dhclient or udhcpc command
-+ exists.
-
- If the nic is invalid or undiscoverable or dhclient command is not found,
- skip dhcp_discovery and return an empty dict.
-
-- @param nic: Name of the network interface we want to run dhclient on.
-+ @param nic: Name of the network interface we want to run the dhcp client
-+ on.
- @param dhcp_log_func: A callable accepting the dhclient output and error
- streams.
- @param tmp_dir: Tmp dir with exec permissions.
-@@ -66,11 +104,16 @@ def maybe_perform_dhcp_discovery(nic=None, dhcp_log_func=None, tmp_dir=None):
- "Skip dhcp_discovery: nic %s not found in get_devicelist.", nic
- )
- raise NoDHCPLeaseInterfaceError()
-+ udhcpc_path = subp.which("udhcpc")
-+ if udhcpc_path:
-+ return dhcp_udhcpc_discovery(udhcpc_path, nic, dhcp_log_func)
- dhclient_path = subp.which("dhclient")
-- if not dhclient_path:
-- LOG.debug("Skip dhclient configuration: No dhclient command found.")
-- raise NoDHCPLeaseMissingDhclientError()
-- return dhcp_discovery(dhclient_path, nic, dhcp_log_func)
-+ if dhclient_path:
-+ return dhcp_discovery(dhclient_path, nic, dhcp_log_func)
-+ LOG.debug(
-+ "Skip dhclient configuration: No dhclient or udhcpc command found."
-+ )
-+ raise NoDHCPLeaseMissingDhclientError()
-
++class NoDHCPLeaseMissingUdhcpcError(NoDHCPLeaseError):
++ """Raised when unable to find udhcpc client."""
++
++
+ def select_dhcp_client(distro):
+ """distros set priority list, select based on this order which to use
- def parse_dhcp_lease_file(lease_file):
-@@ -107,6 +150,61 @@ def parse_dhcp_lease_file(lease_file):
- return dhcp_leases
+@@ -60,7 +96,10 @@ def select_dhcp_client(distro):
+ dhcp_client = client()
+ LOG.debug("DHCP client selected: %s", client.client_name)
+ return dhcp_client
+- except NoDHCPLeaseMissingDhclientError:
++ except (
++ NoDHCPLeaseMissingDhclientError,
++ NoDHCPLeaseMissingUdhcpcError,
++ ):
+ LOG.warning("DHCP client not found: %s", client.client_name)
+ raise NoDHCPLeaseMissingDhclientError()
+@@ -497,3 +536,91 @@ class Dhcpcd:
-+def dhcp_udhcpc_discovery(udhcpc_cmd_path, interface, dhcp_log_func=None):
-+ """Run udhcpc on the interface without scripts or filesystem artifacts.
-+
-+ @param udhcpc_cmd_path: Full path to the udhcpc used.
-+ @param interface: Name of the network interface on which to dhclient.
-+ @param dhcp_log_func: A callable accepting the dhclient output and error
-+ streams.
-+
-+ @return: A list of dicts of representing the dhcp leases parsed from the
-+ dhclient.lease file or empty list.
-+ """
-+ LOG.debug("Performing a dhcp discovery on %s", interface)
-+
-+ tmp_dir = temp_utils.get_tmp_ancestor(needs_exe=True)
-+ lease_file = os.path.join(tmp_dir, interface + ".lease.json")
-+ with contextlib.suppress(FileNotFoundError):
-+ os.remove(lease_file)
-+
-+ # udhcpc needs the interface up to send initial discovery packets.
-+ # Generally dhclient relies on dhclient-script PREINIT action to bring the
-+ # link up before attempting discovery. Since we are using -sf /bin/true,
-+ # we need to do that "link up" ourselves first.
-+ subp.subp(["ip", "link", "set", "dev", interface, "up"], capture=True)
-+ udhcpc_script = os.path.join(tmp_dir, "udhcpc_script")
-+ util.write_file(udhcpc_script, UDHCPC_SCRIPT, 0o755)
-+ cmd = [
-+ udhcpc_cmd_path,
-+ "-O",
-+ "staticroutes",
-+ "-i",
+ def __init__(self):
+ raise NoDHCPLeaseMissingDhclientError("Dhcpcd not yet implemented")
++
++
++class Udhcpc(DhcpClient):
++ client_name = "udhcpc"
++
++ def __init__(self):
++ self.udhcpc_path = subp.which("udhcpc")
++ if not self.udhcpc_path:
++ LOG.debug("Skip udhcpc configuration: No udhcpc command found.")
++ raise NoDHCPLeaseMissingUdhcpcError()
++
++ def dhcp_discovery(
++ self,
+ interface,
-+ "-s",
-+ udhcpc_script,
-+ "-n", # Exit if lease is not obtained
-+ "-q", # Exit after obtaining lease
-+ "-f", # Run in foreground
-+ "-v",
-+ ]
-+
-+ out, err = subp.subp(
-+ cmd, update_env={"LEASE_FILE": lease_file}, capture=True
-+ )
-+
-+ if dhcp_log_func is not None:
-+ dhcp_log_func(out, err)
-+ lease_json = util.load_json(util.load_file(lease_file))
-+ static_routes = lease_json["static_routes"].split()
-+ if static_routes:
-+ # format: dest1/mask gw1 ... destn/mask gwn
-+ lease_json["static_routes"] = [
-+ i for i in zip(static_routes[::2], static_routes[1::2])
++ dhcp_log_func=None,
++ distro=None,
++ ):
++ """Run udhcpc on the interface without scripts or filesystem artifacts.
++
++ @param interface: Name of the network interface on which to run udhcpc.
++ @param dhcp_log_func: A callable accepting the udhcpc output and
++ error streams.
++
++ @return: A list of dicts of representing the dhcp leases parsed from
++ the udhcpc lease file.
++ """
++ LOG.debug("Performing a dhcp discovery on %s", interface)
++
++ tmp_dir = temp_utils.get_tmp_ancestor(needs_exe=True)
++ lease_file = os.path.join(tmp_dir, interface + ".lease.json")
++ with contextlib.suppress(FileNotFoundError):
++ os.remove(lease_file)
++
++ # udhcpc needs the interface up to send initial discovery packets
++ subp.subp(["ip", "link", "set", "dev", interface, "up"], capture=True)
++
++ udhcpc_script = os.path.join(tmp_dir, "udhcpc_script")
++ util.write_file(udhcpc_script, UDHCPC_SCRIPT, 0o755)
++
++ cmd = [
++ self.udhcpc_path,
++ "-O",
++ "staticroutes",
++ "-i",
++ interface,
++ "-s",
++ udhcpc_script,
++ "-n", # Exit if lease is not obtained
++ "-q", # Exit after obtaining lease
++ "-f", # Run in foreground
++ "-v",
+ ]
-+ return [lease_json]
+
++ # For INFINIBAND port the dhcpc must be running with
++ # client id option. So here we are checking if the interface is
++ # INFINIBAND or not. If yes, we are generating the the client-id to be
++ # used with the udhcpc
++ if is_ib_interface(interface):
++ dhcp_client_identifier = get_ib_interface_hwaddr(
++ interface, ethernet_format=True
++ )
++ cmd.extend(
++ ["-x", "0x3d:%s" % dhcp_client_identifier.replace(":", "")]
++ )
++ try:
++ out, err = subp.subp(
++ cmd, update_env={"LEASE_FILE": lease_file}, capture=True
++ )
++ except subp.ProcessExecutionError as error:
++ LOG.debug(
++ "udhcpc exited with code: %s stderr: %r stdout: %r",
++ error.exit_code,
++ error.stderr,
++ error.stdout,
++ )
++ raise NoDHCPLeaseError from error
+
- def dhcp_discovery(dhclient_cmd_path, interface, dhcp_log_func=None):
- """Run dhclient on the interface without scripts or filesystem artifacts.
-
++ if dhcp_log_func is not None:
++ dhcp_log_func(out, err)
++
++ lease_json = util.load_json(util.load_file(lease_file))
++ static_routes = lease_json["static_routes"].split()
++ if static_routes:
++ # format: dest1/mask gw1 ... destn/mask gwn
++ lease_json["static_routes"] = [
++ i for i in zip(static_routes[::2], static_routes[1::2])
++ ]
++ return [lease_json]
diff --git a/tests/unittests/net/test_dhcp.py b/tests/unittests/net/test_dhcp.py
-index 40340553..8913cf65 100644
+index 55d4c6e9..9123cd15 100644
--- a/tests/unittests/net/test_dhcp.py
+++ b/tests/unittests/net/test_dhcp.py
-@@ -12,6 +12,7 @@ from cloudinit.net.dhcp import (
+@@ -13,6 +13,8 @@ from cloudinit.net.dhcp import (
NoDHCPLeaseError,
NoDHCPLeaseInterfaceError,
NoDHCPLeaseMissingDhclientError,
-+ dhcp_udhcpc_discovery,
- dhcp_discovery,
++ NoDHCPLeaseMissingUdhcpcError,
++ Udhcpc,
maybe_perform_dhcp_discovery,
networkd_load_leases,
-@@ -334,6 +335,43 @@ class TestDHCPParseStaticRoutes(CiTestCase):
+ )
+@@ -388,11 +390,13 @@ class TestDHCPDiscoveryClean(CiTestCase):
+ self.logs.getvalue(),
)
++ @mock.patch("cloudinit.temp_utils.get_tmp_ancestor", return_value="/tmp")
+ @mock.patch("cloudinit.net.dhcp.find_fallback_nic", return_value="eth9")
+ @mock.patch("cloudinit.net.dhcp.os.remove")
+ @mock.patch("cloudinit.net.dhcp.subp.subp")
+ @mock.patch("cloudinit.net.dhcp.subp.which")
+- def test_dhcp_client_failover(self, m_which, m_subp, m_remove, m_fallback):
++ def test_dhcp_client_failover(self, m_which, m_subp, m_remove, m_fallback,
++ m_get_tmp_ancestor):
+ """Log and do nothing when nic is absent and no fallback is found."""
+ m_subp.side_effect = [
+ ("", ""),
+@@ -928,3 +932,172 @@ class TestEphemeralDhcpLeaseErrors:
+ pass
+ assert len(m_dhcp.mock_calls) == 1
++
++
+class TestUDHCPCDiscoveryClean(CiTestCase):
++ with_logs = True
+ maxDiff = None
+
++ @mock.patch("cloudinit.temp_utils.get_tmp_ancestor", return_value="/tmp")
++ @mock.patch("cloudinit.net.dhcp.subp.which")
++ @mock.patch("cloudinit.net.dhcp.find_fallback_nic")
++ def test_absent_udhcpc_command(self, m_fallback, m_which,
++ m_get_tmp_ancestor):
++ """When dhclient doesn't exist in the OS, log the issue and no-op."""
++ m_fallback.return_value = "eth9"
++ m_which.return_value = None # udhcpc isn't found
++
++ distro = MockDistro()
++ distro.dhcp_client_priority = [Udhcpc]
++
++ with pytest.raises(NoDHCPLeaseMissingDhclientError):
++ maybe_perform_dhcp_discovery(distro)
++
++ self.assertIn(
++ "Skip udhcpc configuration: No udhcpc command found.",
++ self.logs.getvalue(),
++ )
++
++ @mock.patch("cloudinit.temp_utils.get_tmp_ancestor", return_value="/tmp")
++ @mock.patch("cloudinit.net.dhcp.is_ib_interface", return_value=False)
++ @mock.patch("cloudinit.net.dhcp.subp.which", return_value="/sbin/udhcpc")
+ @mock.patch("cloudinit.net.dhcp.os.remove")
+ @mock.patch("cloudinit.net.dhcp.subp.subp")
+ @mock.patch("cloudinit.util.load_json")
+ @mock.patch("cloudinit.util.load_file")
+ @mock.patch("cloudinit.util.write_file")
+ def test_udhcpc_discovery(
-+ self, m_write_file, m_load_file, m_loadjson, m_subp, m_remove
++ self,
++ m_write_file,
++ m_load_file,
++ m_loadjson,
++ m_subp,
++ m_remove,
++ m_which,
++ mocked_is_ib_interface,
++ m_get_tmp_ancestor,
+ ):
-+ """dhcp_discovery waits for the presence of pidfile and dhcp.leases."""
++ """dhcp_discovery runs udcpc and parse the dhcp leases."""
+ m_subp.return_value = ("", "")
+ m_loadjson.return_value = {
+ "interface": "eth9",
@@ -201,22 +302,120 @@ index 40340553..8913cf65 100644
+ "subnet-mask": "255.255.255.0",
+ }
+ ],
-+ dhcp_udhcpc_discovery("/sbin/udhcpc", "eth9"),
++ Udhcpc().dhcp_discovery("eth9", distro=MockDistro()),
++ )
++ # Interface was brought up before dhclient called
++ m_subp.assert_has_calls(
++ [
++ mock.call(
++ ["ip", "link", "set", "dev", "eth9", "up"],
++ capture=True,
++ ),
++ mock.call(
++ [
++ "/sbin/udhcpc",
++ "-O",
++ "staticroutes",
++ "-i",
++ "eth9",
++ "-s",
++ "/tmp/udhcpc_script",
++ "-n",
++ "-q",
++ "-f",
++ "-v",
++ ],
++ update_env={"LEASE_FILE": "/tmp/eth9.lease.json"},
++ capture=True,
++ ),
++ ]
+ )
+
-+
- class TestDHCPDiscoveryClean(CiTestCase):
- with_logs = True
-
-@@ -372,7 +410,7 @@ class TestDHCPDiscoveryClean(CiTestCase):
- maybe_perform_dhcp_discovery()
-
- self.assertIn(
-- "Skip dhclient configuration: No dhclient command found.",
-+ "Skip dhclient configuration: No dhclient or udhcpc command found.",
- self.logs.getvalue(),
- )
-
++ @mock.patch("cloudinit.temp_utils.get_tmp_ancestor", return_value="/tmp")
++ @mock.patch("cloudinit.net.dhcp.is_ib_interface", return_value=True)
++ @mock.patch("cloudinit.net.dhcp.get_ib_interface_hwaddr")
++ @mock.patch("cloudinit.net.dhcp.subp.which", return_value="/sbin/udhcpc")
++ @mock.patch("cloudinit.net.dhcp.os.remove")
++ @mock.patch("cloudinit.net.dhcp.subp.subp")
++ @mock.patch("cloudinit.util.load_json")
++ @mock.patch("cloudinit.util.load_file")
++ @mock.patch("cloudinit.util.write_file")
++ def test_udhcpc_discovery_ib(
++ self,
++ m_write_file,
++ m_load_file,
++ m_loadjson,
++ m_subp,
++ m_remove,
++ m_which,
++ m_get_ib_interface_hwaddr,
++ m_is_ib_interface,
++ m_get_tmp_ancestor,
++ ):
++ """dhcp_discovery runs udcpc and parse the dhcp leases."""
++ m_subp.return_value = ("", "")
++ m_loadjson.return_value = {
++ "interface": "ib0",
++ "fixed-address": "192.168.2.74",
++ "subnet-mask": "255.255.255.0",
++ "routers": "192.168.2.1",
++ "static_routes": "10.240.0.1/32 0.0.0.0 0.0.0.0/0 10.240.0.1",
++ }
++ m_get_ib_interface_hwaddr.return_value = "00:21:28:00:01:cf:4b:01"
++ self.assertEqual(
++ [
++ {
++ "fixed-address": "192.168.2.74",
++ "interface": "ib0",
++ "routers": "192.168.2.1",
++ "static_routes": [
++ ("10.240.0.1/32", "0.0.0.0"),
++ ("0.0.0.0/0", "10.240.0.1"),
++ ],
++ "subnet-mask": "255.255.255.0",
++ }
++ ],
++ Udhcpc().dhcp_discovery("ib0", distro=MockDistro()),
++ )
++ # Interface was brought up before dhclient called
++ m_subp.assert_has_calls(
++ [
++ mock.call(
++ ["ip", "link", "set", "dev", "ib0", "up"], capture=True
++ ),
++ mock.call(
++ [
++ "/sbin/udhcpc",
++ "-O",
++ "staticroutes",
++ "-i",
++ "ib0",
++ "-s",
++ "/tmp/udhcpc_script",
++ "-n",
++ "-q",
++ "-f",
++ "-v",
++ "-x",
++ "0x3d:0021280001cf4b01",
++ ],
++ update_env={"LEASE_FILE": "/tmp/ib0.lease.json"},
++ capture=True,
++ ),
++ ]
++ )
+diff --git a/tools/.github-cla-signers b/tools/.github-cla-signers
+index b4a9326e..4d82a055 100644
+--- a/tools/.github-cla-signers
++++ b/tools/.github-cla-signers
+@@ -65,6 +65,7 @@ jacobsalmela
+ jamesottinger
+ Jehops
+ jf
++jfroche
+ Jille
+ JohnKepplers
+ johnsonshi
--
-2.38.4
+2.40.1
diff --git a/pkgs/tools/virtualization/cloud-init/0003-vultr-remove-check_route-check.patch b/pkgs/tools/virtualization/cloud-init/0003-vultr-remove-check_route-check.patch
deleted file mode 100644
index d0d635b939f2..000000000000
--- a/pkgs/tools/virtualization/cloud-init/0003-vultr-remove-check_route-check.patch
+++ /dev/null
@@ -1,110 +0,0 @@
-From 6df2a198013ebed9aeff119ee0d15cb2d616474c Mon Sep 17 00:00:00 2001
-From: zimbatm <zimbatm@zimbatm.com>
-Date: Sun, 30 Apr 2023 12:13:54 +0200
-Subject: [PATCH] vultr: remove check_route check
-
-The heuristic is assuming that the URL will contain an IP, and that the
-route explicitly lists that IP (eg: 0.0.0.0/0 should match but doesn't).
-In order for the heuristic to be 100% reliable, it would have to
-replicate exactly what the system is doing both in terms of DNS and
-route resolution.
-
-Because the HTTP request below is already exercising the python nd
-system resolution, it is simpler to just remove this check and lean on
-the HTTP request to provide the answer if the network is up or not.
----
- cloudinit/sources/helpers/vultr.py | 22 ----------------------
- tests/unittests/sources/test_vultr.py | 12 ------------
- 2 files changed, 34 deletions(-)
-
-diff --git a/cloudinit/sources/helpers/vultr.py b/cloudinit/sources/helpers/vultr.py
-index 71676bb1..aac2a610 100644
---- a/cloudinit/sources/helpers/vultr.py
-+++ b/cloudinit/sources/helpers/vultr.py
-@@ -32,10 +32,6 @@ def get_metadata(
- iface=iface,
- connectivity_url_data={"url": url},
- ):
-- # Check for the metadata route, skip if not there
-- if not check_route(url):
-- continue
--
- # Fetch the metadata
- v1 = read_metadata(url, timeout, retries, sec_between, agent)
-
-@@ -75,24 +71,6 @@ def get_interface_list():
- return ifaces
-
-
--# Check for /32 route that our dhcp servers inject
--# in order to determine if this a customer-run dhcp server
--def check_route(url):
-- # Get routes, confirm entry exists
-- routes = netinfo.route_info()
--
-- # If no tools exist and empty dict is returned
-- if "ipv4" not in routes:
-- return False
--
-- # Parse each route into a more searchable format
-- for route in routes["ipv4"]:
-- if route.get("destination", None) in url:
-- return True
--
-- return False
--
--
- # Read the system information from SMBIOS
- def get_sysinfo():
- return {
-diff --git a/tests/unittests/sources/test_vultr.py b/tests/unittests/sources/test_vultr.py
-index ba21ae24..7fa02b1c 100644
---- a/tests/unittests/sources/test_vultr.py
-+++ b/tests/unittests/sources/test_vultr.py
-@@ -274,14 +274,6 @@ INTERFACE_MAP = {
- FINAL_INTERFACE_USED = ""
-
-
--# Static override, pylint doesnt like this in
--# classes without self
--def check_route(url):
-- if FINAL_INTERFACE_USED == "eth0":
-- return True
-- return False
--
--
- class TestDataSourceVultr(CiTestCase):
- def setUp(self):
- global VULTR_V1_3
-@@ -431,7 +423,6 @@ class TestDataSourceVultr(CiTestCase):
- @mock.patch(
- "cloudinit.net.ephemeral.EphemeralDHCPv4.__exit__", override_exit
- )
-- @mock.patch("cloudinit.sources.helpers.vultr.check_route")
- @mock.patch("cloudinit.sources.helpers.vultr.is_vultr")
- @mock.patch("cloudinit.sources.helpers.vultr.read_metadata")
- @mock.patch("cloudinit.sources.helpers.vultr.get_interface_list")
-@@ -440,12 +431,10 @@ class TestDataSourceVultr(CiTestCase):
- mock_interface_list,
- mock_read_metadata,
- mock_isvultr,
-- mock_check_route,
- ):
- mock_read_metadata.return_value = {}
- mock_isvultr.return_value = True
- mock_interface_list.return_value = FILTERED_INTERFACES
-- mock_check_route.return_value = True
-
- distro = mock.MagicMock()
- distro.get_tmp_exec_path = self.tmp_dir
-@@ -461,7 +450,6 @@ class TestDataSourceVultr(CiTestCase):
- self.assertEqual(FINAL_INTERFACE_USED, INTERFACES[3])
-
- # Test route checking sucessful DHCPs
-- @mock.patch("cloudinit.sources.helpers.vultr.check_route", check_route)
- @mock.patch(
- "cloudinit.net.ephemeral.EphemeralDHCPv4.__init__",
- ephemeral_init_always,
---
-2.40.0
-
diff --git a/pkgs/tools/virtualization/cloud-init/default.nix b/pkgs/tools/virtualization/cloud-init/default.nix
index fa9b21defc75..bb3197d53537 100644
--- a/pkgs/tools/virtualization/cloud-init/default.nix
+++ b/pkgs/tools/virtualization/cloud-init/default.nix
@@ -16,22 +16,20 @@
python3.pkgs.buildPythonApplication rec {
pname = "cloud-init";
- version = "23.1.2";
+ version = "23.2";
namePrefix = "";
src = fetchFromGitHub {
owner = "canonical";
repo = "cloud-init";
rev = "refs/tags/${version}";
- hash = "sha256-tn4flcrf04hVWhqkmK4qDenXcnV93pP+C+8J63b6FXQ=";
+ hash = "sha256-/bhezXS5GunlgID7e/QaTC4UsQ2hDvS5HnG8Wphk64k=";
};
patches = [
./0001-add-nixos-support.patch
- # upstream: https://github.com/canonical/cloud-init/pull/2125
+ # upstream: https://github.com/canonical/cloud-init/pull/4190
./0002-Add-Udhcpc-support.patch
- # upstream: https://github.com/canonical/cloud-init/pull/2151
- ./0003-vultr-remove-check_route-check.patch
];
prePatch = ''