Signed-off-by: Alexandre Derumier <aderum...@odiso.com>
---
 PVE/QemuMigrate.pm | 376 +++++++++++++++++++++++----------------------
 1 file changed, 191 insertions(+), 185 deletions(-)

diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
index 5063b7b..1768afc 100644
--- a/PVE/QemuMigrate.pm
+++ b/PVE/QemuMigrate.pm
@@ -548,8 +548,6 @@ sub phase2 {
 
     my $nodename = PVE::INotify::nodename();
 
-    my $conf = $self->{vmconf};
-
     $self->log('info', "starting VM $vmid on remote node '$self->{node}'");
 
     my $migration_type = $self->{opts}->{migration_type};
@@ -561,189 +559,7 @@ sub phase2 {
 
     livemigrate_storage($self, $vmid);
 
-    my $start = time();
-
-    my $opt_bwlimit = $self->{opts}->{bwlimit};
-
-    $self->log('info', "starting online/live migration on $ruri");
-    $self->{livemigration} = 1;
-
-    # load_defaults
-    my $defaults = PVE::QemuServer::load_defaults();
-
-    $self->log('info', "set migration_caps");
-    eval {
-       PVE::QemuServer::set_migration_caps($vmid);
-    };
-    warn $@ if $@;
-
-    my $qemu_migrate_params = {};
-
-    # migrate speed can be set via bwlimit (datacenter.cfg and API) and via the
-    # migrate_speed parameter in qm.conf - take the lower of the two.
-    my $bwlimit = PVE::Storage::get_bandwidth_limit('migration', undef, 
$opt_bwlimit) // 0;
-    my $migrate_speed = $conf->{migrate_speed} // $bwlimit;
-    # migrate_speed is in MB/s, bwlimit in KB/s
-    $migrate_speed *= 1024;
-
-    $migrate_speed = ($bwlimit < $migrate_speed) ? $bwlimit : $migrate_speed;
-
-    # always set migrate speed (overwrite kvm default of 32m) we set a very 
high
-    # default of 8192m which is basically unlimited
-    $migrate_speed ||= ($defaults->{migrate_speed} || 8192) * 1024;
-
-    # qmp takes migrate_speed in B/s.
-    $migrate_speed *= 1024;
-    $self->log('info', "migration speed limit: $migrate_speed B/s");
-    $qemu_migrate_params->{'max-bandwidth'} = int($migrate_speed);
-
-    my $migrate_downtime = $defaults->{migrate_downtime};
-    $migrate_downtime = $conf->{migrate_downtime} if 
defined($conf->{migrate_downtime});
-    if (defined($migrate_downtime)) {
-       # migrate-set-parameters expects limit in ms
-       $migrate_downtime *= 1000;
-       $self->log('info', "migration downtime limit: $migrate_downtime ms");
-       $qemu_migrate_params->{'downtime-limit'} = int($migrate_downtime);
-    }
-
-    # set cachesize to 10% of the total memory
-    my $memory =  $conf->{memory} || $defaults->{memory};
-    my $cachesize = int($memory * 1048576 / 10);
-    $cachesize = round_powerof2($cachesize);
-
-    $self->log('info', "migration cachesize: $cachesize B");
-    $qemu_migrate_params->{'xbzrle-cache-size'} = int($cachesize);
-
-    $self->log('info', "set migration parameters");
-    eval {
-       mon_cmd($vmid, "migrate-set-parameters", %{$qemu_migrate_params});
-    };
-    $self->log('info', "migrate-set-parameters error: $@") if $@;
-
-    if (PVE::QemuServer::vga_conf_has_spice($conf->{vga})) {
-       my $rpcenv = PVE::RPCEnvironment::get();
-       my $authuser = $rpcenv->get_user();
-
-       my (undef, $proxyticket) = 
PVE::AccessControl::assemble_spice_ticket($authuser, $vmid, $self->{node});
-
-       my $filename = "/etc/pve/nodes/$self->{node}/pve-ssl.pem";
-       my $subject =  PVE::AccessControl::read_x509_subject_spice($filename);
-
-       $self->log('info', "spice client_migrate_info");
-
-       eval {
-           mon_cmd($vmid, "client_migrate_info", protocol => 'spice',
-                                               hostname => $proxyticket, 
'port' => 0, 'tls-port' => $spice_port,
-                                               'cert-subject' => $subject);
-       };
-       $self->log('info', "client_migrate_info error: $@") if $@;
-
-    }
-
-    $self->log('info', "start migrate command to $ruri");
-    eval {
-       mon_cmd($vmid, "migrate", uri => $ruri);
-    };
-    my $merr = $@;
-    $self->log('info', "migrate uri => $ruri failed: $merr") if $merr;
-
-    my $lstat = 0;
-    my $usleep = 1000000;
-    my $i = 0;
-    my $err_count = 0;
-    my $lastrem = undef;
-    my $downtimecounter = 0;
-    while (1) {
-       $i++;
-       my $avglstat = $lstat/$i if $lstat;
-
-       usleep($usleep);
-       my $stat;
-       eval {
-           $stat = mon_cmd($vmid, "query-migrate");
-       };
-       if (my $err = $@) {
-           $err_count++;
-           warn "query migrate failed: $err\n";
-           $self->log('info', "query migrate failed: $err");
-           if ($err_count <= 5) {
-               usleep(1000000);
-               next;
-           }
-           die "too many query migrate failures - aborting\n";
-       }
-
-        if (defined($stat->{status}) && $stat->{status} =~ m/^(setup)$/im) {
-            sleep(1);
-            next;
-        }
-
-       if (defined($stat->{status}) && $stat->{status} =~ 
m/^(active|completed|failed|cancelled)$/im) {
-           $merr = undef;
-           $err_count = 0;
-           if ($stat->{status} eq 'completed') {
-               my $delay = time() - $start;
-               if ($delay > 0) {
-                   my $mbps = sprintf "%.2f", $memory / $delay;
-                   my $downtime = $stat->{downtime} || 0;
-                   $self->log('info', "migration speed: $mbps MB/s - downtime 
$downtime ms");
-               }
-           }
-
-           if ($stat->{status} eq 'failed' || $stat->{status} eq 'cancelled') {
-               $self->log('info', "migration status error: $stat->{status}");
-               die "aborting\n"
-           }
-
-           if ($stat->{status} ne 'active') {
-               $self->log('info', "migration status: $stat->{status}");
-               last;
-           }
-
-           if ($stat->{ram}->{transferred} ne $lstat) {
-               my $trans = $stat->{ram}->{transferred} || 0;
-               my $rem = $stat->{ram}->{remaining} || 0;
-               my $total = $stat->{ram}->{total} || 0;
-               my $xbzrlecachesize = $stat->{"xbzrle-cache"}->{"cache-size"} 
|| 0;
-               my $xbzrlebytes = $stat->{"xbzrle-cache"}->{"bytes"} || 0;
-               my $xbzrlepages = $stat->{"xbzrle-cache"}->{"pages"} || 0;
-               my $xbzrlecachemiss = $stat->{"xbzrle-cache"}->{"cache-miss"} 
|| 0;
-               my $xbzrleoverflow = $stat->{"xbzrle-cache"}->{"overflow"} || 0;
-               # reduce sleep if remainig memory is lower than the average 
transfer speed
-               $usleep = 100000 if $avglstat && $rem < $avglstat;
-
-               $self->log('info', "migration status: $stat->{status} 
(transferred ${trans}, " .
-                          "remaining ${rem}), total ${total})");
-
-               if (${xbzrlecachesize}) {
-                   $self->log('info', "migration xbzrle cachesize: 
${xbzrlecachesize} transferred ${xbzrlebytes} pages ${xbzrlepages} cachemiss 
${xbzrlecachemiss} overflow ${xbzrleoverflow}");
-               }
-
-               if (($lastrem  && $rem > $lastrem ) || ($rem == 0)) {
-                   $downtimecounter++;
-               }
-               $lastrem = $rem;
-
-               if ($downtimecounter > 5) {
-                   $downtimecounter = 0;
-                   $migrate_downtime *= 2;
-                   $self->log('info', "migrate_set_downtime: 
$migrate_downtime");
-                   eval {
-                       mon_cmd($vmid, "migrate_set_downtime", value => 
int($migrate_downtime*100)/100);
-                   };
-                   $self->log('info', "migrate_set_downtime error: $@") if $@;
-               }
-
-           }
-
-
-           $lstat = $stat->{ram}->{transferred};
-
-       } else {
-           die $merr if $merr;
-           die "unable to parse migration status '$stat->{status}' - 
aborting\n";
-       }
-    }
+    livemigrate($self, $vmid, $ruri, $spice_port);
 }
 
 sub phase2_cleanup {
@@ -1130,4 +946,194 @@ sub livemigrate_storage {
     }
 }
 
+sub livemigrate {
+    my ($self, $vmid, $ruri, $spice_port) = @_;
+
+    my $conf = $self->{vmconf};
+
+    my $start = time();
+
+    my $opt_bwlimit = $self->{opts}->{bwlimit};
+
+    $self->log('info', "starting online/live migration on $ruri");
+    $self->{livemigration} = 1;
+
+    # load_defaults
+    my $defaults = PVE::QemuServer::load_defaults();
+
+    $self->log('info', "set migration_caps");
+    eval {
+       PVE::QemuServer::set_migration_caps($vmid);
+    };
+    warn $@ if $@;
+
+    my $qemu_migrate_params = {};
+
+    # migrate speed can be set via bwlimit (datacenter.cfg and API) and via the
+    # migrate_speed parameter in qm.conf - take the lower of the two.
+    my $bwlimit = PVE::Storage::get_bandwidth_limit('migration', undef, 
$opt_bwlimit) // 0;
+    my $migrate_speed = $conf->{migrate_speed} // $bwlimit;
+    # migrate_speed is in MB/s, bwlimit in KB/s
+    $migrate_speed *= 1024;
+
+    $migrate_speed = ($bwlimit < $migrate_speed) ? $bwlimit : $migrate_speed;
+
+    # always set migrate speed (overwrite kvm default of 32m) we set a very 
high
+    # default of 8192m which is basically unlimited
+    $migrate_speed ||= ($defaults->{migrate_speed} || 8192) * 1024;
+
+    # qmp takes migrate_speed in B/s.
+    $migrate_speed *= 1024;
+    $self->log('info', "migration speed limit: $migrate_speed B/s");
+    $qemu_migrate_params->{'max-bandwidth'} = int($migrate_speed);
+
+    my $migrate_downtime = $defaults->{migrate_downtime};
+    $migrate_downtime = $conf->{migrate_downtime} if 
defined($conf->{migrate_downtime});
+    if (defined($migrate_downtime)) {
+       # migrate-set-parameters expects limit in ms
+       $migrate_downtime *= 1000;
+       $self->log('info', "migration downtime limit: $migrate_downtime ms");
+       $qemu_migrate_params->{'downtime-limit'} = int($migrate_downtime);
+    }
+
+    # set cachesize to 10% of the total memory
+    my $memory =  $conf->{memory} || $defaults->{memory};
+    my $cachesize = int($memory * 1048576 / 10);
+    $cachesize = round_powerof2($cachesize);
+
+    $self->log('info', "migration cachesize: $cachesize B");
+    $qemu_migrate_params->{'xbzrle-cache-size'} = int($cachesize);
+
+    $self->log('info', "set migration parameters");
+    eval {
+       mon_cmd($vmid, "migrate-set-parameters", %{$qemu_migrate_params});
+    };
+    $self->log('info', "migrate-set-parameters error: $@") if $@;
+
+    if (PVE::QemuServer::vga_conf_has_spice($conf->{vga})) {
+       my $rpcenv = PVE::RPCEnvironment::get();
+       my $authuser = $rpcenv->get_user();
+
+       my (undef, $proxyticket) = 
PVE::AccessControl::assemble_spice_ticket($authuser, $vmid, $self->{node});
+
+       my $filename = "/etc/pve/nodes/$self->{node}/pve-ssl.pem";
+       my $subject =  PVE::AccessControl::read_x509_subject_spice($filename);
+
+       $self->log('info', "spice client_migrate_info");
+
+       eval {
+           mon_cmd($vmid, "client_migrate_info", protocol => 'spice',
+                                               hostname => $proxyticket, 
'port' => 0, 'tls-port' => $spice_port,
+                                               'cert-subject' => $subject);
+       };
+       $self->log('info', "client_migrate_info error: $@") if $@;
+
+    }
+
+    $self->log('info', "start migrate command to $ruri");
+    eval {
+       mon_cmd($vmid, "migrate", uri => $ruri);
+    };
+    my $merr = $@;
+    $self->log('info', "migrate uri => $ruri failed: $merr") if $merr;
+
+    my $lstat = 0;
+    my $usleep = 1000000;
+    my $i = 0;
+    my $err_count = 0;
+    my $lastrem = undef;
+    my $downtimecounter = 0;
+    while (1) {
+       $i++;
+       my $avglstat = $lstat/$i if $lstat;
+
+       usleep($usleep);
+       my $stat;
+       eval {
+           $stat = mon_cmd($vmid, "query-migrate");
+       };
+       if (my $err = $@) {
+           $err_count++;
+           warn "query migrate failed: $err\n";
+           $self->log('info', "query migrate failed: $err");
+           if ($err_count <= 5) {
+               usleep(1000000);
+               next;
+           }
+           die "too many query migrate failures - aborting\n";
+       }
+
+        if (defined($stat->{status}) && $stat->{status} =~ m/^(setup)$/im) {
+            sleep(1);
+            next;
+        }
+
+       if (defined($stat->{status}) && $stat->{status} =~ 
m/^(active|completed|failed|cancelled)$/im) {
+           $merr = undef;
+           $err_count = 0;
+           if ($stat->{status} eq 'completed') {
+               my $delay = time() - $start;
+               if ($delay > 0) {
+                   my $mbps = sprintf "%.2f", $memory / $delay;
+                   my $downtime = $stat->{downtime} || 0;
+                   $self->log('info', "migration speed: $mbps MB/s - downtime 
$downtime ms");
+               }
+           }
+
+           if ($stat->{status} eq 'failed' || $stat->{status} eq 'cancelled') {
+               $self->log('info', "migration status error: $stat->{status}");
+               die "aborting\n"
+           }
+
+           if ($stat->{status} ne 'active') {
+               $self->log('info', "migration status: $stat->{status}");
+               last;
+           }
+
+           if ($stat->{ram}->{transferred} ne $lstat) {
+               my $trans = $stat->{ram}->{transferred} || 0;
+               my $rem = $stat->{ram}->{remaining} || 0;
+               my $total = $stat->{ram}->{total} || 0;
+               my $xbzrlecachesize = $stat->{"xbzrle-cache"}->{"cache-size"} 
|| 0;
+               my $xbzrlebytes = $stat->{"xbzrle-cache"}->{"bytes"} || 0;
+               my $xbzrlepages = $stat->{"xbzrle-cache"}->{"pages"} || 0;
+               my $xbzrlecachemiss = $stat->{"xbzrle-cache"}->{"cache-miss"} 
|| 0;
+               my $xbzrleoverflow = $stat->{"xbzrle-cache"}->{"overflow"} || 0;
+               # reduce sleep if remainig memory is lower than the average 
transfer speed
+               $usleep = 100000 if $avglstat && $rem < $avglstat;
+
+               $self->log('info', "migration status: $stat->{status} 
(transferred ${trans}, " .
+                          "remaining ${rem}), total ${total})");
+
+               if (${xbzrlecachesize}) {
+                   $self->log('info', "migration xbzrle cachesize: 
${xbzrlecachesize} transferred ${xbzrlebytes} pages ${xbzrlepages} cachemiss 
${xbzrlecachemiss} overflow ${xbzrleoverflow}");
+               }
+
+               if (($lastrem  && $rem > $lastrem ) || ($rem == 0)) {
+                   $downtimecounter++;
+               }
+               $lastrem = $rem;
+
+               if ($downtimecounter > 5) {
+                   $downtimecounter = 0;
+                   $migrate_downtime *= 2;
+                   $self->log('info', "migrate_set_downtime: 
$migrate_downtime");
+                   eval {
+                       mon_cmd($vmid, "migrate_set_downtime", value => 
int($migrate_downtime*100)/100);
+                   };
+                   $self->log('info', "migrate_set_downtime error: $@") if $@;
+               }
+
+           }
+
+
+           $lstat = $stat->{ram}->{transferred};
+
+       } else {
+           die $merr if $merr;
+           die "unable to parse migration status '$stat->{status}' - 
aborting\n";
+       }
+    }
+}
+
 1;
-- 
2.20.1

_______________________________________________
pve-devel mailing list
pve-devel@pve.proxmox.com
https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel

Reply via email to