otherwise it is possible that multiple users create monitors at the same
time, resulting in a wrong ceph.conf and probably worse

Signed-off-by: Dominik Csapak <d.csa...@proxmox.com>
---
changes from v1:
* replace $firstmon use with $rados
 PVE/API2/Ceph/MON.pm | 97 +++++++++++++++++++++++++++++-----------------------
 1 file changed, 54 insertions(+), 43 deletions(-)

diff --git a/PVE/API2/Ceph/MON.pm b/PVE/API2/Ceph/MON.pm
index 678719b8..2d61142e 100644
--- a/PVE/API2/Ceph/MON.pm
+++ b/PVE/API2/Ceph/MON.pm
@@ -195,62 +195,73 @@ __PACKAGE__->register_method ({
        my $worker = sub  {
            my $upid = shift;
 
-           my $client_keyring = 
PVE::Ceph::Tools::get_or_create_admin_keyring();
-           my $mon_keyring = PVE::Ceph::Tools::get_config('pve_mon_key_path');
+           PVE::Cluster::cfs_lock_file('ceph.conf', undef, sub {
+               # update cfg content and reassert prereqs inside the lock
+               $cfg = cfs_read_file('ceph.conf');
+               # reopen with longer timeout
+               if (defined($rados)) {
+                   $rados = PVE::RADOS->new(timeout => 
PVE::Ceph::Tools::get_config('long_rados_timeout'));
+               }
+               $monhash = PVE::Ceph::Services::get_services_info('mon', $cfg, 
$rados);
+               $assert_mon_prerequisites->($cfg, $monhash, $monid, $ip);
 
-           if (! -f $mon_keyring) {
-               run_command("ceph-authtool --create-keyring $mon_keyring ".
-                   " --gen-key -n mon. --cap mon 'allow *'");
-               run_command("ceph-authtool $mon_keyring --import-keyring 
$client_keyring");
-           }
+               my $client_keyring = 
PVE::Ceph::Tools::get_or_create_admin_keyring();
+               my $mon_keyring = 
PVE::Ceph::Tools::get_config('pve_mon_key_path');
 
-           my $ccname = PVE::Ceph::Tools::get_config('ccname');
-           my $mondir =  "/var/lib/ceph/mon/$ccname-$monid";
-           -d $mondir && die "monitor filesystem '$mondir' already exist\n";
+               if (! -f $mon_keyring) {
+                   run_command("ceph-authtool --create-keyring $mon_keyring ".
+                       " --gen-key -n mon. --cap mon 'allow *'");
+                   run_command("ceph-authtool $mon_keyring --import-keyring 
$client_keyring");
+               }
 
-           my $monmap = "/tmp/monmap";
+               my $ccname = PVE::Ceph::Tools::get_config('ccname');
+               my $mondir =  "/var/lib/ceph/mon/$ccname-$monid";
+               -d $mondir && die "monitor filesystem '$mondir' already 
exist\n";
 
-           eval {
-               mkdir $mondir;
+               my $monmap = "/tmp/monmap";
 
-               run_command("chown ceph:ceph $mondir");
+               eval {
+                   mkdir $mondir;
 
-               if (defined($rados)) { # we can only have a RADOS object if we 
have a monitor
-                   my $rados = PVE::RADOS->new(timeout => 
PVE::Ceph::Tools::get_config('long_rados_timeout'));
-                   my $mapdata = $rados->mon_command({ prefix => 'mon getmap', 
format => 'plain' });
-                   file_set_contents($monmap, $mapdata);
-               } else { # we need to create a monmap for the first monitor
-                   my $monaddr = $ip;
-                   if (Net::IP::ip_is_ipv6($ip)) {
-                       $monaddr = "[$ip]";
-                       $cfg->{global}->{ms_bind_ipv6} = 'true';
+                   run_command("chown ceph:ceph $mondir");
+
+                   if (defined($rados)) { # we can only have a RADOS object if 
we have a monitor
+                       my $mapdata = $rados->mon_command({ prefix => 'mon 
getmap', format => 'plain' });
+                       file_set_contents($monmap, $mapdata);
+                   } else { # we need to create a monmap for the first monitor
+                       my $monaddr = $ip;
+                       if (Net::IP::ip_is_ipv6($ip)) {
+                           $monaddr = "[$ip]";
+                           $cfg->{global}->{ms_bind_ipv6} = 'true';
+                       }
+                       run_command("monmaptool --create --clobber --addv 
$monid '[v2:$monaddr:3300,v1:$monaddr:6789]' --print $monmap");
                    }
-                   run_command("monmaptool --create --clobber --addv $monid 
'[v2:$monaddr:3300,v1:$monaddr:6789]' --print $monmap");
-               }
 
-               run_command("ceph-mon --mkfs -i $monid --monmap $monmap 
--keyring $mon_keyring --public-addr $ip");
-               run_command("chown ceph:ceph -R $mondir");
-           };
-           my $err = $@;
-           unlink $monmap;
-           if ($err) {
-               File::Path::remove_tree($mondir);
-               die $err;
-           }
+                   run_command("ceph-mon --mkfs -i $monid --monmap $monmap 
--keyring $mon_keyring --public-addr $ip");
+                   run_command("chown ceph:ceph -R $mondir");
+               };
+               my $err = $@;
+               unlink $monmap;
+               if ($err) {
+                   File::Path::remove_tree($mondir);
+                   die $err;
+               }
 
-           # update ceph.conf
-           my $monhost = $cfg->{global}->{mon_host} // "";
-           $monhost .= " $ip";
-           $cfg->{global}->{mon_host} = $monhost;
+               # update ceph.conf
+               my $monhost = $cfg->{global}->{mon_host} // "";
+               $monhost .= " $ip";
+               $cfg->{global}->{mon_host} = $monhost;
 
-           cfs_write_file('ceph.conf', $cfg);
+               cfs_write_file('ceph.conf', $cfg);
 
-           PVE::Ceph::Services::ceph_service_cmd('start', $monsection);
+               PVE::Ceph::Services::ceph_service_cmd('start', $monsection);
 
-           eval { PVE::Ceph::Services::ceph_service_cmd('enable', $monsection) 
};
-           warn "Enable ceph-mon\@${monid}.service failed, do manually: $@\n" 
if $@;
+               eval { PVE::Ceph::Services::ceph_service_cmd('enable', 
$monsection) };
+               warn "Enable ceph-mon\@${monid}.service failed, do manually: 
$@\n" if $@;
 
-           PVE::Ceph::Services::broadcast_ceph_services();
+               PVE::Ceph::Services::broadcast_ceph_services();
+           });
+           die $@ if $@;
        };
 
        return $rpcenv->fork_worker('cephcreatemon', $monsection, $authuser, 
$worker);
-- 
2.11.0


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

Reply via email to