public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
To: pve-devel@lists.proxmox.com
Cc: Stefan Reiter <s.reiter@proxmox.com>
Subject: [PATCH qemu-server 8/8] api: qemu: Add CRUD handlers for custom CPU models
Date: Thu, 12 Mar 2026 09:40:21 +0100	[thread overview]
Message-ID: <20260312084021.124465-9-a.bied-charreton@proxmox.com> (raw)
In-Reply-To: <20260312084021.124465-1-a.bied-charreton@proxmox.com>

Add GET handlers for both all custom CPU models and specific ones, POST
handler for creating custom CPU models, PUT handler for updating them,
and DELETE handler for deleting them.

Original patches:
https://lore.proxmox.com/pve-devel/20211028114150.3245864-4-s.reiter@proxmox.com/
https://lore.proxmox.com/pve-devel/20211028114150.3245864-5-s.reiter@proxmox.com/

Originally-by: Stefan Reiter <s.reiter@proxmox.com>
Signed-off-by: Arthur Bied-Charreton <a.bied-charreton@proxmox.com>
---
 src/PVE/API2/Qemu/CPU.pm | 236 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 235 insertions(+), 1 deletion(-)

diff --git a/src/PVE/API2/Qemu/CPU.pm b/src/PVE/API2/Qemu/CPU.pm
index f8a7e11d..9d89504d 100644
--- a/src/PVE/API2/Qemu/CPU.pm
+++ b/src/PVE/API2/Qemu/CPU.pm
@@ -52,7 +52,7 @@ __PACKAGE__->register_method({
                 },
             },
         },
-        links => [{ rel => 'child', href => '{name}' }],
+        links => [{ rel => 'child', href => 'model/{cputype}' }],
     },
     code => sub {
         my ($param) = @_;
@@ -67,4 +67,238 @@ __PACKAGE__->register_method({
     },
 });
 
+__PACKAGE__->register_method({
+    name => 'config',
+    path => 'model',
+    method => 'GET',
+    description => 'Read all custom CPU models definitions',
+    permissions => {
+        check => ['perm', '/nodes', ['Sys.Audit']],
+    },
+    parameters => {
+        additionalProperties => 0,
+        properties => {
+            node => get_standard_option('pve-node'),
+        },
+    },
+    returns => {
+        type => 'array',
+        items => {
+            type => 'object',
+            properties => get_standard_option('pve-qemu-cpu'),
+        },
+    },
+    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};
+        }
+        return $ids;
+    },
+});
+
+__PACKAGE__->register_method({
+    name => 'create',
+    path => 'model',
+    method => 'POST',
+    protected => 1,
+    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',
+    protected => 1,
+    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',
+                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_no_prefix' does not 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',
+    protected => 1,
+    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 model's '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_no_prefix' does not 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);
+        });
+    },
+});
+
+__PACKAGE__->register_method({
+    name => 'info',
+    path => 'model/{cputype}',
+    method => 'GET',
+    description => 'Retrieve details about a specific CPU model',
+    permissions => {
+        check => ['perm', '/nodes', ['Sys.Audit']],
+    },
+    parameters => {
+        additionalProperties => 0,
+        properties => {
+            node => get_standard_option('pve-node'),
+            cputype => {
+                type => 'string',
+                description =>
+                    "Name of the CPU model to query. Prefix with 'custom-' for custom models.",
+            },
+        },
+    },
+    returns => {
+        type => 'object',
+        properties => PVE::QemuServer::CPUConfig::add_cpu_json_properties({
+            vendor => {
+                type => 'string',
+                description => 'The CPU vendor reported to the guest OS. Only'
+                    . ' relevant for default models.',
+                optional => 1,
+            },
+            digest => get_standard_option('pve-config-digest'),
+        }),
+    },
+    code => sub {
+        my ($param) = @_;
+        my $cputype = $param->{cputype};
+
+        if ($cputype =~ m/^custom-/) {
+            my $conf = PVE::QemuServer::CPUConfig::load_custom_model_conf();
+            my $digest = $conf->{digest};
+            my $retval = PVE::QemuServer::CPUConfig::get_custom_model($cputype);
+            $retval->{digest} = $digest;
+            return $retval;
+        }
+
+        # this correctly errors in case $cputype is unknown
+        my $vendor = PVE::QemuServer::CPUConfig::get_cpu_vendor($cputype);
+
+        my $retval = {
+            cputype => $cputype,
+            vendor => $vendor,
+        };
+
+        return $retval;
+    },
+});
+
 1;
-- 
2.47.3




      parent reply	other threads:[~2026-03-12  8:41 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-12  8:40 [PATCH manager/qemu-server 0/8] Add API and UI " Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 1/8] ui: VMCPUFlagSelector: Fix unknownFlags behaviour Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 2/8] ui: CPUModelSelector: Fix dirty state on default Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 3/8] ui: CPUModelSelector: Allow filtering out custom models Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 4/8] ui: Add basic custom CPU model editor Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH pve-manager 5/8] ui: Add CPU flag editor for custom models Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH qemu-server 6/8] qemu: Add helpers for new custom models endpoints Arthur Bied-Charreton
2026-03-12  8:40 ` [PATCH qemu-server 7/8] api: qemu: Extend cpu-flags endpoint to return actually supported flags Arthur Bied-Charreton
2026-03-12  8:40 ` Arthur Bied-Charreton [this message]

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=20260312084021.124465-9-a.bied-charreton@proxmox.com \
    --to=a.bied-charreton@proxmox.com \
    --cc=pve-devel@lists.proxmox.com \
    --cc=s.reiter@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal