]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer/ImportDisk.pm
migration: add missing use statements
[qemu-server.git] / PVE / QemuServer / ImportDisk.pm
index db7db6343c4c0af67a094b695d0c9e329ff80ab8..132932aeb460f9eba562e930569b91aef606ff6f 100755 (executable)
@@ -9,14 +9,15 @@ 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
-# $optional->{drive_name} may be used to specify ide0, scsi1, etc ...
-# $optional->{format} may be used to specify qcow2, raw, etc ...
+# $params->{drive_name} may be used to specify ide0, scsi1, etc ...
+# $params->{format} may be used to specify qcow2, raw, etc ...
+# $params->{skiplock} may be used to skip checking for a lock in the VM config
+# $params->{'skip-config-update'} may be used to import the disk without updating the VM config
 sub do_import {
-    my ($src_path, $vmid, $storage_id, $optional) = @_;
+    my ($src_path, $vmid, $storage_id, $params) = @_;
 
-    my $drive_name = extract_param($optional, 'drive_name');
-    my $format = extract_param($optional, 'format');
-    my $debug = extract_param($optional, 'debug');
+    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";
     }
@@ -26,58 +27,41 @@ sub do_import {
 
     # 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);
-    warn "format : $dst_format\n" if $debug;
-
-    my $dst_volid = PVE::Storage::vdisk_alloc($storecfg, $storage_id, $vmid,
-       $dst_format, undef, $src_size / 1024);
-    my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
-
-    warn "args:  $src_path, $vmid, $storage_id, $optional\n",
-       "\$dst_volid: $dst_volid\n", if $debug;
-
-    # qemu-img convert does the hard job
-    # we don't attempt to guess filetypes ourselves
-    my $convert_command = ['qemu-img', 'convert', $src_path, '-p', '-n', '-O', $dst_format];
-    if (PVE::Storage::volume_has_feature($storecfg, 'sparseinit', $dst_volid)) {
-       push @$convert_command, "zeroinit:$dst_path";
-    } else {
-       push @$convert_command, $dst_path;
-    }
+    my $dst_format = PVE::QemuServer::resolve_dst_disk_format($storecfg, $storage_id, undef, $format);
+    warn "format '$format' is not supported by the target storage - using '$dst_format' instead\n"
+       if $format && $format ne $dst_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);
-       PVE::QemuConfig->check_lock($vm_conf);
+       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);
-                   if (scalar(keys %$errors)) {
-                       foreach my $k (keys %$errors) {
-                           warn "$k: $errors->{$k}\n" if $debug;
-                           warn "hotplugging imported disk failed\n";
-                       }
-                   }
-               } else {
-                   PVE::QemuServer::vmconfig_apply_pending($vmid, $vm_conf, $storecfg);
-               }
+           # 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 {
-           PVE::QemuConfig->add_unused_volume($vm_conf, $dst_volid);
+           $drive_name = PVE::QemuConfig->add_unused_volume($vm_conf, $dst_volid);
            PVE::QemuConfig->write_config($vmid, $vm_conf);
        }
-
     };
 
     eval {
@@ -86,20 +70,20 @@ sub do_import {
            local $SIG{TERM} =
            local $SIG{QUIT} =
            local $SIG{HUP} =
-           local $SIG{PIPE} = sub { die "interrupted by signal\n"; };
+           local $SIG{PIPE} = sub { die "interrupted by signal $!\n"; };
+
        PVE::Storage::activate_volumes($storecfg, [$dst_volid]);
-       run_command($convert_command);
+       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);
+       PVE::QemuConfig->lock_config($vmid, $create_drive) if !$params->{'skip-config-update'};
     };
-
-    my $err = $@;
-    if ($err) {
-       eval { # do not die before we returned $err
-           PVE::Storage::vdisk_free($storecfg, $dst_volid);
-       };
+    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;