[pve-devel] [PATCH v10 qemu-server 2/6] Include "-cpu" parameter with snapshots/suspend

Stefan Reiter s.reiter at proxmox.com
Tue Apr 7 15:56:16 CEST 2020


Just like with live-migration, custom CPU models might change after a
snapshot has been taken (or a VM suspended), which would lead to a
different QEMU invocation on rollback/resume.

Save the "-cpu" argument as a new "runningcpu" option into the VM conf
akin to "runningmachine" and use as override during rollback/resume.

No functional change with non-custom CPU types intended.

Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
---

Changes in v10:
* Use PVE::QemuServer::CPUConfig::get_cpu_from_running_vm helper

 PVE/API2/Qemu.pm  |  1 +
 PVE/QemuConfig.pm | 26 +++++++++++++++++++-------
 PVE/QemuServer.pm | 31 ++++++++++++++++++++++---------
 3 files changed, 42 insertions(+), 16 deletions(-)

diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 9e453d2..ff61e4d 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1129,6 +1129,7 @@ my $update_vm_api  = sub {
 		push @delete, 'lock'; # this is the real deal to write it out
 	    }
 	    push @delete, 'runningmachine' if $conf->{runningmachine};
+	    push @delete, 'runningcpu' if $conf->{runningcpu};
 	}
 
 	PVE::QemuConfig->check_lock($conf) if !$skiplock;
diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
index f32618e..d29b88b 100644
--- a/PVE/QemuConfig.pm
+++ b/PVE/QemuConfig.pm
@@ -5,6 +5,7 @@ use warnings;
 
 use PVE::AbstractConfig;
 use PVE::INotify;
+use PVE::QemuServer::CPUConfig;
 use PVE::QemuServer::Drive;
 use PVE::QemuServer::Helpers;
 use PVE::QemuServer::Monitor qw(mon_cmd);
@@ -186,15 +187,20 @@ sub __snapshot_save_vmstate {
     my $statefile = PVE::Storage::vdisk_alloc($storecfg, $target, $vmid, 'raw', $name, $size*1024);
     my $runningmachine = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
 
-    if ($suspend) {
-	$conf->{vmstate} = $statefile;
-	$conf->{runningmachine} = $runningmachine;
-    } else {
-	my $snap = $conf->{snapshots}->{$snapname};
-	$snap->{vmstate} = $statefile;
-	$snap->{runningmachine} = $runningmachine;
+    # get current QEMU -cpu argument to ensure consistency of custom CPU models
+    my $runningcpu;
+    if (my $pid = PVE::QemuServer::check_running($vmid)) {
+	$runningcpu = PVE::QemuServer::CPUConfig::get_cpu_from_running_vm($pid);
+    }
+
+    if (!$suspend) {
+	$conf = $conf->{snapshots}->{$snapname};
     }
 
+    $conf->{vmstate} = $statefile;
+    $conf->{runningmachine} = $runningmachine;
+    $conf->{runningcpu} = $runningcpu;
+
     return $statefile;
 }
 
@@ -340,6 +346,11 @@ sub __snapshot_rollback_hook {
 	if (defined($conf->{runningmachine})) {
 	    $data->{forcemachine} = $conf->{runningmachine};
 	    delete $conf->{runningmachine};
+
+	    # runningcpu is newer than runningmachine, so assume it only exists
+	    # here, if at all
+	    $data->{forcecpu} = delete $conf->{runningcpu}
+		if defined($conf->{runningcpu});
 	} else {
 	    # Note: old code did not store 'machine', so we try to be smart
 	    # and guess the snapshot was generated with kvm 1.4 (pc-i440fx-1.4).
@@ -395,6 +406,7 @@ sub __snapshot_rollback_vm_start {
     my $params = {
 	statefile => $vmstate,
 	forcemachine => $data->{forcemachine},
+	forcecpu => $data->{forcecpu},
     };
     PVE::QemuServer::vm_start($storecfg, $vmid, $params);
 }
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index a0f8429..2d5ae7d 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -567,8 +567,15 @@ EODESCR
 	optional => 1,
     }),
     runningmachine => get_standard_option('pve-qemu-machine', {
-	description => "Specifies the Qemu machine type of the running vm. This is used internally for snapshots.",
+	description => "Specifies the QEMU machine type of the running vm. This is used internally for snapshots.",
     }),
+    runningcpu => {
+	description => "Specifies the QEMU '-cpu' parameter of the running vm. This is used internally for snapshots.",
+	optional => 1,
+	type => 'string',
+	pattern => $PVE::QemuServer::CPUConfig::qemu_cmdline_cpu_re,
+	format_description => 'QEMU -cpu parameter'
+    },
     machine => get_standard_option('pve-qemu-machine'),
     arch => {
 	description => "Virtual processor architecture. Defaults to the host.",
@@ -1948,7 +1955,8 @@ sub json_config_properties {
     my $prop = shift;
 
     foreach my $opt (keys %$confdesc) {
-	next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate' || $opt eq 'runningmachine';
+	next if $opt eq 'parent' || $opt eq 'snaptime' || $opt eq 'vmstate' ||
+	    $opt eq 'runningmachine' || $opt eq 'runningcpu';
 	$prop->{$opt} = $confdesc->{$opt};
     }
 
@@ -4845,14 +4853,16 @@ sub vm_start_nolock {
     PVE::GuestHelpers::exec_hookscript($conf, $vmid, 'pre-start', 1);
 
     my $forcemachine = $params->{forcemachine};
+    my $forcecpu = $params->{forcecpu};
     if ($resume) {
-	# enforce machine type on suspended vm to ensure HW compatibility
+	# enforce machine and CPU type on suspended vm to ensure HW compatibility
 	$forcemachine = $conf->{runningmachine};
+	$forcecpu = $conf->{runningcpu};
 	print "Resuming suspended VM\n";
     }
 
     my ($cmd, $vollist, $spice_port) = config_to_command($storecfg, $vmid, $conf,
-	$defaults, $forcemachine, $params->{forcecpu});
+	$defaults, $forcemachine, $forcecpu);
 
     my $migration_ip;
     my $get_migration_ip = sub {
@@ -5105,7 +5115,7 @@ sub vm_start_nolock {
 	    PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
 	    PVE::Storage::vdisk_free($storecfg, $vmstate);
 	}
-	delete $conf->@{qw(lock vmstate runningmachine)};
+	delete $conf->@{qw(lock vmstate runningmachine runningcpu)};
 	PVE::QemuConfig->write_config($vmid, $conf);
     }
 
@@ -5117,13 +5127,15 @@ sub vm_commandline {
 
     my $conf = PVE::QemuConfig->load_config($vmid);
     my $forcemachine;
+    my $forcecpu;
 
     if ($snapname) {
 	my $snapshot = $conf->{snapshots}->{$snapname};
 	die "snapshot '$snapname' does not exist\n" if !defined($snapshot);
 
-	# check for a 'runningmachine' in snapshot
-	$forcemachine = $snapshot->{runningmachine} if $snapshot->{runningmachine};
+	# check for machine or CPU overrides in snapshot
+	$forcemachine = $snapshot->{runningmachine};
+	$forcecpu = $snapshot->{runningcpu};
 
 	$snapshot->{digest} = $conf->{digest}; # keep file digest for API
 
@@ -5132,7 +5144,8 @@ sub vm_commandline {
 
     my $defaults = load_defaults();
 
-    my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults, $forcemachine);
+    my $cmd = config_to_command($storecfg, $vmid, $conf, $defaults,
+	$forcemachine, $forcecpu);
 
     return PVE::Tools::cmd2string($cmd);
 }
@@ -5406,7 +5419,7 @@ sub vm_suspend {
 		    mon_cmd($vmid, "savevm-end");
 		    PVE::Storage::deactivate_volumes($storecfg, [$vmstate]);
 		    PVE::Storage::vdisk_free($storecfg, $vmstate);
-		    delete $conf->@{qw(vmstate runningmachine)};
+		    delete $conf->@{qw(vmstate runningmachine runningcpu)};
 		    PVE::QemuConfig->write_config($vmid, $conf);
 		};
 		warn $@ if $@;
-- 
2.26.0





More information about the pve-devel mailing list