From 3fea77a2e4ced3baec27ca5f9b3c91df252dd0c9 Mon Sep 17 00:00:00 2001 From: Selby Mashiki Date: Sun, 25 Oct 2026 19:11:38 +0200 Subject: [PATCH] fix: check symlink names when matching wwn/nvme-eui in get_unique_path_for_device In get_unique_path_for_device(), linked_targets maps resolved device paths (e.g. /dev/sda, /dev/nvme0n1) to their /dev/disk/by-id/* symlinks. Previously, linked_wwn_targets iterated over the keys of linked_targets (the resolved /dev/sdX or /dev/nvmeXnY paths) and checked whether the resolved device name started with 'wwn-' or 'nvme-eui.', which was always False. In addition, because multiple /dev/disk/by-id symlinks resolve to the same block device, building linked_wwn_targets from linked_targets would miss wwn-/nvme-eui. symlinks whenever another symlink (such as ata-* or nvme-*) appeared later in the glob iteration. Materialize the glob results and build linked_wwn_targets directly from the /dev/disk/by-id symlink paths. --- archinstall/lib/disk/utils.py | 4 +-- tests/test_disk_utils.py | 54 +++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 tests/test_disk_utils.py diff --git a/archinstall/lib/disk/utils.py b/archinstall/lib/disk/utils.py index efa1f16515..bf79165369 100644 --- a/archinstall/lib/disk/utils.py +++ b/archinstall/lib/disk/utils.py @@ -116,9 +116,9 @@ def get_parent_device_path(dev_path: Path) -> Path: def get_unique_path_for_device(dev_path: Path) -> Path | None: - paths = Path('/dev/disk/by-id').glob('*') + paths = list(Path('/dev/disk/by-id').glob('*')) linked_targets = {p.resolve(): p for p in paths} - linked_wwn_targets = {p: linked_targets[p] for p in linked_targets if p.name.startswith('wwn-') or p.name.startswith('nvme-eui.')} + linked_wwn_targets = {p.resolve(): p for p in paths if p.name.startswith('wwn-') or p.name.startswith('nvme-eui.')} if dev_path in linked_wwn_targets: return linked_wwn_targets[dev_path] diff --git a/tests/test_disk_utils.py b/tests/test_disk_utils.py new file mode 100644 index 0000000000..3c631e2484 --- /dev/null +++ b/tests/test_disk_utils.py @@ -0,0 +1,54 @@ +from pathlib import Path + +from pytest import MonkeyPatch + +from archinstall.lib.disk.utils import get_unique_path_for_device + + +def test_get_unique_path_for_device_prefers_wwn_and_nvme_eui( + tmp_path: Path, + monkeypatch: MonkeyPatch, +) -> None: + dev_dir = tmp_path / 'dev' + by_id_dir = dev_dir / 'disk' / 'by-id' + by_id_dir.mkdir(parents=True) + + sda = dev_dir / 'sda' + sda.touch() + nvme0n1 = dev_dir / 'nvme0n1' + nvme0n1.touch() + sdb = dev_dir / 'sdb' + sdb.touch() + + ata_link = by_id_dir / 'ata-Samsung_SSD_1234' + wwn_link = by_id_dir / 'wwn-0x5002538e00000000' + ata_link.symlink_to(sda) + wwn_link.symlink_to(sda) + + nvme_model_link = by_id_dir / 'nvme-Samsung_SSD_980_PRO_ABCD' + nvme_eui_link = by_id_dir / 'nvme-eui.002538b123456789' + nvme_model_link.symlink_to(nvme0n1) + nvme_eui_link.symlink_to(nvme0n1) + + usb_link = by_id_dir / 'usb-Generic_Flash_Disk-0:0' + usb_link.symlink_to(sdb) + + orig_glob = Path.glob + + def fake_glob(self: Path, pattern: str) -> list[Path]: + if self == Path('/dev/disk/by-id'): + return [ + wwn_link, + ata_link, + nvme_eui_link, + nvme_model_link, + usb_link, + ] + return list(orig_glob(self, pattern)) + + monkeypatch.setattr(Path, 'glob', fake_glob) + + assert get_unique_path_for_device(sda) == wwn_link + assert get_unique_path_for_device(nvme0n1) == nvme_eui_link + assert get_unique_path_for_device(sdb) == usb_link + assert get_unique_path_for_device(dev_dir / 'sdc') is None