Turn CPUConfig into a SectionConfig with parsing/writing support for custom CPU models. IO is handled using cfs.
Namespacing will be provided using "custom-" prefix for custom model names (in VM config only, cpu-models.conf will contain unprefixed names). Includes two overrides to avoid writing redundant information to the config file, additionally get_custom_model is used to retrieve a custom model configuration by name. Signed-off-by: Stefan Reiter <s.rei...@proxmox.com> --- Depends on updated pve-cluster. PVE/QemuServer/CPUConfig.pm | 109 +++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 3 deletions(-) diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm index 86febe8..36a9439 100644 --- a/PVE/QemuServer/CPUConfig.pm +++ b/PVE/QemuServer/CPUConfig.pm @@ -4,15 +4,26 @@ use strict; use warnings; use PVE::JSONSchema; +use PVE::Cluster qw(cfs_register_file cfs_read_file); use PVE::QemuServer::Helpers qw(min_version); -use base qw(Exporter); +use base qw(PVE::SectionConfig Exporter); our @EXPORT_OK = qw( print_cpu_device get_cpu_options ); +mkdir "/etc/pve/virtual-guest"; +my $default_filename = "virtual-guest/cpu-models.conf"; +cfs_register_file($default_filename, + sub { PVE::QemuServer::CPUConfig->parse_config(@_); }, + sub { PVE::QemuServer::CPUConfig->write_config(@_); }); + +sub load_custom_model_conf { + return cfs_read_file($default_filename); +} + my $cpu_vendor_list = { # Intel CPUs 486 => 'GenuineIntel', @@ -84,11 +95,20 @@ my $cpu_flag = qr/[+-](@{[join('|', @supported_cpu_flags)]})/; our $cpu_fmt = { cputype => { - description => "Emulated CPU type.", + description => "Emulated CPU type. Can be default or custom name (custom model names must be prefixed with 'custom-').", type => 'string', - enum => [ sort { "\L$a" cmp "\L$b" } keys %$cpu_vendor_list ], + format_description => 'string', default => 'kvm64', default_key => 1, + optional => 1, + }, + 'reported-model' => { + description => "CPU model and vendor to report to the guest. Must be a QEMU/KVM supported model." + . " Only valid for custom CPU model definitions, default models will always report themselves to the guest OS.", + type => 'string', + enum => [ sort { lc("$a") cmp lc("$b") } keys %$cpu_vendor_list ], + default => 'kvm64', + optional => 1, }, hidden => { description => "Do not identify as a KVM virtual machine.", @@ -114,6 +134,86 @@ our $cpu_fmt = { }, }; +# Section config settings +my $defaultData = { + # shallow copy, since SectionConfig modifies propertyList internally + propertyList => { %$cpu_fmt }, +}; + +sub private { + return $defaultData; +} + +sub options { + return { %$cpu_fmt }; +} + +sub type { + return 'cpu-model'; +} + +sub parse_section_header { + my ($class, $line) = @_; + + my ($type, $sectionId, $errmsg, $config) = + $class->SUPER::parse_section_header($line); + + return undef if !$type; + return ($type, $sectionId, $errmsg, { + # to avoid duplicate model name in config file, parse id as cputype + # models parsed from file are by definition always custom + cputype => "custom-$sectionId", + }); +} + +sub write_config { + my ($class, $filename, $cfg) = @_; + + for my $model (keys %{$cfg->{ids}}) { + my $model_conf = $cfg->{ids}->{$model}; + + die "internal error: tried saving built-in CPU model (or missing prefix)\n" + if !is_custom_model($model_conf->{cputype}); + + die "internal error: tried saving custom cpumodel with cputype (ignoring prefix) not equal to \$cfg->ids entry\n" + if "custom-$model" ne $model_conf->{cputype}; + + # saved in section header + delete $model_conf->{cputype}; + } + + $class->SUPER::write_config($filename, $cfg); +} + +sub is_custom_model { + my ($cputype) = @_; + return $cputype =~ m/^custom-/; +} + +# Use this to get a single model in the format described by $cpu_fmt. +# Allows names with and without custom- prefix. +sub get_custom_model { + my ($name, $noerr) = @_; + + $name =~ s/^custom-//; + my $conf = load_custom_model_conf(); + + my $entry = $conf->{ids}->{$name}; + if (!defined($entry)) { + die "Custom cputype '$name' not found\n" if !$noerr; + return undef; + } + + my $model = {}; + for my $property (keys %$cpu_fmt) { + if (my $value = $entry->{$property}) { + $model->{$property} = $value; + } + } + + return $model; +} + # Print a QEMU device node for a given VM configuration for hotplugging CPUs sub print_cpu_device { my ($conf, $id) = @_; @@ -229,4 +329,7 @@ sub add_hyperv_enlightenments { } } +__PACKAGE__->register(); +__PACKAGE__->init(); + 1; -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel