[pve-devel] [PATCH v7 qemu-server 10/10] Include "-cpu" parameter with snapshots/suspend
Stefan Reiter
s.reiter at proxmox.com
Mon Jan 27 10:52:31 CET 2020
On 1/27/20 9:54 AM, Thomas Lamprecht wrote:
> On 1/16/20 4:40 PM, Stefan Reiter wrote:
>> 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.
>
> few general things:
>
> 1. wouldn't this belong before or in patch 03/10 to avoid temporary
> breakage possibility? I mean a user has to actively enable it so
> it could be OK, but still.
Rebasing 09/10 & 10/10 after 04/10 is the earliest it works without
(trivial, but still) conflicts, but that should be fine as well (since
only 06/10 allows a user to actually choose a custom CPU for a VM). So
yes, I agree it makes sense to do that.
>
> 2. Doesn't this need a bump of the perversion for the machine? Else
> this fails on migration with due to the new option, which could
> be confusing/seem like a bug. Maybe only allow/add the whole custom
> thing with a bumped machine version?
>
The only issue I see is with taking a snapshot and trying to restore on
an older version? What scenario did you come up with where it breaks?
Slightly off-topic, but relevant: should it be possible to run newer
+pveX machine types on older qemu-server versions? I.e. we currently
check for QEMU version ("Installed QEMU version FOO is too old to run
machine type BAR ..."), but accept a newer pveversion, say
'pc-q35-4.1+pve42', without warning/error.
>>
>> Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
>> ---
>>
>> New in v7.
>>
>> PVE/API2/Qemu.pm | 1 +
>> PVE/QemuConfig.pm | 36 +++++++++++++++++++++++++++---------
>> PVE/QemuServer.pm | 28 ++++++++++++++++++++--------
>> 3 files changed, 48 insertions(+), 17 deletions(-)
>>
>> diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
>> index f0b9e58..c2f6513 100644
>> --- a/PVE/API2/Qemu.pm
>> +++ b/PVE/API2/Qemu.pm
>> @@ -1098,6 +1098,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 1ba728a..852c309 100644
>> --- a/PVE/QemuConfig.pm
>> +++ b/PVE/QemuConfig.pm
>> @@ -5,9 +5,10 @@ use warnings;
>>
>> use PVE::AbstractConfig;
>> use PVE::INotify;
>> +use PVE::QemuServer;
>> +use PVE::QemuServer::CPUConfig;
>> use PVE::QemuServer::Helpers;
>> use PVE::QemuServer::Monitor qw(mon_cmd);
>> -use PVE::QemuServer;
>> use PVE::QemuServer::Machine;
>> use PVE::Storage;
>> use PVE::Tools;
>> @@ -156,15 +157,26 @@ 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
>> + my $runningcpu;
>> + if (my $pid = PVE::QemuServer::check_running($vmid)) {
>> + my $cmdline = PVE::QemuServer::Helpers::parse_cmdline($pid);
>> + die "could not read commandline of running machine\n"
>> + if !$cmdline->{cpu}->{value};
>> +
>> + # sanitize and untaint value
>> + $cmdline->{cpu}->{value} =~ $PVE::QemuServer::CPUConfig::qemu_cmdline_cpu_re;
>> + $runningcpu = $1;
>> }
>>
>> + if (!$suspend) {
>> + $conf = $conf->{snapshots}->{$snapname};
>> + }
>> +
>> + $conf->{vmstate} = $statefile;
>> + $conf->{runningmachine} = $runningmachine;
>> + $conf->{runningcpu} = $runningcpu;
>> +
>> return $statefile;
>> }
>>
>> @@ -310,6 +322,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).
>> @@ -362,7 +379,8 @@ sub __snapshot_rollback_vm_start {
>> my ($class, $vmid, $vmstate, $data) = @_;
>>
>> my $storecfg = PVE::Storage::config();
>> - PVE::QemuServer::vm_start($storecfg, $vmid, $vmstate, undef, undef, undef, $data->{forcemachine});
>> + PVE::QemuServer::vm_start($storecfg, $vmid, $vmstate, undef, undef, undef,
>> + $data->{forcemachine}, undef, undef, undef, undef, undef, $data->{forcecpu});
>> }
>>
>> sub __snapshot_rollback_get_unused {
>> diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
>> index 4a5dfac..d7b9c09 100644
>> --- a/PVE/QemuServer.pm
>> +++ b/PVE/QemuServer.pm
>> @@ -532,8 +532,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.",
>> @@ -2364,7 +2371,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};
>> }
>>
>> @@ -5231,8 +5239,9 @@ sub vm_start {
>> PVE::GuestHelpers::exec_hookscript($conf, $vmid, 'pre-start', 1);
>>
>> if ($is_suspended) {
>> - # enforce machine type on suspended vm to ensure HW compatibility
>> + # enforce machine type and CPU on suspended vm to ensure HW compatibility
>> $forcemachine = $conf->{runningmachine};
>> + $force_cpu = $conf->{runningcpu};
>> print "Resuming suspended VM\n";
>> }
>>
>> @@ -5478,7 +5487,7 @@ sub vm_start {
>> 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);
>> }
>>
>> @@ -5491,13 +5500,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
>>
>> @@ -5506,7 +5517,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);
>> }
>> @@ -5780,7 +5792,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 $@;
>>
>
More information about the pve-devel
mailing list