[pve-devel] [PATCH qemu-server 1/2] Add DiskImport module to import external disk images into a VM
Emmanuel Kasper
e.kasper at proxmox.com
Tue Apr 25 10:56:01 CEST 2017
Each disk passed as paramater is add as 'unused[n]' in the vm.conf
(the default) or ide[n]|scsi[n]|sata[n]
We rely on qemu-img(1) convert heuristics to detect the file type,
as this works in most case.
---
PVE/QemuServer/DiskImport.pm | 93 ++++++++++++++++++++++++++++++++++++++++++++
PVE/QemuServer/Makefile | 1 +
2 files changed, 94 insertions(+)
create mode 100755 PVE/QemuServer/DiskImport.pm
diff --git a/PVE/QemuServer/DiskImport.pm b/PVE/QemuServer/DiskImport.pm
new file mode 100755
index 0000000..2d210ae
--- /dev/null
+++ b/PVE/QemuServer/DiskImport.pm
@@ -0,0 +1,93 @@
+package PVE::QemuServer::DiskImport;
+
+use strict;
+use warnings;
+use Data::Dumper;
+
+use PVE::Storage;
+use PVE::Storage::Plugin;
+use PVE::QemuServer;
+use PVE::Tools 'run_command';
+
+# given a hash reference with the following structure,
+# { src_path => $path_to_file,
+# vmid => target_vmid,
+# storage_id => $storage_id,
+# disk_entry => $disk_entry, # leave this undef to create an 'unused' volume
+# debug => 0 }
+# this sub will import an external disk image to a PVE storage
+# and create a disk_entry key (ide0 | unused0) pointing to the created volume
+sub do_import {
+ my ($args) = @_;
+ my $dst = {}; # parameters that we will pass to qemu-img
+
+ # get the needed size from source disk
+ my ($virtual_src_size, $src_format, $used, $parent) = PVE::Storage::Plugin::file_size_info($args->{src_path});
+
+ # allocate an image of the needed size
+ my $storecfg = PVE::Storage::config();
+ $dst->{volid} = PVE::Storage::vdisk_alloc($storecfg,
+ $args->{storage_id}, $args->{vmid}, undef, undef, $virtual_src_size / 1024);
+
+ # get target image's path, whether it's possible to sparseinit, and target format
+ $dst->{path} = PVE::Storage::path($storecfg, $dst->{volid});
+ $dst->{sparseinit} = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $dst->{volid});
+ $dst->{format} = PVE::QemuServer::qemu_img_format($storecfg, $args->{storage_id});
+ $dst->{size} = $virtual_src_size;
+
+ warn "\$args: ", Dumper($args), "\$dst->{volid}: $dst->{volid}", "\$dst: ", Dumper($dst) if $args->{debug};
+
+ # qemu-img convert does the hard job
+ # we don't attempt to guest filetypes ourselves
+ my $convert_command = ['qemu-img', 'convert', $args->{src_path}, '-p', '-n'];
+ if ($dst->{has_sparseinit}) {
+ push @$convert_command, "zeroinit:$dst->{path}";
+ } else {
+ push @$convert_command, $dst->{path};
+ }
+
+ my $config_key;
+ eval {
+ # trap interrupts so we have a chance to clean up
+ local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = $SIG{PIPE} = sub {
+ die "interrupted by signal\n";
+ };
+ PVE::Storage::activate_volumes($storecfg, [$dst->{volid}]);
+ run_command($convert_command);
+ PVE::Storage::deactivate_volumes($storecfg, [$dst->{volid}]);
+ $config_key = __create_disk_entry($storecfg, $args->{vmid}, $args->{disk_entry}, $dst);
+ };
+ my $err = $@;
+ if ($err) {
+ PVE::Storage::vdisk_free($storecfg, $dst->{volid}) if PVE::Storage::path($storecfg, $dst->{volid});
+ die $err;
+ }
+
+ return $config_key;
+}
+
+sub __create_disk_entry {
+ my ($storecfg, $vmid, $disk_entry, $dst) = @_;
+ if (PVE::QemuServer::vm_is_volid_owner($storecfg, $vmid, $dst->{volid})) {
+ my $vm_conf = PVE::QemuConfig->load_config($vmid);
+
+ my $create_active_disk_entry = sub {
+ if (PVE::QemuServer::is_valid_disk_entryname($disk_entry)) {
+ my $vm_conf->{$disk_entry} = PVE::QemuServer::print_disk_entry($vmid, { file => $dst->{volid}, size => $dst->{size} });
+ PVE::QemuConfig->write_config($vmid, $vm_conf);
+ return $disk_entry;
+ }
+ return undef;
+ };
+
+ my $create_unused_disk_entry = sub {
+ my $disk_key = PVE::QemuConfig->add_unused_volume($vm_conf, $dst->{volid});
+ PVE::QemuConfig->write_config($vmid, $vm_conf);
+ return $disk_key;
+ };
+
+ return PVE::QemuConfig->lock_config($vmid, $disk_entry ? $create_active_disk_entry : $create_unused_disk_entry);
+ }
+}
+
+1;
diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile
index 06617c5..b61a99a 100644
--- a/PVE/QemuServer/Makefile
+++ b/PVE/QemuServer/Makefile
@@ -3,3 +3,4 @@ install:
install -D -m 0644 PCI.pm ${DESTDIR}${PERLDIR}/PVE/QemuServer/PCI.pm
install -D -m 0644 USB.pm ${DESTDIR}${PERLDIR}/PVE/QemuServer/USB.pm
install -D -m 0644 Memory.pm ${DESTDIR}${PERLDIR}/PVE/QemuServer/Memory.pm
+ install -D -m 0644 DiskImport.pm ${DESTDIR}${PERLDIR}/PVE/QemuServer/DiskImport.pm
--
2.11.0
More information about the pve-devel
mailing list