all lists on lists.proxmox.com
 help / color / mirror / Atom feed
From: Stefan Reiter <s.reiter@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [RFC qemu-server 4/9] api: add /cpu/model/* get/create/delete/update endpoints
Date: Thu, 28 Oct 2021 13:41:45 +0200	[thread overview]
Message-ID: <20211028114150.3245864-5-s.reiter@proxmox.com> (raw)
In-Reply-To: <20211028114150.3245864-1-s.reiter@proxmox.com>

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 <s.reiter@proxmox.com>
---
 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





  parent reply	other threads:[~2021-10-28 11:42 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-10-28 11:41 [pve-devel] [RFC 0/9] Unfinished: Custom CPU type API and GUI Stefan Reiter
2021-10-28 11:41 ` [pve-devel] [RFC pve-qemu 1/9] Add -list-flags command line option Stefan Reiter
2021-10-28 11:41 ` [pve-devel] [RFC qemu-server 2/9] api: add recognized-flags and supported-flags endpoints Stefan Reiter
2021-10-28 11:41 ` [pve-devel] [RFC qemu-server 3/9] api: add /cpu/model/* get endpoint Stefan Reiter
2021-10-28 11:41 ` Stefan Reiter [this message]
2021-10-28 11:41 ` [pve-devel] [RFC manager 5/9] gui: VMCPUFlagSelector: fix unknownFlags behaviour Stefan Reiter
2021-10-28 11:41 ` [pve-devel] [RFC manager 6/9] gui: CPUModelSelector: fix dirty state on default Stefan Reiter
2021-10-28 11:41 ` [pve-devel] [RFC manager 7/9] gui: CPUModelSelector: add 'allowCustom' Stefan Reiter
2021-10-28 11:41 ` [pve-devel] [RFC manager 8/9] gui: add basic custom CPU model editor Stefan Reiter
2021-10-28 11:41 ` [pve-devel] [RFC manager 9/9] Initial attempt at CPU flag editor for custom models Stefan Reiter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211028114150.3245864-5-s.reiter@proxmox.com \
    --to=s.reiter@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal