]> git.proxmox.com Git - pve-manager.git/blobdiff - PVE/Ceph/Services.pm
api: backup: update: check permissions of delete params too
[pve-manager.git] / PVE / Ceph / Services.pm
index 45eb6c3ff0c8ca7ab3d1d2dc03542c7c20c0f15f..e0f31e8eb6bc9b3777b3d0d548497276efaa5c41 100644 (file)
@@ -11,6 +11,8 @@ use PVE::RADOS;
 use JSON;
 use File::Path;
 
+use constant SERVICE_REGEX => '[a-zA-Z0-9]([a-zA-Z0-9\-]*[a-zA-Z0-9])?';
+
 # checks /etc/systemd/system/ceph-* to list all services, even if not running
 # also checks /var/lib/ceph/$type
 sub get_local_services {
@@ -45,15 +47,52 @@ sub broadcast_ceph_services {
     }
 }
 
+sub broadcast_ceph_versions {
+    my ($version, $buildcommit, $vers_parts) = PVE::Ceph::Tools::get_local_version(1);
+
+    if ($version) {
+       my $nodename = PVE::INotify::nodename();
+       my $old = PVE::Cluster::get_node_kv("ceph-versions", $nodename);
+       if (defined($old->{$nodename})) {
+           $old = eval { decode_json($old->{$nodename}) };
+           warn $@ if $@; # should not happen
+           if (defined($old) && $old->{buildcommit} eq $buildcommit && $old->{version}->{str} eq $version) {
+               return; # up to date, nothing to do so avoid (not exactly cheap) broadcast
+           }
+       }
+       # FIXME: remove with 8.0 (or 7.2, its not _that_ bad) - for backward compat only
+       PVE::Cluster::broadcast_node_kv("ceph-version", $version);
+
+       my $node_versions = {
+           version => {
+               str => $version,
+               parts => $vers_parts,
+           },
+           buildcommit => $buildcommit,
+       };
+       PVE::Cluster::broadcast_node_kv("ceph-versions", encode_json($node_versions));
+    }
+}
+
+sub get_ceph_versions {
+    my $res;
+
+    if (defined(my $versions = PVE::Cluster::get_node_kv("ceph-versions"))) {
+       $res = {
+           map { eval { $_ => decode_json($versions->{$_}) } } keys %$versions
+       };
+    }
+
+    return $res;
+}
+
 sub get_cluster_service {
     my ($type) = @_;
 
     my $raw = PVE::Cluster::get_node_kv("ceph-$type");
-    my $res = {};
-
-    for my $host (keys %$raw) {
-       $res->{$host} = eval { decode_json($raw->{$host}) };
-    }
+    my $res = {
+       map { $_ => eval { decode_json($raw->{$_}) } } keys $raw->%*
+    };
 
     return $res;
 }
@@ -61,8 +100,7 @@ sub get_cluster_service {
 sub ceph_service_cmd {
     my ($action, $service) = @_;
 
-    my $pve_ceph_cfgpath = PVE::Ceph::Tools::get_config('pve_ceph_cfgpath');
-    if ($service && $service =~ m/^(mon|osd|mds|mgr|radosgw)(\.([A-Za-z0-9\-]{1,32}))?$/) {
+    if ($service && $service =~ m/^(mon|osd|mds|mgr|radosgw)(\.(${\SERVICE_REGEX}))?$/) {
        $service = defined($3) ? "ceph-$1\@$3" : "ceph-$1.target";
     } else {
        $service = "ceph.target";
@@ -148,13 +186,14 @@ sub get_cluster_mds_state {
     }
 
     my $add_state = sub {
-       my ($mds) = @_;
+       my ($mds, $fsname) = @_;
 
        my $state = {};
        $state->{addr} = $mds->{addr};
        $state->{rank} = $mds->{rank};
        $state->{standby_replay} = $mds->{standby_replay} ? 1 : 0;
        $state->{state} = $mds->{state};
+       $state->{fs_name} = $fsname;
 
        $mds_state->{$mds->{name}} = $state;
     };
@@ -167,35 +206,39 @@ sub get_cluster_mds_state {
        $add_state->($mds);
     }
 
-    my $fs_info = $fsmap->{filesystems}->[0];
-    my $active_mds = $fs_info->{mdsmap}->{info};
+    for my $fs_info (@{$fsmap->{filesystems}}) {
+       my $active_mds = $fs_info->{mdsmap}->{info};
 
-    # normally there's only one active MDS, but we can have multiple active for
-    # different ranks (e.g., different cephs path hierarchy). So just add all.
-    foreach my $mds (values %$active_mds) {
-       $add_state->($mds);
+       # normally there's only one active MDS, but we can have multiple active for
+       # different ranks (e.g., different cephs path hierarchy). So just add all.
+       foreach my $mds (values %$active_mds) {
+           $add_state->($mds, $fs_info->{mdsmap}->{fs_name});
+       }
     }
 
     return $mds_state;
 }
 
-sub is_any_mds_active {
-    my ($rados) = @_;
+sub is_mds_active {
+    my ($rados, $fs_name) = @_;
 
     if (!defined($rados)) {
        $rados = PVE::RADOS->new();
     }
 
     my $mds_dump = $rados->mon_command({ prefix => 'mds stat' });
-    my $fs = $mds_dump->{fsmap}->{filesystems};
+    my $fsmap = $mds_dump->{fsmap}->{filesystems};
 
-    if (!($fs && scalar(@$fs) > 0)) {
+    if (!($fsmap && scalar(@$fsmap) > 0)) {
        return undef;
     }
-    my $active_mds = $fs->[0]->{mdsmap}->{info};
+    for my $fs (@$fsmap) {
+       next if defined($fs_name) && $fs->{mdsmap}->{fs_name} ne $fs_name;
 
-    for my $mds (values %$active_mds) {
-       return 1 if $mds->{state} eq 'up:active';
+       my $active_mds = $fs->{mdsmap}->{info};
+       for my $mds (values %$active_mds) {
+           return 1 if $mds->{state} eq 'up:active';
+       }
     }
 
     return 0;
@@ -301,20 +344,21 @@ sub create_mgr {
     my $mgrkeyring = "$mgrdir/keyring";
     my $mgrname = "mgr.$id";
 
-    die "ceph manager directory '$mgrdir' already exists\n"
-       if -d $mgrdir;
+    die "ceph manager directory '$mgrdir' already exists\n" if -d $mgrdir;
 
     print "creating manager directory '$mgrdir'\n";
     mkdir $mgrdir;
     print "creating keys for '$mgrname'\n";
-    my $output = $rados->mon_command({ prefix => 'auth get-or-create',
-                                      entity => $mgrname,
-                                      caps => [
-                                          mon => 'allow profile mgr',
-                                          osd => 'allow *',
-                                          mds => 'allow *',
-                                      ],
-                                      format => 'plain'});
+    my $output = $rados->mon_command({
+       prefix => 'auth get-or-create',
+       entity => $mgrname,
+       caps => [
+           mon => 'allow profile mgr',
+           osd => 'allow *',
+           mds => 'allow *',
+       ],
+       format => 'plain'
+    });
     PVE::Tools::file_set_contents($mgrkeyring, $output);
 
     print "setting owner for directory\n";