From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gate001.proxmox.com (gate001.proxmox.com [45.144.208.40]) by lore.proxmox.com (Postfix) with ESMTPS id DAB9C1FF0E4 for ; Tue, 28 Jul 2026 14:22:47 +0200 (CEST) Received: from gate001.proxmox.com (localhost.localdomain [127.0.0.1]) by gate001.proxmox.com (Proxmox) with ESMTP id 9684521320; Tue, 28 Jul 2026 14:22:47 +0200 (CEST) From: Thomas Ellmenreich To: pve-devel@lists.proxmox.com Subject: [PATCH storage 1/2] add subroutine to classify volume ids Date: Tue, 28 Jul 2026 14:22:17 +0200 Message-ID: <20260728122218.202963-2-t.ellmenreich@proxmox.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260728122218.202963-1-t.ellmenreich@proxmox.com> References: <20260728122218.202963-1-t.ellmenreich@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Bm-Milter-Handled: 55990f41-d878-4baa-be0a-ee34c49e34d2 X-Bm-Transport-Timestamp: 1785241326235 X-SPAM-LEVEL: Spam detection results: 0 AWL 0.089 Adjusted score from AWL reputation of From: address DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment (newer systems) RCVD_IN_DNSWL_LOW -0.7 Sender listed at https://www.dnswl.org/, low trust SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record Message-ID-Hash: GDI3UT2DJMAPRK4FLNQDGN4K4IHF2SIH X-Message-ID-Hash: GDI3UT2DJMAPRK4FLNQDGN4K4IHF2SIH X-MailFrom: t.ellmenreich@proxmox.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Thomas Ellmenreich X-Mailman-Version: 3.3.10 Precedence: list List-Id: Proxmox VE development discussion List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: To enable easier branching on different types of volume id's a new subroutine classify_volume_id is added. It classifies the passed type as one of 'volume', 'cdrom', 'none' or 'absolute'. Depending on how the 'noerr' option is set values that cannot be categorized throw an error or return undef. The constants and subroutine are exported by the Storage module Signed-off-by: Thomas Ellmenreich --- src/PVE/Storage.pm | 21 +++++++++++++++++++++ src/PVE/Storage/Plugin.pm | 25 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/PVE/Storage.pm b/src/PVE/Storage.pm index 64ea9da..1401d69 100755 --- a/src/PVE/Storage.pm +++ b/src/PVE/Storage.pm @@ -40,6 +40,16 @@ use PVE::Storage::PBSPlugin; use PVE::Storage::BTRFSPlugin; use PVE::Storage::ESXiPlugin; +use base qw(Exporter); + +our @EXPORT_OK = qw( + classify_volume_id + $VOL_NONE + $VOL_CDROM + $VOL_ABSOLUTE + $VOL_VOLUME +); + # Storage API version. Increment it on changes in storage API interface. use constant APIVER => 15; # Age is the number of versions we're backward compatible with. @@ -131,6 +141,11 @@ our $OVA_CONTENT_RE_1 = qr/${SAFE_CHAR_WITH_WHITESPACE_CLASS_RE}+\.(qcow2|raw|vm # FIXME remove with PVE 9.0, add versioned breaks for pve-manager our $vztmpl_extension_re = $VZTMPL_EXT_RE_1; +our $VOL_NONE = PVE::Storage::Plugin::VOL_NONE(); +our $VOL_CDROM = PVE::Storage::Plugin::VOL_CDROM(); +our $VOL_ABSOLUTE = PVE::Storage::Plugin::VOL_ABSOLUTE(); +our $VOL_VOLUME = PVE::Storage::Plugin::VOL_VOLUME(); + # See the QMP reference documentation. my $allowed_qemu_blockdev_options_file = { filename => 1, @@ -615,6 +630,12 @@ sub parse_volume_id { return PVE::Storage::Plugin::parse_volume_id($volid, $noerr); } +sub classify_volume_id { + my ($volid, $noerr) = @_; + + return PVE::Storage::Plugin::classify_volume_id($volid, $noerr); +} + # test if we have read access to volid sub check_volume_access { my ($rpcenv, $user, $cfg, $vmid, $volid, $type) = @_; diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm index 4f69f9b..180ad6c 100644 --- a/src/PVE/Storage/Plugin.pm +++ b/src/PVE/Storage/Plugin.pm @@ -27,6 +27,14 @@ use constant COMPRESSOR_RE => join('|', KNOWN_COMPRESSION_FORMATS); use constant LOG_EXT => ".log"; use constant NOTES_EXT => ".notes"; +# types of volume ids +use constant { + VOL_NONE => 'none', + VOL_CDROM => 'cdrom', + VOL_ABSOLUTE => 'absolute', + VOL_VOLUME => 'volume', +}; + our @COMMON_TAR_FLAGS = qw( --one-file-system -p --sparse --numeric-owner --acls @@ -427,6 +435,23 @@ sub parse_volume_id { die "unable to parse volume ID '$volid'\n"; } +sub classify_volume_id { + my ($volid, $noerr) = @_; + + if (!defined($volid) || $volid eq "none") { + return VOL_NONE; + } elsif ($volid eq 'cdrom') { + return VOL_CDROM; + } elsif ($volid =~ m|^/|) { + return VOL_ABSOLUTE; + } elsif (parse_volume_id($volid, 1)) { + return VOL_VOLUME; + } + + return undef if $noerr; + die "unable to classify volume ID '$volid'"; +} + PVE::JSONSchema::register_format('pve-dir-override', \&verify_dir_override); sub verify_dir_override { -- 2.47.3