From: Dietmar Maurer <dietmar@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [RFC pve-storage 12/27] api: scan: san-luns: report path state
Date: Fri, 31 Jul 2026 12:21:41 +0200 [thread overview]
Message-ID: <20260731102156.3947857-13-dietmar@proxmox.com> (raw)
In-Reply-To: <20260731102156.3947857-1-dietmar@proxmox.com>
The path count from the sysfs slave list cannot detect a degraded
multipath map: a faulty path stays in the device mapper table until
the transport removes the device. Enrich aggregated multipath
entries with the active path count, the fault counter and the
per-path states from multipathd, so clients can show path health
per LUN. NVMe namespaces handled by native NVMe multipath get the
equivalent controller and ANA states from sysfs. The queries are
best-effort, on failure the entries simply lack the new optional
fields.
Signed-off-by: Dietmar Maurer <dietmar@proxmox.com>
---
src/PVE/API2/Storage/Scan.pm | 96 +++++++++++++++++++++++++++++++++++-
1 file changed, 94 insertions(+), 2 deletions(-)
diff --git a/src/PVE/API2/Storage/Scan.pm b/src/PVE/API2/Storage/Scan.pm
index 9b944d5..b8e5bbe 100644
--- a/src/PVE/API2/Storage/Scan.pm
+++ b/src/PVE/API2/Storage/Scan.pm
@@ -381,7 +381,9 @@ __PACKAGE__->register_method({
path => 'san-luns',
method => 'GET',
description => "List block devices (disks and multipath devices) together with their"
- . " usage, for example as candidates for a SAN backed LVM volume group.",
+ . " usage, for example as candidates for a SAN backed LVM volume group. For multipath"
+ . " mapped devices and NVMe namespaces handled by native NVMe multipath, the state"
+ . " of the member paths is included.",
protected => 1,
proxyto => "node",
permissions => {
@@ -418,10 +420,76 @@ __PACKAGE__->register_method({
serial => { type => 'string', optional => 1 },
wwn => { type => 'string', optional => 1 },
paths => {
- description => "The number of paths of a multipath mapped device.",
+ description => "The number of paths of a multipath mapped device or of"
+ . " an NVMe namespace attached through multiple controllers.",
type => 'integer',
optional => 1,
},
+ 'active-paths' => {
+ description => "The number of paths that are usable, that is, neither"
+ . " reported as failed by multipathd nor on a dead controller or"
+ . " inaccessible through ANA.",
+ type => 'integer',
+ optional => 1,
+ },
+ 'path-faults' => {
+ description => "The number of path failures of a multipath mapped"
+ . " device since its creation, as reported by multipathd.",
+ type => 'integer',
+ optional => 1,
+ },
+ 'path-list' => {
+ description => "The member paths of the device with their state.",
+ type => 'array',
+ optional => 1,
+ items => {
+ type => 'object',
+ properties => {
+ device => {
+ description => "The path block device, or the NVMe"
+ . " controller device the path uses.",
+ type => 'string',
+ },
+ state => {
+ description => "The device mapper state of the path (for"
+ . " example active or failed) or the state of the NVMe"
+ . " controller (for example live or connecting).",
+ type => 'string',
+ },
+ 'checker-state' => {
+ description => "The state reported by the multipathd path"
+ . " checker, for example ready, ghost or faulty.",
+ type => 'string',
+ optional => 1,
+ },
+ 'ana-state' => {
+ description => "The Asymmetric Namespace Access state of"
+ . " the namespace on this path, for example optimized"
+ . " or inaccessible.",
+ type => 'string',
+ optional => 1,
+ },
+ 'host-wwpn' => {
+ description => "The WWPN of the host (initiator) port of"
+ . " Fibre Channel attached paths.",
+ type => 'string',
+ optional => 1,
+ },
+ 'target-wwpn' => {
+ description => "The WWPN of the target port of Fibre"
+ . " Channel attached paths.",
+ type => 'string',
+ optional => 1,
+ },
+ address => {
+ description => "The address of the NVMe controller the"
+ . " path uses.",
+ type => 'string',
+ optional => 1,
+ },
+ },
+ },
+ },
usage => {
description => "How the device is currently used. 'lvm' means it is an LVM"
. " physical volume, see the 'vgname' property.",
@@ -455,6 +523,15 @@ __PACKAGE__->register_method({
my $disks = PVE::Diskmanage::get_disks(undef, 1, 0);
my $multipath = PVE::Diskmanage::get_multipath_disks();
+ # path state is auxiliary information, a multipathd failure must not break the scan
+ my $mp_status = {};
+ if (scalar(keys %$multipath)) {
+ $mp_status = eval { PVE::Diskmanage::get_multipath_status() } // {};
+ warn $@ if $@;
+ }
+ my $nvme_status = eval { PVE::Diskmanage::get_nvme_path_status() } // {};
+ warn $@ if $@;
+
# map PV device to VG name, PVs may sit on a partition of a listed device
my $vgs = PVE::Storage::LVMPlugin::lvm_vgs(1);
my $pv2vg = {};
@@ -507,6 +584,21 @@ __PACKAGE__->register_method({
$entry->{$key} = $disk->{$key} if defined($disk->{$key});
}
+ # aggregated multipath entries carry their member list and their WWID as wwn
+ if (defined($disk->{slaves})) {
+ if (my $status = $mp_status->{ $disk->{wwn} // '' }) {
+ $entry->{'active-paths'} = $status->{active};
+ $entry->{'path-faults'} = $status->{faults};
+ $entry->{'path-list'} = $status->{paths};
+ }
+ } elsif ($disk->{devpath} =~ m|^/dev/(nvme\d+n\d+)$|) {
+ if (my $status = $nvme_status->{$1}) {
+ $entry->{paths} = scalar($status->{paths}->@*);
+ $entry->{'active-paths'} = $status->{active};
+ $entry->{'path-list'} = $status->{paths};
+ }
+ }
+
if (!defined($disk->{used})) {
$entry->{usage} = 'unused';
} elsif ($disk->{used} eq 'LVM') {
--
2.47.3
next prev parent reply other threads:[~2026-07-31 10:23 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 ` [RFC pve-storage 09/27] disks: lvm: allow creating volume groups on multipath devices Dietmar Maurer
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 ` Dietmar Maurer [this message]
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-13-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