public inbox for pve-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: Gabriel Goller <g.goller@proxmox.com>
To: pve-devel@lists.proxmox.com
Subject: [pve-devel] [PATCH network v3 1/5] sdn: add global lock for configuration
Date: Tue, 29 Jul 2025 11:29:29 +0200	[thread overview]
Message-ID: <20250729092933.90118-2-g.goller@proxmox.com> (raw)
In-Reply-To: <20250729092933.90118-1-g.goller@proxmox.com>

From: Stefan Hanreich <s.hanreich@proxmox.com>

Add a new cluster-wide lock for SDN that prevents any changes to the
configuration if the generated lock-token is not provided. It works
by generating and storing a token in sdn/.lock which gets checked by
lock_sdn_config on every invocation. If the lock file exists, then the
lock token has to be supplied in order to make changes to the SDN
configuration.

Lock using the domain lock (`PVE::Cluster::cfs_lock_domain`) and "sdn"
string.

This is mainly a preparation for PDM, where PDM can take the lock and
prevent concurrent modifications to the SDN configuration from other
sources, even across multiple API calls.

Co-authored-by: Gabriel Goller <g.goller@proxmox.com>
Signed-off-by: Stefan Hanreich <s.hanreich@proxmox.com>
---
 debian/control         |  1 +
 src/PVE/Network/SDN.pm | 54 ++++++++++++++++++++++++++++++++++++++----
 2 files changed, 51 insertions(+), 4 deletions(-)

diff --git a/debian/control b/debian/control
index f64a2d4a90b1..b45d12621aab 100644
--- a/debian/control
+++ b/debian/control
@@ -26,6 +26,7 @@ Depends: libpve-common-perl (>= 9.0.2),
          libnet-ip-perl,
          libnetaddr-ip-perl,
          libpve-rs-perl (>= 0.10.3),
+         libuuid-perl,
          ${misc:Depends},
          ${perl:Depends},
 Recommends: frr-pythontools (>= 10.3.1-1+pve2~),
diff --git a/src/PVE/Network/SDN.pm b/src/PVE/Network/SDN.pm
index 0e7d1dfd239c..9f18f76417a5 100644
--- a/src/PVE/Network/SDN.pm
+++ b/src/PVE/Network/SDN.pm
@@ -8,12 +8,13 @@ use IO::Socket::SSL; # important for SSL_verify_callback
 use JSON qw(decode_json from_json to_json);
 use LWP::UserAgent;
 use Net::SSLeay;
+use UUID;
 
 use PVE::Cluster qw(cfs_read_file cfs_write_file cfs_lock_file);
 use PVE::INotify;
 use PVE::RESTEnvironment qw(log_warn);
 use PVE::RPCEnvironment;
-use PVE::Tools qw(extract_param dir_glob_regex run_command);
+use PVE::Tools qw(file_get_contents file_set_contents extract_param dir_glob_regex run_command);
 
 use PVE::Network::SDN::Vnets;
 use PVE::Network::SDN::Zones;
@@ -48,6 +49,8 @@ my $write_running_cfg = sub {
 
 PVE::Cluster::cfs_register_file($running_cfg, $parse_running_cfg, $write_running_cfg);
 
+my $LOCK_TOKEN_FILE = "/etc/pve/sdn/.lock";
+
 # improve me : move status code inside plugins ?
 
 sub ifquery_check {
@@ -197,14 +200,57 @@ sub commit_config {
     cfs_write_file($running_cfg, $cfg);
 }
 
+sub generate_lock_token {
+    my $str;
+    my $uuid;
+
+    UUID::generate_v7($uuid);
+    UUID::unparse($uuid, $str);
+
+    return $str;
+}
+
+sub create_global_lock {
+    my $token = generate_lock_token();
+    PVE::Tools::file_set_contents($LOCK_TOKEN_FILE, $token);
+    return $token;
+}
+
+sub delete_global_lock {
+    unlink $LOCK_TOKEN_FILE if -e $LOCK_TOKEN_FILE;
+}
+
 sub lock_sdn_config {
-    my ($code, $errmsg) = @_;
+    my ($code, $errmsg, $lock_token_user) = @_;
 
-    cfs_lock_file($running_cfg, undef, $code);
+    my $lock_wrapper = sub {
+        my $lock_token = undef;
+        if (-e $LOCK_TOKEN_FILE) {
+            $lock_token = PVE::Tools::file_get_contents($LOCK_TOKEN_FILE);
+        }
+
+        if (
+            defined($lock_token)
+            && (!defined($lock_token_user) || $lock_token ne $lock_token_user)
+        ) {
+            die "invalid lock token provided!";
+        }
+
+        return $code->();
+    };
 
-    if (my $err = $@) {
+    return lock_sdn_domain($lock_wrapper, $errmsg);
+}
+
+sub lock_sdn_domain {
+    my ($code, $errmsg) = @_;
+
+    my $res = PVE::Cluster::cfs_lock_domain("sdn", undef, $code);
+    my $err = $@;
+    if ($err) {
         $errmsg ? die "$errmsg: $err" : die $err;
     }
+    return $res;
 }
 
 sub get_local_vnets {
-- 
2.39.5



_______________________________________________
pve-devel mailing list
pve-devel@lists.proxmox.com
https://lists.proxmox.com/cgi-bin/mailman/listinfo/pve-devel


  reply	other threads:[~2025-07-29  9:28 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-29  9:29 [pve-devel] [PATCH network v3 0/5] Add global locking and configuration rollback to SDN configuration Gabriel Goller
2025-07-29  9:29 ` Gabriel Goller [this message]
2025-07-29  9:29 ` [pve-devel] [PATCH network v3 2/5] api: add lock-token parameter to all api calls Gabriel Goller
2025-07-29  9:29 ` [pve-devel] [PATCH network v3 3/5] api: add lock token parameter to apply endpoint Gabriel Goller
2025-07-29  9:29 ` [pve-devel] [PATCH network v3 4/5] api: add lock and release endpoints for global configuration lock Gabriel Goller
2025-07-29  9:29 ` [pve-devel] [PATCH network v3 5/5] api: add rollback endpoint Gabriel Goller
2025-07-29 11:02 ` [pve-devel] applied-series: [PATCH network v3 0/5] Add global locking and configuration rollback to SDN configuration Thomas Lamprecht

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=20250729092933.90118-2-g.goller@proxmox.com \
    --to=g.goller@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 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