From 4aa6bf8af57b9d7eeed3a6f59bba01baeb54a9f6 Mon Sep 17 00:00:00 2001 From: Markus Hilger Date: Fri, 30 Oct 2026 09:43:54 +0100 Subject: [PATCH] Accept plain device names in deployment.storage and fail on no match The attribute help promises "a specific device name", but getinstalldisk only understood "m2" and "/dev/". A plain "nvme0n1" aborted the install with "Unknown deployment.storage specification", and a "/dev/" that matched no disk was silently ignored, so the OS went to whatever disk the default ordering picked. For an attribute meant to pin the OS disk that is the dangerous failure mode. Accept a kernel name with or without /dev/ and resolve /dev/disk/by-* links to their kernel name, so a disk can be pinned by a stable path. When nothing matches, fail with "No disks match" like the m2 filter already does. Document the accepted forms in the attribute help. --- .../common/profile/scripts/getinstalldisk | 50 ++++++++++--------- .../confluent/config/attributes.py | 2 +- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/confluent_osdeploy/common/profile/scripts/getinstalldisk b/confluent_osdeploy/common/profile/scripts/getinstalldisk index cb65e9bf..3108053e 100644 --- a/confluent_osdeploy/common/profile/scripts/getinstalldisk +++ b/confluent_osdeploy/common/profile/scripts/getinstalldisk @@ -241,31 +241,33 @@ def get_deployment_storage(): def filter_deployment_storage(disks, storagespec, slotinfo=None): if not storagespec: return disks - spec = storagespec.strip().lower() - for disk in list(disks): - if spec == 'm2': - if disk.is_m2: - continue - if disk.model.lower() in PRIORITY_MODELS: - continue - if slotinfo is None: - slotinfo = get_m2_slot_info() - if not getattr(disk, 'busaddr', None): - for kernname in getattr(disk, 'kernnames', []): - if kernname in slotinfo: - break - else: - disks.remove(disk) - continue - if disk.busaddr not in slotinfo: - disks.remove(disk) - elif spec.startswith('/dev/'): - bspec = os.path.basename(spec) - if disk.name.lower() == bspec: + spec = storagespec.strip() + if spec.lower() != 'm2': + # A device name with or without /dev/, or a persistent link such as + # /dev/disk/by-path/..., resolved to its kernel name + if spec.startswith('/dev/'): + spec = os.path.realpath(spec) + devname = os.path.basename(spec).lower() + for disk in disks: + if disk.name.lower() == devname: return [disk] - else: - raise Exception("Unknown deployment.storage specification: {0}".format(storagespec)) - + raise Exception("No disks match deployment.storage specification: {0}".format(storagespec)) + for disk in list(disks): + if disk.is_m2: + continue + if disk.model.lower() in PRIORITY_MODELS: + continue + if slotinfo is None: + slotinfo = get_m2_slot_info() + if not getattr(disk, 'busaddr', None): + for kernname in getattr(disk, 'kernnames', []): + if kernname in slotinfo: + break + else: + disks.remove(disk) + continue + if disk.busaddr not in slotinfo: + disks.remove(disk) if not disks: raise Exception("No disks match deployment.storage specification: {0}".format(storagespec)) return disks diff --git a/confluent_server/confluent/config/attributes.py b/confluent_server/confluent/config/attributes.py index 11c1fa90..fe067368 100644 --- a/confluent_server/confluent/config/attributes.py +++ b/confluent_server/confluent/config/attributes.py @@ -256,7 +256,7 @@ node = { 'description': ('Timestamp of last state change, as reported by an OS profile, when available'), }, 'deployment.storage': { - 'description': ('Indicates the storage to use for OS deployment. This may be a specific device name, or a more generic description such as "m2" to indicate that the OS should be deployed to an M.2 device. If not specified, the default behavior is to prioritize according to various criteria and use the first disk based on that evaluation.'), + 'description': ('Indicates the storage to use for OS deployment. This may be a specific device name (for example nvme0n1 or /dev/nvme0n1), a persistent device link such as /dev/disk/by-path/..., or a more generic description such as "m2" to indicate that the OS should be deployed to an M.2 device. The deployment fails if no disk matches. If not specified, the default behavior is to prioritize according to various criteria and use the first disk based on that evaluation.'), }, 'deployment.useinsecureprotocols': { 'description': ('What phase(s) of boot are permitted to use insecure protocols '