On Tue Apr 1, 2025 at 10:40 AM CEST, Fabian Grünbichler wrote:
> CCing Fiona in case of further input w.r.t. export/import things
>
> On March 26, 2025 3:20 pm, Max Carrara wrote:
> > Adapt the previous description, slightly rewording it and formatting
> > it for POD under the IMPORTS AND EXPORTS section.
> > 
> > Also add docstrings for the following methods:
> > - volume_export
> > - volume_export_formats
> > - volume_import
> > - volume_import_formats
> > 
> > Signed-off-by: Max Carrara <m.carr...@proxmox.com>
> > Co-authored-by: Maximiliano Sandoval <m.sando...@proxmox.com>
> > ---
> >  src/PVE/Storage/PluginBase.pm | 134 ++++++++++++++++++++++++++--------
> >  1 file changed, 105 insertions(+), 29 deletions(-)
> > 
> > diff --git a/src/PVE/Storage/PluginBase.pm b/src/PVE/Storage/PluginBase.pm
> > index a1bfc8d..cfa5087 100644
> > --- a/src/PVE/Storage/PluginBase.pm
> > +++ b/src/PVE/Storage/PluginBase.pm
> > @@ -1345,55 +1345,131 @@ sub prune_backups {
> >  
> >  =head2 IMPORTS AND EXPORTS
> >  
> > +Any path-based storage is assumed to support C<raw> and C<tar> streams, so
> > +the default implementations in C<L<PVE::Storage::Plugin>> will return this 
> > if
> > +C<< $scfg->{path} >> is set (thereby mimicking the old C<< 
> > PVE::Storage::storage_migrate() >>
> > +function).

Replying up here to address all of the comments below: Yeah, we'll
rework this entire section here, I think, and expand upon everything
more. Seems like we missed a lot of details. :s

>
> meh, I don't think this makes sense if we want to document the
> interface, we should document the interface, and not the implementation
> of our plugin hierarchy..
>
> > +
> > +Plugins may fall back to methods like C<volume_export>, C<volume_import>, 
> > etc.
> > +of C<L<PVE::Storage::Plugin>> in case the format doesn't match their
> > +specialized implementations to reuse the C<raw>/C<tar> code.
>
> and these should move to some helper module and be used by
> PVE::Storage::Plugin, if we want to allow external plugins to re-use
> them as basic implementation..
>
> > +
> > +=head3 FORMATS
> > +
> > +The following formats are all prefixed with image information in the form 
> > of a
> > +64 bit little endian unsigned integer (C<< pack('Q\<') >>) in order to be 
> > able
> > +to preallocate the image on storages which require it.
>
> "image information" should maybe be a bit more precise, it's easy to
> guess from the name that information==size, but why not spell it out?
>
> > +
> > +=over
> > +
> > +=item * C<< raw+size >> (image files only)
> > +
> > +A raw binary data stream as produced via C<< dd if=$IMAGE_FILE >>.
>
> A binary data stream containing a volume's logical raw data, for example
> as produced via .. if the image is already in raw format, *or via
> qemu-img convert* if not.
>
> > +
> > +=item * C<< qcow2+size >>, C<< vmdk >> (image files only)
>
> missing +size for vmdk
>
> > +
> > +A raw C<qcow2>/C<vmdk>/... file as produced via C<< dd if=some_file.qcow2 
> > >>
> > +for files which are already in C<qcow2> format, or via C<qemu-img convert>.
>
> "A raw qcow2/vmdk/.. file" is confusing..
>
> A binary data stream containing the qcow2/vmdk-formatted contents of a
> qcow2/vmdk file as produced via ..
>
> the qemu-img convert part got moved to the wrong format, it's not needed
> to produce a qcow2+size stream for raw files (we don't do that), but to
> produce a raw+size stream from a qcow2 file, see above.
>
> > +
> > +B<NOTE:> These formats are only valid with C<$with_snapshots> being true 
> > (C<1>).
>
> that's not strictly speaking true, but an implementation detail of the
> current implementation. what is true is that raw+size can not contain
> snapshots for obvious reasons.
>
> > +
> > +=item * C<< tar+size >> (subvolumes only)
> > +
> > +A GNU C<tar> stream containing just the inner contents of the subvolume. 
> > This
> > +does not distinguish between the contents of a privileged or unprivileged
> > +container. In other words, this is from the root user namespace's point of 
> > view
> > +with no uid-mapping in effect. As produced via e.g.
> > +C<< tar -C vm-100-disk-1.subvol -cpf output_file.dat . >>
>
> what is "inner"? should/must the content be relative or absolute?
> anchored? ...
>
> > +
> > +=back
> > +
> >  =cut
> >  
> > -# Import/Export interface:
> > -#   Any path based storage is assumed to support 'raw' and 'tar' streams, 
> > so
> > -#   the default implementations will return this if $scfg->{path} is set,
> > -#   mimicking the old PVE::Storage::storage_migrate() function.
> > -#
> > -# Plugins may fall back to PVE::Storage::Plugin::volume_{export,import}...
> > -#   functions in case the format doesn't match their specialized
> > -#   implementations to reuse the raw/tar code.
> > -#
> > -# Format specification:
> > -#   The following formats are all prefixed with image information in the 
> > form
> > -#   of a 64 bit little endian unsigned integer (pack('Q<')) in order to be 
> > able
> > -#   to preallocate the image on storages which require it.
> > -#
> > -#   raw+size: (image files only)
> > -#     A raw binary data stream such as produced via `dd if=TheImageFile`.
> > -#   qcow2+size, vmdk: (image files only)
> > -#     A raw qcow2/vmdk/... file such as produced via `dd if=some.qcow2` for
> > -#     files which are already in qcow2 format, or via `qemu-img convert`.
> > -#     Note that these formats are only valid with $with_snapshots being 
> > true.
> > -#   tar+size: (subvolumes only)
> > -#     A GNU tar stream containing just the inner contents of the subvolume.
> > -#     This does not distinguish between the contents of a privileged or
> > -#     unprivileged container. In other words, this is from the root user
> > -#     namespace's point of view with no uid-mapping in effect.
> > -#     As produced via `tar -C vm-100-disk-1.subvol -cpf TheOutputFile.dat 
> > .`
> > +=head3 $plugin->volume_export(\%scfg, $storeid, $fh, $volname, $format [, 
> > $snapshot, $base_snapshot, $with_snapshots])
> > +
> > +=head3 $plugin->volume_export(...)
> > +
> > +Exports a volume or a volume's C<$snapshot> into a file handle C<$fh> as a
> > +stream with a desired export C<$format>. See L<FORMATS> for all 
> > import/export
> > +formats.
> > +
> > +Optionally, C<$snapshot> (if provided) may have a C<$base_snapshot>, and
> > +C<$with_snapshots> states whether the volume has snapshots overall.
>
> this is incomplete/wrong
>
> $with_snapshots means the export should include snapshots, not whether
> the volume has snapshots..
> $snapshot means "this is the snapshot to export" if only exporting the
> snapshot ($with_snapshots == 0), or "this is the *last* snapshot export"
> if exporting a stream of snapshots ($with_snapshots == 1)
> $base_snapshot means "this is the start of the snapshot range to export"
> (i.e., do an incremental export on top of this base)
>
> this is mostly only relevant for zfs at the moment (other storages can
> either export a volume including its snapshots, or just the volume, but
> no complicated incremental streams of snapshots), but will change once
> we implement replication export/import for other storages..
>
> > +
> > +C<die>s in order to abort the export if there are (grave) problems, if the
> > +given C<$format> is not supported, or if exporting volumes is not 
> > supported as
> > +a whole.
> > +
> > +=cut
> >  
> > -# Export a volume into a file handle as a stream of desired format.
> >  sub volume_export {
> >      my ($class, $scfg, $storeid, $fh, $volname, $format, $snapshot, 
> > $base_snapshot, $with_snapshots) = @_;
> >      croak "implement me in sub-class\n";
> >  }
> >  
> > +=head3 $plugin->volume_export_formats(\%scfg, $storeid, $volname [, 
> > $snapshot, $base_snapshot, $with_snapshot])
> > +
> > +=head3 $plugin->volume_export_formats(...)
> > +
> > +B<OPTIONAL:> May be implemented in a storage plugin.
> > +
> > +Returns a list of supported export formats for the given volume or 
> > snapshot.
> > +
> > +Optionally, C<$snapshot> (if provided) may have a C<$base_snapshot>, and
> > +C<$with_snapshots> states whether the volume has snapshots overall.
>
> see above.. these parameters are used to affect the returned list of
> formats
>
> > +
> > +If the storage does not support exporting volumes at all, and empty list 
> > should
> > +be returned.
> > +
> > +=cut
> > +
> >  sub volume_export_formats {
> >      my ($class, $scfg, $storeid, $volname, $snapshot, $base_snapshot, 
> > $with_snapshots) = @_;
> >      croak "implement me in sub-class\n";
> >  }
> >  
> > -# Import data from a stream, creating a new or replacing or adding to an 
> > existing volume.
> > +=head3 $plugin->volume_import(\%scfg, $storeid, $fh, $volname, $format [, 
> > $snapshot, $base_snapshot, $with_snapshots, $allow_rename])
> > +
> > +=head3 $plugin->volume_import(...)
> > +
> > +B<OPTIONAL:> May be implemented in a storage plugin.
> > +
> > +Imports data with the given C<$format> from a stream / filehandle C<$fh>,
> > +creating a new volume, or replacing or adding to an existing one. Returns 
> > the
> > +volume ID of the imported volume.
>
> I don't think we ever replace an existing volume? what we might do is
> import new snapshots on top of base_snapshot in case of an incremental
> import..
>
> maybe
>
> creating a new volume or importing additional snapshots on top of an
> existing one.
>
> > +
> > +Optionally, C<$snapshot> (if provided) may have a C<$base_snapshot>, and
> > +C<$with_snapshots> states whether the volume has snapshots overall. 
> > Renaming an
> > +existing volume may also optionally be allowed via C<$allow_rename>
>
> see above, but here $snapshot is mainly there to have the same
> arguments for volume_import_formats so a plugin can have a single
> implementation, not because it is used anywhere IIRC..
>
> > +
> > +C<die>s if the import fails, if the given C<$format> is not supported, or 
> > if
> > +importing volumes is not supported as a whole.
> > +
> > +=cut
> > +
> >  sub volume_import {
> >      my ($class, $scfg, $storeid, $fh, $volname, $format, $snapshot, 
> > $base_snapshot, $with_snapshots, $allow_rename) = @_;
> >      croak "implement me in sub-class\n";
> >  }
> >  
> > +=head3 $plugin->volume_import_formats(\%scfg, $storeid, $volname [, 
> > $snapshot, $base_snapshot, $with_snapshot])
> > +
> > +=head3 $plugin->volume_import_formats(...)
> > +
> > +B<OPTIONAL:> May be implemented in a storage plugin.
> > +
> > +Returns a list of supported import formats for the given volume or 
> > snapshot.
> > +
> > +Optionally, C<$snapshot> (if provided) may have a C<$base_snapshot>, and
> > +C<$with_snapshots> states whether the volume has snapshots overall.
>
> see above, these parameters serve the same purpose as for export_formats
> - to affect the return value / inform the plugin about the intended
> export/import
>
> it might make sense to note somewhere that the order of returned formats
> matters for both, since the first element of the intersection of both
> return values will be used to do a storage migration?
>
> > +
> > +If the storage does not support importing volumes at all, and empty list 
> > should
> > +be returned.
> > +
> > +=cut
> > +
> >  sub volume_import_formats {
> >      my ($class, $scfg, $storeid, $volname, $snapshot, $base_snapshot, 
> > $with_snapshots) = @_;
> >      croak "implement me in sub-class\n";
> >  }
> > -
> >  1;
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel@lists.proxmox.com
> https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel



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

Reply via email to