From: Dietmar Maurer <dietmar@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [RFC pve-storage 09/27] disks: lvm: allow creating volume groups on multipath devices
Date: Fri, 31 Jul 2026 12:21:38 +0200 [thread overview]
Message-ID: <20260731102156.3947857-10-dietmar@proxmox.com> (raw)
In-Reply-To: <20260731102156.3947857-1-dietmar@proxmox.com>
The device checks resolved the mapper symlink to the dm device, which
get_disks does not know, so creating a volume group on a multipath
mapped SAN LUN was rejected with 'not a valid local disk'. Accept
multipath devices that are not in use, so the storage wizard can
initialize a shared LVM volume group directly on a multipath LUN.
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
src/PVE/API2/Disks/LVM.pm | 8 +++++---
src/PVE/Diskmanage.pm | 27 +++++++++++++++++++++++----
src/test/disklist_test.pm | 19 +++++++++++++++++++
3 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/src/PVE/API2/Disks/LVM.pm b/src/PVE/API2/Disks/LVM.pm
index 9f8f951..35051fd 100644
--- a/src/PVE/API2/Disks/LVM.pm
+++ b/src/PVE/API2/Disks/LVM.pm
@@ -131,7 +131,8 @@ __PACKAGE__->register_method({
name => get_standard_option('pve-storage-id'),
device => {
type => 'string',
- description => 'The block device you want to create the volume group on',
+ description => 'The block device you want to create the volume group on.'
+ . ' Multipath mapped devices are supported.',
},
add_storage => {
description => "Configure storage using the Volume Group",
@@ -153,7 +154,8 @@ __PACKAGE__->register_method({
my $node = $param->{node};
$dev = PVE::Diskmanage::verify_blockdev_path($dev);
- PVE::Diskmanage::assert_disk_unused($dev);
+
+ PVE::Diskmanage::assert_disk_unused($dev, 1);
my $storage_params = {
type => 'lvm',
@@ -176,7 +178,7 @@ __PACKAGE__->register_method({
my $worker = sub {
PVE::Diskmanage::locked_disk_action(sub {
- PVE::Diskmanage::assert_disk_unused($dev);
+ PVE::Diskmanage::assert_disk_unused($dev, 1);
die "volume group with name '${name}' already exists on node '${node}'\n"
if PVE::Storage::LVMPlugin::lvm_vgs()->{$name};
diff --git a/src/PVE/Diskmanage.pm b/src/PVE/Diskmanage.pm
index 5ac04dd..ab5db06 100644
--- a/src/PVE/Diskmanage.pm
+++ b/src/PVE/Diskmanage.pm
@@ -74,14 +74,22 @@ sub init_disk {
}
sub disk_is_used {
- my ($disk) = @_;
+ my ($disk, $allow_multipath) = @_;
my $dev = $disk;
$dev =~ s|^/dev/||;
my $disklist = get_disks($dev, 1, 1);
- die "'$disk' is not a valid local disk\n" if !defined($disklist->{$dev});
+ if (!defined($disklist->{$dev})) {
+ if ($allow_multipath) {
+ my $multipath = lookup_multipath_map($disk);
+ return defined($multipath->{used}) ? 1 : 0 if defined($multipath);
+ }
+
+ die "'$disk' is not a valid local disk\n";
+ }
+
return 1 if $disklist->{$dev}->{used};
return 0;
@@ -904,6 +912,17 @@ sub get_multipath_disks {
return $disklist;
}
+# Returns the multipath device entry if the given path refers to a multipath mapped device.
+sub lookup_multipath_map {
+ my ($devpath) = @_;
+
+ my $path = abs_path($devpath) // $devpath;
+ my $dev = strip_dev($path);
+ return undef if $dev !~ m/^dm-\d+$/;
+
+ return get_multipath_disks()->{$dev};
+}
+
sub get_partnum {
my ($part_path) = @_;
@@ -958,8 +977,8 @@ sub locked_disk_action {
}
sub assert_disk_unused {
- my ($dev) = @_;
- die "device '$dev' is already in use\n" if disk_is_used($dev);
+ my ($dev, $allow_multipath) = @_;
+ die "device '$dev' is already in use\n" if disk_is_used($dev, $allow_multipath);
return;
}
diff --git a/src/test/disklist_test.pm b/src/test/disklist_test.pm
index dc84510..d2ea3b2 100644
--- a/src/test/disklist_test.pm
+++ b/src/test/disklist_test.pm
@@ -236,6 +236,25 @@ sub test_disk_list {
print Dumper($multipath) if $print;
$testcount++;
is_deeply($multipath, $expected_multipath, 'multipath list should be the same');
+
+ eval { PVE::Diskmanage::assert_disk_unused('/dev/dm-0'); };
+ $testcount++;
+ like($@, qr/not a valid local disk/,
+ 'multipath devices require an explicit opt-in');
+
+ eval { PVE::Diskmanage::assert_disk_unused('/dev/mapper/mpatha', 1); };
+ $testcount++;
+ is($@, '', 'unused multipath alias should pass');
+
+ for my $dev (qw(dm-1 dm-2 dm-3 dm-4)) {
+ eval { PVE::Diskmanage::assert_disk_unused("/dev/$dev", 1); };
+ $testcount++;
+ like($@, qr/already in use/, "used multipath device $dev should fail");
+ }
+
+ eval { PVE::Diskmanage::assert_disk_unused('/dev/dm-99', 1); };
+ $testcount++;
+ like($@, qr/not a valid local disk/, 'unknown device mapper device should fail');
}
done_testing($testcount);
--
2.47.3
next prev parent reply other threads:[~2026-07-31 10:22 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 10:21 [RFC pve-storage/proxmox-widget-toolkit/pve-manager 00/27] add guided remote storage setup and SAN visibility Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 01/27] diskmanage: collect disk transport type from lsblk Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 02/27] diskmanage: add helper to list multipath devices Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 03/27] diskmanage: qualify NVMe over fabrics transport Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 04/27] disks: list: add include-remote parameter Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 05/27] diskmanage: include iSCSI session devices in disk enumeration Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 06/27] diskmanage: link multipath member disks to their map device Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 07/27] iscsi: factor out session device map from device list Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 08/27] api: scan: add san-luns method listing SAN LUN candidates Dietmar Maurer
2026-07-31 10:21 ` Dietmar Maurer [this message]
2026-07-31 10:21 ` [RFC pve-storage 10/27] diskmanage: add helper querying multipath path state Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 11/27] diskmanage: add helper querying NVMe native " Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 12/27] api: scan: san-luns: report " Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 13/27] iscsi plugin: list sessions of all transports and capture transport Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-storage 14/27] api: add node-level iSCSI initiator target and session API Dietmar Maurer
2026-07-31 10:21 ` [RFC proxmox-widget-toolkit 15/27] disk selectors: allow opting into remote devices Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 16/27] ui: storage: allow switching the scan node of the NFS/CIFS scan combos Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 17/27] ui: storage: add guided remote storage wizard with NFS support Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 18/27] ui: storage wizard: add SMB/CIFS support Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 19/27] ui: storage wizard: add iSCSI support Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 20/27] ui: storage wizard: add FC-attached SAN (shared LVM) support Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 21/27] ui: storage wizard: add ZFS over iSCSI support Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 22/27] ui: dc: storage: add remote storage wizard entry to the add menu Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 23/27] ui: node: add SAN LUNs panel Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 24/27] ui: san luns: show multipath path state Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 25/27] api: nodes: add iSCSI initiator API endpoint Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 26/27] pvenode: add iscsi commands Dietmar Maurer
2026-07-31 10:21 ` [RFC pve-manager 27/27] ui: san luns: show iSCSI targets and sessions Dietmar Maurer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260731102156.3947857-10-dietmar@proxmox.com \
--to=dietmar@proxmox.com \
--cc=pve-devel@lists.proxmox.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox