]> git.proxmox.com Git - pve-storage.git/blobdiff - PVE/CephConfig.pm
status: remove sleep(1) in file upload
[pve-storage.git] / PVE / CephConfig.pm
index b420fcc3ca83cb61e4d58cf772595f561f502a57..5c94a04a3bd0491de7c8ad98ba1f44bec0ef2f25 100644 (file)
@@ -21,8 +21,9 @@ sub parse_ceph_config {
     my $section;
 
     foreach my $line (@lines) {
-       $line =~ s/[;#].*$//;
+       $line =~ s/#.*$//;
        $line =~ s/^\s+//;
+       $line =~ s/^;.*$//;
        $line =~ s/\s+$//;
        next if !$line;
 
@@ -33,7 +34,10 @@ sub parse_ceph_config {
        }
 
        if ($line =~ m/^(.*?\S)\s*=\s*(\S.*)$/) {
-           $cfg->{$section}->{$1} = $2;
+           my ($key, $val) = ($1, $2);
+           # ceph treats ' ', '_' and '-' in keys the same, so lets do too
+           $key =~ s/[-\ ]/_/g;
+           $cfg->{$section}->{$key} = $val;
        }
 
     }
@@ -61,7 +65,7 @@ sub write_ceph_config {
     my $cond_write_sec = sub {
        my $re = shift;
 
-       foreach my $section (keys %$cfg) {
+       foreach my $section (sort keys %$cfg) {
            next if $section !~ m/^$re$/;
            $out .= "[$section]\n";
            foreach my $key (sort keys %{$cfg->{$section}}) {
@@ -96,32 +100,58 @@ my $ceph_get_key = sub {
     return $secret;
 };
 
+my $get_host = sub {
+    my ($hostport) = @_;
+    my ($host, $port) = PVE::Tools::parse_host_and_port($hostport);
+    if (!defined($host)) {
+       return "";
+    }
+    $port = defined($port) ? ":$port" : '';
+    $host = "[$host]" if Net::IP::ip_is_ipv6($host);
+    return "${host}${port}";
+};
+
 sub get_monaddr_list {
     my ($configfile) = shift;
 
-    my $server;
-
     if (!defined($configfile)) {
        warn "No ceph config specified\n";
        return;
     }
 
     my $config = $parse_ceph_file->($configfile);
-    @$server = sort map { $config->{$_}->{'mon addr'} } grep {/mon/} %{$config};
 
-    return join(',', @$server);
-};
+    my $monhostlist = {};
+
+    # get all ip addresses from mon_host
+    my $monhosts = [ split (/[ ,;]+/, $config->{global}->{mon_host} // "") ];
+
+    foreach my $monhost (@$monhosts) {
+       $monhost =~ s/^\[?v\d\://; # remove beginning of vector
+       $monhost =~ s|/\d+\]?||; # remove end of vector
+       my $host = $get_host->($monhost);
+       if ($host ne "") {
+           $monhostlist->{$host} = 1;
+       }
+    }
+
+    # then get all addrs from mon. sections
+    for my $section ( keys %$config ) {
+       next if $section !~ m/^mon\./;
+
+       if (my $addr = $config->{$section}->{mon_addr}) {
+           $monhostlist->{$addr} = 1;
+       }
+    }
+
+    return join(',', sort keys %$monhostlist);
+}
 
 sub hostlist {
     my ($list_text, $separator) = @_;
 
     my @monhostlist = PVE::Tools::split_list($list_text);
-    return join($separator, map {
-       my ($host, $port) = PVE::Tools::parse_host_and_port($_);
-       $port = defined($port) ? ":$port" : '';
-       $host = "[$host]" if Net::IP::ip_is_ipv6($host);
-       "${host}${port}"
-    } @monhostlist);
+    return join($separator, map { $get_host->($_) } @monhostlist);
 }
 
 my $ceph_check_keyfile = sub {
@@ -182,7 +212,7 @@ sub ceph_connect_option {
 }
 
 sub ceph_create_keyfile {
-    my ($type, $storeid) = @_;
+    my ($type, $storeid, $secret) = @_;
 
     my $extension = 'keyring';
     $extension = 'secret' if ($type eq 'cephfs');
@@ -191,17 +221,20 @@ sub ceph_create_keyfile {
     my $ceph_storage_keyring = "/etc/pve/priv/ceph/${storeid}.$extension";
 
     die "ceph authx keyring file for storage '$storeid' already exists!\n"
-       if -e $ceph_storage_keyring;
+       if -e $ceph_storage_keyring && !defined($secret);
 
-    if (-e $ceph_admin_keyring) {
+    if (-e $ceph_admin_keyring || defined($secret)) {
        eval {
-           if ($type eq 'rbd') {
+           if (defined($secret)) {
+               mkdir '/etc/pve/priv/ceph';
+               PVE::Tools::file_set_contents($ceph_storage_keyring, $secret, 0400);
+           } elsif ($type eq 'rbd') {
                mkdir '/etc/pve/priv/ceph';
                PVE::Tools::file_copy($ceph_admin_keyring, $ceph_storage_keyring);
            } elsif ($type eq 'cephfs') {
-               my $secret = $ceph_get_key->($ceph_admin_keyring, 'admin');
+               my $cephfs_secret = $ceph_get_key->($ceph_admin_keyring, 'admin');
                mkdir '/etc/pve/priv/ceph';
-               PVE::Tools::file_set_contents($ceph_storage_keyring, $secret, 0400);
+               PVE::Tools::file_set_contents($ceph_storage_keyring, $cephfs_secret, 0400);
           }
        };
        if (my $err = $@) {
@@ -225,4 +258,33 @@ sub ceph_remove_keyfile {
     }
 }
 
+my $ceph_version_parser = sub {
+    my $ceph_version = shift;
+    # FIXME this is the same as pve-manager PVE::Ceph::Tools get_local_version
+    if ($ceph_version =~ /^ceph.*\sv?(\d+(?:\.\d+)+(?:-pve\d+)?)\s+(?:\(([a-zA-Z0-9]+)\))?/) {
+       my ($version, $buildcommit) = ($1, $2);
+       my $subversions = [ split(/\.|-/, $version) ];
+
+       return ($subversions, $version, $buildcommit);
+    }
+    warn "Could not parse Ceph version: '$ceph_version'\n";
+};
+
+sub local_ceph_version {
+    my ($cache) = @_;
+
+    my $version_string = $cache;
+    if (!defined($version_string)) {
+       run_command('ceph --version', outfunc => sub {
+           $version_string = shift;
+       });
+    }
+    return undef if !defined($version_string);
+    # subversion is an array ref. with the version parts from major to minor
+    # version is the filtered version string
+    my ($subversions, $version) = $ceph_version_parser->($version_string);
+
+    return wantarray ? ($subversions, $version) : $version;
+}
+
 1;