[pve-devel] [PATCH v3 qemu-server 5/8] refactor: extract QEMU machine related helpers to package
Fabian Grünbichler
f.gruenbichler at proxmox.com
Tue Nov 19 10:30:47 CET 2019
one probably leftover wrong use, see inline
On November 4, 2019 2:57 pm, Stefan Reiter wrote:
> ...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 | 102 +++++++++++++++++++++++++++++++++++++
> PVE/QemuServer/Makefile | 1 +
> PVE/VZDump/QemuServer.pm | 3 +-
> 6 files changed, 117 insertions(+), 98 deletions(-)
> create mode 100644 PVE/QemuServer/Machine.pm
>
> diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm
> index e2e722d..48b7a7c 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;
>
> @@ -160,7 +161,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 5b5de10..da6c7bb 100644
> --- a/PVE/QemuServer.pm
> +++ b/PVE/QemuServer.pm
> @@ -41,6 +41,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);
> @@ -1827,20 +1828,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';
> @@ -2189,7 +2184,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;
>
> @@ -3486,7 +3481,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);
> @@ -4120,7 +4115,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});
> @@ -4196,7 +4191,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);
>
> @@ -4510,7 +4505,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
> @@ -6975,94 +6970,12 @@ sub clone_disk {
> 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..d47f4e4
> --- /dev/null
> +++ b/PVE/QemuServer/Machine.pm
> @@ -0,0 +1,102 @@
> +package PVE::QemuServer::Machine;
> +
> +use strict;
> +use warnings;
> +
> +use PVE::QemuConfig;
^^^^^^^^^
why?
> +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 4322cb8..1902b2f 100644
> --- a/PVE/VZDump/QemuServer.pm
> +++ b/PVE/VZDump/QemuServer.pm
> @@ -18,6 +18,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);
> @@ -78,7 +79,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
>
>
> _______________________________________________
> pve-devel mailing list
> pve-devel at pve.proxmox.com
> https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel
>
>
More information about the pve-devel
mailing list