[pve-devel] [PATCH qemu-server 3/3] api: create: implement extracting disks when needed for import-from
Dominik Csapak
d.csapak at proxmox.com
Tue Apr 16 15:19:05 CEST 2024
when 'import-from' contains a disk image that needs extraction
(currently only from an 'ova' archive), do that in 'create_disks'
and overwrite the '$source' volid.
Collect the names into a 'delete_sources' list, that we use later
to clean it up again (either when we're finished with importing or in an
error case).
Signed-off-by: Dominik Csapak <d.csapak at proxmox.com>
---
PVE/API2/Qemu.pm | 26 ++++++++++++++++++++------
PVE/QemuServer.pm | 5 ++++-
PVE/QemuServer/Helpers.pm | 9 +++++++++
3 files changed, 33 insertions(+), 7 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index f3ce83d6..afdb507f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -161,8 +161,8 @@ my $check_storage_access = sub {
my $src_vmid;
if (PVE::Storage::parse_volume_id($src_image, 1)) { # PVE-managed volume
(my $vtype, undef, $src_vmid) = PVE::Storage::parse_volname($storecfg, $src_image);
- raise_param_exc({ $ds => "$src_image has wrong type '$vtype' - not an image" })
- if $vtype ne 'images';
+ raise_param_exc({ $ds => "$src_image has wrong type '$vtype' - needs to be 'images' or 'import'" })
+ if $vtype ne 'images' && $vtype ne 'import';
}
if ($src_vmid) { # might be actively used by VM and will be copied via clone_disk()
@@ -335,6 +335,7 @@ my sub create_disks : prototype($$$$$$$$$$) {
my $res = {};
my $live_import_mapping = {};
+ my $delete_sources = [];
my $code = sub {
my ($ds, $disk) = @_;
@@ -391,6 +392,13 @@ my sub create_disks : prototype($$$$$$$$$$) {
$needs_creation = $live_import;
+ if (PVE::Storage::copy_needs_extraction($source)) { # needs extraction beforehand
+ print "extracting $source\n";
+ $source = PVE::Storage::extract_disk_from_import_file($source, $vmid);
+ print "finished extracting to $source\n";
+ push @$delete_sources, $source;
+ }
+
if (PVE::Storage::parse_volume_id($source, 1)) { # PVE-managed volume
if ($live_import && $ds ne 'efidisk0') {
my $path = PVE::Storage::path($storecfg, $source)
@@ -514,13 +522,14 @@ my sub create_disks : prototype($$$$$$$$$$) {
eval { PVE::Storage::vdisk_free($storecfg, $volid); };
warn $@ if $@;
}
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
die $err;
}
# don't return empty import mappings
$live_import_mapping = undef if !%$live_import_mapping;
- return ($vollist, $res, $live_import_mapping);
+ return ($vollist, $res, $live_import_mapping, $delete_sources);
};
my $check_cpu_model_access = sub {
@@ -1079,6 +1088,7 @@ __PACKAGE__->register_method({
my $createfn = sub {
my $live_import_mapping = {};
+ my $delete_sources = [];
# ensure no old replication state are exists
PVE::ReplicationState::delete_guest_states($vmid);
@@ -1096,7 +1106,7 @@ __PACKAGE__->register_method({
my $vollist = [];
eval {
- ($vollist, my $created_opts, $live_import_mapping) = create_disks(
+ ($vollist, my $created_opts, $live_import_mapping, $delete_sources) = create_disks(
$rpcenv,
$authuser,
$conf,
@@ -1148,6 +1158,7 @@ __PACKAGE__->register_method({
eval { PVE::Storage::vdisk_free($storecfg, $volid); };
warn $@ if $@;
}
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
die "$emsg $err";
}
@@ -1164,7 +1175,7 @@ __PACKAGE__->register_method({
warn $@ if $@;
return;
} else {
- return $live_import_mapping;
+ return ($live_import_mapping, $delete_sources);
}
};
@@ -1191,7 +1202,7 @@ __PACKAGE__->register_method({
$code = sub {
# If a live import was requested the create function returns
# the mapping for the startup.
- my $live_import_mapping = eval { $createfn->() };
+ my ($live_import_mapping, $delete_sources) = eval { $createfn->() };
if (my $err = $@) {
eval {
my $conffile = PVE::QemuConfig->config_file($vmid);
@@ -1213,7 +1224,10 @@ __PACKAGE__->register_method({
$vmid,
$conf,
$import_options,
+ $delete_sources,
);
+ } else {
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
}
};
}
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index abe175a4..01133f39 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -7292,7 +7292,7 @@ sub pbs_live_restore {
# therefore already handled in the `$create_disks()` call happening in the
# `create` api call
sub live_import_from_files {
- my ($mapping, $vmid, $conf, $restore_options) = @_;
+ my ($mapping, $vmid, $conf, $restore_options, $delete_sources) = @_;
my $live_restore_backing = {};
for my $dev (keys %$mapping) {
@@ -7353,6 +7353,8 @@ sub live_import_from_files {
mon_cmd($vmid, 'blockdev-del', 'node-name' => "drive-$ds-restore");
}
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
+
close($qmeventd_fd);
};
@@ -7361,6 +7363,7 @@ sub live_import_from_files {
if ($err) {
warn "An error occurred during live-restore: $err\n";
_do_vm_stop($storecfg, $vmid, 1, 1, 10, 0, 1);
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
die "live-restore failed\n";
}
diff --git a/PVE/QemuServer/Helpers.pm b/PVE/QemuServer/Helpers.pm
index 0afb6317..40b90a6e 100644
--- a/PVE/QemuServer/Helpers.pm
+++ b/PVE/QemuServer/Helpers.pm
@@ -225,4 +225,13 @@ sub windows_version {
return $winversion;
}
+sub cleanup_extracted_images {
+ my ($delete_sources) = @_;
+
+ for my $source (@$delete_sources) {
+ eval { PVE::Storage::cleanup_extracted_image($source) };
+ warn $@ if $@;
+ }
+}
+
1;
--
2.39.2
More information about the pve-devel
mailing list