[pve-devel] [PATCH 15/15] qm migrate : add storage migration for local node

Alexandre Derumier aderumier at odiso.com
Thu Jan 17 18:51:34 CET 2013


currently only for local node, works online or offline

syntax:
qm migrate <vmid> <target> -storage -[virtiox|idex|scsix|satax] storeid:[fmt]

sample:
qm migrate <vmid> <target> -storage -virtio0 local:raw -scsi1 local:qcow2 -sata3 rbdstorage: --ide4 lvmstorage:

fixme: how to handle snapshots ? delete them ? or keep the old drive if snapshot exist ?

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 PVE/API2/Qemu.pm  |   40 +++++++++++++++++++++++++++++++++-------
 PVE/QemuServer.pm |   17 +++++++++++++++++
 2 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 633245c..fa878cb 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -135,7 +135,7 @@ my $create_disks = sub {
 };
 
 my $clone_disks = sub {
-    my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $settings, $snap, $mode, $clonefrom, $running) = @_;
+    my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $settings, $snap, $mode, $clonefrom, $running, $onlysettings) = @_;
 
     my $vollist = [];
     my $voliddst = undef;
@@ -143,6 +143,8 @@ my $clone_disks = sub {
     my $res = {};
     PVE::QemuServer::foreach_drive($conf, sub {
 	my ($ds, $disk) = @_;
+	
+	return if ($onlysettings && !$settings->{$ds});
 
 	my $volid = $disk->{file};
 	if (PVE::QemuServer::drive_is_cdrom($disk)) {
@@ -1871,7 +1873,7 @@ __PACKAGE__->register_method({
     },
     parameters => {
     	additionalProperties => 0,
-	properties => {
+	properties => PVE::QemuServer::json_disk_properties({
 	    node => get_standard_option('pve-node'),
 	    vmid => get_standard_option('pve-vmid'),
 	    target => get_standard_option('pve-node', { description => "Target node." }),
@@ -1885,7 +1887,12 @@ __PACKAGE__->register_method({
 		description => "Allow to migrate VMs which use local devices. Only root may use this option.",
 		optional => 1,
 	    },
-	},
+	    storage => {
+		type => 'boolean',
+		description => "Migrate storage.",
+		optional => 1,
+	    },
+	}),
     },
     returns => {
 	type => 'string',
@@ -1900,8 +1907,10 @@ __PACKAGE__->register_method({
 
 	my $target = extract_param($param, 'target');
 
+	my $storage = extract_param($param, 'storage');
+
 	my $localnode = PVE::INotify::nodename();
-	raise_param_exc({ target => "target is local node."}) if $target eq $localnode;
+	raise_param_exc({ target => "target is local node."}) if ($target eq $localnode && !$storage);
 
 	PVE::Cluster::check_cfs_quorum();
 
@@ -1920,8 +1929,8 @@ __PACKAGE__->register_method({
 	# try to detect errors early
 
 	PVE::QemuServer::check_lock($conf);
-
-	if (PVE::QemuServer::check_running($vmid)) {
+	my $running = PVE::QemuServer::check_running($vmid);
+	if ($running) {
 	    die "cant migrate running VM without --online\n"
 		if !$param->{online};
 	}
@@ -1951,8 +1960,25 @@ __PACKAGE__->register_method({
 
 	    my $realcmd = sub {
 		my $upid = shift;
+		if ($target eq $localnode && $storage){
+		    die "disk copy feature is not available" if !PVE::QemuServer::has_feature('copy', $conf, $storecfg);
+		    my $oldconf = { %$conf };
+		    &$clone_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, undef, $param, undef, 'copy', $vmid, $running, 1);
+		    PVE::QemuServer::update_config_nolock($vmid, $conf);
+		    #delete old disks
+		    #fix me : how to handle snapshots removal ?
+		    PVE::QemuServer::foreach_drive($oldconf, sub {
+			my ($ds, $disk) = @_;
+			return if !$param->{$ds};
+		        my $volid = $disk->{file};
+			print "free $volid\n";
+			eval { PVE::Storage::vdisk_free($storecfg, $volid); };
+		        warn $@ if $@;
+		    });
 
-		PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
+		}else{
+		    PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
+		}
 	    };
 
 	    return $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 30a890a..f9fbead 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -150,6 +150,8 @@ mkdir $lock_dir;
 
 my $pcisysfs = "/sys/bus/pci";
 
+my $diskdesc = {};
+
 my $confdesc = {
     onboot => {
 	optional => 1,
@@ -603,21 +605,25 @@ for (my $i = 0; $i < $MAX_HOSTPCI_DEVICES; $i++)  {
 for (my $i = 0; $i < $MAX_IDE_DISKS; $i++)  {
     $drivename_hash->{"ide$i"} = 1;
     $confdesc->{"ide$i"} = $idedesc;
+    $diskdesc->{"ide$i"} = $idedesc;
 }
 
 for (my $i = 0; $i < $MAX_SATA_DISKS; $i++)  {
     $drivename_hash->{"sata$i"} = 1;
     $confdesc->{"sata$i"} = $satadesc;
+    $diskdesc->{"sata$i"} = $satadesc;
 }
 
 for (my $i = 0; $i < $MAX_SCSI_DISKS; $i++)  {
     $drivename_hash->{"scsi$i"} = 1;
     $confdesc->{"scsi$i"} = $scsidesc ;
+    $diskdesc->{"scsi$i"} = $scsidesc ;
 }
 
 for (my $i = 0; $i < $MAX_VIRTIO_DISKS; $i++)  {
     $drivename_hash->{"virtio$i"} = 1;
     $confdesc->{"virtio$i"} = $virtiodesc;
+    $diskdesc->{"virtio$i"} = $virtiodesc;
 }
 
 for (my $i = 0; $i < $MAX_USB_DEVICES; $i++)  {
@@ -1425,6 +1431,17 @@ sub json_config_properties {
     return $prop;
 }
 
+# add JSON properties for create and set function
+sub json_disk_properties {
+    my $prop = shift;
+
+    foreach my $opt (keys %$diskdesc) {
+	$prop->{$opt} = $confdesc->{$opt};
+    }
+
+    return $prop;
+}
+
 sub check_type {
     my ($key, $value) = @_;
 
-- 
1.7.10.4




More information about the pve-devel mailing list