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