]> git.proxmox.com Git - qemu-server.git/commitdiff
implement PVE Version addition for QEMU machine
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Mon, 25 Nov 2019 10:18:13 +0000 (11:18 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Mon, 25 Nov 2019 15:43:38 +0000 (16:43 +0100)
With our QEMU 4.1.1 package we can pass a additional internal version
to QEMU's machine, it will be split out there and ignored, but
returned on a QMP 'query-machines' call.

This allows us to use it for increasing the granularity with which we
can roll-out HW layout changes/additions for VMs. Until now we
required a machine version bump, happening normally every major
release of QEMU, with seldom, for us irrelevant, exceptions.
This often delays rolling out a feature, which would break
live-migration, by several months. That can now be avoided, the new
"pve-version" component of the machine can be bumped at will, and
thus we are much more flexible.

That versions orders after the ($major, $minor) version components
from an stable release - it can thus also be reset on the next
release.

The implementation extends the qemu-machine REGEX, remembers
"pve-version" when doing a "query-machines" and integrates support
into the min_version and extract_version helpers.

We start out with a version of 1.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
Reviewed-by: Stefan Reiter <s.reiter@proxmox.com>
PVE/QemuServer.pm
PVE/QemuServer/Helpers.pm
PVE/QemuServer/Machine.pm
test/cfg2cmd/i440fx-win10-hostpci.conf.cmd
test/cfg2cmd/minimal-defaults.conf.cmd
test/cfg2cmd/q35-linux-hostpci.conf.cmd
test/cfg2cmd/q35-win10-hostpci.conf.cmd
test/cfg2cmd/spice-linux-4.1.conf.cmd

index 89254fb862894d3447c051ee60d378fa0ecd7be9..39351774d9a434a4c7ab17163018405ff2810cc2 100644 (file)
@@ -93,7 +93,7 @@ PVE::JSONSchema::register_standard_option('pve-qm-image-format', {
 PVE::JSONSchema::register_standard_option('pve-qemu-machine', {
        description => "Specifies the Qemu machine type.",
        type => 'string',
-       pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\.pxe)?|virt(?:-\d+(\.\d+)+)?)',
+       pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)',
        maxLength => 40,
        optional => 1,
 });
@@ -1875,7 +1875,7 @@ sub print_drivedevice_full {
            }
 
            # for compatibility only, we prefer scsi-hd (#2408, #2355, #2380)
-           my $version = PVE::QemuServer::Machine::extract_version($machine_type) // kvm_user_version();
+           my $version = PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
            if ($path =~ m/^iscsi\:\/\// &&
               !min_version($version, 4, 1)) {
                $devicetype = 'generic';
@@ -3361,13 +3361,14 @@ my $default_machines = {
 };
 
 sub get_vm_machine {
-    my ($conf, $forcemachine, $arch) = @_;
+    my ($conf, $forcemachine, $arch, $add_pve_version) = @_;
 
     my $machine = $forcemachine || $conf->{machine};
 
-    if (!$machine) {
+    if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) {
        $arch //= 'x86_64';
        $machine ||= $default_machines->{$arch};
+       $machine .= "+pve$PVE::QemuServer::Machine::PVE_MACHINE_VERSION" if $add_pve_version;
     }
 
     return $machine;
@@ -3469,8 +3470,10 @@ sub config_to_command {
     my $kvm_binary = get_command_for_arch($arch);
     my $kvmver = kvm_user_version($kvm_binary);
 
-    my $machine_type = get_vm_machine($conf, $forcemachine, $arch);
-    my $machine_version = PVE::QemuServer::Machine::extract_version($machine_type) // $kvmver;
+    my $add_pve_version = min_version($kvmver, 4, 1);
+
+    my $machine_type = get_vm_machine($conf, $forcemachine, $arch, $add_pve_version);
+    my $machine_version = PVE::QemuServer::Machine::extract_version($machine_type, $kvmver);
     $kvm //= 1 if is_native($arch);
 
     if ($kvm) {
@@ -7049,7 +7052,7 @@ sub qemu_use_old_bios_files {
         $machine_type = $1;
         $use_old_bios_files = 1;
     } else {
-       my $version = PVE::QemuServer::Machine::extract_version($machine_type) // kvm_user_version();
+       my $version = PVE::QemuServer::Machine::extract_version($machine_type, kvm_user_version());
         # Note: kvm version < 2.4 use non-efi pxe files, and have problems when we
         # load new efi bios files on migration. So this hack is required to allow
         # live migration from qemu-2.2 to qemu-2.4, which is sometimes used when
index 0e78f36ab711e16987cf14fcb04bff1b23782c4d..fcc939228339987b90f19511c38eb7b4fc122679 100644 (file)
@@ -103,10 +103,10 @@ sub vm_running_locally {
 }
 
 sub min_version {
-    my ($verstr, $version_major, $version_minor) = @_;
+    my ($verstr, $major, $minor, $pve) = @_;
 
-    if ($verstr =~ m/^(\d+)\.(\d+)/) {
-       return 1 if version_cmp($1, $version_major, $2, $version_minor) >= 0;
+    if ($verstr =~ m/^(\d+)\.(\d+)(?:\.(\d+))?(?:\+pve(\d+))?/) {
+       return 1 if version_cmp($1, $major, $2, $minor, $4, $pve) >= 0;
        return 0;
     }
 
index 40c8eeb09797f656bc0e86cddb562b037c2fc7f1..8c13402e5d95c74991c98d36cf8ba42c66a92b17 100644 (file)
@@ -6,6 +6,10 @@ use warnings;
 use PVE::QemuServer::Helpers;
 use PVE::QemuServer::Monitor;
 
+# Bump this for VM HW layout changes during a release (where the QEMU machine
+# version stays the same)
+our $PVE_MACHINE_VERSION = 1;
+
 sub machine_type_is_q35 {
     my ($conf) = @_;
 
@@ -18,31 +22,43 @@ sub get_current_qemu_machine {
 
     my $res = PVE::QemuServer::Monitor::mon_cmd($vmid, 'query-machines');
 
-    my ($current, $default);
+    my ($current, $pve_version, $default);
     foreach my $e (@$res) {
        $default = $e->{name} if $e->{'is-default'};
        $current = $e->{name} if $e->{'is-current'};
+       $pve_version = $e->{'pve-version'} if $e->{'pve-version'};
     }
 
+    $current .= "+$pve_version" if $current && $pve_version;
+
     # fallback to the default machine if current is not supported by qemu
     return $current || $default || 'pc';
 }
 
+# returns a string with major.minor+pve<VERSION>, patch version-part is ignored
+# as it's seldom ressembling a real QEMU machine type, so it would be '0' 99% of
+# the time anyway.. This explicitly separates pveversion from the machine.
 sub extract_version {
-    my ($machine_type) = @_;
-
-    if ($machine_type && $machine_type =~ m/^((?:pc(-i440fx|-q35)?|virt)-(\d+)\.(\d+))/) {
-       return "$3.$4";
+    my ($machine_type, $kvmversion) = @_;
+
+    if (defined($machine_type) && $machine_type =~ m/^(?:pc(?:-i440fx|-q35)?|virt)-(\d+)\.(\d+)(?:\.(\d+))?(\+pve\d+)?/) {
+       my $versionstr = "$1.$2";
+       $versionstr .= $4 if $4;
+       return $versionstr;
+    } elsif (defined($kvmversion)) {
+       if ($kvmversion =~ m/^(\d+)\.(\d+)/) {
+           return "$1.$2+pve$PVE_MACHINE_VERSION";
+       }
     }
 
     return undef;
 }
 
 sub machine_version {
-    my ($machine_type, $version_major, $version_minor) = @_;
+    my ($machine_type, $major, $minor, $pve) = @_;
 
     return PVE::QemuServer::Helpers::min_version(
-       extract_version($machine_type), $version_major, $version_minor);
+       extract_version($machine_type), $major, $minor, $pve);
 }
 
 # dies if a) VM not running or not exisiting b) Version query failed
index 414d222e6b9d8fe8b9adf19c8731d146f3adf091..2bc1eefab7d077ba86afdd2b63ccf56fee9ba9c5 100644 (file)
@@ -33,5 +33,5 @@
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300' \
   -rtc 'driftfix=slew,base=localtime' \
-  -machine 'type=pc' \
+  -machine 'type=pc+pve1' \
   -global 'kvm-pit.lost_tick_policy=discard'
index 5abebe9f3884f90b0a4efd46fe751e865428b123..83ae328c361be0df7b1e6c643fbef43ad6dc7ceb 100644 (file)
@@ -21,4 +21,4 @@
   -device 'VGA,id=vga,bus=pci.0,addr=0x2' \
   -device 'virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3' \
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
-  -machine 'type=pc'
+  -machine 'type=pc+pve1'
index 21fb18ba107a94bd4d30b9141e649e3d4149f12c..6fde1c6f2c45d5edce172b1170dbb96a0a455bf9 100644 (file)
@@ -36,4 +36,4 @@
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300' \
-  -machine 'type=q35'
+  -machine 'type=q35+pve1'
index f2c08cafc12fbcbd01e2bdf2e233f9f9677e5054..cd004d95031352790786123538e4df2b5984b1e0 100644 (file)
@@ -34,5 +34,5 @@
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=2E:01:68:F9:9C:87,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300' \
   -rtc 'driftfix=slew,base=localtime' \
-  -machine 'type=q35' \
+  -machine 'type=q35+pve1' \
   -global 'kvm-pit.lost_tick_policy=discard'
index 158e73b5bf098a32e3d625cc68b85822c6d4c1a2..4ed6fd2537b1997fd28ee1bb63071e1824f7d6f0 100644 (file)
@@ -27,4 +27,4 @@
   -iscsi 'initiator-name=iqn.1993-08.org.debian:01:aabbccddeeff' \
   -netdev 'type=tap,id=net0,ifname=tap8006i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown,vhost=on' \
   -device 'virtio-net-pci,mac=A2:C0:43:67:08:A1,netdev=net0,bus=pci.0,addr=0x12,id=net0,bootindex=300' \
-  -machine 'type=pc'
+  -machine 'type=pc+pve1'