From 3a582f994998fa925a6f2b619326bfc24616306b Mon Sep 17 00:00:00 2001 From: Greg Farnum Date: Thu, 9 Jun 2011 17:21:33 -0700 Subject: [PATCH] mon: add new "tell" infrastructure. This lets you issue commands like "ceph mon tell 0 heap start_profiler". Hurray! Signed-off-by: Greg Farnum --- src/mon/Monitor.cc | 71 +++++++++++++++++++++++++++++++++++++++++++++- src/mon/Monitor.h | 3 ++ 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/mon/Monitor.cc b/src/mon/Monitor.cc index f7347aa10e2..1cb4872da7a 100644 --- a/src/mon/Monitor.cc +++ b/src/mon/Monitor.cc @@ -316,7 +316,8 @@ void Monitor::handle_command(MMonCommand *m) pgmon()->dispatch(m); return; } - if (m->cmd[0] == "mon") { + if (m->cmd[0] == "mon" && + ((m->cmd.size() < 3 ) || m->cmd[1] != "tell")) { monmon()->dispatch(m); return; } @@ -378,6 +379,46 @@ void Monitor::handle_command(MMonCommand *m) ss << " " << combined; rs = ss.str(); r = 0; + } else if (m->cmd[0] == "mon" && m->cmd.size() >= 3 && m->cmd[1] == "tell") { + if (m->cmd[2] == "*") { // send to all mons and do myself + char *num = new char[8]; + for (unsigned i = 0; i < monmap->size(); ++i) { + if (monmap->get_inst(i) != messenger->get_myinst()) { + sprintf(num, "%d", i); + m->cmd[2] = num; + messenger->send_message(m, monmap->get_inst(i)); + } + } + handle_mon_tell(m); + rs = "delivered command to all mons"; + r = 0; + } else { + // find target + int target = atoi(m->cmd[2].c_str()); + stringstream ss; + if (target == 0 && m->cmd[2] != "0") { + ss << "could not parse target " << m->cmd[2]; + rs = ss.str(); + } else { + // send to target, or handle if it's me + if (monmap->get_inst(target) != messenger->get_myinst()) { + messenger->send_message(m, monmap->get_inst(target)); + ss << "forwarded to target mon" << m->cmd[2]; + rs = ss.str(); + r = 0; + } + else { + handle_mon_tell(m); + rs = "interpreting...(see clog for more information)"; + r = 0; + } + } + if (m->get_source().is_mon()) { + // don't respond directly to sender, just put in log and back out + m->put(); + return; + } + } } } else rs = "no command"; @@ -385,6 +426,34 @@ void Monitor::handle_command(MMonCommand *m) reply_command(m, r, rs, rdata, 0); } +/** + * Handle commands of the format "ceph mon tell x", where x + * is a mon number. This function presumes it's supposed + * to execute the actual command; delivery is handled by + */ +void Monitor::handle_mon_tell(MMonCommand *m) +{ + dout(0) << "handle_command " << *m << dendl; + stringstream ss; + + // remove monitor direction instructions + m->cmd.erase(m->cmd.begin()); + m->cmd.erase(m->cmd.begin()); + m->cmd.erase(m->cmd.begin()); + + if ((m->cmd.size()) && (m->cmd[0] == "heap")) { + if (!ceph_using_tcmalloc()) + ss << "tcmalloc not enabled, can't use heap profiler commands\n"; + else + ceph_heap_profiler_handle_command(m->cmd, clog); + } else { + ss << "unrecognized command " << m->cmd; + } + + if (!ss.eof()) + clog.error(ss); +} + void Monitor::reply_command(MMonCommand *m, int rc, const string &rs, version_t version) { bufferlist rdata; diff --git a/src/mon/Monitor.h b/src/mon/Monitor.h index a780e004e01..b792fd6beb1 100644 --- a/src/mon/Monitor.h +++ b/src/mon/Monitor.h @@ -39,6 +39,8 @@ #include "auth/cephx/CephxKeyServer.h" +#include "perfglue/heap_profiler.h" + #include class MonitorStore; @@ -147,6 +149,7 @@ public: void handle_subscribe(MMonSubscribe *m); void handle_mon_get_map(MMonGetMap *m); void handle_command(class MMonCommand *m); + void handle_mon_tell(MMonCommand *m); void handle_observe(MMonObserve *m); void handle_route(MRoute *m);