From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id BB48779F66 for ; Thu, 28 Oct 2021 13:42:04 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id F197D1FA43 for ; Thu, 28 Oct 2021 13:42:02 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id AEB7A1F92C for ; Thu, 28 Oct 2021 13:41:57 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 8878F45FDF for ; Thu, 28 Oct 2021 13:41:57 +0200 (CEST) From: Stefan Reiter To: pve-devel@lists.proxmox.com Date: Thu, 28 Oct 2021 13:41:45 +0200 Message-Id: <20211028114150.3245864-5-s.reiter@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211028114150.3245864-1-s.reiter@proxmox.com> References: <20211028114150.3245864-1-s.reiter@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.440 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [cpu.pm, cpuconfig.pm] Subject: [pve-devel] [RFC qemu-server 4/9] api: add /cpu/model/* get/create/delete/update endpoints X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Oct 2021 11:42:04 -0000 Standard API, loosely based on Storage config API code. Uses digests and 'delete'-parameter (parameters not given to an update call are untouched). Locking and writing helpers are added to CPUConfig. write_config is fixed with adding 'type' to every section, otherwise SectionConfig fails. Signed-off-by: Stefan Reiter --- PVE/API2/Qemu/CPU.pm | 174 +++++++++++++++++++++++++++++++++++- PVE/QemuServer/CPUConfig.pm | 17 +++- 2 files changed, 189 insertions(+), 2 deletions(-) diff --git a/PVE/API2/Qemu/CPU.pm b/PVE/API2/Qemu/CPU.pm index 9cc1d77..8a3dcfd 100644 --- a/PVE/API2/Qemu/CPU.pm +++ b/PVE/API2/Qemu/CPU.pm @@ -8,7 +8,8 @@ use PVE::JSONSchema qw(get_standard_option); use PVE::INotify; use PVE::QemuServer; use PVE::QemuServer::CPUConfig; -use PVE::Tools qw(run_command get_host_arch); +use PVE::SectionConfig; +use PVE::Tools qw(run_command get_host_arch extract_param); use base qw(PVE::RESTHandler); @@ -218,4 +219,175 @@ __PACKAGE__->register_method({ return $retval; }}); +__PACKAGE__->register_method({ + name => 'config', + path => 'model', + method => 'GET', + description => "Read all custom CPU model definitions.", + permissions => { + check => ['perm', '/nodes', ['Sys.Audit']], + }, + parameters => { + additionalProperties => 0, + properties => { + node => get_standard_option('pve-node'), + }, + }, + returns => { type => 'object' }, + code => sub { + my $conf = PVE::QemuServer::CPUConfig::load_custom_model_conf(); + delete $conf->{order}; + my $ids = []; + foreach my $id (keys %{$conf->{ids}}) { + delete $conf->{ids}->{$id}->{type}; + push @$ids, $conf->{ids}->{$id}; + } + $conf->{ids} = $ids; + return $conf; + }}); + +__PACKAGE__->register_method({ + name => 'create', + path => 'model', + method => 'POST', + description => "Add a custom CPU model definition.", + permissions => { + check => ['perm', '/nodes', ['Sys.Console']], + }, + parameters => { + additionalProperties => 0, + properties => PVE::QemuServer::CPUConfig::add_cpu_json_properties({ + digest => get_standard_option('pve-config-digest'), + node => get_standard_option('pve-node'), + }), + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + delete $param->{node}; + + my $digest = extract_param($param, 'digest'); + + my $name = $param->{'cputype'}; + die "custom cpu models 'cputype' must start with 'custom-' prefix\n" + if $name !~ m/^custom-/; + (my $name_no_prefix = $name) =~ s/^custom-//; + + PVE::QemuServer::CPUConfig::lock_cpu_config(sub { + my $conf = PVE::QemuServer::CPUConfig::load_custom_model_conf(); + PVE::SectionConfig::assert_if_modified($conf, $digest); + + die "custom cpu model '$name' already exists\n" + if defined($conf->{ids}->{$name_no_prefix}); + $conf->{ids}->{$name_no_prefix} = $param; + + PVE::QemuServer::CPUConfig::write_custom_model_conf($conf); + }); + }}); + +__PACKAGE__->register_method({ + name => 'delete', + path => 'model/{cputype}', + method => 'DELETE', + description => "Delete a custom CPU model definition.", + permissions => { + check => ['perm', '/nodes', ['Sys.Console']], + }, + parameters => { + additionalProperties => 0, + properties => { + node => get_standard_option('pve-node'), + digest => get_standard_option('pve-config-digest'), + cputype => { + type => 'string', + format_description => 'string', + description => "The custom model to delete. Must be prefixed" + . " with 'custom-'.", + }, + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my $digest = extract_param($param, 'digest'); + + my $name = $param->{'cputype'}; + die "cputype must start with 'custom-' prefix\n" + if $name !~ m/^custom-/; + (my $name_no_prefix = $name) =~ s/^custom-//; + + PVE::QemuServer::CPUConfig::lock_cpu_config(sub { + my $conf = PVE::QemuServer::CPUConfig::load_custom_model_conf(); + PVE::SectionConfig::assert_if_modified($conf, $digest); + + die "custom cpu model '$name' doesn't exist\n" + if !defined($conf->{ids}->{$name_no_prefix}); + delete $conf->{ids}->{$name_no_prefix}; + + PVE::QemuServer::CPUConfig::write_custom_model_conf($conf); + }); + }}); + +__PACKAGE__->register_method({ + name => 'update', + path => 'model/{cputype}', + method => 'PUT', + description => "Update a custom CPU model definition.", + permissions => { + check => ['perm', '/nodes', ['Sys.Console']], + }, + parameters => { + additionalProperties => 0, + properties => PVE::QemuServer::CPUConfig::add_cpu_json_properties({ + node => get_standard_option('pve-node'), + digest => get_standard_option('pve-config-digest'), + delete => { + type => 'string', + format => 'pve-configid-list', + description => "A list of properties to delete.", + optional => 1, + }, + }), + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + delete $param->{node}; + + my $digest = extract_param($param, 'digest'); + my $delete = extract_param($param, 'delete') // ''; + my %delete_hash = map { $_ => 1 } PVE::Tools::split_list($delete); + + my $name = $param->{'cputype'}; + die "custom cpu models 'cputype' must start with 'custom-' prefix\n" + if $name !~ m/^custom-/; + (my $name_no_prefix = $name) =~ s/^custom-//; + + PVE::QemuServer::CPUConfig::lock_cpu_config(sub { + my $conf = PVE::QemuServer::CPUConfig::load_custom_model_conf(); + + PVE::SectionConfig::assert_if_modified($conf, $digest); + + my $model = $conf->{ids}->{$name_no_prefix}; + die "custom cpu model '$name' doesn't exist\n" + if !defined($model); + + my $props = PVE::QemuServer::CPUConfig::add_cpu_json_properties({}); + for my $p (keys %$props) { + if ($delete_hash{$p}) { + die "cannot delete 'cputype' property\n" + if $p eq 'cputype'; + die "cannot set and delete property '$p' at once\n" + if $param->{$p}; + delete $model->{$p}; + } elsif (defined($param->{$p})) { + $model->{$p} = $param->{$p}; + } + } + + PVE::QemuServer::CPUConfig::write_custom_model_conf($conf); + }); + }}); + 1; diff --git a/PVE/QemuServer/CPUConfig.pm b/PVE/QemuServer/CPUConfig.pm index 9be8022..08a174f 100644 --- a/PVE/QemuServer/CPUConfig.pm +++ b/PVE/QemuServer/CPUConfig.pm @@ -4,7 +4,7 @@ use strict; use warnings; use PVE::JSONSchema; -use PVE::Cluster qw(cfs_register_file cfs_read_file); +use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file); use PVE::QemuServer::Helpers qw(min_version); use base qw(PVE::SectionConfig Exporter); @@ -29,6 +29,19 @@ sub load_custom_model_conf { return cfs_read_file($default_filename); } +sub write_custom_model_conf { + my ($conf) = @_; + cfs_write_file($default_filename, $conf); +} + +sub lock_cpu_config { + my ($code) = @_; + cfs_lock_file($default_filename, undef, $code); + if (my $err = $@) { + die $err; + } +} + my $cpu_vendor_list = { # Intel CPUs 486 => 'GenuineIntel', @@ -270,6 +283,8 @@ sub write_config { # saved in section header delete $model_conf->{cputype}; + + $model_conf->{type} = $class->type(); } $class->SUPER::write_config($filename, $cfg); -- 2.30.2