summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/control1
-rw-r--r--src/PVE/Network/SDN.pm54
-rwxr-xr-xsrc/test/run_test_vnets_blackbox.pl26
3 files changed, 73 insertions, 8 deletions
diff --git a/debian/control b/debian/control
index f64a2d4..b45d126 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 0e7d1df..9f18f76 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 {
diff --git a/src/test/run_test_vnets_blackbox.pl b/src/test/run_test_vnets_blackbox.pl
index 2e1c505..468b1ed 100755
--- a/src/test/run_test_vnets_blackbox.pl
+++ b/src/test/run_test_vnets_blackbox.pl
@@ -33,7 +33,10 @@ my $test_state = undef;
sub clear_test_state {
$test_state = {
- locks => {},
+ locks => {
+ file => {},
+ domain => {},
+ },
datacenter_config => {},
subnets_config => {},
controller_config => {},
@@ -57,13 +60,27 @@ clear_test_state();
my $mocked_cfs_lock_file = sub {
my ($filename, $timeout, $code, @param) = @_;
- die "$filename already locked\n" if ($test_state->{locks}->{$filename});
+ die "$filename already locked\n" if $test_state->{locks}->{file}->{$filename};
- $test_state->{locks}->{$filename} = 1;
+ $test_state->{locks}->{file}->{$filename} = 1;
my $res = eval { $code->(@param); };
- delete $test_state->{locks}->{$filename};
+ delete $test_state->{locks}->{file}->{$filename};
+
+ return $res;
+};
+
+my $mocked_cfs_lock_domain = sub {
+ my ($domain, $timeout, $code, @param) = @_;
+
+ die "domain '$domain' already locked\n" if $test_state->{locks}->{domain}->{$domain};
+
+ $test_state->{locks}->{domain}->{$domain} = 1;
+
+ my $res = eval { $code->(@param) };
+
+ delete $test_state->{locks}->{domain}->{$domain};
return $res;
};
@@ -224,6 +241,7 @@ $mocked_rpc_env_obj->mock(
my $mocked_pve_cluster_obj = Test::MockModule->new('PVE::Cluster');
$mocked_pve_cluster_obj->mock(
check_cfs_quorum => sub { return 1; },
+ cfs_lock_domain => $mocked_cfs_lock_domain,
);
# ------- TEST FUNCTIONS --------------