Signed-off-by: Alexandre Derumier <[email protected]>
---
 PVE/API2/Qemu.pm |   96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 96 insertions(+)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index ab8eaa7..bd2d2a2 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -133,6 +133,102 @@ my $create_disks = sub {
     return $vollist;
 };
 
+my $clone_disks = sub {
+    my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $settings, $snap, 
$mode, $clonefrom, $running, $onlysettings) = @_;
+
+    my $vollist = [];
+    my $voliddst = undef;
+    my $currentdrive = undef;
+    my $res = {};
+
+    eval {
+        local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {die 
"interrupted by signal\n";};
+
+       PVE::QemuServer::foreach_drive($conf, sub {
+           my ($ds, $disk) = @_;
+
+           $currentdrive = $ds;
+
+           return if ($onlysettings && !$settings->{$ds});
+
+           my $volid = $disk->{file};
+           if (PVE::QemuServer::drive_is_cdrom($disk)) {
+               $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
+           } else{
+
+               if($mode eq 'clone'){
+                   print "clone volume $volid\n";
+                   $voliddst = PVE::Storage::volume_clone($storecfg, $volid, 
$snap, $vmid);
+                   push @$vollist, $voliddst;
+
+               }elsif($mode eq 'copy'){
+
+                   my ($storeid, $volname) = 
PVE::Storage::parse_volume_id($volid, 1);
+                   die "no storage ID specified (and no default storage)\n" if 
!$storeid;
+
+                   my $fmt = undef;
+                   if ($volname =~ m/\.(raw|qcow2|vmdk)$/){
+                       $fmt = $1;
+                   }
+
+                   #target storage is different ? (ex: -virtio0:storeid:fmt)
+                   if($settings->{$ds} && $settings->{$ds} =~ 
m/^(\S+):(raw|qcow2|vmdk)?$/){
+                       ($storeid, $fmt) = ($1, $2);
+                   }
+
+                   $rpcenv->check($authuser, "/storage/$storeid", 
['Datastore.AllocateSpace']);
+                   print "activate volume source $volid\n";
+                   PVE::Storage::activate_volumes($storecfg, [ $volid ]);
+
+                   my ($size) = PVE::Storage::volume_size_info($storecfg, 
$volid, 1);
+                   print "create target volume\n";
+                   $voliddst = PVE::Storage::vdisk_alloc($storecfg, $storeid, 
$vmid, $fmt, undef, ($size/1024));
+
+                   push @$vollist, $voliddst;
+
+                   print "activate volume $voliddst\n";
+                   PVE::Storage::activate_volumes($storecfg, [ $voliddst ]);
+
+                   print "copy $volid to $voliddst\n";
+                   if(!$running || $snap){
+                       PVE::QemuServer::qemu_img_convert($volid, $voliddst, 
$snap);
+                   }else{
+                       PVE::QemuServer::qemu_drive_mirror($clonefrom, $ds, 
$voliddst, $vmid);
+                   }
+               }
+
+               $disk->{file} = $voliddst;
+               $disk->{size} = PVE::Storage::volume_size_info($storecfg, 
$voliddst, 1);
+
+               delete $disk->{format}; # no longer needed
+               $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
+           }
+       });
+    };
+    # free allocated images on error
+    if (my $err = $@) {
+       syslog('err', "VM $vmid clone disks failed");
+
+       eval {
+           PVE::QemuServer::vm_mon_cmd($vmid, "block-job-cancel", device => 
"drive-$currentdrive") if ($mode eq 'copy' && $running);
+       };
+
+       sleep 1; #some storage like rbd need to wait before release volume
+       foreach my $volid (@$vollist) {
+           eval { PVE::Storage::vdisk_free($storecfg, $volid); };
+           warn $@ if $@;
+       }
+       die $err;
+    }
+
+    # modify vm config if everything went well
+    foreach my $ds (keys %$res) {
+       $conf->{$ds} = $res->{$ds};
+    }
+
+    return $vollist;
+};
+
 my $check_vm_modify_config_perm = sub {
     my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_;
 
-- 
1.7.10.4

_______________________________________________
pve-devel mailing list
[email protected]
http://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to