From: Dominik Csapak <d.csapak@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH qemu-server v2 3/4] api: create: implement extracting disks when needed for import-from
Date: Fri, 19 Apr 2024 11:46:06 +0200 [thread overview]
Message-ID: <20240419094613.1427891-14-d.csapak@proxmox.com> (raw)
In-Reply-To: <20240419094613.1427891-1-d.csapak@proxmox.com>
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@proxmox.com>
---
changes from v1:
* put extraction into branch for managed volids
* adapt to new module location
* add checks for the impor storage if it support 'images'
(otherwise we cannot extract there)
* add cleanup to other 'create_disks' method
PVE/API2/Qemu.pm | 44 ++++++++++++++++++++++++++++++---------
PVE/QemuServer.pm | 5 ++++-
PVE/QemuServer/Helpers.pm | 10 +++++++++
3 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 2a349c8c..d32967dc 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -24,6 +24,7 @@ use PVE::JSONSchema qw(get_standard_option);
use PVE::RESTHandler;
use PVE::ReplicationConfig;
use PVE::GuestHelpers qw(assert_tag_permissions);
+use PVE::GuestImport;
use PVE::QemuConfig;
use PVE::QemuServer;
use PVE::QemuServer::Cloudinit;
@@ -159,10 +160,19 @@ my $check_storage_access = sub {
if (my $src_image = $drive->{'import-from'}) {
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';
+ if (my ($storeid, $volname) = PVE::Storage::parse_volume_id($src_image, 1)) { # PVE-managed volume
+ my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
+ my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+ (my $vtype, undef, $src_vmid) = $plugin->parse_volname($volname);
+
+ raise_param_exc({ $ds => "$src_image has wrong type '$vtype' - needs to be 'images' or 'import'" })
+ if $vtype ne 'images' && $vtype ne 'import';
+
+ if (PVE::GuestImport::copy_needs_extraction($src_image)) {
+ raise_param_exc({ $ds => "$src_image is not on an storage with 'images' content type."})
+ if !$scfg->{content}->{images};
+ $rpcenv->check($authuser, "/storage/$storeid", ['Datastore.AllocateSpace']);
+ }
}
if ($src_vmid) { # might be actively used by VM and will be copied via clone_disk()
@@ -335,6 +345,7 @@ my sub create_disks : prototype($$$$$$$$$$) {
my $res = {};
my $live_import_mapping = {};
+ my $delete_sources = [];
my $code = sub {
my ($ds, $disk) = @_;
@@ -392,6 +403,12 @@ my sub create_disks : prototype($$$$$$$$$$) {
$needs_creation = $live_import;
if (PVE::Storage::parse_volume_id($source, 1)) { # PVE-managed volume
+ if (PVE::GuestImport::copy_needs_extraction($source)) { # needs extraction beforehand
+ print "extracting $source\n";
+ $source = PVE::GuestImport::extract_disk_from_import_file($source, $vmid);
+ print "finished extracting to $source\n";
+ push @$delete_sources, $source;
+ }
if ($live_import && $ds ne 'efidisk0') {
my $path = PVE::Storage::path($storecfg, $source)
or die "failed to get a path for '$source'\n";
@@ -514,13 +531,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 +1097,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 +1115,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,
@@ -1149,6 +1168,7 @@ __PACKAGE__->register_method({
eval { PVE::Storage::vdisk_free($storecfg, $volid); };
warn $@ if $@;
}
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
die "$emsg $err";
}
@@ -1165,7 +1185,7 @@ __PACKAGE__->register_method({
warn $@ if $@;
return;
} else {
- return $live_import_mapping;
+ return ($live_import_mapping, $delete_sources);
}
};
@@ -1192,7 +1212,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);
@@ -1214,7 +1234,10 @@ __PACKAGE__->register_method({
$vmid,
$conf,
$import_options,
+ $delete_sources,
);
+ } else {
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
}
};
}
@@ -1939,8 +1962,7 @@ my $update_vm_api = sub {
assert_scsi_feature_compatibility($opt, $conf, $storecfg, $param->{$opt})
if $opt =~ m/^scsi\d+$/;
-
- my (undef, $created_opts) = create_disks(
+ my (undef, $created_opts, undef, $delete_sources) = create_disks(
$rpcenv,
$authuser,
$conf,
@@ -1954,6 +1976,8 @@ my $update_vm_api = sub {
);
$conf->{pending}->{$_} = $created_opts->{$_} for keys $created_opts->%*;
+ PVE::QemuServer::Helpers::cleanup_extracted_images($delete_sources);
+
# default legacy boot order implies all cdroms anyway
if (@bootorder) {
# append new CD drives to bootorder to mark them bootable
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 28e630d3..f842451e 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -7303,7 +7303,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) {
@@ -7364,6 +7364,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);
};
@@ -7372,6 +7374,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..f6bec1d4 100644
--- a/PVE/QemuServer/Helpers.pm
+++ b/PVE/QemuServer/Helpers.pm
@@ -6,6 +6,7 @@ use warnings;
use File::stat;
use JSON;
+use PVE::GuestImport;
use PVE::INotify;
use PVE::ProcFSTools;
@@ -225,4 +226,13 @@ sub windows_version {
return $winversion;
}
+sub cleanup_extracted_images {
+ my ($delete_sources) = @_;
+
+ for my $source (@$delete_sources) {
+ eval { PVE::GuestImport::cleanup_extracted_image($source) };
+ warn $@ if $@;
+ }
+}
+
1;
--
2.39.2
_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
next prev parent reply other threads:[~2024-04-19 9:47 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-19 9:45 [pve-devel] [PATCH storage/qemu-server/manager v2] implement ova/ovf import for file based storages Dominik Csapak
2024-04-19 9:45 ` [pve-devel] [PATCH storage v2 01/10] copy OVF.pm from qemu-server Dominik Csapak
2024-04-19 9:45 ` [pve-devel] [PATCH storage v2 02/10] plugin: dir: implement import content type Dominik Csapak
2024-04-22 11:00 ` Fiona Ebner
2024-04-22 11:09 ` Dominik Csapak
2024-04-22 11:34 ` Fiona Ebner
2024-04-22 11:56 ` Dominik Csapak
2024-04-22 12:14 ` Fiona Ebner
2024-04-19 9:45 ` [pve-devel] [PATCH storage v2 03/10] plugin: dir: handle ova files for import Dominik Csapak
2024-04-19 9:45 ` [pve-devel] [PATCH storage v2 04/10] ovf: implement parsing the ostype Dominik Csapak
2024-04-19 9:45 ` [pve-devel] [PATCH storage v2 05/10] ovf: implement parsing out firmware type Dominik Csapak
2024-04-19 9:45 ` [pve-devel] [PATCH storage v2 06/10] ovf: implement rudimentary boot order Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH storage v2 07/10] ovf: implement parsing nics Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH storage v2 08/10] api: allow ova upload/download Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH storage v2 09/10] plugin: enable import for nfs/btrfs/cifs/cephfs/glusterfs Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH storage v2 10/10] add 'import' content type to 'check_volume_access' Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH qemu-server v2 1/4] api: delete unused OVF.pm Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH qemu-server v2 2/4] use OVF from Storage Dominik Csapak
2024-04-19 9:46 ` Dominik Csapak [this message]
2024-04-19 9:46 ` [pve-devel] [PATCH qemu-server v2 4/4] api: create: add 'import-extraction-storage' parameter Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH manager v2 1/6] ui: fix special 'import' icon for non-esxi storages Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH manager v2 2/6] ui: guest import: add ova-needs-extracting warning text Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH manager v2 3/6] ui: enable import content type for relevant storages Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH manager v2 4/6] ui: enable upload/download/remove buttons for 'import' type storages Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH manager v2 5/6] ui: guest import: add storage selector for ova extraction storage Dominik Csapak
2024-04-19 9:46 ` [pve-devel] [PATCH manager v2 6/6] ui: guest import: change icon/text for non-esxi import storage Dominik Csapak
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=20240419094613.1427891-14-d.csapak@proxmox.com \
--to=d.csapak@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