[pve-devel] [PATCH 16/16] Manage interrupt call when cloning disks

Alexandre Derumier aderumier at odiso.com
Mon Jan 21 10:48:11 CET 2013


Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 PVE/API2/Qemu.pm |  101 ++++++++++++++++++++++++++++++------------------------
 1 file changed, 57 insertions(+), 44 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index d186d97..0045b54 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -139,69 +139,82 @@ my $clone_disks = sub {
 
     my $vollist = [];
     my $voliddst = undef;
-
+    my $currentdrive = undef;
     my $res = {};
-    PVE::QemuServer::foreach_drive($conf, sub {
-	my ($ds, $disk) = @_;
 
-	return if ($onlysettings && !$settings->{$ds});
+    eval {
+        local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {die "interrupted by signal\n";};
 
-	my $volid = $disk->{file};
-	if (PVE::QemuServer::drive_is_cdrom($disk)) {
-	    $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
-	} else{
+	PVE::QemuServer::foreach_drive($conf, sub {
+	    my ($ds, $disk) = @_;
 
-	    if($mode eq 'clone'){
-	        $voliddst = PVE::Storage::volume_clone($storecfg, $volid, $snap, $vmid);
-	        push @$vollist, $voliddst;
+	    $currentdrive = $ds;
 
-	    }elsif($mode eq 'copy'){
+	    return if ($onlysettings && !$settings->{$ds});
 
-		my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
-		die "no storage ID specified (and no default storage)\n" if !$storeid;
+	    my $volid = $disk->{file};
+	    if (PVE::QemuServer::drive_is_cdrom($disk)) {
+		$res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
+	    } else{
 
-		my $fmt = undef;
-		if ($volname =~ m/\.(raw|qcow2|vmdk)$/){
-		    $fmt = $1;
-		}
+		if($mode eq 'clone'){
+    		    print "clone volume $volid\n";
+		    $voliddst = PVE::Storage::volume_clone($storecfg, $volid, $snap, $vmid);
+	            push @$vollist, $voliddst;
 
-		#target storage is different ? (ex: -virtio0:storeid:fmt)
-		if($settings->{$ds} && $settings->{$ds} =~ m/^(\S+):(raw|qcow2|vmdk)?$/){
-		    ($storeid, $fmt) = ($1, $2);
-		}
+		}elsif($mode eq 'copy'){
 
-		$rpcenv->check($authuser, "/storage/$storeid", ['Datastore.AllocateSpace']);
+		    my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
+		    die "no storage ID specified (and no default storage)\n" if !$storeid;
 
-		PVE::Storage::activate_volumes($storecfg, [ $volid ]);
-
-		my ($size) = PVE::Storage::volume_size_info($storecfg, $volid, 1);
+		    my $fmt = undef;
+		    if ($volname =~ m/\.(raw|qcow2|vmdk)$/){
+			$fmt = $1;
+		    }
 
-		$voliddst = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid,
-                                                  $fmt, undef, ($size/1024));
-		push @$vollist, $voliddst;
+		    #target storage is different ? (ex: -virtio0:storeid:fmt)
+		    if($settings->{$ds} && $settings->{$ds} =~ m/^(\S+):(raw|qcow2|vmdk)?$/){
+			($storeid, $fmt) = ($1, $2);
+		    }
 
-		PVE::Storage::activate_volumes($storecfg, [ $voliddst ]);
+		    $rpcenv->check($authuser, "/storage/$storeid", ['Datastore.AllocateSpace']);
+       		    print "activate volume source $volid\n";
+		    PVE::Storage::activate_volumes($storecfg, [ $volid ]);
 
-		#copy from source
-		if(!$running){
-		    PVE::QemuServer::qemu_img_convert($volid, $voliddst, $snap);
-		}else{
-		    PVE::QemuServer::qemu_drive_mirror($clonefrom, $ds, $voliddst, $vmid);
-		}
+		    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 ]);
 
-	    $disk->{file} = $voliddst;
-	    $disk->{size} = PVE::Storage::volume_size_info($storecfg, $voliddst, 1);
+		    print "copy $volid to $voliddst\n";
+		    if(!$running){
+			PVE::QemuServer::qemu_img_convert($volid, $voliddst, $snap);
+		    }else{
+			PVE::QemuServer::qemu_drive_mirror($clonefrom, $ds, $voliddst, $vmid);
+		    }
+		}
 
-	    delete $disk->{format}; # no longer needed
-	    $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
-	}
-    });
+		$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 creating disks failed");
+	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 $@;
-- 
1.7.10.4




More information about the pve-devel mailing list