public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Filip Schauer <f.schauer@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH storage v8 3/9] plugin: allow volume import of iso, snippets, vztmpl and import
Date: Tue, 16 Sep 2025 14:32:48 +0200	[thread overview]
Message-ID: <20250916123257.107491-4-f.schauer@proxmox.com> (raw)
In-Reply-To: <20250916123257.107491-1-f.schauer@proxmox.com>

Extend volume import functionality to support 'iso', 'snippets',
'vztmpl', and 'import' types, in addition to the existing support for
'images' and 'rootdir'. This is a prerequisite for the ability to move
ISOs, snippets and container templates between nodes.

Existing behavior for importing VM disks and container volumes remains
unchanged.

Signed-off-by: Filip Schauer <f.schauer@proxmox.com>
---
 src/PVE/Storage/Plugin.pm | 89 ++++++++++++++++++++++++---------------
 1 file changed, 56 insertions(+), 33 deletions(-)

diff --git a/src/PVE/Storage/Plugin.pm b/src/PVE/Storage/Plugin.pm
index 2291d72..ecf68c8 100644
--- a/src/PVE/Storage/Plugin.pm
+++ b/src/PVE/Storage/Plugin.pm
@@ -2039,7 +2039,7 @@ sub volume_export {
         if ($format eq 'raw+size') {
             die $err_msg if $with_snapshots || $file_format eq 'subvol';
             write_common_header($fh, $size);
-            if ($file_format eq 'raw') {
+            if ($file_format =~ /^(raw|ova|ovf)$/) {
                 run_command(
                     ['dd', "if=$file", "bs=4k", "status=progress"],
                     output => '>&' . fileno($fh),
@@ -2085,14 +2085,14 @@ sub volume_export {
 sub volume_export_formats {
     my ($class, $scfg, $storeid, $volname, $snapshot, $base_snapshot, $with_snapshots) = @_;
     if ($scfg->{path} && !defined($snapshot) && !defined($base_snapshot)) {
-        my $format = ($class->parse_volname($volname))[6];
+        my ($vtype, $format) = ($class->parse_volname($volname))[0, 6];
 
         if ($with_snapshots) {
             return ($format . '+size') if ($format eq 'qcow2' || $format eq 'vmdk');
             return ();
         }
         return ('tar+size') if $format eq 'subvol';
-        return ('raw+size');
+        return ('raw+size') if $vtype =~ /^(iso|snippets|vztmpl|import)$/;
     }
     return ();
 }
@@ -2126,14 +2126,20 @@ sub volume_import {
 
     # XXX: Should we bother with conversion routines at this level? This won't
     # happen without manual CLI usage, so for now we just error out...
-    die "cannot import format $format into a file of format $file_format\n"
-        if $data_format ne $file_format && !($data_format eq 'tar' && $file_format eq 'subvol');
+    if (
+        ($vtype eq 'images' || $vtype eq 'rootdir')
+        && $data_format ne $file_format
+        && !($data_format eq 'tar' && $file_format eq 'subvol')
+    ) {
+        die "cannot import format $format into a file of format $file_format\n";
+    }
 
     # Check for an existing file first since interrupting alloc_image doesn't
     # free it.
     my ($file) = $class->path($scfg, $volname, $storeid);
     if (-e $file) {
-        die "file '$file' already exists\n" if !$allow_rename;
+        die "file '$file' already exists\n"
+            if !$allow_rename || ($vtype ne 'images' && $vtype ne 'rootdir');
         warn "file '$file' already exists - importing with a different name\n";
         $name = undef;
     }
@@ -2141,33 +2147,49 @@ sub volume_import {
     my ($size) = read_common_header($fh);
     $size = PVE::Storage::Common::align_size_up($size, 1024) / 1024;
 
-    eval {
-        my $allocname = $class->alloc_image($storeid, $scfg, $vmid, $file_format, $name, $size);
-        my $oldname = $volname;
-        $volname = $allocname;
-        if (defined($name) && $allocname ne $oldname) {
-            die "internal error: unexpected allocated name: '$allocname' != '$oldname'\n";
+    if ($vtype eq 'images' || $vtype eq 'rootdir') {
+        eval {
+            my $allocname =
+                $class->alloc_image($storeid, $scfg, $vmid, $file_format, $name, $size);
+            my $oldname = $volname;
+            $volname = $allocname;
+            if (defined($name) && $allocname ne $oldname) {
+                die "internal error: unexpected allocated name: '$allocname' != '$oldname'\n";
+            }
+            my ($file) = $class->path($scfg, $volname, $storeid)
+                or die "internal error: failed to get path to newly allocated volume $volname\n";
+            if ($data_format eq 'raw' || $data_format eq 'qcow2' || $data_format eq 'vmdk') {
+                run_command(
+                    ['dd', "of=$file", 'conv=sparse', 'bs=64k'],
+                    input => '<&' . fileno($fh),
+                );
+            } elsif ($data_format eq 'tar') {
+                run_command(
+                    ['tar', @COMMON_TAR_FLAGS, '-C', $file, '-xf', '-'],
+                    input => '<&' . fileno($fh),
+                );
+            } else {
+                die "volume import format '$format' not available for $class";
+            }
+        };
+        if (my $err = $@) {
+            eval { $class->free_image($storeid, $scfg, $volname, 0, $file_format) };
+            warn $@ if $@;
+            die $err;
         }
-        my ($file) = $class->path($scfg, $volname, $storeid)
-            or die "internal error: failed to get path to newly allocated volume $volname\n";
-        if ($data_format eq 'raw' || $data_format eq 'qcow2' || $data_format eq 'vmdk') {
-            run_command(
-                ['dd', "of=$file", 'conv=sparse', 'bs=64k'],
-                input => '<&' . fileno($fh),
-            );
-        } elsif ($data_format eq 'tar') {
-            run_command(
-                ['tar', @COMMON_TAR_FLAGS, '-C', $file, '-xf', '-'],
-                input => '<&' . fileno($fh),
-            );
-        } else {
-            die "volume import format '$format' not available for $class";
+    } elsif (grep { $vtype eq $_ } qw(import iso snippets vztmpl)) {
+        eval {
+            run_command(['dd', "of=$file", 'conv=excl', 'bs=64k'], input => '<&' . fileno($fh));
+        };
+        if (my $err = $@) {
+            if (-e $file) {
+                eval { unlink($file) };
+                warn $@ if $@;
+            }
+            die $err;
         }
-    };
-    if (my $err = $@) {
-        eval { $class->free_image($storeid, $scfg, $volname, 0, $file_format) };
-        warn $@ if $@;
-        die $err;
+    } else {
+        die "importing volume of type '$vtype' not implemented\n";
     }
 
     return "$storeid:$volname";
@@ -2176,13 +2198,14 @@ sub volume_import {
 sub volume_import_formats {
     my ($class, $scfg, $storeid, $volname, $snapshot, $base_snapshot, $with_snapshots) = @_;
     if ($scfg->{path} && !defined($base_snapshot)) {
-        my $format = ($class->parse_volname($volname))[6];
+        my ($vtype, $format) = ($class->parse_volname($volname))[0, 6];
+
         if ($with_snapshots) {
             return ($format . '+size') if ($format eq 'qcow2' || $format eq 'vmdk');
             return ();
         }
         return ('tar+size') if $format eq 'subvol';
-        return ('raw+size');
+        return ('raw+size') if $vtype =~ /^(iso|snippets|vztmpl|import)$/;
     }
     return ();
 }
-- 
2.47.3



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


  parent reply	other threads:[~2025-09-16 12:35 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-16 12:32 [pve-devel] [PATCH storage v8 0/9] support copying volumes between storages Filip Schauer
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 1/9] storage migrate: remove remnant from rsync-based migration Filip Schauer
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 2/9] storage migrate: avoid ssh when moving a volume locally Filip Schauer
2025-09-16 12:32 ` Filip Schauer [this message]
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 4/9] api: content: implement copying volumes between storages Filip Schauer
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 5/9] introduce $vtype+meta export formats Filip Schauer
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 6/9] api: content: support copying backups between path based storages Filip Schauer
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 7/9] storage: introduce decompress_archive_into_pipe helper Filip Schauer
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 8/9] support copying VMA backups to PBS Filip Schauer
2025-09-16 12:32 ` [pve-devel] [PATCH storage v8 9/9] pvesm: add a copy-volume command Filip Schauer

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=20250916123257.107491-4-f.schauer@proxmox.com \
    --to=f.schauer@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
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal