diff options
| author | Stefan Hanreich <s.hanreich@proxmox.com> | 2025-07-29 11:29:30 +0200 |
|---|---|---|
| committer | Thomas Lamprecht <t.lamprecht@proxmox.com> | 2025-07-29 12:59:51 +0200 |
| commit | f5966bbacd2998234795fb02f56bff24c7ecf7d6 (patch) | |
| tree | e60247bd424744276281349640b5fdc6f8df248b | |
| parent | f7d4f22a42a506e6cd60f0de8fbac9f580b85c6f (diff) | |
api: add lock-token parameter to all api calls
The parameter is optional, so all existing create/update/delete
invocations can work as before, only failing if the global lock is
currently set. This ensures backwards-compatibility with the existing
calls to the API in the frontend. If the lock is set, users will get
an error message when trying to modify the configuration from the web
UI.
Co-authored-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
Link: https://lore.proxmox.com/20250729092933.90118-3-g.goller@proxmox.com
| -rw-r--r-- | src/PVE/API2/Network/SDN/Controllers.pm | 21 | ||||
| -rw-r--r-- | src/PVE/API2/Network/SDN/Dns.pm | 21 | ||||
| -rw-r--r-- | src/PVE/API2/Network/SDN/Fabrics/Fabric.pm | 8 | ||||
| -rw-r--r-- | src/PVE/API2/Network/SDN/Fabrics/FabricNode.pm | 9 | ||||
| -rw-r--r-- | src/PVE/API2/Network/SDN/Ipams.pm | 21 | ||||
| -rw-r--r-- | src/PVE/API2/Network/SDN/Subnets.pm | 22 | ||||
| -rw-r--r-- | src/PVE/API2/Network/SDN/Vnets.pm | 21 | ||||
| -rw-r--r-- | src/PVE/API2/Network/SDN/Zones.pm | 21 | ||||
| -rw-r--r-- | src/PVE/Network/SDN.pm | 9 | ||||
| -rw-r--r-- | src/PVE/Network/SDN/Fabrics.pm | 2 |
10 files changed, 143 insertions, 12 deletions
diff --git a/src/PVE/API2/Network/SDN/Controllers.pm b/src/PVE/API2/Network/SDN/Controllers.pm index e6eb4cb..5c2b6c3 100644 --- a/src/PVE/API2/Network/SDN/Controllers.pm +++ b/src/PVE/API2/Network/SDN/Controllers.pm @@ -168,13 +168,19 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/controllers', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Controllers::Plugin->createSchema(), + parameters => PVE::Network::SDN::Controllers::Plugin->createSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; my $type = extract_param($param, 'type'); my $id = extract_param($param, 'controller'); + my $lock_token = extract_param($param, 'lock-token'); my $plugin = PVE::Network::SDN::Controllers::Plugin->lookup($type); my $opts = $plugin->check_config($id, $param, 1, 1); @@ -204,6 +210,7 @@ __PACKAGE__->register_method({ }, "create sdn controller object failed", + $lock_token, ); return undef; @@ -219,7 +226,12 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/controllers', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Controllers::Plugin->updateSchema(), + parameters => PVE::Network::SDN::Controllers::Plugin->updateSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; @@ -227,6 +239,7 @@ __PACKAGE__->register_method({ my $id = extract_param($param, 'controller'); my $digest = extract_param($param, 'digest'); my $delete = extract_param($param, 'delete'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -257,6 +270,7 @@ __PACKAGE__->register_method({ }, "update sdn controller object failed", + $lock_token, ); return undef; @@ -281,6 +295,7 @@ __PACKAGE__->register_method({ completion => \&PVE::Network::SDN::Controllers::complete_sdn_controllers, }, ), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), }, }, returns => { type => 'null' }, @@ -288,6 +303,7 @@ __PACKAGE__->register_method({ my ($param) = @_; my $id = extract_param($param, 'controller'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -307,6 +323,7 @@ __PACKAGE__->register_method({ }, "delete sdn controller object failed", + $lock_token, ); return undef; diff --git a/src/PVE/API2/Network/SDN/Dns.pm b/src/PVE/API2/Network/SDN/Dns.pm index c82e354..48fc2f6 100644 --- a/src/PVE/API2/Network/SDN/Dns.pm +++ b/src/PVE/API2/Network/SDN/Dns.pm @@ -123,13 +123,19 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/dns', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Dns::Plugin->createSchema(), + parameters => PVE::Network::SDN::Dns::Plugin->createSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; my $type = extract_param($param, 'type'); my $id = extract_param($param, 'dns'); + my $lock_token = extract_param($param, 'lock-token'); my $plugin = PVE::Network::SDN::Dns::Plugin->lookup($type); my $opts = $plugin->check_config($id, $param, 1, 1); @@ -157,6 +163,7 @@ __PACKAGE__->register_method({ }, "create sdn dns object failed", + $lock_token, ); return undef; @@ -172,7 +179,12 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/dns', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Dns::Plugin->updateSchema(), + parameters => PVE::Network::SDN::Dns::Plugin->updateSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; @@ -180,6 +192,7 @@ __PACKAGE__->register_method({ my $id = extract_param($param, 'dns'); my $digest = extract_param($param, 'digest'); my $delete = extract_param($param, 'delete'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -209,6 +222,7 @@ __PACKAGE__->register_method({ }, "update sdn dns object failed", + $lock_token, ); return undef; @@ -233,6 +247,7 @@ __PACKAGE__->register_method({ completion => \&PVE::Network::SDN::Dns::complete_sdn_dns, }, ), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), }, }, returns => { type => 'null' }, @@ -240,6 +255,7 @@ __PACKAGE__->register_method({ my ($param) = @_; my $id = extract_param($param, 'dns'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -255,6 +271,7 @@ __PACKAGE__->register_method({ }, "delete sdn dns object failed", + $lock_token, ); return undef; diff --git a/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm b/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm index 8c47b1b..1201654 100644 --- a/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm +++ b/src/PVE/API2/Network/SDN/Fabrics/Fabric.pm @@ -138,6 +138,8 @@ __PACKAGE__->register_method({ code => sub { my ($param) = @_; + my $lock_token = extract_param($param, 'lock-token'); + PVE::Network::SDN::lock_sdn_config( sub { my $config = PVE::Network::SDN::Fabrics::config(); @@ -149,6 +151,7 @@ __PACKAGE__->register_method({ PVE::Network::SDN::Fabrics::write_config($config); }, "adding fabric failed", + $lock_token, ); }, }); @@ -170,6 +173,7 @@ __PACKAGE__->register_method({ }, code => sub { my ($param) = @_; + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -184,6 +188,7 @@ __PACKAGE__->register_method({ PVE::Network::SDN::Fabrics::write_config($config); }, "updating fabric failed", + $lock_token, ); }, }); @@ -208,6 +213,8 @@ __PACKAGE__->register_method({ code => sub { my ($param) = @_; + my $lock_token = extract_param($param, 'lock-token'); + PVE::Network::SDN::lock_sdn_config( sub { my $id = extract_param($param, 'id'); @@ -253,6 +260,7 @@ __PACKAGE__->register_method({ PVE::Network::SDN::Fabrics::write_config($config); }, "deleting fabric failed", + $lock_token, ); }, }); diff --git a/src/PVE/API2/Network/SDN/Fabrics/FabricNode.pm b/src/PVE/API2/Network/SDN/Fabrics/FabricNode.pm index b288844..000e4c3 100644 --- a/src/PVE/API2/Network/SDN/Fabrics/FabricNode.pm +++ b/src/PVE/API2/Network/SDN/Fabrics/FabricNode.pm @@ -153,6 +153,8 @@ __PACKAGE__->register_method({ code => sub { my ($param) = @_; + my $lock_token = extract_param($param, 'lock-token'); + PVE::Network::SDN::lock_sdn_config( sub { my $config = PVE::Network::SDN::Fabrics::config(); @@ -164,6 +166,7 @@ __PACKAGE__->register_method({ PVE::Network::SDN::Fabrics::write_config($config); }, "adding node failed", + $lock_token, ); }, }); @@ -190,6 +193,8 @@ __PACKAGE__->register_method({ code => sub { my ($param) = @_; + my $lock_token = extract_param($param, 'lock-token'); + PVE::Network::SDN::lock_sdn_config( sub { my $fabric_id = extract_param($param, 'fabric_id'); @@ -204,6 +209,7 @@ __PACKAGE__->register_method({ PVE::Network::SDN::Fabrics::write_config($config); }, "updating node failed", + $lock_token, ); }, }); @@ -233,6 +239,8 @@ __PACKAGE__->register_method({ code => sub { my ($param) = @_; + my $lock_token = extract_param($param, 'lock-token'); + PVE::Network::SDN::lock_sdn_config( sub { my $fabric_id = extract_param($param, 'fabric_id'); @@ -247,6 +255,7 @@ __PACKAGE__->register_method({ PVE::Network::SDN::Fabrics::write_config($config); }, "deleting node failed", + $lock_token, ); }, }); diff --git a/src/PVE/API2/Network/SDN/Ipams.pm b/src/PVE/API2/Network/SDN/Ipams.pm index e30d28f..89e05ee 100644 --- a/src/PVE/API2/Network/SDN/Ipams.pm +++ b/src/PVE/API2/Network/SDN/Ipams.pm @@ -128,13 +128,19 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/ipams', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Ipams::Plugin->createSchema(), + parameters => PVE::Network::SDN::Ipams::Plugin->createSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; my $type = extract_param($param, 'type'); my $id = extract_param($param, 'ipam'); + my $lock_token = extract_param($param, 'lock-token'); my $plugin = PVE::Network::SDN::Ipams::Plugin->lookup($type); my $opts = $plugin->check_config($id, $param, 1, 1); @@ -164,6 +170,7 @@ __PACKAGE__->register_method({ }, "create sdn ipam object failed", + $lock_token, ); return undef; @@ -179,7 +186,12 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/ipams', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Ipams::Plugin->updateSchema(), + parameters => PVE::Network::SDN::Ipams::Plugin->updateSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; @@ -187,6 +199,7 @@ __PACKAGE__->register_method({ my $id = extract_param($param, 'ipam'); my $digest = extract_param($param, 'digest'); my $delete = extract_param($param, 'delete'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -216,6 +229,7 @@ __PACKAGE__->register_method({ }, "update sdn ipam object failed", + $lock_token, ); return undef; @@ -240,6 +254,7 @@ __PACKAGE__->register_method({ completion => \&PVE::Network::SDN::Ipams::complete_sdn_ipams, }, ), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), }, }, returns => { type => 'null' }, @@ -247,6 +262,7 @@ __PACKAGE__->register_method({ my ($param) = @_; my $id = extract_param($param, 'ipam'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -264,6 +280,7 @@ __PACKAGE__->register_method({ }, "delete sdn zone object failed", + $lock_token, ); return undef; diff --git a/src/PVE/API2/Network/SDN/Subnets.pm b/src/PVE/API2/Network/SDN/Subnets.pm index c9f5452..fc56532 100644 --- a/src/PVE/API2/Network/SDN/Subnets.pm +++ b/src/PVE/API2/Network/SDN/Subnets.pm @@ -190,13 +190,19 @@ __PACKAGE__->register_method({ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'", user => 'all', }, - parameters => PVE::Network::SDN::SubnetPlugin->createSchema(), + parameters => PVE::Network::SDN::SubnetPlugin->createSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; my $type = extract_param($param, 'type'); my $cidr = extract_param($param, 'subnet'); + my $lock_token = extract_param($param, 'lock-token'); my $vnet = $param->{vnet}; my $privs = ['SDN.Allocate']; @@ -234,6 +240,7 @@ __PACKAGE__->register_method({ }, "create sdn subnet object failed", + $lock_token, ); return undef; @@ -250,7 +257,12 @@ __PACKAGE__->register_method({ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'", user => 'all', }, - parameters => PVE::Network::SDN::SubnetPlugin->updateSchema(), + parameters => PVE::Network::SDN::SubnetPlugin->updateSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; @@ -258,6 +270,7 @@ __PACKAGE__->register_method({ my $id = extract_param($param, 'subnet'); my $digest = extract_param($param, 'digest'); my $delete = extract_param($param, 'delete'); + my $lock_token = extract_param($param, 'lock-token'); my $vnet = $param->{vnet}; @@ -295,6 +308,7 @@ __PACKAGE__->register_method({ }, "update sdn subnet object failed", + $lock_token, ); return undef; @@ -321,6 +335,7 @@ __PACKAGE__->register_method({ completion => \&PVE::Network::SDN::Subnets::complete_sdn_subnets, }, ), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), }, }, returns => { type => 'null' }, @@ -329,6 +344,8 @@ __PACKAGE__->register_method({ my $id = extract_param($param, 'subnet'); my $vnet = extract_param($param, 'vnet'); + my $lock_token = extract_param($param, 'lock-token'); + my $privs = ['SDN.Allocate']; &$check_vnet_access($vnet, $privs); @@ -354,6 +371,7 @@ __PACKAGE__->register_method({ }, "delete sdn subnet object failed", + $lock_token, ); return undef; diff --git a/src/PVE/API2/Network/SDN/Vnets.pm b/src/PVE/API2/Network/SDN/Vnets.pm index 5608283..e6eb5d4 100644 --- a/src/PVE/API2/Network/SDN/Vnets.pm +++ b/src/PVE/API2/Network/SDN/Vnets.pm @@ -205,13 +205,19 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::VnetPlugin->createSchema(), + parameters => PVE::Network::SDN::VnetPlugin->createSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; my $type = extract_param($param, 'type'); my $id = extract_param($param, 'vnet'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Cluster::check_cfs_quorum(); mkdir("/etc/pve/sdn"); @@ -238,6 +244,7 @@ __PACKAGE__->register_method({ }, "create sdn vnet object failed", + $lock_token, ); return undef; @@ -254,7 +261,12 @@ __PACKAGE__->register_method({ description => "Require 'SDN.Allocate' permission on '/sdn/zones/<zone>/<vnet>'", user => 'all', }, - parameters => PVE::Network::SDN::VnetPlugin->updateSchema(), + parameters => PVE::Network::SDN::VnetPlugin->updateSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; @@ -262,6 +274,7 @@ __PACKAGE__->register_method({ my $id = extract_param($param, 'vnet'); my $digest = extract_param($param, 'digest'); my $delete = extract_param($param, 'delete'); + my $lock_token = extract_param($param, 'lock-token'); my $privs = ['SDN.Allocate']; &$check_vnet_access($id, $privs); @@ -307,6 +320,7 @@ __PACKAGE__->register_method({ }, "update sdn vnet object failed", + $lock_token, ); return undef; @@ -332,6 +346,7 @@ __PACKAGE__->register_method({ completion => \&PVE::Network::SDN::Vnets::complete_sdn_vnets, }, ), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), }, }, returns => { type => 'null' }, @@ -339,6 +354,7 @@ __PACKAGE__->register_method({ my ($param) = @_; my $id = extract_param($param, 'vnet'); + my $lock_token = extract_param($param, 'lock-token'); my $privs = ['SDN.Allocate']; &$check_vnet_access($id, $privs); @@ -356,6 +372,7 @@ __PACKAGE__->register_method({ }, "delete sdn vnet object failed", + $lock_token, ); return undef; diff --git a/src/PVE/API2/Network/SDN/Zones.pm b/src/PVE/API2/Network/SDN/Zones.pm index e53e6e7..0e4726b 100644 --- a/src/PVE/API2/Network/SDN/Zones.pm +++ b/src/PVE/API2/Network/SDN/Zones.pm @@ -207,13 +207,19 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/zones', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Zones::Plugin->createSchema(), + parameters => PVE::Network::SDN::Zones::Plugin->createSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; my $type = extract_param($param, 'type'); my $id = extract_param($param, 'zone'); + my $lock_token = extract_param($param, 'lock-token'); my $plugin = PVE::Network::SDN::Zones::Plugin->lookup($type); my $opts = $plugin->check_config($id, $param, 1, 1); @@ -256,6 +262,7 @@ __PACKAGE__->register_method({ }, "create sdn zone object failed", + $lock_token, ); return; @@ -271,7 +278,12 @@ __PACKAGE__->register_method({ permissions => { check => ['perm', '/sdn/zones/{zone}', ['SDN.Allocate']], }, - parameters => PVE::Network::SDN::Zones::Plugin->updateSchema(), + parameters => PVE::Network::SDN::Zones::Plugin->updateSchema( + undef, + { + 'lock-token' => get_standard_option('pve-sdn-lock-token'), + }, + ), returns => { type => 'null' }, code => sub { my ($param) = @_; @@ -279,6 +291,7 @@ __PACKAGE__->register_method({ my $id = extract_param($param, 'zone'); my $digest = extract_param($param, 'digest'); my $delete = extract_param($param, 'delete'); + my $lock_token = extract_param($param, 'lock-token'); if ($delete) { $delete = [PVE::Tools::split_list($delete)]; @@ -344,6 +357,7 @@ __PACKAGE__->register_method({ }, "update sdn zone object failed", + $lock_token, ); return; @@ -368,6 +382,7 @@ __PACKAGE__->register_method({ completion => \&PVE::Network::SDN::Zones::complete_sdn_zones, }, ), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), }, }, returns => { type => 'null' }, @@ -375,6 +390,7 @@ __PACKAGE__->register_method({ my ($param) = @_; my $id = extract_param($param, 'zone'); + my $lock_token = extract_param($param, 'lock-token'); PVE::Network::SDN::lock_sdn_config( sub { @@ -391,6 +407,7 @@ __PACKAGE__->register_method({ PVE::Network::SDN::Zones::write_config($cfg); }, "delete sdn zone object failed", + $lock_token, ); return; diff --git a/src/PVE/Network/SDN.pm b/src/PVE/Network/SDN.pm index 9f18f76..8a963cb 100644 --- a/src/PVE/Network/SDN.pm +++ b/src/PVE/Network/SDN.pm @@ -51,6 +51,15 @@ PVE::Cluster::cfs_register_file($running_cfg, $parse_running_cfg, $write_running my $LOCK_TOKEN_FILE = "/etc/pve/sdn/.lock"; +PVE::JSONSchema::register_standard_option( + 'pve-sdn-lock-token', + { + type => 'string', + description => "the token for unlocking the global SDN configuration", + optional => 1, + }, +); + # improve me : move status code inside plugins ? sub ifquery_check { diff --git a/src/PVE/Network/SDN/Fabrics.pm b/src/PVE/Network/SDN/Fabrics.pm index 796d149..d90992a 100644 --- a/src/PVE/Network/SDN/Fabrics.pm +++ b/src/PVE/Network/SDN/Fabrics.pm @@ -128,6 +128,7 @@ sub node_properties { node_id => get_standard_option('pve-sdn-fabric-node-id'), protocol => get_standard_option('pve-sdn-fabric-protocol'), digest => get_standard_option('pve-config-digest'), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), ip => { type => 'string', format => 'ipv4', @@ -227,6 +228,7 @@ sub fabric_properties { id => get_standard_option('pve-sdn-fabric-id'), protocol => get_standard_option('pve-sdn-fabric-protocol'), digest => get_standard_option('pve-config-digest'), + 'lock-token' => get_standard_option('pve-sdn-lock-token'), ip_prefix => { type => 'string', format => 'CIDR', |
