From 9b5bbafc8472f9119c846540a228c43732212034 Mon Sep 17 00:00:00 2001 From: wynnfeng Date: Fri, 3 Jul 2026 09:46:03 +0800 Subject: [PATCH] backport PR #5115 to fix interface rename busy with dhcpcd --- Support-TencentCloud.patch | 2 +- cloud-init.spec | 8 +- fix-interface-rename-dhcpcd.patch | 157 ++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+), 2 deletions(-) create mode 100644 fix-interface-rename-dhcpcd.patch diff --git a/Support-TencentCloud.patch b/Support-TencentCloud.patch index 0d16ad2..1b95c90 100644 --- a/Support-TencentCloud.patch +++ b/Support-TencentCloud.patch @@ -46,7 +46,7 @@ index 8d83433..373381f 100644 "check_exe": "/usr/lib/systemd/systemd-timesyncd", }, }, -+ "OpencloudOS": { ++ "OpenCloudOS": { + "ntp": { + "service_name": "ntpd", + }, diff --git a/cloud-init.spec b/cloud-init.spec index 78d61a7..48c3404 100644 --- a/cloud-init.spec +++ b/cloud-init.spec @@ -1,7 +1,7 @@ Summary: Cloud instance init scripts Name: cloud-init Version: 23.2.1 -Release: 12%{?dist} +Release: 13%{?dist} License: ASL 2.0 or GPLv3 URL: https://github.com/canonical/cloud-init Source0: %{url}/archive/%{version}/%{name}-%{version}.tar.gz @@ -12,6 +12,8 @@ Patch5000: Support-TencentCloud.patch Patch0001: fix-CVE-2024-6174.patch # https://github.com/canonical/cloud-init/commit/8b45006c4765fd75f20ce244571b563dbc49d4f2 Patch0002: fix-CVE-2024-11584.patch +# https://github.com/canonical/cloud-init/pull/5115 +Patch0003: fix-interface-rename-dhcpcd.patch BuildArch: noarch @@ -165,6 +167,10 @@ fi %changelog +* Thu Jul 02 2026 Feng Weiyao - 23.2.1-13 +- [type] bugfix +- [desc] backport PR #5115 to fix interface rename busy with dhcpcd + * Mon Jun 30 2025 Feng Weiyao - 23.2.1-12 - [type] security - [desc] fix CVE-2024-6174 and CVE-2024-11584 diff --git a/fix-interface-rename-dhcpcd.patch b/fix-interface-rename-dhcpcd.patch new file mode 100644 index 0000000..469a853 --- /dev/null +++ b/fix-interface-rename-dhcpcd.patch @@ -0,0 +1,157 @@ +From 9e2d6f8b1442aec9fec904445a44ef8366fb9431 Mon Sep 17 00:00:00 2001 +From: Brett Holman +Date: Thu, 28 Mar 2024 14:43:15 -0600 +Subject: [PATCH] fix(dhcpcd): Interface rename (backport PR #5115 to 23.2.1) + +Address assignment and link management is manual for isc-dhcp-client +whereas dhcpcd brings up its own interface and assigns the IP address. + +Interface rename code assumes that the link will be down for rename. +Make sure to set dhcpcd's interface to the same state. + +Adapted for 23.2.1 which uses ip command lists instead of net_ops. +--- + cloudinit/net/__init__.py | 8 ++++-- + cloudinit/net/dhcp.py | 1 + + cloudinit/net/ephemeral.py | 57 +++++++++++++++++++++++++++++++++++----- + 3 files changed, 58 insertions(+), 8 deletions(-) + +diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py +index bf21633..51fe339 100644 +--- a/cloudinit/net/__init__.py ++++ b/cloudinit/net/__init__.py +@@ -834,11 +834,15 @@ def _rename_interfaces( + + if len(ops) + len(ups) == 0: + if len(errors): +- LOG.debug("unable to do any work for renaming of %s", renames) ++ LOG.warning( ++ "Unable to rename interfaces: %s due to errors: %s", ++ renames, ++ errors, ++ ) + else: + LOG.debug("no work necessary for renaming of %s", renames) + else: +- LOG.debug("achieving renaming of %s with ops %s", renames, ops + ups) ++ LOG.debug("Renamed %s with ops %s", renames, ops + ups) + + for op, mac, new_name, params in ops + ups: + try: +diff --git a/cloudinit/net/dhcp.py b/cloudinit/net/dhcp.py +index 6c8c2f5..71b8e63 100644 +--- a/cloudinit/net/dhcp.py ++++ b/cloudinit/net/dhcp.py +@@ -89,6 +89,7 @@ def maybe_perform_dhcp_discovery(distro, nic=None, dhcp_log_func=None): + ) + raise NoDHCPLeaseInterfaceError() + client = select_dhcp_client(distro) ++ distro.dhcp_client = client + return client.dhcp_discovery(nic, dhcp_log_func, distro) + + +diff --git a/cloudinit/net/ephemeral.py b/cloudinit/net/ephemeral.py +index 8339f16..d0f91c0 100644 +--- a/cloudinit/net/ephemeral.py ++++ b/cloudinit/net/ephemeral.py +@@ -9,6 +9,7 @@ from typing import Any, Dict, List, Optional + import cloudinit.net as net + from cloudinit import subp + from cloudinit.net.dhcp import ( ++ Dhcpcd, + IscDhclient, + NoDHCPLeaseError, + maybe_perform_dhcp_discovery, +@@ -70,6 +71,7 @@ class EphemeralIPv4Network: + self.broadcast = broadcast + self.router = router + self.static_routes = static_routes ++ self.cidr = "{0}/{1}".format(self.ip, self.prefix) + # List of commands to run to cleanup state. + self.cleanup_cmds: List[str] = [] + +@@ -118,11 +120,10 @@ class EphemeralIPv4Network: + + def _bringup_device(self): + """Perform the ip comands to fully setup the device.""" +- cidr = "{0}/{1}".format(self.ip, self.prefix) + LOG.debug( + "Attempting setup of ephemeral network on %s with %s brd %s", + self.interface, +- cidr, ++ self.cidr, + self.broadcast, + ) + try: +@@ -133,7 +134,7 @@ class EphemeralIPv4Network: + "inet", + "addr", + "add", +- cidr, ++ self.cidr, + "broadcast", + self.broadcast, + "dev", +@@ -184,7 +185,7 @@ class EphemeralIPv4Network: + "inet", + "addr", + "del", +- cidr, ++ self.cidr, + "dev", + self.interface, + ] +@@ -395,7 +396,10 @@ class EphemeralDHCPv4: + ) + if self.connectivity_url_data: + kwargs["connectivity_url_data"] = self.connectivity_url_data +- ephipv4 = EphemeralIPv4Network(**kwargs) ++ if isinstance(getattr(self.distro, "dhcp_client", None), Dhcpcd): ++ ephipv4 = DhcpcdEphemeralIPv4Network(**kwargs) ++ else: ++ ephipv4 = EphemeralIPv4Network(**kwargs) + ephipv4.__enter__() + self._ephipv4 = ephipv4 + return self.lease +@@ -419,6 +423,41 @@ class EphemeralDHCPv4: + result[internal_mapping] = self.lease.get(different_names) + + ++class DhcpcdEphemeralIPv4Network(EphemeralIPv4Network): ++ """dhcpcd sets up its own ephemeral network and routes""" ++ ++ def __init__(self, *args, **kwargs): ++ super().__init__(*args, **kwargs) ++ # clean up after dhcpcd ++ self.cleanup_cmds.append( ++ [ ++ "ip", ++ "-family", ++ "inet", ++ "link", ++ "set", ++ "dev", ++ self.interface, ++ "down", ++ ] ++ ) ++ self.cleanup_cmds.append( ++ [ ++ "ip", ++ "-family", ++ "inet", ++ "addr", ++ "del", ++ self.cidr, ++ "dev", ++ self.interface, ++ ] ++ ) ++ ++ def __enter__(self): ++ return ++ ++ + class EphemeralIPNetwork: + """Marries together IPv4 and IPv6 ephemeral context managers""" + -- Gitee