On September 2, 2019 4:27 pm, Stefan Reiter wrote: > Inherits from SectionConfig to provide base parsing infrastructure. > > Use with helper functions: > * config_from_file gives bless'd config > * get_model_by_name returns a "formatted" hash for a single CPU model > * config_to_file writes changes back > > File reads are cached in a local hash.
high-level: use cfs_register/write/read_file please (it's our mechanism for handling config files on pmxcfs after all ;)) is there a reason you need a class-like interface here? we usually use that if we want to have multiple implementations of a certain interface with a common shared code base, but that is not the case here.. > > Signed-off-by: Stefan Reiter <s.rei...@proxmox.com> > --- > > This will definitely require some sort of versioning mechanism, otherwise CPU > definitions could be changed after starting a VM, thus breaking live-migration > by starting the migration-target with different parameters. > > Hints, ideas, recommendations? versioning is one possibility (cumbersome with SectionConfig though). another would be to retrieve the CPU model from the running Qemu instance, and convert that back to a '-cpu ...' string for starting the target instance. if nothing hot-pluggable can change the generated -cpu string, we could also record that somewhere (or take it from /proc/$pid/cmdline) and override the target instance with that. > PVE/QemuServer/CustomCPUConfig.pm | 129 ++++++++++++++++++++++++++++++ > PVE/QemuServer/Makefile | 1 + > 2 files changed, 130 insertions(+) > create mode 100644 PVE/QemuServer/CustomCPUConfig.pm > > diff --git a/PVE/QemuServer/CustomCPUConfig.pm > b/PVE/QemuServer/CustomCPUConfig.pm > new file mode 100644 > index 0000000..87ba9e6 > --- /dev/null > +++ b/PVE/QemuServer/CustomCPUConfig.pm > @@ -0,0 +1,129 @@ > +package PVE::QemuServer::CustomCPUConfig; > + > +use strict; > +use warnings; > +use PVE::Tools qw(file_get_contents file_set_contents); > + > +use base qw(PVE::SectionConfig); > + > +my $defaultData = { > + propertyList => { > + basemodel => { > + description => "Emulated CPU type to inherit defaults from.", > + type => 'string', > + format_description => 'string', > + default => 'kvm64', should have the same pattern/format as QemuServer's $cpu_fmt->{cputype}. in other words, it probably makes sense to extract and re-use that ;) > + }, > + flags => { > + description => "List of additional CPU flags separated by ';'." > + . " Use '+FLAG' to enable, '-FLAG' to disable a flag." > + . " Supports all flags supported by QEMU/KVM.", > + format_description => '+FLAG[;-FLAG...]', > + type => 'string', > + pattern => qr/[+-][a-zA-Z0-9\-_\.]+(;[+-][a-zA-Z0-9\-_\.]+)*/, same here (different description, please just use a single definition for both instances) > + optional => 1, > + }, > + 'phys-bits' => { > + type => 'integer', > + minimum => 1, > + maximum => 64, > + optional => 1, > + description => "The physical memory bits that are reported to the > guest OS. Must be smaller or equal to the host.", this one might make sense to also allow in the regular, per-VM 'cpu' option (and then we could again re-use the definition) > + }, > + 'host-phys-bits' => { > + type => 'boolean', > + default => 0, > + description => "Whether to report the host's physical memory bits. > Overrides 'phys-bits' when set.", > + }, same > + vendor => { > + type => 'string', > + enum => [qw(default AuthenticAMD GenuineIntel)], > + default => 'default', > + description => "The CPU vendor to report. 'default' uses the > host's.", > + }, > + } this probably only makes sense for the custom types. the default value means that you never inherit the vendor from your basemodel - is that intended? there are two more from the regular one that we might want to include in custom ones as well: hidden hv-vendor-id I am not sure whether just moving some format definitions, or moving all/most CPU related stuff to a new module (e.g., QemuServer/CPUConfig.pm instead of QemuServer/CustomCPUConfig.pm) is more clean / feasible. the latter probably would require moving some helpers from QemuServer.pm to another new module as well, as they'd be used by the CPU module and QemuServer.pm I think we all agree that QemuServer.pm is way too big, so a patch (series) that adds new features and reduces that bloat would be more than welcome :D but if you think it's too much for this series, we can also do it as a follow-up since it's mostly about moving code and format definitions. > +}; > + > +sub private { > + return $defaultData; > +} > + > +sub options { > + return { > + basemodel => { optional => 1 }, > + flags => { optional => 1 }, > + 'phys-bits' => { optional => 1 }, > + 'host-phys-bits' => { optional => 1 }, > + vendor => { optional => 1 } > + }; > +} > + > +sub type { > + return 'cpu-model'; > +} > + > +# helpers for reading/parsing and writing/formatting of config files > + > +my $default_filename = "/etc/pve/cpu-models.conf"; > +my $cfg_cache = {}; > + > +sub config_from_file { > + my ($filename) = @_; > + > + $filename //= $default_filename; > + > + if (my $cached = $cfg_cache->{$filename}) { > + return $cached; > + } > + > + return undef if ! -e $filename; > + > + my $raw = file_get_contents($filename); > + my $cfg = __PACKAGE__->parse_config($filename, $raw); > + > + bless $cfg, qw(PVE::QemuServer::CustomCPUConfig); > + $cfg_cache->{$filename} = $cfg; > + > + return $cfg; > +} > + > +sub config_to_file { > + my ($class, $filename) = @_; > + > + $filename //= $default_filename; > + > + $cfg_cache->{$filename} = $class; > + > + my $raw = $class->write_config($filename); > + file_set_contents($filename, $raw); > +} > + > +# Use this to get a single model in the format described by $defaultData > above > +# Includes the name as an additional property and sets default values for > undefs > +# Returns undef for unknown $name > +sub get_model_by_name { > + my ($class, $name) = @_; > + > + return undef if !defined($class->{ids}->{$name}); > + > + my $model = { > + name => $name > + }; > + > + for my $property (keys %{$defaultData->{propertyList}}) { > + next if $property eq 'type'; > + > + if (my $value = $class->{ids}->{$name}->{$property}) { > + $model->{$property} = $value; > + } elsif (my $default = > $defaultData->{propertyList}->{$property}->{default}) { > + $model->{$property} = $default; > + } > + } > + > + return $model; > +} > + > +__PACKAGE__->register(); > +__PACKAGE__->init(); > + > +1; > diff --git a/PVE/QemuServer/Makefile b/PVE/QemuServer/Makefile > index afc39a3..41b4cb6 100644 > --- a/PVE/QemuServer/Makefile > +++ b/PVE/QemuServer/Makefile > @@ -5,6 +5,7 @@ SOURCES=PCI.pm \ > OVF.pm \ > Cloudinit.pm \ > Agent.pm \ > + CustomCPUConfig.pm \ > > .PHONY: install > install: ${SOURCES} > -- > 2.20.1 > > > _______________________________________________ > pve-devel mailing list > pve-devel@pve.proxmox.com > https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel > > _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel