]> git.proxmox.com Git - pve-cluster.git/commitdiff
lock locally on cluster create and join
authorThomas Lamprecht <t.lamprecht@proxmox.com>
Tue, 9 Jan 2018 14:31:00 +0000 (15:31 +0100)
committerFabian Grünbichler <f.gruenbichler@proxmox.com>
Fri, 16 Feb 2018 12:50:46 +0000 (13:50 +0100)
If we are not part of a cluster we do not need to worry about other
members messing with the config. But there may be local contenders,
e.g., two automation script instances started in parallel by mistake
or two admin (sessions) which start a create or join clsuter request
at the same time.
Reuse the local flock for this purpose.

lock_file silents an exception, but does not alters it so we die if
$@ is set, to ensure a worker gets to know that something bad
happened.

Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
data/PVE/API2/ClusterConfig.pm
data/PVE/CLI/pvecm.pm

index 2fa3da29cb9de6c16e2bff1ed31f01e2ebbba874..f07dca898573519b98e271368efb162bf06813f2 100644 (file)
@@ -16,6 +16,7 @@ use base qw(PVE::RESTHandler);
 
 my $clusterconf = "/etc/pve/corosync.conf";
 my $authfile = "/etc/corosync/authkey";
+my $local_cluster_lock = "/var/lock/pvecm.lock";
 
 my $ring0_desc = {
     type => 'string', format => 'address',
@@ -119,7 +120,7 @@ __PACKAGE__->register_method ({
        my $rpcenv = PVE::RPCEnvironment::get();
        my $authuser = $rpcenv->get_user();
 
-       my $worker = sub {
+       my $code = sub {
            PVE::Cluster::setup_sshd_config(1);
            PVE::Cluster::setup_rootsshconfig();
            PVE::Cluster::setup_ssh_keys();
@@ -145,6 +146,11 @@ __PACKAGE__->register_method ({
            PVE::Tools::run_command('systemctl restart corosync pve-cluster');
        };
 
+       my $worker = sub {
+           PVE::Tools::lock_file($local_cluster_lock, 10, $code);
+           die $@ if $@;
+       };
+
        return $rpcenv->fork_worker('clustercreate', '',  $authuser, $worker);
 }});
 
@@ -186,8 +192,7 @@ __PACKAGE__->register_method({
 my $config_change_lock = sub {
     my ($code) = @_;
 
-    my $local_lock_fn = "/var/lock/pvecm.lock";
-    PVE::Tools::lock_file($local_lock_fn, 10, sub {
+    PVE::Tools::lock_file($local_cluster_lock, 10, sub {
        PVE::Cluster::cfs_update(1);
        my $members = PVE::Cluster::get_members();
        if (scalar(keys %$members) > 1) {
@@ -507,7 +512,8 @@ __PACKAGE__->register_method ({
        my $authuser = $rpcenv->get_user();
 
        my $worker = sub {
-           PVE::Cluster::join($param);
+           PVE::Tools::lock_file($local_cluster_lock, 10, \&PVE::Cluster::join, $param);
+           die $@ if $@;
        };
 
        return $rpcenv->fork_worker('clusterjoin', '',  $authuser, $worker);
index 5c030e22931aad86ddd2f60bd67db8f6497f3966..9b988151c770a5f6f26a8bc9fb85f2bac90bd18f 100755 (executable)
@@ -117,7 +117,8 @@ __PACKAGE__->register_method ({
            delete $param->{use_ssh};
            $param->{password} = $password;
 
-           eval { PVE::Cluster::join($param) };
+           my $local_cluster_lock = "/var/lock/pvecm.lock";
+           PVE::Tools::lock_file($local_cluster_lock, 10, \&PVE::Cluster::join, $param);
 
            if (my $err = $@) {
                if (ref($err) eq 'PVE::APIClient::Exception' && $err->{code} == 501) {