[pve-devel] [PATCH manager v2 3/7] ceph: mon create: lock monitor creation
Dominik Csapak
d.csapak at proxmox.com
Wed Jun 19 13:45:50 CEST 2019
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.csapak at 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
More information about the pve-devel
mailing list