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

Fabian Grünbichler f.gruenbichler at proxmox.com
Fri Jun 9 11:11:52 CEST 2017


same comments as for LXC apply

On Fri, Jun 09, 2017 at 08:19:50AM +0200, Wolfgang Link wrote:
> ---
>  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
> 
> 
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel




More information about the pve-devel mailing list