[pve-devel] [RFC PATCH qemu-server 6/7] migration, memory: explicit dimm configuration
Wolfgang Bumiller
w.bumiller at proxmox.com
Tue Dec 20 12:49:25 CET 2016
Migration needs to replicate the dimm configuration on the
remote side.
Since our explicit dimm configuration is still partially
abstracted in a way that we don't need to care about
addresses or slots, we need a way to pass this information
to the remote side.
This "upgrades" the stdin information passing we use for
the spice ticket to a json object which can now contain the
spice ticket as well as qemu's current dimm list obtained
from the 'query-memory-devices' qmp command.
---
PVE/API2/Qemu.pm | 14 +++++++++++---
PVE/QemuMigrate.pm | 20 +++++++++++++++-----
PVE/QemuServer.pm | 13 ++++++++-----
PVE/QemuServer/Memory.pm | 18 ++++++++++++++++--
4 files changed, 50 insertions(+), 15 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index d0070a6..ae2ae76 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -5,6 +5,7 @@ use warnings;
use Cwd 'abs_path';
use Net::SSLeay;
use UUID;
+use JSON;
use PVE::Cluster qw (cfs_read_file cfs_write_file);;
use PVE::SafeSyslog;
@@ -1680,12 +1681,19 @@ __PACKAGE__->register_method({
raise_param_exc({ migration_network => "Only root may use this option." })
if $migration_network && $authuser ne 'root at pam';
- # read spice ticket from STDIN
+ # read state info (spice ticket, hotplugged memory) from STDIN
+ my $stateinfo;
my $spice_ticket;
if ($stateuri && ($stateuri eq 'tcp') && $migratedfrom && ($rpcenv->{type} eq 'cli')) {
- if (defined(my $line = <>)) {
+ my $line = <>;
+ if (defined($line) && $line !~ /^\{/) {
+ # backward compatibility: we only got a spice ticket
chomp $line;
$spice_ticket = $line;
+ } elsif (defined($line)) { # starts with a {
+ $line .= do { local $/ = undef; <> } // '';
+ $stateinfo = from_json($line);
+ $spice_ticket = $stateinfo->{spice_ticket};
}
}
@@ -1720,7 +1728,7 @@ __PACKAGE__->register_method({
syslog('info', "start VM $vmid: $upid\n");
PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock, $migratedfrom, undef,
- $machine, $spice_ticket, $migration_network, $migration_type);
+ $machine, $spice_ticket, $migration_network, $migration_type, $stateinfo);
return;
};
diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
index 76ae55e..1415a13 100644
--- a/PVE/QemuMigrate.pm
+++ b/PVE/QemuMigrate.pm
@@ -6,6 +6,7 @@ use PVE::AbstractMigrate;
use IO::File;
use IPC::Open2;
use POSIX qw( WNOHANG );
+use JSON;
use PVE::INotify;
use PVE::Tools;
use PVE::Cluster;
@@ -443,13 +444,15 @@ sub phase2 {
my $ruri; # the whole migration dst. URI (protocol:address[:port])
my $nodename = PVE::INotify::nodename();
+ my $stateinfo = {};
+
## start on remote node
my $cmd = [@{$self->{rem_ssh}}];
- my $spice_ticket;
if (PVE::QemuServer::vga_conf_has_spice($conf->{vga})) {
my $res = PVE::QemuServer::vm_mon_cmd($vmid, 'query-spice');
- $spice_ticket = $res->{ticket};
+ # spice ticket should be "secret" and not passed via the command line
+ $stateinfo->{spice_ticket} = $res->{ticket};
}
push @$cmd , 'qm', 'start', $vmid, '--skiplock', '--migratedfrom', $nodename;
@@ -484,9 +487,16 @@ sub phase2 {
my $spice_port;
- # Note: We try to keep $spice_ticket secret (do not pass via command line parameter)
- # instead we pipe it through STDIN
- PVE::Tools::run_command($cmd, input => $spice_ticket, outfunc => sub {
+ my $hotplug_features = {};
+ if (my $hotplug = $conf->{hotplug}) {
+ $hotplug_features = PVE::QemuServer::parse_hotplug_features($hotplug);
+ }
+ if ($hotplug_features->{memory} && defined($conf->{dimms})) {
+ $stateinfo->{dimms} = PVE::QemuServer::Memory::qemu_dimm_list($vmid);
+ }
+
+ my $statedata = to_json($stateinfo) if %$stateinfo;
+ PVE::Tools::run_command($cmd, input => $statedata, outfunc => sub {
my $line = shift;
if ($line =~ m/^migration listens on tcp:(localhost|[\d\.]+|\[[\d\.:a-fA-F]+\]):(\d+)$/) {
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 3724249..66aad3a 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -2776,7 +2776,7 @@ sub vga_conf_has_spice {
}
sub config_to_command {
- my ($storecfg, $vmid, $conf, $defaults, $forcemachine) = @_;
+ my ($storecfg, $vmid, $conf, $defaults, $forcemachine, $stateinfo) = @_;
my $cmd = [];
my $globalFlags = [];
@@ -3107,8 +3107,9 @@ sub config_to_command {
push @$cmd, '-cpu', $cpu;
- PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd);
-
+ PVE::QemuServer::Memory::config($conf, $vmid, $sockets, $cores,
+ $defaults, $hotplug_features,
+ $cmd, $stateinfo->{dimms});
push @$cmd, '-S' if $conf->{freeze};
# set keyboard layout
@@ -4459,7 +4460,8 @@ sub vmconfig_update_disk {
sub vm_start {
my ($storecfg, $vmid, $statefile, $skiplock, $migratedfrom, $paused,
- $forcemachine, $spice_ticket, $migration_network, $migration_type) = @_;
+ $forcemachine, $spice_ticket, $migration_network, $migration_type,
+ $stateinfo) = @_;
PVE::QemuConfig->lock_config($vmid, sub {
my $conf = PVE::QemuConfig->load_config($vmid, $migratedfrom);
@@ -4480,7 +4482,8 @@ sub vm_start {
# set environment variable useful inside network script
$ENV{PVE_MIGRATED_FROM} = $migratedfrom if $migratedfrom;
- my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
+ my ($cmd, $vollist, $spice_port) =
+ config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine, $stateinfo);
my $migrate_port = 0;
my $migrate_uri;
diff --git a/PVE/QemuServer/Memory.pm b/PVE/QemuServer/Memory.pm
index 002eadd..89f1aff 100644
--- a/PVE/QemuServer/Memory.pm
+++ b/PVE/QemuServer/Memory.pm
@@ -395,7 +395,7 @@ sub qemu_dimm_list {
}
sub config {
- my ($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd) = @_;
+ my ($conf, $vmid, $sockets, $cores, $defaults, $hotplug_features, $cmd, $qemu_dimms) = @_;
my $dimmlist = $conf->{dimms};
my @dimms = parse_dimmlist($dimmlist) if $dimmlist;
@@ -491,7 +491,21 @@ sub config {
}
if ($hotplug_features->{memory}) {
- if ($dimmlist) {
+ if ($qemu_dimms) {
+ foreach my $name (keys %$qemu_dimms) {
+ my $dimm = $qemu_dimms->{$name};
+ my $size = $dimm->{size};
+ my $megs = $size / (1024*1024);
+ die "migration requested dimm size of invalid size\n"
+ if $megs*1024*1024 != $size;
+ my $mem_object = print_mem_object($conf, "mem-$name", $megs);
+ push @$cmd, '-object', $mem_object;
+ push @$cmd, '-device', "pc-dimm,id=$name,memdev=mem-$name"
+ . ",slot=$dimm->{slot}"
+ . ",node=$dimm->{node}"
+ . sprintf(",addr=0x%x", $dimm->{addr});
+ }
+ } elsif ($dimmlist) {
my $id = 0;
foreach my $dimm (@dimms) {
my ($dimm_size, $numanode) = @$dimm;
--
2.1.4
More information about the pve-devel
mailing list