From 8082eb8ca1c5ca4cd0e86d713faf22bc31b6db69 Mon Sep 17 00:00:00 2001 From: Markus Frank Date: Wed, 24 Jan 2024 10:49:15 +0100 Subject: [PATCH] config: define machine schema as property-string Convert the machine parameter to a property-string and use the machine type as the default key for backward compatibility. Signed-off-by: Markus Frank --- PVE/API2/Qemu.pm | 9 +++++++-- PVE/QemuConfig.pm | 3 ++- PVE/QemuServer.pm | 16 ++++++--------- PVE/QemuServer/Machine.pm | 42 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 55 insertions(+), 15 deletions(-) diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index dc44dee..f3ce83d 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -1127,11 +1127,13 @@ __PACKAGE__->register_method({ $conf->{vmgenid} = PVE::QemuServer::generate_uuid(); } - my $machine = $conf->{machine}; + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); + my $machine = $machine_conf->{type}; if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) { # always pin Windows' machine version on create, they get to easily confused if (PVE::QemuServer::Helpers::windows_version($conf->{ostype})) { - $conf->{machine} = PVE::QemuServer::windows_get_pinned_machine_version($machine); + $machine_conf->{type} = PVE::QemuServer::windows_get_pinned_machine_version($machine); + $conf->{machine} = PVE::QemuServer::Machine::print_machine($machine_conf); } } @@ -1996,6 +1998,9 @@ my $update_vm_api = sub { ); } $conf->{pending}->{$opt} = $param->{$opt}; + } elsif ($opt eq 'machine') { + my $machine_conf = PVE::QemuServer::Machine::parse_machine($param->{$opt}); + $conf->{pending}->{$opt} = $param->{$opt}; } else { $conf->{pending}->{$opt} = $param->{$opt}; diff --git a/PVE/QemuConfig.pm b/PVE/QemuConfig.pm index ca30eda..8e8a782 100644 --- a/PVE/QemuConfig.pm +++ b/PVE/QemuConfig.pm @@ -432,7 +432,8 @@ sub __snapshot_rollback_hook { } 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). - $data->{forcemachine} = $conf->{machine} || 'pc-i440fx-1.4'; + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); + $data->{forcemachine} = $machine_conf->{type} || 'pc-i440fx-1.4'; # we remove the 'machine' configuration if not explicitly specified # in the original config. diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 4728811..abe175a 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -124,14 +124,6 @@ PVE::JSONSchema::register_standard_option('pve-qm-stateuri', { optional => 1, }); -PVE::JSONSchema::register_standard_option('pve-qemu-machine', { - description => "Specifies the QEMU machine type.", - type => 'string', - 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, -}); - # FIXME: remove in favor of just using the INotify one, it's cached there exactly the same way my $nodename_cache; sub nodename { @@ -2102,8 +2094,9 @@ sub qemu_created_version_fixups { # check if we need to apply some handling for VMs that always use the latest machine version but # had a machine version transition happen that affected HW such that, e.g., an OS config change # would be required (we do not want to pin machine version for non-windows OS type) + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); if ( - (!defined($conf->{machine}) || $conf->{machine} =~ m/^(?:pc|q35|virt)$/) # non-versioned machine + (!defined($machine_conf->{type}) || $machine_conf->{type} =~ m/^(?:pc|q35|virt)$/) # non-versioned machine && (!defined($meta->{'creation-qemu'}) || !min_version($meta->{'creation-qemu'}, 6, 1)) # created before 6.1 && (!$forced_vers || min_version($forced_vers, 6, 1)) # handle snapshot-rollback/migrations && min_version($kvmver, 6, 1) # only need to apply the change since 6.1 @@ -3259,7 +3252,8 @@ sub windows_get_pinned_machine_version { sub get_vm_machine { my ($conf, $forcemachine, $arch, $add_pve_version, $kvmversion) = @_; - my $machine = $forcemachine || $conf->{machine}; + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); + my $machine = $forcemachine || $machine_conf->{type}; if (!$machine || $machine =~ m/^(?:pc|q35|virt)$/) { $kvmversion //= kvm_user_version(); @@ -3508,6 +3502,8 @@ sub config_to_command { my $kvm = $conf->{kvm}; my $nodename = nodename(); + my $machine_conf = PVE::QemuServer::Machine::parse_machine($conf->{machine}); + my $arch = get_vm_arch($conf); my $kvm_binary = get_command_for_arch($arch); my $kvmver = kvm_user_version($kvm_binary); diff --git a/PVE/QemuServer/Machine.pm b/PVE/QemuServer/Machine.pm index 13721ae..5e3a75c 100644 --- a/PVE/QemuServer/Machine.pm +++ b/PVE/QemuServer/Machine.pm @@ -5,6 +5,7 @@ use warnings; use PVE::QemuServer::Helpers; use PVE::QemuServer::Monitor; +use PVE::JSONSchema qw(get_standard_option parse_property_string); # Bump this for VM HW layout changes during a release (where the QEMU machine # version stays the same) @@ -12,10 +13,46 @@ our $PVE_MACHINE_VERSION = { '4.1' => 2, }; +my $machine_fmt = { + type => { + default_key => 1, + description => "Specifies the QEMU machine type.", + type => 'string', + pattern => '(pc|pc(-i440fx)?-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|q35|pc-q35-\d+(\.\d+)+(\+pve\d+)?(\.pxe)?|virt(?:-\d+(\.\d+)+)?(\+pve\d+)?)', + maxLength => 40, + format_description => 'machine type', + optional => 1, + }, +}; + +PVE::JSONSchema::register_format('pve-qemu-machine-fmt', $machine_fmt); + +PVE::JSONSchema::register_standard_option('pve-qemu-machine', { + description => "Specify the QEMU machine type.", + type => 'string', + optional => 1, + format => PVE::JSONSchema::get_format('pve-qemu-machine-fmt'), +}); + +sub parse_machine { + my ($value) = @_; + + return if !$value; + + my $res = parse_property_string($machine_fmt, $value); + return $res; +} + +sub print_machine { + my ($machine_conf) = @_; + return print_property_string($machine_conf, $machine_fmt); +} + sub machine_type_is_q35 { my ($conf) = @_; - return $conf->{machine} && ($conf->{machine} =~ m/q35/) ? 1 : 0; + my $machine_conf = parse_machine($conf->{machine}); + return $machine_conf->{type} && ($machine_conf->{type} =~ m/q35/) ? 1 : 0; } # In list context, also returns whether the current machine is deprecated or not. @@ -126,7 +163,8 @@ sub qemu_machine_pxe { my $machine = get_current_qemu_machine($vmid); - if ($conf->{machine} && $conf->{machine} =~ m/\.pxe$/) { + my $machine_conf = parse_machine($conf->{machine}); + if ($machine_conf->{type} && $machine_conf->{type} =~ m/\.pxe$/) { $machine .= '.pxe'; } -- 2.39.2