]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/mgr/DaemonServer.cc
update sources to v12.1.0
[ceph.git] / ceph / src / mgr / DaemonServer.cc
index bb1927e25d6fa7e1405920f5061ffd6f45ec8c2f..e8d8c8a212865f007054299787ced8db5d3a590a 100644 (file)
 
 #include "DaemonServer.h"
 
+#include "include/str_list.h"
 #include "auth/RotatingKeyRing.h"
-
 #include "json_spirit/json_spirit_writer.h"
 
 #include "messages/MMgrOpen.h"
 #include "messages/MMgrConfigure.h"
+#include "messages/MMonMgrReport.h"
 #include "messages/MCommand.h"
 #include "messages/MCommandReply.h"
 #include "messages/MPGStats.h"
@@ -171,6 +172,14 @@ bool DaemonServer::ms_verify_authorizer(Connection *con,
       }
     }
     con->set_priv(s->get());
+
+    if (peer_type == CEPH_ENTITY_TYPE_OSD) {
+      Mutex::Locker l(lock);
+      s->osd_id = atoi(s->entity_name.get_id().c_str());
+      dout(10) << __func__ << " registering osd." << s->osd_id << " session "
+              << s << " con " << con << dendl;
+      osd_cons[s->osd_id].insert(con);
+    }
   }
 
   return true;
@@ -196,6 +205,22 @@ bool DaemonServer::ms_get_authorizer(int dest_type,
   return *authorizer != NULL;
 }
 
+bool DaemonServer::ms_handle_reset(Connection *con)
+{
+  if (con->get_peer_type() == CEPH_ENTITY_TYPE_OSD) {
+    MgrSessionRef session(static_cast<MgrSession*>(con->get_priv()));
+    if (!session) {
+      return false;
+    }
+    session->put(); // SessionRef takes a ref
+    Mutex::Locker l(lock);
+    dout(10) << __func__ << " unregistering osd." << session->osd_id
+            << "  session " << session << " con " << con << dendl;
+    osd_cons[session->osd_id].erase(con);
+  }
+  return false;
+}
+
 bool DaemonServer::ms_handle_refused(Connection *con)
 {
   // do nothing for now
@@ -235,15 +260,19 @@ void DaemonServer::shutdown()
 
 bool DaemonServer::handle_open(MMgrOpen *m)
 {
-  DaemonKey key(
-      m->get_connection()->get_peer_type(),
-      m->daemon_name);
+  uint32_t type = m->get_connection()->get_peer_type();
+  DaemonKey key(type, m->daemon_name);
 
   dout(4) << "from " << m->get_connection() << " name "
-          << m->daemon_name << dendl;
+          << ceph_entity_type_name(type) << "." << m->daemon_name << dendl;
 
   auto configure = new MMgrConfigure();
-  configure->stats_period = g_conf->mgr_stats_period;
+  if (m->get_connection()->get_peer_type() == entity_name_t::TYPE_CLIENT) {
+    // We don't want clients to send us stats
+    configure->stats_period = 0;
+  } else {
+    configure->stats_period = g_conf->mgr_stats_period;
+  }
   m->get_connection()->send_message(configure);
 
   if (daemon_state.exists(key)) {
@@ -257,12 +286,18 @@ bool DaemonServer::handle_open(MMgrOpen *m)
 
 bool DaemonServer::handle_report(MMgrReport *m)
 {
-  DaemonKey key(
-      m->get_connection()->get_peer_type(),
-      m->daemon_name);
+  uint32_t type = m->get_connection()->get_peer_type();
+  DaemonKey key(type, m->daemon_name);
 
   dout(4) << "from " << m->get_connection() << " name "
-          << m->daemon_name << dendl;
+          << ceph_entity_type_name(type) << "." << m->daemon_name << dendl;
+
+  if (m->get_connection()->get_peer_type() == entity_name_t::TYPE_CLIENT) {
+    // Clients should not be sending us stats
+    dout(4) << "rejecting report from client " << m->daemon_name << dendl;
+    m->put();
+    return true;
+  }
 
   DaemonStatePtr daemon;
   if (daemon_state.exists(key)) {
@@ -492,17 +527,14 @@ bool DaemonServer::handle_command(MCommand *m)
                           "mgr", pyc.perm, "cli", 0);
       cmdnum++;
     }
-#if 0
-    for (MgrCommand *cp = mgr_commands;
-        cp < &mgr_commands[ARRAY_SIZE(mgr_commands)]; cp++) {
 
+    for (const auto &cp : mgr_commands) {
       ostringstream secname;
       secname << "cmd" << setfill('0') << std::setw(3) << cmdnum;
-      dump_cmddesc_to_json(f, secname.str(), cp->cmdstring, cp->helpstring,
-                          cp->module, cp->perm, cp->availability, 0);
+      dump_cmddesc_to_json(&f, secname.str(), cp.cmdstring, cp.helpstring,
+                          cp.module, cp.perm, cp.availability, 0);
       cmdnum++;
     }
-#endif
     f.close_section(); // command_descriptions
     f.flush(cmdctx->odata);
     cmdctx->reply(0, ss);
@@ -518,7 +550,8 @@ bool DaemonServer::handle_command(MCommand *m)
     if (!_allowed_command(session.get(), py_command.module, prefix, cmdctx->cmdmap,
                           param_str_map, &py_command)) {
       dout(1) << " access denied" << dendl;
-      ss << "access denied";
+      ss << "access denied; does your client key have mgr caps?"
+       " See http://docs.ceph.com/docs/master/mgr/administrator/#client-authentication";
       cmdctx->reply(-EACCES, ss);
       return true;
     }
@@ -530,7 +563,8 @@ bool DaemonServer::handle_command(MCommand *m)
       audit_clog->info() << "from='" << session->inst << "' "
                          << "entity='" << session->entity_name << "' "
                          << "cmd=" << m->cmd << ":  access denied";
-      ss << "access denied";
+      ss << "access denied' does your client key have mgr caps?"
+       " See http://docs.ceph.com/docs/master/mgr/administrator/#client-authentication";
       cmdctx->reply(-EACCES, ss);
       return true;
     }
@@ -566,26 +600,90 @@ bool DaemonServer::handle_command(MCommand *m)
       return true;
     }
     int acting_primary = -1;
-    entity_inst_t inst;
     cluster_state.with_osdmap([&](const OSDMap& osdmap) {
        acting_primary = osdmap.get_pg_acting_primary(pgid);
-       if (acting_primary >= 0) {
-         inst = osdmap.get_inst(acting_primary);
-       }
       });
     if (acting_primary == -1) {
       ss << "pg " << pgid << " has no primary osd";
       cmdctx->reply(-EAGAIN, ss);
       return true;
     }
+    auto p = osd_cons.find(acting_primary);
+    if (p == osd_cons.end()) {
+      ss << "pg " << pgid << " primary osd." << acting_primary
+        << " is not currently connected";
+      cmdctx->reply(-EAGAIN, ss);
+    }
     vector<pg_t> pgs = { pgid };
-    msgr->send_message(new MOSDScrub(monc->get_fsid(),
-                                    pgs,
-                                    scrubop == "repair",
-                                    scrubop == "deep-scrub"),
-                      inst);
+    for (auto& con : p->second) {
+      con->send_message(new MOSDScrub(monc->get_fsid(),
+                                     pgs,
+                                     scrubop == "repair",
+                                     scrubop == "deep-scrub"));
+    }
     ss << "instructing pg " << pgid << " on osd." << acting_primary
-       << " (" << inst << ") to " << scrubop;
+       << " to " << scrubop;
+    cmdctx->reply(0, ss);
+    return true;
+  } else if (prefix == "osd scrub" ||
+             prefix == "osd deep-scrub" ||
+             prefix == "osd repair") {
+    string whostr;
+    cmd_getval(g_ceph_context, cmdctx->cmdmap, "who", whostr);
+    vector<string> pvec;
+    get_str_vec(prefix, pvec);
+
+    set<int> osds;
+    if (whostr == "*") {
+      cluster_state.with_osdmap([&](const OSDMap& osdmap) {
+         for (int i = 0; i < osdmap.get_max_osd(); i++)
+           if (osdmap.is_up(i)) {
+             osds.insert(i);
+           }
+       });
+    } else {
+      long osd = parse_osd_id(whostr.c_str(), &ss);
+      if (osd < 0) {
+       ss << "invalid osd '" << whostr << "'";
+       cmdctx->reply(-EINVAL, ss);
+       return true;
+      }
+      cluster_state.with_osdmap([&](const OSDMap& osdmap) {
+         if (osdmap.is_up(osd)) {
+           osds.insert(osd);
+         }
+       });
+      if (osds.empty()) {
+       ss << "osd." << osd << " is not up";
+       cmdctx->reply(-EAGAIN, ss);
+       return true;
+      }
+    }
+    set<int> sent_osds, failed_osds;
+    for (auto osd : osds) {
+      auto p = osd_cons.find(osd);
+      if (p == osd_cons.end()) {
+       failed_osds.insert(osd);
+      } else {
+       sent_osds.insert(osd);
+       for (auto& con : p->second) {
+         con->send_message(new MOSDScrub(monc->get_fsid(),
+                                         pvec.back() == "repair",
+                                         pvec.back() == "deep-scrub"));
+       }
+      }
+    }
+    if (failed_osds.size() == osds.size()) {
+      ss << "failed to instruct osd(s) " << osds << " to " << pvec.back()
+        << " (not connected)";
+      r = -EAGAIN;
+    } else {
+      ss << "instructed osd(s) " << sent_osds << " to " << pvec.back();
+      if (!failed_osds.empty()) {
+       ss << "; osd(s) " << failed_osds << " were not connected";
+      }
+      r = 0;
+    }
     cmdctx->reply(0, ss);
     return true;
   } else if (prefix == "osd reweight-by-pg" ||
@@ -682,6 +780,20 @@ bool DaemonServer::handle_command(MCommand *m)
                              &on_finish->from_mon, &on_finish->outs, on_finish);
       return true;
     }
+  } else if (prefix == "osd df") {
+    string method;
+    cmd_getval(g_ceph_context, cmdctx->cmdmap, "output_method", method);
+    r = cluster_state.with_pgservice([&](const PGMapStatService& pgservice) {
+       return cluster_state.with_osdmap([&](const OSDMap& osdmap) {
+           print_osd_utilization(osdmap, &pgservice, ss,
+                                 f.get(), method == "tree");
+                                 
+           cmdctx->odata.append(ss);
+           return 0;
+         });
+      });
+    cmdctx->reply(r, "");
+    return true;
   } else {
     r = cluster_state.with_pgmap([&](const PGMap& pg_map) {
        return cluster_state.with_osdmap([&](const OSDMap& osdmap) {
@@ -728,3 +840,26 @@ bool DaemonServer::handle_command(MCommand *m)
     return true;
   }
 }
+
+void DaemonServer::send_report()
+{
+  auto m = new MMonMgrReport();
+  cluster_state.with_pgmap([&](const PGMap& pg_map) {
+      cluster_state.update_delta_stats();
+
+      // FIXME: reporting health detail here might be a bad idea?
+      cluster_state.with_osdmap([&](const OSDMap& osdmap) {
+         // FIXME: no easy way to get mon features here.  this will do for
+         // now, though, as long as we don't make a backward-incompat change.
+         pg_map.encode_digest(osdmap, m->get_data(), CEPH_FEATURES_ALL);
+         dout(10) << pg_map << dendl;
+         pg_map.get_health(g_ceph_context, osdmap,
+                           m->health_summary,
+                           &m->health_detail);
+       });
+    });
+  // TODO? We currently do not notify the PyModules
+  // TODO: respect needs_send, so we send the report only if we are asked to do
+  //       so, or the state is updated.
+  monc->send_mon_message(m);
+}