[pve-devel] [PATCH v4 qemu-server 5/8] refactor: extract QEMU machine related helpers to package
Stefan Reiter
s.reiter at proxmox.com
Tue Nov 19 12:23:48 CET 2019
...PVE::QemuServer::Machine.
qemu_machine_feature_enabled is exported since it has a *lot* of users
in PVE::QemuServer and a long enough name as it is.
Signed-off-by: Stefan Reiter <s.reiter at proxmox.com>
---
I left the code exporting qemu_machine_feature_enabled from v2 and only remove
it in the next patch, just to make sure this patch works standalone as well.
PVE/QemuConfig.pm | 3 +-
PVE/QemuMigrate.pm | 3 +-
PVE/QemuServer.pm | 103 +++-----------------------------------
PVE/QemuServer/Machine.pm | 101 +++++++++++++++++++++++++++++++++++++
PVE/QemuServer/Makefile | 1 +
PVE/VZDump/QemuServer.pm | 3 +-
6 files changed, 116 insertions(+), 98 deletions(-)
create mode 100644 PVE/QemuServer/Machine.pm
diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
index c3b9ac5..f13c7b0 100644
--- a/PVE/QemuConfig.pm
+++ b/PVE/QemuConfig.pm
@@ -8,6 +8,7 @@ use PVE::INotify;
use PVE::QemuServer::Helpers;
use PVE::QemuServer::Monitor qw(mon_cmd);
use PVE::QemuServer;
+use PVE::QemuServer::Machine;
use PVE::Storage;
use PVE::Tools;
@@ -165,7 +166,7 @@ sub __snapshot_save_vmstate {
$name .= ".raw" if $scfg->{path}; # add filename extension for file base storage
my $statefile = PVE::Storage::vdisk_alloc($storecfg, $target, $vmid, 'raw', $name, $size*1024);
- my $runningmachine = PVE::QemuServer::get_current_qemu_machine($vmid);
+ my $runningmachine = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
if ($suspend) {
$conf->{vmstate} = $statefile;
diff --git a/PVE/QemuMigrate.pm b/PVE/QemuMigrate.pm
index ce06af0..20cf473 100644
--- a/PVE/QemuMigrate.pm
+++ b/PVE/QemuMigrate.pm
@@ -11,6 +11,7 @@ use PVE::Tools;
use PVE::Cluster;
use PVE::Storage;
use PVE::QemuServer;
+use PVE::QemuServer::Machine;
use PVE::QemuServer::Monitor qw(mon_cmd);
use Time::HiRes qw( usleep );
use PVE::RPCEnvironment;
@@ -216,7 +217,7 @@ sub prepare {
die "can't migrate running VM without --online\n" if !$online;
$running = $pid;
- $self->{forcemachine} = PVE::QemuServer::qemu_machine_pxe($vmid, $conf);
+ $self->{forcemachine} = PVE::QemuServer::Machine::qemu_machine_pxe($vmid, $conf);
}
my $loc_res = PVE::QemuServer::check_local_resources($conf, 1);
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 8d8ebc9..1ad6242 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -43,6 +43,7 @@ use PVE::QMPClient;
use PVE::QemuConfig;
use PVE::QemuServer::Helpers;
use PVE::QemuServer::Cloudinit;
+use PVE::QemuServer::Machine qw(qemu_machine_feature_enabled);
use PVE::QemuServer::Memory;
use PVE::QemuServer::Monitor qw(mon_cmd);
use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port);
@@ -1836,20 +1837,14 @@ sub path_is_scsi {
return $res;
}
-sub machine_type_is_q35 {
- my ($conf) = @_;
-
- return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
-}
-
sub print_tabletdevice_full {
my ($conf, $arch) = @_;
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
# we use uhci for old VMs because tablet driver was buggy in older qemu
my $usbbus;
- if (machine_type_is_q35($conf) || $arch eq 'aarch64') {
+ if (PVE::QemuServer::Machine::machine_type_is_q35($conf) || $arch eq 'aarch64') {
$usbbus = 'ehci';
} else {
$usbbus = 'uhci';
@@ -2198,7 +2193,7 @@ sub print_vga_device {
$memory = ",ram_size=67108864,vram_size=33554432";
}
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
my $vgaid = "vga" . ($id // '');
my $pciaddr;
@@ -3481,7 +3476,7 @@ sub config_to_command {
die "detected old qemu-kvm binary ($kvmver)\n" if $vernum < 15000;
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
my $hotplug_features = parse_hotplug_features(defined($conf->{hotplug}) ? $conf->{hotplug} : '1');
my $use_old_bios_files = undef;
($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
@@ -4122,7 +4117,7 @@ sub vm_devices_list {
sub vm_deviceplug {
my ($storecfg, $conf, $vmid, $deviceid, $device, $arch, $machine_type) = @_;
- my $q35 = machine_type_is_q35($conf);
+ my $q35 = PVE::QemuServer::Machine::machine_type_is_q35($conf);
my $devices_list = vm_devices_list($vmid);
return 1 if defined($devices_list->{$deviceid});
@@ -4198,7 +4193,7 @@ sub vm_deviceplug {
return undef if !qemu_netdevadd($vmid, $conf, $arch, $device, $deviceid);
- my $machine_type = PVE::QemuServer::qemu_machine_pxe($vmid, $conf);
+ my $machine_type = PVE::QemuServer::Machine::qemu_machine_pxe($vmid, $conf);
my $use_old_bios_files = undef;
($use_old_bios_files, $machine_type) = qemu_use_old_bios_files($machine_type);
@@ -4512,7 +4507,7 @@ sub qemu_usb_hotplug {
sub qemu_cpu_hotplug {
my ($vmid, $conf, $vcpus) = @_;
- my $machine_type = PVE::QemuServer::get_current_qemu_machine($vmid);
+ my $machine_type = PVE::QemuServer::Machine::get_current_qemu_machine($vmid);
my $sockets = 1;
$sockets = $conf->{smp} if $conf->{smp}; # old style - no longer iused
@@ -7016,94 +7011,12 @@ no_data_clone:
return $disk;
}
-# this only works if VM is running
-sub get_current_qemu_machine {
- my ($vmid) = @_;
-
- my $res = mon_cmd($vmid, "query-machines");
-
- my ($current, $default);
- foreach my $e (@$res) {
- $default = $e->{name} if $e->{'is-default'};
- $current = $e->{name} if $e->{'is-current'};
- }
-
- # fallback to the default machine if current is not supported by qemu
- return $current || $default || 'pc';
-}
-
sub get_running_qemu_version {
my ($vmid) = @_;
my $res = mon_cmd($vmid, "query-version");
return "$res->{qemu}->{major}.$res->{qemu}->{minor}";
}
-sub qemu_machine_feature_enabled {
- my ($machine, $kvmver, $version_major, $version_minor) = @_;
-
- my $current_major;
- my $current_minor;
-
- if ($machine && $machine =~ m/^((?:pc(-i440fx|-q35)?|virt)-(\d+)\.(\d+))/) {
-
- $current_major = $3;
- $current_minor = $4;
-
- } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
-
- $current_major = $1;
- $current_minor = $2;
- }
-
- return 1 if version_cmp($current_major, $version_major, $current_minor, $version_minor) >= 0;
-}
-
-# gets in pairs the versions you want to compares, i.e.:
-# ($a-major, $b-major, $a-minor, $b-minor, $a-extra, $b-extra, ...)
-# returns 0 if same, -1 if $a is older than $b, +1 if $a is newer than $b
-sub version_cmp {
- my @versions = @_;
-
- my $size = scalar(@versions);
-
- return 0 if $size == 0;
- die "cannot compare odd count of versions" if $size & 1;
-
- for (my $i = 0; $i < $size; $i += 2) {
- my ($a, $b) = splice(@versions, 0, 2);
- $a //= 0;
- $b //= 0;
-
- return 1 if $a > $b;
- return -1 if $a < $b;
- }
- return 0;
-}
-
-# dies if a) VM not running or not exisiting b) Version query failed
-# So, any defined return value is valid, any invalid state can be caught by eval
-sub runs_at_least_qemu_version {
- my ($vmid, $major, $minor, $extra) = @_;
-
- my $v = mon_cmd($vmid, "query-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;
-}
-
-sub qemu_machine_pxe {
- my ($vmid, $conf) = @_;
-
- my $machine = PVE::QemuServer::get_current_qemu_machine($vmid);
-
- if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) {
- $machine .= '.pxe';
- }
-
- return $machine;
-}
-
sub qemu_use_old_bios_files {
my ($machine_type) = @_;
diff --git a/PVE/QemuServer/Machine.pm b/PVE/QemuServer/Machine.pm
new file mode 100644
index 0000000..c3e0004
--- /dev/null
+++ b/PVE/QemuServer/Machine.pm
@@ -0,0 +1,101 @@
+package PVE::QemuServer::Machine;
+
+use strict;
+use warnings;
+
+use PVE::QemuServer::Monitor;
+
+use base 'Exporter';
+our @EXPORT_OK = qw(
+qemu_machine_feature_enabled
+);
+
+sub machine_type_is_q35 {
+ my ($conf) = @_;
+
+ return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0;
+}
+
+# this only works if VM is running
+sub get_current_qemu_machine {
+ my ($vmid) = @_;
+
+ my $res = PVE::QemuServer::Monitor::mon_cmd($vmid, 'query-machines');
+
+ my ($current, $default);
+ foreach my $e (@$res) {
+ $default = $e->{name} if $e->{'is-default'};
+ $current = $e->{name} if $e->{'is-current'};
+ }
+
+ # fallback to the default machine if current is not supported by qemu
+ return $current || $default || 'pc';
+}
+
+sub qemu_machine_feature_enabled {
+ my ($machine, $kvmver, $version_major, $version_minor) = @_;
+
+ my $current_major;
+ my $current_minor;
+
+ if ($machine && $machine =~ m/^((?:pc(-i440fx|-q35)?|virt)-(\d+)\.(\d+))/) {
+
+ $current_major = $3;
+ $current_minor = $4;
+
+ } elsif ($kvmver =~ m/^(\d+)\.(\d+)/) {
+
+ $current_major = $1;
+ $current_minor = $2;
+ }
+
+ return 1 if version_cmp($current_major, $version_major, $current_minor, $version_minor) >= 0;
+}
+
+# gets in pairs the versions you want to compares, i.e.:
+# ($a-major, $b-major, $a-minor, $b-minor, $a-extra, $b-extra, ...)
+# returns 0 if same, -1 if $a is older than $b, +1 if $a is newer than $b
+sub version_cmp {
+ my @versions = @_;
+
+ my $size = scalar(@versions);
+
+ return 0 if $size == 0;
+ die "cannot compare odd count of versions" if $size & 1;
+
+ for (my $i = 0; $i < $size; $i += 2) {
+ my ($a, $b) = splice(@versions, 0, 2);
+ $a //= 0;
+ $b //= 0;
+
+ return 1 if $a > $b;
+ return -1 if $a < $b;
+ }
+ return 0;
+}
+
+# dies if a) VM not running or not exisiting b) Version query failed
+# So, any defined return value is valid, any invalid state can be caught by eval
+sub runs_at_least_qemu_version {
+ my ($vmid, $major, $minor, $extra) = @_;
+
+ my $v = PVE::QemuServer::Monitor::mon_cmd($vmid, 'query-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;
+}
+
+sub qemu_machine_pxe {
+ my ($vmid, $conf) = @_;
+
+ my $machine = get_current_qemu_machine($vmid);
+
+ if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) {
+ $machine .= '.pxe';
+ }
+
+ return $machine;
+}
+
+1;
diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile
index 02b0209..670105a 100644
--- a/PVE/QemuServer/Makefile
+++ b/PVE/QemuServer/Makefile
@@ -7,6 +7,7 @@ SOURCES=PCI.pm \
Agent.pm \
Helpers.pm \
Monitor.pm \
+ Machine.pm \
.PHONY: install
install: ${SOURCES}
diff --git a/PVE/VZDump/QemuServer.pm b/PVE/VZDump/QemuServer.pm
index ca93258..1826edb 100644
--- a/PVE/VZDump/QemuServer.pm
+++ b/PVE/VZDump/QemuServer.pm
@@ -19,6 +19,7 @@ use PVE::Tools;
use PVE::VZDump;
use PVE::QemuServer;
+use PVE::QemuServer::Machine;
use PVE::QemuServer::Monitor qw(mon_cmd);
use base qw (PVE::VZDump::Plugin);
@@ -79,7 +80,7 @@ sub prepare {
$self->loginfo("exclude disk '$ds' '$volid' (backup=no)");
return;
} elsif ($self->{vm_was_running} && $drive->{iothread}) {
- if (!PVE::QemuServer::runs_at_least_qemu_version($vmid, 4, 0, 1)) {
+ if (!PVE::QemuServer::Machine::runs_at_least_qemu_version($vmid, 4, 0, 1)) {
die "disk '$ds' '$volid' (iothread=on) can't use backup feature with running QEMU " .
"version < 4.0.1! Either set backup=no for this drive or upgrade QEMU and restart VM\n";
}
--
2.20.1
More information about the pve-devel
mailing list