[pve-devel] [qemu-server] Qemu implement migration on replicated storage.

Wolfgang Link w.link at proxmox.com
Fri Jun 9 08:19:50 CEST 2017


---
 PVE/QemuMigrate.pm | 77 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 69 insertions(+), 8 deletions(-)

diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
index bf756a6..a303851 100644
--- a/PVE/QemuMigrate.pm
+++ b/PVE/QemuMigrate.pm
@@ -13,6 +13,9 @@ use PVE::Storage;
 use PVE::QemuServer;
 use Time::HiRes qw( usleep );
 use PVE::RPCEnvironment;
+use PVE::ReplicationConfig;
+use PVE::ReplicationState;
+use JSON;
 
 use base qw(PVE::AbstractMigrate);
 
@@ -214,7 +217,7 @@ sub prepare {
 }
 
 sub sync_disks {
-    my ($self, $vmid) = @_;
+    my ($self, $vmid, $base_snapshot) = @_;
 
     my $conf = $self->{vmconf};
 
@@ -400,7 +403,7 @@ sub sync_disks {
 	    } else {
 		push @{$self->{volumes}}, $volid;
 		my $insecure = $self->{opts}->{migration_type} eq 'insecure';
-		PVE::Storage::storage_migrate($self->{storecfg}, $volid, $self->{ssh_info}, $sid, undef, undef, undef, undef, $insecure);
+		PVE::Storage::storage_migrate($self->{storecfg}, $volid, $self->{ssh_info}, $sid, undef, $base_snapshot, undef, undef, $insecure);
 	    }
 	}
     };
@@ -450,7 +453,33 @@ sub phase1 {
     }
     $self->{opts}->{migration_type} = $migration_type;
 
-    sync_disks($self, $vmid);
+    my $rep_cfg = PVE::ReplicationConfig->new();
+    my $jobid;
+    my $last_replica;
+
+    if ($jobid = PVE::ReplicationConfig::get_jobid($rep_cfg, $vmid, $self->{node}) ) {
+	my $stateobj = PVE::ReplicationState::read_state();
+	my $state = PVE::ReplicationState::extract_job_state($stateobj, $rep_cfg->{ids}->{$jobid});
+	$last_replica = PVE::ReplicationState::replication_snapshot_name($jobid, $state->{last_sync});
+    }
+    sync_disks($self, $vmid, $last_replica);
+
+    # set new replica_target if we migrate to replica target.
+
+    if ($jobid) {
+
+	my $update_target = sub {
+
+	    if ($rep_cfg->{ids}->{$jobid}->{target} eq $self->{node}) {
+		$self->log('info', "change replica target to Node: $self->{opts}->{node}");
+		$rep_cfg->{ids}->{$jobid}->{target} = $self->{opts}->{node};
+		$rep_cfg->write();
+	    }
+
+	};
+
+	PVE::ReplicationConfig::lock($update_target);
+    }
 
 };
 
@@ -848,13 +877,21 @@ sub phase3 {
     my $volids = $self->{volumes};
     return if $self->{phase2errors};
 
+    my $rep_cfg = PVE::ReplicationConfig->new();
+    my $new_target = $self->{opts}->{node};
+    # get no jobid if this is not the new target
+    my $jobid = PVE::ReplicationConfig::get_jobid($rep_cfg, $vmid, $new_target);
+
     # destroy local copies
     foreach my $volid (@$volids) {
-	eval { PVE::Storage::vdisk_free($self->{storecfg}, $volid); };
-	if (my $err = $@) {
-	    $self->log('err', "removing local copy of '$volid' failed - $err");
-	    $self->{errors} = 1;
-	    last if $err =~ /^interrupted by signal$/;
+	# do not destroy if new target is local_host
+	if (!$jobid) {
+	    eval { PVE::Storage::vdisk_free($self->{storecfg}, $volid); };
+	    if (my $err = $@) {
+		$self->log('err', "removing local copy of '$volid' failed - $err");
+		$self->{errors} = 1;
+		last if $err =~ /^interrupted by signal$/;
+	    }
 	}
     }
 }
@@ -968,6 +1005,30 @@ sub phase3_cleanup {
     # clear migrate lock
     my $cmd = [ @{$self->{rem_ssh}}, 'qm', 'unlock', $vmid ];
     $self->cmd_logerr($cmd, errmsg => "failed to clear migrate lock");
+
+    my $rep_cfg = PVE::ReplicationConfig->new();
+    my $new_target = $self->{opts}->{node};
+    # transfer replication state to migration target node.
+    if (PVE::ReplicationConfig::get_jobid($rep_cfg, $vmid, $new_target)) {
+	my $stateobj = PVE::ReplicationState::read_state();
+	my $old_target =  $self->{node};
+
+	my $vm_state = {};
+	foreach my $key (keys %{$stateobj->{$vmid}}) {
+	    if ($key =~ /^(.*\/)\Q$old_target\E$/) {
+		$vm_state->{"$1$new_target"} = $stateobj->{$vmid}->{$key};
+	    } else {
+		$vm_state->{$key} = $stateobj->{$vmid}->{$key};
+	    }
+	}
+
+	# This have to be double quoted when it run it over ssh.
+	my $state = PVE::Tools::shellquote(encode_json $vm_state);
+
+	my $cmd = [ @{$self->{rem_ssh}}, 'pvesr', 'set-state', $vmid, $state];
+	$self->cmd_logerr($cmd, errmsg => "failed to activate replica");
+    }
+
 }
 
 sub final_cleanup {
-- 
2.11.0





More information about the pve-devel mailing list