mirror of
git://git.proxmox.com/git/qemu-server.git
synced 2025-01-08 21:18:03 +03:00
migrate: fix replication false-positives
by only checking for replicatable volumes when a replication job is defined, and passing only actually replicated volumes to the target node via STDIN, and back via STDOUT. otherwise this can pick up theoretically replicatable, but not actually replicated volumes and treat them wrong. Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
This commit is contained in:
parent
1dbe979c7c
commit
88126be3f7
@ -2073,6 +2073,7 @@ __PACKAGE__->register_method({
|
||||
# read spice ticket from STDIN
|
||||
my $spice_ticket;
|
||||
my $nbd_protocol_version = 0;
|
||||
my $replicated_volumes = {};
|
||||
if ($stateuri && ($stateuri eq 'tcp' || $stateuri eq 'unix') && $migratedfrom && ($rpcenv->{type} eq 'cli')) {
|
||||
while (defined(my $line = <STDIN>)) {
|
||||
chomp $line;
|
||||
@ -2080,6 +2081,8 @@ __PACKAGE__->register_method({
|
||||
$spice_ticket = $1;
|
||||
} elsif ($line =~ m/^nbd_protocol_version: (\d+)$/) {
|
||||
$nbd_protocol_version = $1;
|
||||
} elsif ($line =~ m/^replicated_volume: (.*)$/) {
|
||||
$replicated_volumes->{$1} = 1;
|
||||
} else {
|
||||
# fallback for old source node
|
||||
$spice_ticket = $line;
|
||||
@ -2113,7 +2116,7 @@ __PACKAGE__->register_method({
|
||||
|
||||
PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef, $machine,
|
||||
$spice_ticket, $migration_network, $migration_type, $targetstorage, $timeout,
|
||||
$nbd_protocol_version);
|
||||
$nbd_protocol_version, $replicated_volumes);
|
||||
return;
|
||||
};
|
||||
|
||||
|
@ -330,7 +330,9 @@ sub sync_disks {
|
||||
});
|
||||
}
|
||||
|
||||
my $replicatable_volumes = PVE::QemuConfig->get_replicatable_volumes($self->{storecfg}, $self->{vmid}, $conf, 0, 1);
|
||||
my $rep_cfg = PVE::ReplicationConfig->new();
|
||||
my $replication_jobcfg = $rep_cfg->find_local_replication_job($vmid, $self->{node});
|
||||
my $replicatable_volumes = $replication_jobcfg ? PVE::QemuConfig->get_replicatable_volumes($self->{storecfg}, $self->{vmid}, $conf, 0, 1) : {};
|
||||
|
||||
my $test_volid = sub {
|
||||
my ($volid, $attr) = @_;
|
||||
@ -449,8 +451,7 @@ sub sync_disks {
|
||||
}
|
||||
}
|
||||
|
||||
my $rep_cfg = PVE::ReplicationConfig->new();
|
||||
if (my $jobcfg = $rep_cfg->find_local_replication_job($vmid, $self->{node})) {
|
||||
if ($replication_jobcfg) {
|
||||
if ($self->{running}) {
|
||||
|
||||
my $version = PVE::QemuServer::kvm_user_version();
|
||||
@ -484,7 +485,7 @@ sub sync_disks {
|
||||
my $start_time = time();
|
||||
my $logfunc = sub { $self->log('info', shift) };
|
||||
$self->{replicated_volumes} = PVE::Replication::run_replication(
|
||||
'PVE::QemuConfig', $jobcfg, $start_time, $start_time, $logfunc);
|
||||
'PVE::QemuConfig', $replication_jobcfg, $start_time, $start_time, $logfunc);
|
||||
}
|
||||
|
||||
# sizes in config have to be accurate for remote node to correctly
|
||||
@ -657,6 +658,11 @@ sub phase2 {
|
||||
# TODO change to 'spice_ticket: <ticket>\n' in 7.0
|
||||
my $input = $spice_ticket ? "$spice_ticket\n" : "\n";
|
||||
$input .= "nbd_protocol_version: $nbd_protocol_version\n";
|
||||
foreach my $volid (keys %{$self->{replicated_volumes}}) {
|
||||
$input .= "replicated_volume: $volid\n";
|
||||
}
|
||||
|
||||
my $target_replicated_volumes = {};
|
||||
|
||||
# Note: We try to keep $spice_ticket secret (do not pass via command line parameter)
|
||||
# instead we pipe it through STDIN
|
||||
@ -701,6 +707,10 @@ sub phase2 {
|
||||
$self->{target_drive}->{$targetdrive}->{nbd_uri} = $nbd_uri;
|
||||
push @$tunnel_addr, "$nbd_unix_addr:$nbd_unix_addr";
|
||||
push @$sock_addr, $nbd_unix_addr;
|
||||
} elsif ($line =~ m/^re-using replicated volume: (\S+) - (.*)$/) {
|
||||
my $drive = $1;
|
||||
my $volid = $2;
|
||||
$target_replicated_volumes->{$volid} = $drive;
|
||||
} elsif ($line =~ m/^QEMU: (.*)$/) {
|
||||
$self->log('info', "[$self->{node}] $1\n");
|
||||
}
|
||||
@ -713,6 +723,10 @@ sub phase2 {
|
||||
|
||||
die "unable to detect remote migration address\n" if !$raddr;
|
||||
|
||||
if (scalar(keys %$target_replicated_volumes) != scalar(keys %{$self->{replicated_volumes}})) {
|
||||
die "number of replicated disks on source and target node do not match - target node too old?\n"
|
||||
}
|
||||
|
||||
$self->log('info', "start remote tunnel");
|
||||
|
||||
if ($migration_type eq 'secure') {
|
||||
|
@ -4706,7 +4706,7 @@ sub vmconfig_update_disk {
|
||||
sub vm_start {
|
||||
my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
|
||||
$forcemachine, $spice_ticket, $migration_network, $migration_type,
|
||||
$targetstorage, $timeout, $nbd_protocol_version) = @_;
|
||||
$targetstorage, $timeout, $nbd_protocol_version, $replicated_volumes) = @_;
|
||||
|
||||
PVE::QemuConfig->lock_config($vmid, sub {
|
||||
my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
|
||||
@ -4755,16 +4755,15 @@ sub vm_start {
|
||||
$local_volumes->{$ds} = [$volid, $storeid, $volname];
|
||||
});
|
||||
|
||||
my $replicatable_volumes = PVE::QemuConfig->get_replicatable_volumes($storecfg, $vmid, $conf, 0, 1);
|
||||
|
||||
my $format = undef;
|
||||
|
||||
foreach my $opt (sort keys %$local_volumes) {
|
||||
|
||||
my ($volid, $storeid, $volname) = @{$local_volumes->{$opt}};
|
||||
if ($replicatable_volumes->{$volid}) {
|
||||
if ($replicated_volumes->{$volid}) {
|
||||
# re-use existing, replicated volume with bitmap on source side
|
||||
$local_volumes->{$opt} = $conf->{${opt}};
|
||||
print "re-using replicated volume: $opt - $volid\n";
|
||||
next;
|
||||
}
|
||||
my $drive = parse_drive($opt, $conf->{$opt});
|
||||
|
Loading…
Reference in New Issue
Block a user