[pve-devel] [PATCH v1 pve-storage 3/8] pluginbase: document SectionConfig methods
Max Carrara
m.carrara at proxmox.com
Wed Mar 26 15:20:54 CET 2025
This commit adds docstrings for the relevant PVE::SectionConfig
methods in the context of the storage plugin API.
Signed-off-by: Max Carrara <m.carrara at proxmox.com>
---
src/PVE/Storage/PluginBase.pm | 194 +++++++++++++++++++++++++++++++++-
1 file changed, 192 insertions(+), 2 deletions(-)
diff --git a/src/PVE/Storage/PluginBase.pm b/src/PVE/Storage/PluginBase.pm
index 16977f3..5f7e6fd 100644
--- a/src/PVE/Storage/PluginBase.pm
+++ b/src/PVE/Storage/PluginBase.pm
@@ -88,7 +88,7 @@ package PVE::Storage::PluginBase;
use strict;
use warnings;
-use Carp qw(croak);
+use Carp qw(croak confess);
use parent qw(PVE::SectionConfig);
@@ -100,27 +100,217 @@ use parent qw(PVE::SectionConfig);
=cut
+=head3 $plugin->type()
+
+B<REQUIRED:> Must be implemented in every storage plugin.
+
+This should return a string with which the plugin can be uniquely identified.
+
+Any string is acceptable, as long as it's descriptive and you're sure it won't
+conflict with another plugin. In the cases of built-in plugins, you will often
+find the filesystem name or something similar being used.
+
+See C<L<PVE::SectionConfig/type>> for more information.
+
+=cut
+
sub type {
croak "implement me in sub-class\n";
}
+=head3 $plugin->properties()
+
+B<OPTIONAL:> May be implemented in a storage plugin.
+
+This method should be implemented if there are additional properties to be used
+by your plugin. Since properties are global and may be reused across plugins,
+the names of properties must not collide with one another.
+
+When implementing a third-party plugin, it is recommended to prefix properties
+with some kind of identifier, like so:
+
+ sub properties {
+ return {
+ 'example-storage-address' => {
+ description => 'Host address of the ExampleStorage to connect to.',
+ type => 'string',
+ },
+ 'example-storage-pool' => {
+ description => 'Name of the ExampleStorage pool to use.',
+ type => 'string',
+ },
+ # [...]
+ };
+ }
+
+However, it is encouraged to reuse properties of inbuilt plugins whenever
+possible. There are a few provided properties that are regarded as I<sensitive>
+and will be treated differently in order to not expose them or write them as
+plain text into configuration files. One such property fit for external use is
+C<password>, which you can use to provide a password, API secret, or similar.
+
+See C<L<PVE::SectionConfig/properties>> for more information.
+
+=cut
+
sub properties {
my ($class) = @_;
return $class->SUPER::properties();
}
+=head3 $plugin->options()
+
+B<REQUIRED:> Must be implemented in every storage plugin.
+
+This method returns a hash of the properties used by the plugin. Because
+properties are shared among plugins, it is recommended to reuse any existing
+ones of inbuilt plugins and only define custom properties via
+C<L<< properties()|/"$plugin->properties()" >>> if necessary.
+
+The properties a plugin uses are then declared as follows:
+
+ sub options {
+ return {
+ nodes => { optional => 1 },
+ content => { optional => 1 },
+ disable => { optional => 1 },
+ 'example-storage-pool' => { fixed => 1 },
+ 'example-storage-address' => { fixed => 1 },
+ password => { optional => 1 },
+ };
+ }
+
+C<optional> properties are not required to be set. It is recommended to set
+most properties optional by default, unless it I<really> is required to always
+exist.
+
+C<fixed> properties can only be set when creating a new storage via the plugin
+and cannot be changed afterwards.
+
+See C<L<PVE::SectionConfig/options>> for more information.
+
+=cut
+
sub options {
my ($class) = @_;
return $class->SUPER::options();
}
+=head3 $plugin->plugindata()
+
+B<REQUIRED:> Must be implemented in every storage plugin.
+
+This method returns a hash that specifies additional capabilities of the storage
+plugin, such as what kinds of data may be stored on it or what VM disk formats
+the storage supports. Additionally, defaults may also be set. This is done
+through the C<content> and C<format> keys.
+
+The C<content> key is used to declare B<supported content types> and their
+defaults, while the C<format> key declares B<supported disk formats> and the
+default disk format of the storage:
+
+ sub plugindata {
+ return {
+ content => [
+ # possible content types
+ {
+ images => 1, # disk images
+ rootdir => 1, # container root directories
+ vztmpl => 1, # container templates
+ iso => 1, # iso images
+ backup => 1, # vzdump backup files
+ snippets => 1, # snippets
+ import => 1, # imports; see explanation below
+ none => 1, # no content; see explanation below
+ },
+ # defaults if 'content' isn't explicitly set
+ {
+ images => 1, # store disk images by default
+ rootdir => 1 # store containers by default
+ # possible to add more or have no defaults
+ }
+ ],
+ format => [
+ # possible disk formats
+ {
+ raw => 1, # raw disk image
+ qcow2 => 1, # QEMU image format
+ vmdk => 1, # VMware image format
+ subvol => 1 # subvolumes; see explanation below
+ },
+ "qcow2" # default if 'format' isn't explicitly set
+ ]
+ # [...]
+ };
+ }
+
+While the example above depicts a rather capable storage, the following
+shows a simpler storage that can only be used for VM disks:
+
+ sub plugindata {
+ return {
+ content => [
+ { images => 1 },
+ ],
+ format => [
+ { raw => 1 },
+ "raw",
+ ]
+ };
+ }
+
+Which content types and formats are supported depends on the underlying storage
+implementation.
+
+B<Regarding C<import>:> The C<import> content type is used internally to
+interface with virtual guests of foreign sources or formats. The corresponding
+functionality has not yet been published to the public parts of the storage
+API. Third-party plugins therefore should not declare this content type.
+
+B<Regarding C<none>:> The C<none> content type denotes the I<absence> of other
+types of content, i.e. this content type may only be set on a storage if no
+other content type is set. This is used internally for storages that support
+adding another storage "on top" of them; at the moment, this makes it possible
+to set up an LVM (thin) pool on top of an iSCSI LUN. The corresponding
+functionality has not yet been published to the public parts of the storage
+API. Third-party plugins therefore should not declare this content type.
+
+B<Regarding C<subvol>:> The C<subvol> format is used internally to allow the
+root directories of containers to use ZFS subvolumes (also known as
+I<ZFS datasets>, not to be confused with I<ZVOLs>). Third-party plugins should
+not declare this format type.
+
+There is one more key, C<select_existing>, which is used internally for
+ISCSI-related GUI functionality. Third-party plugins should not declare this
+key.
+
+=cut
+
sub plugindata {
my ($class) = @_;
return $class->SUPER::plugindata();
}
+=head3 $plugin->private()
+
+B<WARNING:> This method is provided by C<L<PVE::Storage::Plugin>> and
+must be used as-is. It is merely documented here for informal purposes
+and B<must not be overridden.>
+
+Returns a hash containing the tracked plugin metadata, most notably the
+C<propertyList>, which contains all known properties of all plugins.
+
+C<L<PVE::Storage::Plugin>> uses this to predefine a lot of useful properties
+that are relevant for all plugins. Core functionality such as defining
+whether a storage is shared, which nodes may use it, whether a storage
+is enabled or not, etc. are implemented via these properties.
+
+See C<L<PVE::SectionConfig/private>> for more information.
+
+=cut
+
sub private {
- croak "implement me in sub-class\n";
+ confess "private() is provided by PVE::Storage::Plugin and must not be overridden";
}
=head2 GENERAL
--
2.39.5
More information about the pve-devel
mailing list