all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Max Carrara <m.carrara@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [RFC pve-storage 16/36] plugin: dir: factor storage methods into separate common subs
Date: Wed, 17 Jul 2024 11:40:14 +0200	[thread overview]
Message-ID: <20240717094034.124857-17-m.carrara@proxmox.com> (raw)
In-Reply-To: <20240717094034.124857-1-m.carrara@proxmox.com>

This creates new helper subroutines in the `Common` module in order
to remove other plugins' dependency on `DirPlugin` in the future.
The methods are changed to call these helpers instead.

Simultaneously, emit a `warn`ing if deprecated methods / functions are
being used instead of just relying on a comment in the source code.

The new helper functions are also fully documented and use prototyes.

Signed-off-by: Max Carrara <m.carrara@proxmox.com>
---
 src/PVE/Storage/Common.pm    | 201 +++++++++++++++++++++++++++++++++++
 src/PVE/Storage/DirPlugin.pm | 104 +++++-------------
 2 files changed, 227 insertions(+), 78 deletions(-)

diff --git a/src/PVE/Storage/Common.pm b/src/PVE/Storage/Common.pm
index 0ca0db1..3cc3c37 100644
--- a/src/PVE/Storage/Common.pm
+++ b/src/PVE/Storage/Common.pm
@@ -3,13 +3,21 @@ package PVE::Storage::Common;
 use strict;
 use warnings;
 
+use Encode qw(decode encode);
+use POSIX;
+
 use PVE::JSONSchema;
+use PVE::Tools;
 
 use parent qw(Exporter);
 
 our @EXPORT_OK = qw(
     get_deprecation_warning
     storage_parse_is_mountpoint
+    storage_dir_get_volume_notes
+    storage_dir_update_volume_notes
+    storage_dir_get_volume_attribute
+    storage_dir_update_volume_attribute
 );
 
 =pod
@@ -91,4 +99,197 @@ sub storage_parse_is_mountpoint : prototype($) {
     return $is_mp; # contains a path
 }
 
+# FIXME move into 'storage_dir_get_volume_attribute' when removing
+# 'storage_dir_get_volume_notes'
+my $get_volume_notes_impl = sub {
+    my ($class, $scfg, $storeid, $volname, $timeout) = @_;
+
+    my ($vtype) = $class->parse_volname($volname);
+    return if $vtype ne 'backup';
+
+    my $path = $class->filesystem_path($scfg, $volname);
+    $path .= $class->SUPER::NOTES_EXT;
+
+    if (-f $path) {
+	my $data = PVE::Tools::file_get_contents($path);
+	return eval { decode('UTF-8', $data, 1) } // $data;
+    }
+
+    return '';
+};
+
+=pod
+
+=head3 storage_dir_get_volume_notes
+
+    $notes = storage_dir_get_volume_notes($class, $scfg, $storeid, $volname, $timeout)
+
+B<DEPRECATED:> This helper is deprecated in favour of
+C<L</storage_dir_get_volume_attribute>> and will be removed in the future.
+
+This is a general implementation of C<L<PVE::Storage::Plugin::get_volume_notes>>
+that may be used by storage plugins with a directory-based storage. It is therefore
+useful for something like L<an NFS storage|PVE::Storage::NFSPlugin>, which
+(network stuff aside) also behaves like a directory.
+
+Returns the notes from a volume named C<$volname>. The volume is expected to
+belong to the storage with ID C<$storeid> that has the configuration C<$scfg>.
+The storage must in turn stem from the storage plugin C<$class>.
+
+The C<$timeout> parameter has no effect in this case.
+
+=cut
+
+sub storage_dir_get_volume_notes : prototype($$$$$) {
+    warn get_deprecation_warning(
+	__PACKAGE__ . "::storage_dir_get_volume_attribute"
+    );
+
+    my ($class, $scfg, $storeid, $volname, $timeout) = @_;
+
+    return $get_volume_notes_impl->($class, $scfg, $storeid, $volname, $timeout);
+}
+
+# FIXME move into 'storage_dir_update_volume_attribute' when removing
+# 'storage_dir_update_volume_notes'
+my $update_volume_notes_impl = sub {
+    my ($class, $scfg, $storeid, $volname, $notes, $timeout) = @_;
+
+    my ($vtype) = $class->parse_volname($volname);
+    die "only backups can have notes\n" if $vtype ne 'backup';
+
+    my $path = $class->filesystem_path($scfg, $volname);
+    $path .= $class->SUPER::NOTES_EXT;
+
+    if (defined($notes) && $notes ne '') {
+	my $encoded = encode('UTF-8', $notes);
+	PVE::Tools::file_set_contents($path, $encoded);
+    } else {
+	unlink $path or $! == ENOENT or die "could not delete notes - $!\n";
+    }
+    return;
+};
+
+
+=pod
+
+=head3 storage_dir_update_volume_notes
+
+    $notes = storage_dir_update_volume_notes($class, $scfg, $storeid, $volname, $notes, $timeout)
+
+B<DEPRECATED:> This helper is deprecated in favour of
+C<L</storage_dir_update_volume_attribute>> and will be removed in the future.
+
+This is a general implementation of C<L<PVE::Storage::Plugin::update_volume_notes>>
+that may be used by storage plugins with a directory-based storage. It is therefore
+useful for something like L<an NFS storage|PVE::Storage::NFSPlugin>, which
+(network stuff aside) also behaves like a directory.
+
+Sets the notes of a volume named C<$volname> to C<$notes>. The volume is
+expected to belong to the storage with ID C<$storeid> that has the configuration
+C<$scfg>. The storage must in turn stem from the storage plugin C<$class>.
+
+The C<$timeout> parameter has no effect in this case.
+
+=cut
+
+sub storage_dir_update_volume_notes : prototype($$$$$$) {
+    warn get_deprecation_warning(
+	__PACKAGE__ . "storage_dir_update_volume_attribute"
+    );
+
+    my ($class, $scfg, $storeid, $volname, $notes, $timeout) = @_;
+
+    return $update_volume_notes_impl->($class, $scfg, $storeid, $volname, $notes, $timeout);
+}
+
+=pod
+
+=head3 storage_dir_get_volume_attribute
+
+    $attr_value = storage_dir_get_volume_attribute($class, $scfg, $storeid, $volname, $attribute)
+
+This is a general implementation of C<L<PVE::Storage::Plugin::get_volume_attribute>>
+that may be used by storage plugins with a directory-based storage. It is therefore
+useful for something like L<an NFS storage|PVE::Storage::NFSPlugin>, which
+(network stuff aside) also behaves like a directory.
+
+Returns the value of the attribute named C<$attribute> from a volume named
+C<$volname>. The volume is expected to belong to the storage with ID C<$storeid>
+that has the configuration C<$scfg>. The storage must in turn stem from the
+storage plugin C<$class>.
+
+Returns C<undef> if the attribute is not supported by the plugin.
+
+Dies if it encounters an error while getting the attribute.
+
+=cut
+
+sub storage_dir_get_volume_attribute : prototype($$$$$) {
+    my ($class, $scfg, $storeid, $volname, $attribute) = @_;
+
+    if ($attribute eq 'notes') {
+	return $get_volume_notes_impl->($class, $scfg, $storeid, $volname);
+    }
+
+    my ($vtype) = $class->parse_volname($volname);
+    return if $vtype ne 'backup';
+
+    if ($attribute eq 'protected') {
+	my $path = $class->filesystem_path($scfg, $volname);
+	return -e PVE::Storage::protection_file_path($path) ? 1 : 0;
+    }
+
+    return;
+}
+
+=pod
+
+=head3 storage_dir_update_volume_attribute
+
+    storage_dir_update_volume_attribute($class, $scfg, $storeid, $volname, $attribute, $value)
+
+This is a general implementation of C<L<PVE::Storage::Plugin::get_volume_attribute>>
+that may be used by storage plugins with a directory-based storage. It is therefore
+useful for something like L<an NFS storage|PVE::Storage::NFSPlugin>, which
+(network stuff aside) also behaves like a directory.
+
+Sets the value of the attribute named C<$attribute> from a volume named
+C<$volname> to C<$value>. The volume is expected to belong to the storage with
+ID C<$storeid> that has the configuration C<$scfg>. The storage must in turn
+stem from the storage plugin C<$class>.
+
+=cut
+
+sub storage_dir_update_volume_attribute : prototype($$$$$$) {
+    my ($class, $scfg, $storeid, $volname, $attribute, $value) = @_;
+
+    if ($attribute eq 'notes') {
+	return $update_volume_notes_impl->($class, $scfg, $storeid, $volname, $value);
+    }
+
+    my ($vtype) = $class->parse_volname($volname);
+    die "only backups support attribute '$attribute'\n" if $vtype ne 'backup';
+
+    if ($attribute eq 'protected') {
+	my $path = $class->filesystem_path($scfg, $volname);
+	my $protection_path = PVE::Storage::protection_file_path($path);
+
+	return if !((-e $protection_path) xor $value); # protection status already correct
+
+	if ($value) {
+	    my $fh = IO::File->new($protection_path, O_CREAT, 0644)
+		or die "unable to create protection file '$protection_path' - $!\n";
+	    close($fh);
+	} else {
+	    unlink $protection_path or $! == ENOENT
+		or die "could not delete protection file '$protection_path' - $!\n";
+	}
+
+	return;
+    }
+
+    die "attribute '$attribute' is not supported for storage type '$scfg->{type}'\n";
+}
+
 1;
diff --git a/src/PVE/Storage/DirPlugin.pm b/src/PVE/Storage/DirPlugin.pm
index ac0d365..f6e1d73 100644
--- a/src/PVE/Storage/DirPlugin.pm
+++ b/src/PVE/Storage/DirPlugin.pm
@@ -11,6 +11,10 @@ use POSIX;
 use PVE::Storage::Common qw(
     get_deprecation_warning
     storage_parse_is_mountpoint
+    storage_dir_get_volume_notes
+    storage_dir_update_volume_notes
+    storage_dir_get_volume_attribute
+    storage_dir_update_volume_attribute
 );
 use PVE::Storage::Common::Path;
 use PVE::Storage::Plugin;
@@ -106,104 +110,48 @@ sub parse_is_mountpoint {
     return storage_parse_is_mountpoint(@_);
 }
 
-# FIXME move into 'get_volume_attribute' when removing 'get_volume_notes'
-my $get_volume_notes_impl = sub {
-    my ($class, $scfg, $storeid, $volname, $timeout) = @_;
-
-    my ($vtype) = $class->parse_volname($volname);
-    return if $vtype ne 'backup';
-
-    my $path = $class->filesystem_path($scfg, $volname);
-    $path .= $class->SUPER::NOTES_EXT;
-
-    if (-f $path) {
-	my $data = PVE::Tools::file_get_contents($path);
-	return eval { decode('UTF-8', $data, 1) } // $data;
-    }
-
-    return '';
-};
-
 # FIXME remove on the next APIAGE reset.
 # Deprecated, use get_volume_attribute instead.
 sub get_volume_notes {
-    my ($class, $scfg, $storeid, $volname, $timeout) = @_;
-    return $get_volume_notes_impl->($class, $scfg, $storeid, $volname, $timeout);
-}
-
-# FIXME move into 'update_volume_attribute' when removing 'update_volume_notes'
-my $update_volume_notes_impl = sub {
-    my ($class, $scfg, $storeid, $volname, $notes, $timeout) = @_;
-
-    my ($vtype) = $class->parse_volname($volname);
-    die "only backups can have notes\n" if $vtype ne 'backup';
+    warn get_deprecation_warning(
+	"PVE::Storage::Common::storage_dir_get_volume_notes"
+    );
 
-    my $path = $class->filesystem_path($scfg, $volname);
-    $path .= $class->SUPER::NOTES_EXT;
+    my ($class, $scfg, $storeid, $volname, $timeout) = @_;
 
-    if (defined($notes) && $notes ne '') {
-	my $encoded = encode('UTF-8', $notes);
-	PVE::Tools::file_set_contents($path, $encoded);
-    } else {
-	unlink $path or $! == ENOENT or die "could not delete notes - $!\n";
-    }
-    return;
-};
+    return storage_dir_get_volume_notes(
+	$class, $scfg, $storeid, $volname, $timeout
+    );
+}
 
 # FIXME remove on the next APIAGE reset.
 # Deprecated, use update_volume_attribute instead.
 sub update_volume_notes {
+    warn get_deprecation_warning(
+	"PVE::Storage::Common::storage_dir_update_volume_notes"
+    );
+
     my ($class, $scfg, $storeid, $volname, $notes, $timeout) = @_;
-    return $update_volume_notes_impl->($class, $scfg, $storeid, $volname, $notes, $timeout);
+
+    return storage_dir_update_volume_notes(
+	$class, $scfg, $storeid, $volname, $notes, $timeout
+    );
 }
 
 sub get_volume_attribute {
     my ($class, $scfg, $storeid, $volname, $attribute) = @_;
 
-    if ($attribute eq 'notes') {
-	return $get_volume_notes_impl->($class, $scfg, $storeid, $volname);
-    }
-
-    my ($vtype) = $class->parse_volname($volname);
-    return if $vtype ne 'backup';
-
-    if ($attribute eq 'protected') {
-	my $path = $class->filesystem_path($scfg, $volname);
-	return -e PVE::Storage::protection_file_path($path) ? 1 : 0;
-    }
-
-    return;
+    return storage_dir_get_volume_attribute(
+	$class, $scfg, $storeid, $volname, $attribute
+    );
 }
 
 sub update_volume_attribute {
     my ($class, $scfg, $storeid, $volname, $attribute, $value) = @_;
 
-    if ($attribute eq 'notes') {
-	return $update_volume_notes_impl->($class, $scfg, $storeid, $volname, $value);
-    }
-
-    my ($vtype) = $class->parse_volname($volname);
-    die "only backups support attribute '$attribute'\n" if $vtype ne 'backup';
-
-    if ($attribute eq 'protected') {
-	my $path = $class->filesystem_path($scfg, $volname);
-	my $protection_path = PVE::Storage::protection_file_path($path);
-
-	return if !((-e $protection_path) xor $value); # protection status already correct
-
-	if ($value) {
-	    my $fh = IO::File->new($protection_path, O_CREAT, 0644)
-		or die "unable to create protection file '$protection_path' - $!\n";
-	    close($fh);
-	} else {
-	    unlink $protection_path or $! == ENOENT
-		or die "could not delete protection file '$protection_path' - $!\n";
-	}
-
-	return;
-    }
-
-    die "attribute '$attribute' is not supported for storage type '$scfg->{type}'\n";
+    return storage_dir_update_volume_attribute(
+	$class, $scfg, $storeid, $volname, $attribute, $value
+    );
 }
 
 sub status {
-- 
2.39.2



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  parent reply	other threads:[~2024-07-17  9:41 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-07-17  9:39 [pve-devel] [RFC pve-storage 00/36] Refactor / Cleanup of Storage Plugins Max Carrara
2024-07-17  9:39 ` [pve-devel] [RFC pve-storage 01/36] plugin: base: remove old fixme comments Max Carrara
2024-07-17 16:02   ` Thomas Lamprecht
2024-07-18  7:43     ` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 02/36] plugin: btrfs: make plugin-specific helpers private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 03/36] plugin: cephfs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 04/36] api: remove unused import of CIFS storage plugin Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 05/36] plugin: cifs: make plugin-specific helpers private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 06/36] api: remove unused import of LVM storage plugin Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 07/36] common: introduce common module Max Carrara
2024-12-13 15:40   ` Fiona Ebner
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 08/36] plugin: dir: move helper subs of directory plugin to common modules Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 09/36] plugin: lvm: move LVM helper subroutines into separate common module Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 10/36] api: replace usages of deprecated LVM helper subs with new ones Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 11/36] plugin: lvmthin: replace usages of deprecated LVM helpers " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 12/36] plugin: lvmthin: move helper that lists thinpools to common LVM module Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 13/36] common: lvm: update code style Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 14/36] api: replace usages of deprecated LVM thin pool helper sub Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 15/36] plugin: btrfs: replace deprecated helpers from directory plugin Max Carrara
2024-07-17  9:40 ` Max Carrara [this message]
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 17/36] plugin: dir: factor path validity check into helper methods Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 18/36] plugin: btrfs: remove dependency on directory plugin Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 19/36] plugin: cifs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 20/36] plugin: cephfs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 21/36] plugin: nfs: " Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 22/36] plugin: btrfs: make helper methods private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 23/36] plugin: esxi: make helper subroutines private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 24/36] plugin: esxi: remove unused helper subroutine `query_vmdk_size` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 25/36] plugin: esxi: make helper methods private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 26/36] plugin: gluster: make helper subroutines private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 27/36] plugin: iscsi-direct: make helper subroutine `iscsi_ls` private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 28/36] plugin: iscsi: factor helper functions into common module Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 29/36] plugin: iscsi: make helper subroutine `iscsi_session` private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 30/36] plugin: lvm: update definition of subroutine `check_tags` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 31/36] plugin: lvmthin: update definition of subroutine `activate_lv` Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 32/36] plugin: nfs: make helper subroutines private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 33/36] plugin: rbd: update private sub signatures and make helpers private Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 34/36] common: zfs: introduce module for common ZFS helpers Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 35/36] plugin: zfspool: move helper `zfs_parse_zvol_list` to common module Max Carrara
2024-07-17  9:40 ` [pve-devel] [RFC pve-storage 36/36] plugin: zfspool: refactor method `zfs_request` into helper subroutine Max Carrara

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=20240717094034.124857-17-m.carrara@proxmox.com \
    --to=m.carrara@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal