]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer/Machine.pm
config: parse: also warn about invalid lines
[qemu-server.git] / PVE / QemuServer / Machine.pm
index 165e25a4592ae10e4c97832b59ad08e30acace4d..c168adee6a6a246fbfc2dab7b8aac93e4f74f1ec 100644 (file)
@@ -6,6 +6,12 @@ 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 = {
+    '4.1' => 2,
+};
+
 sub machine_type_is_q35 {
     my ($conf) = @_;
 
@@ -18,31 +24,75 @@ 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+)/) {
+           my $pvever = get_pve_version($kvmversion);
+           return "$1.$2+pve$pvever";
+       }
     }
 
-    return undef;
+    return;
 }
 
 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);
+}
+
+sub get_pve_version {
+    my ($verstr) = @_;
+
+    if ($verstr =~ m/^(\d+\.\d+)/) {
+       return $PVE_MACHINE_VERSION->{$1} // 0;
+    }
+
+    die "internal error: cannot get pve version for invalid string '$verstr'";
+}
+
+sub can_run_pve_machine_version {
+    my ($machine_version, $kvmversion) = @_;
+
+    $machine_version =~ m/^(\d+)\.(\d+)(?:\+pve(\d+))$/;
+    my $major = $1;
+    my $minor = $2;
+    my $pvever = $3;
+
+    $kvmversion =~ m/(\d+)\.(\d+)/;
+    return 0 if PVE::QemuServer::Helpers::version_cmp($1, $major, $2, $minor) < 0;
+
+    # if $pvever is missing or 0, we definitely support it as long as we didn't
+    # fail the QEMU version check above
+    return 1 if !$pvever;
+
+    my $max_supported = get_pve_version("$major.$minor");
+    return 1 if $max_supported >= $pvever;
+
+    return 0;
 }
 
 # dies if a) VM not running or not exisiting b) Version query failed
@@ -54,7 +104,7 @@ sub runs_at_least_qemu_version {
     die "could not query currently running version for VM $vmid\n" if !defined($v);
     $v = $v->{qemu};
 
-    return version_cmp($v->{major}, $major, $v->{minor}, $minor, $v->{micro}, $extra) >= 0;
+    return PVE::QemuServer::Helpers::version_cmp($v->{major}, $major, $v->{minor}, $minor, $v->{micro}, $extra) >= 0;
 }
 
 sub qemu_machine_pxe {