mon: add new "tell" infrastructure.

This lets you issue commands
like "ceph mon tell 0 heap start_profiler". Hurray!

Signed-off-by: Greg Farnum <gregory.farnum@dreamhost.com>
This commit is contained in:
Greg Farnum 2011-06-09 17:21:33 -07:00
parent 2c4367f95d
commit 3a582f9949
2 changed files with 73 additions and 1 deletions

View File

@ -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;

View File

@ -39,6 +39,8 @@
#include "auth/cephx/CephxKeyServer.h"
#include "perfglue/heap_profiler.h"
#include <memory>
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);