From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <pve-devel-bounces@lists.proxmox.com>
Received: from firstgate.proxmox.com (firstgate.proxmox.com [IPv6:2a01:7e0:0:424::9])
	by lore.proxmox.com (Postfix) with ESMTPS id 501E01FF15C
	for <inbox@lore.proxmox.com>; Wed, 26 Mar 2025 15:21:22 +0100 (CET)
Received: from firstgate.proxmox.com (localhost [127.0.0.1])
	by firstgate.proxmox.com (Proxmox) with ESMTP id 684AA391CE;
	Wed, 26 Mar 2025 15:21:10 +0100 (CET)
From: Max Carrara <m.carrara@proxmox.com>
To: pve-devel@lists.proxmox.com
Date: Wed, 26 Mar 2025 15:20:54 +0100
Message-Id: <20250326142059.261938-4-m.carrara@proxmox.com>
X-Mailer: git-send-email 2.39.5
In-Reply-To: <20250326142059.261938-1-m.carrara@proxmox.com>
References: <20250326142059.261938-1-m.carrara@proxmox.com>
MIME-Version: 1.0
X-SPAM-LEVEL: Spam detection results:  0
 AWL 0.074 Adjusted score from AWL reputation of From: address
 BAYES_00                 -1.9 Bayes spam probability is 0 to 1%
 DMARC_MISSING             0.1 Missing DMARC policy
 KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment
 SPF_HELO_NONE           0.001 SPF: HELO does not publish an SPF Record
 SPF_PASS               -0.001 SPF: sender matches SPF record
Subject: [pve-devel] [PATCH v1 pve-storage 3/8] pluginbase: document
 SectionConfig methods
X-BeenThere: pve-devel@lists.proxmox.com
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: Proxmox VE development discussion <pve-devel.lists.proxmox.com>
List-Unsubscribe: <https://lists.proxmox.com/cgi-bin/mailman/options/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=unsubscribe>
List-Archive: <http://lists.proxmox.com/pipermail/pve-devel/>
List-Post: <mailto:pve-devel@lists.proxmox.com>
List-Help: <mailto:pve-devel-request@lists.proxmox.com?subject=help>
List-Subscribe: <https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel>, 
 <mailto:pve-devel-request@lists.proxmox.com?subject=subscribe>
Reply-To: Proxmox VE development discussion <pve-devel@lists.proxmox.com>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: pve-devel-bounces@lists.proxmox.com
Sender: "pve-devel" <pve-devel-bounces@lists.proxmox.com>

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@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



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