Skip to content

Commit abd0f44

Browse files
committed
Skip adapter rename when set-name is not explicitly provided
When using network-config v2 with match.macaddress, cloudbase-init always renames the adapter to the ethernets dict key name. This causes failures on Windows because: 1. The WMI rename call (MSFT_NetAdapter.rename) is unreliable during early boot — the new name is not immediately queryable, causing "Network interface not found" errors (#101, #151) 2. The rename can hang for minutes on some Windows versions (#82) 3. Multiple adapters can cause name collisions This aligns with cloud-init (Linux) behavior where the ethernets dict key is just an opaque identifier when match is present, and only set-name triggers an actual rename. The fix checks link.id vs link.name: when they match (no set-name was provided), the adapter is used with its current Windows name instead of being renamed. When set-name is explicitly provided (link.id != link.name), rename proceeds as before. Signed-off-by: Max Makarov <maxpain@linux.com>
1 parent d63509f commit abd0f44

File tree

2 files changed

+114
-5
lines changed

2 files changed

+114
-5
lines changed

cloudbaseinit/plugins/common/networkconfig.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -198,11 +198,27 @@ def _process_physical_links(osutils, network_details):
198198
link.mac_address)
199199

200200
if adapter_name != link.name:
201-
LOG.info(
202-
"Renaming network adapter \"%(old_name)s\" to "
203-
"\"%(new_name)s\"",
204-
{"old_name": adapter_name, "new_name": link.name})
205-
osutils.rename_network_adapter(adapter_name, link.name)
201+
if link.id != link.name:
202+
# set-name was explicitly provided, honor the rename
203+
LOG.info(
204+
"Renaming network adapter \"%(old_name)s\" to "
205+
"\"%(new_name)s\"",
206+
{"old_name": adapter_name, "new_name": link.name})
207+
osutils.rename_network_adapter(adapter_name, link.name)
208+
else:
209+
# No set-name, use the actual adapter name to avoid
210+
# unreliable WMI rename (see issues #82, #101, #151)
211+
LOG.info(
212+
"Network adapter \"%(adapter_name)s\" found by "
213+
"MAC for config name \"%(config_name)s\", "
214+
"skipping rename",
215+
{"adapter_name": adapter_name,
216+
"config_name": link.name})
217+
for idx, net in enumerate(network_details.networks):
218+
if net.link == link.name:
219+
network_details.networks[idx] = net._replace(
220+
link=adapter_name)
221+
link = link._replace(name=adapter_name)
206222

207223
NetworkConfigPlugin._process_link_common(osutils, link)
208224

cloudbaseinit/tests/plugins/common/test_networkconfig.py

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,3 +473,96 @@ def test_execute_network_details_v2_ipv4_dns_list(self):
473473

474474
def test_execute_network_details_v2_ipv6_dns_list(self):
475475
self._test_execute_network_details_v2(both_ipv6_dns_list=True)
476+
477+
@mock.patch("cloudbaseinit.osutils.factory.get_os_utils")
478+
def test_execute_network_details_v2_no_rename_without_set_name(
479+
self, mock_get_os_utils):
480+
"""When link.id == link.name (no set-name), skip adapter rename."""
481+
link1 = network_model.Link(
482+
id="eth0",
483+
name="eth0",
484+
type=network_model.LINK_TYPE_PHYSICAL,
485+
enabled=True,
486+
mac_address=u"00:00:00:00:00:01",
487+
mtu=1500,
488+
bond=None,
489+
vlan_link=None,
490+
vlan_id=None)
491+
492+
route1 = network_model.Route(
493+
network_cidr=u"0.0.0.0/0",
494+
gateway=u"10.0.0.254")
495+
496+
network1 = network_model.Network(
497+
link="eth0",
498+
address_cidr=u"10.0.0.1/24",
499+
dns_nameservers=["10.0.0.1"],
500+
routes=[route1])
501+
502+
network_details = network_model.NetworkDetailsV2(
503+
links=[link1],
504+
networks=[network1],
505+
services=[])
506+
507+
service = mock.Mock()
508+
service.get_network_details_v2.return_value = network_details
509+
510+
mock_os_utils = mock.Mock()
511+
mock_get_os_utils.return_value = mock_os_utils
512+
mock_os_utils.get_network_adapter_name_by_mac_address.return_value = \
513+
"Ethernet 3"
514+
515+
plugin = networkconfig.NetworkConfigPlugin()
516+
plugin.execute(service, {})
517+
518+
# Should NOT rename when link.id == link.name (no set-name)
519+
mock_os_utils.rename_network_adapter.assert_not_called()
520+
521+
# Should use actual adapter name for all operations
522+
mock_os_utils.enable_network_adapter.assert_called_once_with(
523+
"Ethernet 3", True)
524+
mock_os_utils.set_network_adapter_mtu.assert_called_once_with(
525+
"Ethernet 3", 1500)
526+
mock_os_utils.set_static_network_config.assert_called_once_with(
527+
"Ethernet 3", "10.0.0.1", "24", "10.0.0.254", ["10.0.0.1"])
528+
529+
@mock.patch("cloudbaseinit.osutils.factory.get_os_utils")
530+
def test_execute_network_details_v2_rename_with_set_name(
531+
self, mock_get_os_utils):
532+
"""When link.id != link.name (set-name used), rename adapter."""
533+
link1 = network_model.Link(
534+
id="eth0",
535+
name="my-nic",
536+
type=network_model.LINK_TYPE_PHYSICAL,
537+
enabled=True,
538+
mac_address=u"00:00:00:00:00:01",
539+
mtu=None,
540+
bond=None,
541+
vlan_link=None,
542+
vlan_id=None)
543+
544+
network1 = network_model.Network(
545+
link="my-nic",
546+
address_cidr=u"10.0.0.1/24",
547+
dns_nameservers=["10.0.0.1"],
548+
routes=[])
549+
550+
network_details = network_model.NetworkDetailsV2(
551+
links=[link1],
552+
networks=[network1],
553+
services=[])
554+
555+
service = mock.Mock()
556+
service.get_network_details_v2.return_value = network_details
557+
558+
mock_os_utils = mock.Mock()
559+
mock_get_os_utils.return_value = mock_os_utils
560+
mock_os_utils.get_network_adapter_name_by_mac_address.return_value = \
561+
"Ethernet"
562+
563+
plugin = networkconfig.NetworkConfigPlugin()
564+
plugin.execute(service, {})
565+
566+
# Should rename when link.id != link.name (set-name was used)
567+
mock_os_utils.rename_network_adapter.assert_called_once_with(
568+
"Ethernet", "my-nic")

0 commit comments

Comments
 (0)