[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