[pve-devel] [PATCH qemu-server 4/4] add API2 handler for uploading disk images
Timo Grodzinski
t.grodzinski at profihost.ag
Mon Feb 15 14:33:49 CET 2016
Signed-off-by: Timo Grodzinski <t.grodzinski at profihost.ag>
---
PVE/API2/Qemu.pm | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 226e597..47a0a56 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -3,6 +3,7 @@ package PVE::API2::Qemu;
use strict;
use warnings;
use Cwd 'abs_path';
+use File::Basename;
use Net::SSLeay;
use UUID;
@@ -2492,6 +2493,128 @@ __PACKAGE__->register_method({
}});
__PACKAGE__->register_method({
+ name => 'upload_image',
+ path => '{vmid}/upload_image',
+ method => 'POST',
+ proxyto => 'node',
+ description => "Upload vm disk images.",
+ permissions => { user => 'all' },
+ protected => 1,
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option( 'pve-node' ),
+ vmid => get_standard_option( 'pve-vmid' ),
+ disk => {
+ type => 'string',
+ description => "The target disk where you want to upload.",
+ enum => [ PVE::QemuServer::disknames() ],
+ },
+ filename => {
+ description => "The name of the file to create.",
+ type => 'string',
+ },
+ tmpfilename => {
+ description =>
+"The source file name. This parameter is usually set by the REST handler. You can only overwrite it when connecting to the trustet port on localhost.",
+ type => 'string',
+ optional => 1,
+ },
+ },
+ },
+ returns => { type => "string" },
+ code => sub {
+ my ( $param ) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+
+ my $authuser = $rpcenv->get_user();
+
+ my $node = extract_param( $param, 'node' );
+
+ my $vmid = extract_param( $param, 'vmid' );
+ die "vm $vmid is running\n" if PVE::QemuServer::check_running( $vmid );
+
+ my $digest = extract_param( $param, 'digest' );
+
+ my $conf = PVE::QemuServer::load_config( $vmid );
+ die "checksum missmatch (file change by other user?)\n" if $digest && $digest ne $conf->{digest};
+
+ my $disk = extract_param( $param, 'disk' );
+ die "disk '$disk' does not exist\n" if !$conf->{$disk};
+
+ my $tmpfilename = extract_param( $param, 'tmpfilename' );
+ die "missing temporary file name\n" if !$tmpfilename;
+
+ my $size = -s $tmpfilename;
+ die "temporary file '$tmpfilename' does not exists\n" if !defined( $size );
+
+ my $filename = extract_param( $param, 'filename' );
+
+ chomp $filename;
+ $filename =~ s/^.*[\/\\]//;
+ $filename =~ s/[;:,=\s\x80-\xff]/_/g;
+
+ my @allowed_extensions = map { ( $_, "$_.gz" ) } qw(raw qcow qcow2 cow vdi vmdk vpc cloop);
+ raise_param_exc( { filename => "extension must be one of " . join ', ', map ".$_", @allowed_extensions } )
+ if !grep { $filename =~ m![^/]+\.$_$! } @allowed_extensions;
+
+ my $storecfg = PVE::Storage::config();
+
+ my $drive = PVE::QemuServer::parse_drive( $disk, $conf->{$disk} );
+
+ my $worker = sub {
+ my ( $upid ) = @_;
+
+ my $dirname = dirname( $tmpfilename );
+ my $file = "$dirname/$filename";
+ my $new_filename;
+
+ eval {
+
+ # rename file (pigz wont work without .gz extension)
+ rename( $tmpfilename, $file );
+
+ # parallel gunzip if file has .gz extension
+ if ( $filename =~ /(.*?)\.gz$/i ) {
+
+ print "\nextracting file...\n";
+
+ $new_filename = $1;
+
+ my @unzip_cmd = ( 'unpigz', $file );
+ print "running '" . PVE::Tools::cmd2string( \@unzip_cmd ) . "'\n";
+ eval { PVE::Tools::run_command( \@unzip_cmd, errmsg => 'Extract failed' ); };
+ die "extracting file failed: $@\n" if $@;
+
+ print "extracted file successfully\n";
+ $filename = $new_filename;
+ $file = "$dirname/$new_filename";
+ }
+
+ my $img_volid = PVE::Storage::path_to_volume_id( $storecfg, $file );
+ die "cannot get volume id for file '$file'\n" if !$img_volid;
+
+ my $err;
+ my $newdrive = eval { PVE::QemuServer::import_disk( $storecfg, $vmid, $img_volid, $drive ) };
+ die "error with disk import: $@\n" if $@;
+
+ };
+
+ unlink $file;
+ unlink $new_filename if defined $new_filename;
+
+ print "\nimport successfull\n";
+
+ };
+
+ my $upid = $rpcenv->fork_worker( 'imgupload', undef, $authuser, $worker );
+
+ return $upid;
+
+ }});
+
+__PACKAGE__->register_method({
name => 'migrate_vm',
path => '{vmid}/migrate',
method => 'POST',
--
2.1.4
More information about the pve-devel
mailing list