Move existing import functionality to the API so that it is available for the
GUI.

Signed-off-by: Dominic Jäger <d.jae...@proxmox.com>
---
I haven't checked everything (e.g. permissions, code style) yet, but
1. a large part of intermediate bloat is away (some may be left)
2. it's rebased
3. so clicking through the GUI works (again)
Therefore I wanted to send a short update before going on holiday.

 PVE/API2/Qemu.pm             | 258 ++++++++++++++++++++++++++++++++++-
 PVE/CLI/qm.pm                | 127 +++--------------
 PVE/QemuServer.pm            |  18 ++-
 PVE/QemuServer/Drive.pm      |  21 +++
 PVE/QemuServer/ImportDisk.pm |  85 ------------
 PVE/QemuServer/Makefile      |   1 -
 PVE/QemuServer/OVF.pm        |  10 +-
 7 files changed, 319 insertions(+), 201 deletions(-)
 delete mode 100755 PVE/QemuServer/ImportDisk.pm

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index e2d2d67..e6856e6 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -45,7 +45,6 @@ BEGIN {
     }
 }
 
-use Data::Dumper; # fixme: remove
 
 use base qw(PVE::RESTHandler);
 
@@ -173,6 +172,28 @@ my $create_disks = sub {
            push @$vollist, $volid;
            delete $disk->{format}; # no longer needed
            $res->{$ds} = PVE::QemuServer::print_drive($disk);
+       } elsif ($disk->{importsource}) {
+           # must be before $NEW_DISK_RE because $NEW_DISK_RE is matched in 
imports
+           # because the "magic" number of the volid is irrelevant and 
arbitrarily set to 0 so the API allows it
+           my $volid_as_path = eval { # Nonempty iff $original_source is a 
volid
+               PVE::Storage::path($storecfg, $disk->{importsource});
+           };
+           my $source_as_path = $volid_as_path ||  $disk->{importsource} ;
+           my $volid = $PVE::API2::Qemu::import_disk->({
+               vmid => $vmid,
+               original_source => $disk->{importsource},
+               device_options => "discard=on",
+               storage => (split(':', $disk->{file}))[0],
+               source_as_path => $source_as_path,
+               format => $disk->{format},
+               skiplock => 1,
+               }
+           );
+
+           delete $disk->{importsource};
+           $disk->{file} = $volid;
+           push @$vollist, $volid;
+           $res->{$ds} =  PVE::QemuServer::print_drive($disk);
        } elsif ($volid =~ $NEW_DISK_RE) {
            my ($storeid, $size) = ($2 || $default_storage, $3);
            die "no storage ID specified (and no default storage)\n" if 
!$storeid;
@@ -1281,6 +1302,19 @@ my $update_vm_api  = sub {
                        if defined($conf->{pending}->{$opt});
 
                    &$create_disks($rpcenv, $authuser, $conf->{pending}, $arch, 
$storecfg, $vmid, undef, {$opt => $param->{$opt}});
+               } elsif ($param->{$opt} =~ m/importsource/) {
+                       my $disk = $param->{$opt};
+                       $disk =~ s/importsource=([^,]+),?//;
+                       my $path = $1;
+                       $disk =~ m/^(.+):0/;
+                       my $storage = $1;
+                       my $volid = $PVE::API2::Qemu::import_disk->({
+                           vmid => $vmid,
+                           source_as_path => $path,
+                           storage => $storage,
+                       });
+
+                       $conf->{pending}->{$opt} = $volid;
                } elsif ($opt =~ m/^serial\d+/) {
                    if ((!defined($conf->{$opt}) || $conf->{$opt} eq 'socket') 
&& $param->{$opt} eq 'socket') {
                        $rpcenv->check_vm_perm($authuser, $vmid, undef, 
['VM.Config.HWType']);
@@ -4320,4 +4354,226 @@ __PACKAGE__->register_method({
        return PVE::QemuServer::Cloudinit::dump_cloudinit_config($conf, 
$param->{vmid}, $param->{type});
     }});
 
+# TODO Make locally scoped when importovf is moved from qm to API / this 
package
+#
+# 2-step process:
+#   1. convert is qemu-img convert
+#   2. attach is update_vm_api
+#
+# vmid ... target VM ID
+# source_as_path ... absolute path of the source image (volid must be 
converted before)
+# device ... device/drive where the image will be attached (ide0, sata2, ...)
+# device_options ... options for attaching the device 
(discard=on,cache=unsafe, ...)
+# storage ... target storage for the disk image
+# format ... target format for the disk image
+# skiplock ... if skiploc during attach/upate_vm_api,
+our $import_disk = sub {
+    my ($param) = @_;
+    my $vm_conf = PVE::QemuConfig->load_config($param->{vmid});
+    my $store_conf = PVE::Storage::config();
+    PVE::QemuConfig->check_lock($vm_conf) if !$param->{skiplock};
+    if (!$param->{storage}) {
+       die "It is necessary to pass the storage parameter";
+    }
+    if ($param->{device} && $vm_conf->{$param->{device}}) {
+       die "Could not import because device $param->{device} is already in ".
+       "use in VM $param->{vmid}. Choose a different device!\n";
+    }
+    if ($param->{digest} && $param->{digest} ne $vm_conf->{digest}) {
+       die "VM $param->{vmid} config checksum missmatch (file change by other 
user?)\n";
+    }
+
+    my $msg = $param->{device} ? "to $param->{device} on" : 'as unused disk 
to';
+    print "Importing disk '$param->{source_as_path}' $msg VM 
$param->{vmid}...\n";
+
+    my $src_size = PVE::Storage::file_size_info($param->{source_as_path});
+    if (!defined($src_size)) {
+       die "Could not get file size of $param->{source_as_path}";
+    } elsif (!$src_size) {
+       die "Size of file $param->{source_as_path} is 0";
+    } elsif ($src_size==1) {
+       die "Cannot import directory";
+    }
+
+    my $dst_format = PVE::QemuServer::resolve_dst_disk_format(
+       $store_conf, $param->{storage}, undef, $param->{format});
+    my $dst_volid = PVE::Storage::vdisk_alloc($store_conf, $param->{storage},
+       $param->{vmid}, $dst_format, undef, $src_size / 1024);
+
+    eval {
+       local $SIG{INT} =
+       local $SIG{TERM} =
+       local $SIG{QUIT} =
+       local $SIG{HUP} =
+       local $SIG{PIPE} = sub { die "Interrupted by signal $!\n"; };
+
+       my $zeroinit = PVE::Storage::volume_has_feature($store_conf,
+           'sparseinit', $dst_volid);
+
+       PVE::Storage::activate_volumes($store_conf, [$dst_volid]);
+       PVE::QemuServer::qemu_img_convert($param->{source_as_path}, $dst_volid,
+       $src_size, undef, $zeroinit);
+       PVE::Storage::deactivate_volumes($store_conf, [$dst_volid]);
+
+    };
+    if (my $err = $@) {
+       eval { PVE::Storage::vdisk_free($store_conf, $dst_volid) };
+       warn "Cleanup of $dst_volid failed: $@ \n" if $@;
+
+       die "Importing disk '$param->{source_as_path}' failed: $err\n" if $err;
+    }
+
+    return $dst_volid;
+};
+
+__PACKAGE__->register_method ({
+    name => 'importdisk',
+    path => '{vmid}/importdisk',
+    method => 'POST',
+    protected => 1, # for worker upid file
+    proxyto => 'node',
+    description => "Import an external disk image into a VM. The image format 
".
+       "has to be supported by qemu-img.",
+    permissions => {
+       check => [ 'and',
+           [ 'perm', '/storage/{storage}', ['Datastore.Audit']],
+           [ 'perm', '/storage/{storage}', ['Datastore.Allocate']],
+           [ 'perm', '/storage/{storage}', ['Datastore.AllocateTemplate']],
+           [ 'perm', '/storage/{storage}', ['Datastore.AllocateSpace']],
+           [ 'perm', '/vms/{vmid}', ['VM.Allocate']],
+           [ 'perm', '/vms/{vmid}', ['VM.Config.Disk']],
+       ],
+    },
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+           vmid => get_standard_option('pve-vmid',
+               {completion => \&PVE::QemuServer::complete_vmid}),
+           source => {
+               description => "Disk image to import. Can be a volid ".
+                   "(local-lvm:vm-104-disk-0), an image on a PVE storage ".
+                   "(local:104/toImport.raw) or (for root only) an absolute ".
+                   "path on the server.",
+               type => 'string',
+           },
+           device => {
+               type => 'string',
+               description => "Bus/Device type of the new disk (e.g. 'ide0', ".
+                   "'scsi2'). Will add the image as unused disk if omitted.",
+               enum => [PVE::QemuServer::Drive::valid_drive_names()],
+               optional => 1,
+           },
+           device_options => {
+               type => 'string',
+               format => 'drive_options',
+               description => "Options to set for the new disk ".
+                   "(e.g. 'discard=on,backup=0')",
+               optional => 1,
+           },
+           storage => get_standard_option('pve-storage-id', {
+               description => "The storage to which the image will be imported 
to.",
+               completion => \&PVE::QemuServer::complete_storage,
+           }),
+           format => {
+               type => 'string',
+               description => 'Target format.',
+               enum => [ 'raw', 'qcow2', 'vmdk' ],
+               optional => 1,
+           },
+           digest => get_standard_option('pve-config-digest'),
+           skiplock => get_standard_option('skiplock'),
+       },
+    },
+    returns => { type => 'null'},
+    code => sub {
+       my ($param) = @_;
+       my $rpcenv = PVE::RPCEnvironment::get();
+       my $authuser = $rpcenv->get_user();
+
+       my $vmid = extract_param($param, 'vmid');
+       my $original_source = extract_param($param, 'source');
+       my $digest = extract_param($param, 'digest');
+       my $device_options = extract_param($param, 'device_options');
+       my $device = extract_param($param, 'device');
+       # importovf holds a lock itself which would make automatically updating
+       # VM configs fail
+       my $skiplock = extract_param($param, 'skiplock');
+       my $storecfg = PVE::Storage::config();
+
+       if ($skiplock && $authuser ne 'root@pam') {
+           raise_perm_exc("Only root may use skiplock.");
+       }
+       if ($original_source eq "") {
+           die "Could not import because source parameter is an empty 
string!\n";
+       }
+       if ($device && !PVE::QemuServer::is_valid_drivename($device)) {
+           die "Invalid device name: $device!";
+       }
+       if ($device_options && !$device) {
+           die "Cannot use --device_options without specifying --device!"
+       }
+       
+       if ($original_source =~ m/^http/) {
+               die "implement me";
+       #     my $tmpPath = '/tmp';
+       #     PVE::Tools::run_command(['/usr/bin/wget', $original_source, '-P', 
$tmpPath]);
+       #     $original_source =~ m!([^/]+)$!;
+       #     my $filename = $tmpPath . '/' . $1;
+       #     my $extractDir = $tmpPath .'/' . 'pve_importing';
+       #     if ($filename =~ m/.zip$/) {
+       #       PVE::Tools::run_command(['/usr/bin/unzip', $filename, '-d', 
$extractDir], outfunc => sub {
+       #           my $line = shift;
+       #           if ($line =~ m!\s*extracting:\s*(\S+)\s*$!) {
+       #               my $extracted_file = $1;
+       #               $original_source = $extracted_file; # only one file for 
the moment
+       #           }
+
+       #       });
+       #     } else {
+       #       die "Can only import .zip files from URLs";
+       #     }
+       } else {
+           eval {
+           PVE::Storage::check_volume_access($rpcenv, $authuser, $storecfg,
+               $vmid, $original_source)
+           };
+           raise_perm_exc($@) if $@;
+       }
+
+       # A path is required for $import_disk
+       my $volid_as_path = eval { # Nonempty iff $original_source is a volid
+           PVE::Storage::path($storecfg, $original_source);
+       };
+       my $source_as_path = $volid_as_path || $original_source ;
+       if (!-e $source_as_path) {
+           die "Could not import because source '$original_source' does not 
exist!\n";
+       }
+
+       my $storeid = extract_param($param, 'storage');
+       my $format = extract_param($param, 'format');
+       my $conf = PVE::QemuConfig->load_config($vmid);
+
+       my $volid = "${storeid}:0";
+               if ($device_options) {
+                       $volid .= ",${device_options}";
+               }
+               $volid .= ",importsource=${source_as_path}";
+       if ($device) {
+               $update_vm_api->({
+                       node => "dev",
+                       vmid => $vmid,
+                       $device => $volid,
+               });
+       } else {
+               $device = PVE::QemuConfig->add_unused_volume($conf, $volid);
+               $update_vm_api->({
+                       node => "dev",
+                       vmid => $vmid,
+                       $device => $volid,
+               });
+       }
+       return;
+    }});
+
 1;
diff --git a/PVE/CLI/qm.pm b/PVE/CLI/qm.pm
index b9b6051..56e57ea 100755
--- a/PVE/CLI/qm.pm
+++ b/PVE/CLI/qm.pm
@@ -27,11 +27,12 @@ use PVE::Tools qw(extract_param);
 
 use PVE::API2::Qemu::Agent;
 use PVE::API2::Qemu;
+use PVE::API2::Nodes;
+use PVE::Storage::Plugin;
 use PVE::QemuConfig;
 use PVE::QemuServer::Drive;
 use PVE::QemuServer::Helpers;
 use PVE::QemuServer::Agent qw(agent_available);
-use PVE::QemuServer::ImportDisk;
 use PVE::QemuServer::Monitor qw(mon_cmd);
 use PVE::QemuServer::OVF;
 use PVE::QemuServer;
@@ -440,61 +441,6 @@ __PACKAGE__->register_method ({
        return;
     }});
 
-__PACKAGE__->register_method ({
-    name => 'importdisk',
-    path => 'importdisk',
-    method => 'POST',
-    description => "Import an external disk image as an unused disk in a VM. 
The
- image format has to be supported by qemu-img(1).",
-    parameters => {
-       additionalProperties => 0,
-       properties => {
-           vmid => get_standard_option('pve-vmid', {completion => 
\&PVE::QemuServer::complete_vmid}),
-           source => {
-               description => 'Path to the disk image to import',
-               type => 'string',
-               optional => 0,
-           },
-            storage => get_standard_option('pve-storage-id', {
-               description => 'Target storage ID',
-               completion => \&PVE::QemuServer::complete_storage,
-               optional => 0,
-            }),
-           format => {
-               type => 'string',
-               description => 'Target format',
-               enum => [ 'raw', 'qcow2', 'vmdk' ],
-               optional => 1,
-           },
-       },
-    },
-    returns => { type => 'null'},
-    code => sub {
-       my ($param) = @_;
-
-       my $vmid = extract_param($param, 'vmid');
-       my $source = extract_param($param, 'source');
-       my $storeid = extract_param($param, 'storage');
-       my $format = extract_param($param, 'format');
-
-       my $vm_conf = PVE::QemuConfig->load_config($vmid);
-       PVE::QemuConfig->check_lock($vm_conf);
-       die "$source: non-existent or non-regular file\n" if (! -f $source);
-
-       my $storecfg = PVE::Storage::config();
-       PVE::Storage::storage_check_enabled($storecfg, $storeid);
-
-       my $target_storage_config =  PVE::Storage::storage_config($storecfg, 
$storeid);
-       die "storage $storeid does not support vm images\n"
-           if !$target_storage_config->{content}->{images};
-
-       print "importing disk '$source' to VM $vmid ...\n";
-       my ($drive_id, $volid) = 
PVE::QemuServer::ImportDisk::do_import($source, $vmid, $storeid, { format => 
$format });
-       print "Successfully imported disk as '$drive_id:$volid'\n";
-
-       return;
-    }});
-
 __PACKAGE__->register_method ({
     name => 'terminal',
     path => 'terminal',
@@ -612,63 +558,26 @@ __PACKAGE__->register_method ({
        my $format = PVE::Tools::extract_param($param, 'format');
        my $dryrun = PVE::Tools::extract_param($param, 'dryrun');
 
-       die "$ovf_file: non-existent or non-regular file\n" if (! -f $ovf_file);
-       my $storecfg = PVE::Storage::config();
-       PVE::Storage::storage_check_enabled($storecfg, $storeid);
-
-       my $parsed = PVE::QemuServer::OVF::parse_ovf($ovf_file);
-
-       if ($dryrun) {
-           print to_json($parsed, { pretty => 1, canonical => 1});
-           return;
+       my $all_storages = PVE::Storage::config();
+       PVE::Storage::storage_check_enabled($all_storages, $storeid);
+       if ($format) {
+               my $target_storage_config = 
PVE::Storage::storage_config($all_storages, $storeid);
+               my (undef, $valid_formats) = 
PVE::Storage::Plugin::default_format($target_storage_config);
+               if (!grep( /^$format$/, @$valid_formats)) {
+                       die "Format $format is not supported in storage 
$storeid";
+               }
        }
 
-       eval { PVE::QemuConfig->create_and_lock_config($vmid) };
-       die "Reserving empty config for OVF import to VM $vmid failed: $@" if 
$@;
-
-       my $conf = PVE::QemuConfig->load_config($vmid);
-       die "Internal error: Expected 'create' lock in config of VM $vmid!"
-           if !PVE::QemuConfig->has_lock($conf, "create");
-
-       $conf->{name} = $parsed->{qm}->{name} if defined($parsed->{qm}->{name});
-       $conf->{memory} = $parsed->{qm}->{memory} if 
defined($parsed->{qm}->{memory});
-       $conf->{cores} = $parsed->{qm}->{cores} if 
defined($parsed->{qm}->{cores});
-
-       eval {
-           # order matters, as do_import() will load_config() internally
-           $conf->{vmgenid} = PVE::QemuServer::generate_uuid();
-           $conf->{smbios1} = PVE::QemuServer::generate_smbios1_uuid();
-           PVE::QemuConfig->write_config($vmid, $conf);
-
-           foreach my $disk (@{ $parsed->{disks} }) {
-               my ($file, $drive) = ($disk->{backing_file}, 
$disk->{disk_address});
-               PVE::QemuServer::ImportDisk::do_import($file, $vmid, $storeid, {
-                   drive_name => $drive,
-                   format => $format,
-                   skiplock => 1,
-               });
+       my $parsed = PVE::API2::Nodes::Nodeinfo->readovf({node=>"dev", 
manifest=> $ovf_file});
+       delete $parsed->{digest};
+       foreach my $key (keys %$parsed) {
+           if (PVE::QemuServer::is_valid_drivename($key)) {
+               $parsed->{$key} = "$storeid:0,$parsed->{$key}";
            }
-
-           # reload after disks entries have been created
-           $conf = PVE::QemuConfig->load_config($vmid);
-           my $devs = PVE::QemuServer::get_default_bootdevices($conf);
-           $conf->{boot} = PVE::QemuServer::print_bootorder($devs);
-           PVE::QemuConfig->write_config($vmid, $conf);
-       };
-
-       my $err = $@;
-       if ($err) {
-           my $skiplock = 1;
-           # eval for additional safety in error path
-           eval { PVE::QemuServer::destroy_vm($storecfg, $vmid, $skiplock) };
-           warn "Could not destroy VM $vmid: $@" if "$@";
-           die "import failed - $err";
        }
-
-       PVE::QemuConfig->remove_lock($vmid, "create");
-
+       my $config = {%$parsed, node=>"dev", vmid=>$vmid};
+       PVE::API2::Qemu->create_vm($config);
        return;
-
     }
 });
 
@@ -979,7 +888,7 @@ our $cmddef = {
 
     terminal => [ __PACKAGE__, 'terminal', ['vmid']],
 
-    importdisk => [ __PACKAGE__, 'importdisk', ['vmid', 'source', 'storage']],
+    importdisk => [ "PVE::API2::Qemu", 'importdisk', ['vmid', 'source', 
'storage'], { node => $nodename }],
 
     importovf => [ __PACKAGE__, 'importovf', ['vmid', 'manifest', 'storage']],
 
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 43b11c3..02202b4 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -998,6 +998,22 @@ sub verify_volume_id_or_qm_path {
     return $volid;
 }
 
+PVE::JSONSchema::register_format('pve-volume-id-or-absolute-path', 
\&verify_volume_id_or_absolute_path);
+sub verify_volume_id_or_absolute_path {
+    my ($volid, $noerr) = @_;
+
+    if ($volid =~ m|^/|) {
+       return $volid;
+    }
+
+    $volid = eval { PVE::JSONSchema::check_format('pve-volume-id', $volid, '') 
};
+    if ($@) {
+       return undef if $noerr;
+       die $@;
+    }
+    return $volid;
+}
+
 my $usb_fmt = {
     host => {
        default_key => 1,
@@ -6658,7 +6674,7 @@ sub qemu_img_convert {
        $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
        $src_is_iscsi = ($src_path =~ m|^iscsi://|);
        $cachemode = 'none' if $src_scfg->{type} eq 'zfspool';
-    } elsif (-f $src_volid) {
+    } elsif (-f $src_volid || -b _) { # -b for LVM images for example
        $src_path = $src_volid;
        if ($src_path =~ m/\.($PVE::QemuServer::Drive::QEMU_FORMAT_RE)$/) {
            $src_format = $1;
diff --git a/PVE/QemuServer/Drive.pm b/PVE/QemuServer/Drive.pm
index d560937..5850e92 100644
--- a/PVE/QemuServer/Drive.pm
+++ b/PVE/QemuServer/Drive.pm
@@ -145,6 +145,13 @@ my %drivedesc_base = (
        verbose_description => "Mark this locally-managed volume as available 
on all nodes.\n\nWARNING: This option does not share the volume automatically, 
it assumes it is shared already!",
        optional => 1,
        default => 0,
+    },
+    importsource => {
+       type => 'string',
+       format => 'pve-volume-id-or-absolute-path',
+       format_description => 'Absolute path or volid',
+       description => 'Source to import the disk',
+       optional => 1,
     }
 );
 
@@ -308,6 +315,19 @@ my $alldrive_fmt = {
     %wwn_fmt,
 };
 
+my %optional_file_drivedesc_base = %drivedesc_base;
+$optional_file_drivedesc_base{file}{optional} = 1;
+my $drive_options_fmt = {
+    %optional_file_drivedesc_base,
+    %iothread_fmt,
+    %model_fmt,
+    %queues_fmt,
+    %scsiblock_fmt,
+    %ssd_fmt,
+    %wwn_fmt,
+};
+PVE::JSONSchema::register_format('drive_options', $drive_options_fmt);
+
 my $efidisk_fmt = {
     volume => { alias => 'file' },
     file => {
@@ -435,6 +455,7 @@ sub parse_drive {
        warn "invalid drive key: $key\n";
        return;
     }
+       use Data::Dumper;
 
     my $desc = $drivedesc_hash->{$key}->{format};
     my $res = eval { PVE::JSONSchema::parse_property_string($desc, $data) };
diff --git a/PVE/QemuServer/ImportDisk.pm b/PVE/QemuServer/ImportDisk.pm
deleted file mode 100755
index 51ad52e..0000000
--- a/PVE/QemuServer/ImportDisk.pm
+++ /dev/null
@@ -1,85 +0,0 @@
-package PVE::QemuServer::ImportDisk;
-
-use strict;
-use warnings;
-
-use PVE::Storage;
-use PVE::QemuServer;
-use PVE::Tools qw(run_command extract_param);
-
-# imports an external disk image to an existing VM
-# and creates by default a drive entry unused[n] pointing to the created volume
-# $params->{drive_name} may be used to specify ide0, scsi1, etc ...
-# $params->{format} may be used to specify qcow2, raw, etc ...
-sub do_import {
-    my ($src_path, $vmid, $storage_id, $params) = @_;
-
-    my $drive_name = extract_param($params, 'drive_name');
-    my $format = extract_param($params, 'format');
-    if ($drive_name && !(PVE::QemuServer::is_valid_drivename($drive_name))) {
-       die "invalid drive name: $drive_name\n";
-    }
-
-    # get the needed size from  source disk
-    my $src_size = PVE::Storage::file_size_info($src_path);
-
-    # get target format, target image's path, and whether it's possible to 
sparseinit
-    my $storecfg = PVE::Storage::config();
-    my $dst_format = PVE::QemuServer::resolve_dst_disk_format($storecfg, 
$storage_id, undef, $format);
-
-    my $dst_volid = PVE::Storage::vdisk_alloc($storecfg, $storage_id, $vmid, 
$dst_format, undef, $src_size / 1024);
-
-    my $zeroinit = PVE::Storage::volume_has_feature($storecfg, 'sparseinit', 
$dst_volid);
-
-    my $create_drive = sub {
-       my $vm_conf = PVE::QemuConfig->load_config($vmid);
-       if (!$params->{skiplock}) {
-           PVE::QemuConfig->check_lock($vm_conf);
-       }
-
-       if ($drive_name) {
-           # should never happen as setting $drive_name is not exposed to 
public interface
-           die "cowardly refusing to overwrite existing entry: $drive_name\n" 
if $vm_conf->{$drive_name};
-
-           my $modified = {}; # record what $option we modify
-           $modified->{$drive_name} = 1;
-           $vm_conf->{pending}->{$drive_name} = $dst_volid;
-           PVE::QemuConfig->write_config($vmid, $vm_conf);
-
-           my $running = PVE::QemuServer::check_running($vmid);
-           if ($running) {
-               my $errors = {};
-               PVE::QemuServer::vmconfig_hotplug_pending($vmid, $vm_conf, 
$storecfg, $modified, $errors);
-               warn "hotplugging imported disk '$_' failed: $errors->{$_}\n" 
for keys %$errors;
-           } else {
-               PVE::QemuServer::vmconfig_apply_pending($vmid, $vm_conf, 
$storecfg);
-           }
-       } else {
-           $drive_name = PVE::QemuConfig->add_unused_volume($vm_conf, 
$dst_volid);
-           PVE::QemuConfig->write_config($vmid, $vm_conf);
-       }
-    };
-
-    eval {
-       # trap interrupts so we have a chance to clean up
-       local $SIG{INT} =
-           local $SIG{TERM} =
-           local $SIG{QUIT} =
-           local $SIG{HUP} =
-           local $SIG{PIPE} = sub { die "interrupted by signal $!\n"; };
-
-       PVE::Storage::activate_volumes($storecfg, [$dst_volid]);
-       PVE::QemuServer::qemu_img_convert($src_path, $dst_volid, $src_size, 
undef, $zeroinit);
-       PVE::Storage::deactivate_volumes($storecfg, [$dst_volid]);
-       PVE::QemuConfig->lock_config($vmid, $create_drive);
-    };
-    if (my $err = $@) {
-       eval { PVE::Storage::vdisk_free($storecfg, $dst_volid) };
-       warn "cleanup of $dst_volid failed: $@\n" if $@;
-       die $err;
-    }
-
-    return ($drive_name, $dst_volid);
-}
-
-1;
diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile
index e4ed184..7a8a38f 100644
--- a/PVE/QemuServer/Makefile
+++ b/PVE/QemuServer/Makefile
@@ -1,7 +1,6 @@
 SOURCES=PCI.pm         \
        USB.pm          \
        Memory.pm       \
-       ImportDisk.pm   \
        OVF.pm          \
        Cloudinit.pm    \
        Agent.pm        \
diff --git a/PVE/QemuServer/OVF.pm b/PVE/QemuServer/OVF.pm
index c76c199..36b7fff 100644
--- a/PVE/QemuServer/OVF.pm
+++ b/PVE/QemuServer/OVF.pm
@@ -87,7 +87,7 @@ sub id_to_pve {
 
 # returns two references, $qm which holds qm.conf style key/values, and \@disks
 sub parse_ovf {
-    my ($ovf, $debug) = @_;
+    my ($ovf, $debug, $ignore_size) = @_;
 
     my $dom = XML::LibXML->load_xml(location => $ovf, no_blanks => 1);
 
@@ -220,9 +220,11 @@ ovf:Item[rasd:InstanceID='%s']/rasd:ResourceType", 
$controller_id);
            die "error parsing $filepath, file seems not to exist at 
$backing_file_path\n";
        }
 
-       my $virtual_size;
-       if ( !($virtual_size = 
PVE::Storage::file_size_info($backing_file_path)) ) {
-           die "error parsing $backing_file_path, size seems to be 
$virtual_size\n";
+       my $virtual_size = 0;
+       if (!$ignore_size) { # Not possible if manifest is uploaded in web gui
+           if ( !($virtual_size = 
PVE::Storage::file_size_info($backing_file_path)) ) {
+               die "error parsing $backing_file_path: Could not get file size 
info: $@\n";
+           }
        }
 
        $pve_disk = {
-- 
2.20.1


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

Reply via email to