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
next prev parent reply other threads:[~2024-07-17 9:41 UTC|newest]
Thread overview: 39+ 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-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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox