From: Sage Weil Date: Wed, 12 Jun 2013 23:36:39 +0000 (-0700) Subject: librados: new rados_mon_command_target to talk to a specific monitor X-Git-Tag: v0.65~85^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=420e02e818844b466465f75bcaedd62378b9ec3c;p=ceph.git librados: new rados_mon_command_target to talk to a specific monitor Signed-off-by: Sage Weil --- diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h index 69eeccb323bb..eb1a30632b7e 100644 --- a/src/include/rados/librados.h +++ b/src/include/rados/librados.h @@ -1712,7 +1712,7 @@ int rados_break_lock(rados_ioctx_t io, const char *o, const char *name, * @note Takes command string in carefully-formatted JSON; must match * defined commands, types, etc. * - * The result buffers are allocated on the heapt; the caller is + * The result buffers are allocated on the heap; the caller is * expected to release that memory with rados_buffer_free(). The * buffer and length pointers can all be NULL, in which case they are * not filled in. @@ -1732,6 +1732,34 @@ int rados_mon_command(rados_t cluster, const char **cmd, size_t cmdlen, char **outbuf, size_t *outbuflen, char **outs, size_t *outslen); +/** + * Send monitor command to a specific monitor. + * + * @note Takes command string in carefully-formatted JSON; must match + * defined commands, types, etc. + * + * The result buffers are allocated on the heap; the caller is + * expected to release that memory with rados_buffer_free(). The + * buffer and length pointers can all be NULL, in which case they are + * not filled in. + * + * @param cluster cluster handle + * @param name target monitor's name + * @param cmd an array of char *'s representing the command + * @param cmdlen count of valid entries in cmd + * @param inbuf any bulk input data (crush map, etc.) + * @param outbuf double pointer to output buffer + * @param outbuflen pointer to output buffer length + * @param outs double pointer to status string + * @param outslen pointer to status string length + * @returns 0 on success, negative error code on failure + */ +int rados_mon_command_target(rados_t cluster, const char *name, + const char **cmd, size_t cmdlen, + const char *inbuf, size_t inbuflen, + char **outbuf, size_t *outbuflen, + char **outs, size_t *outslen); + /** * free a rados-allocated buffer * diff --git a/src/librados/RadosClient.cc b/src/librados/RadosClient.cc index a2b54abf0583..3b5fabe3f829 100644 --- a/src/librados/RadosClient.cc +++ b/src/librados/RadosClient.cc @@ -583,6 +583,44 @@ int librados::RadosClient::mon_command(const vector& cmd, return rval; } +int librados::RadosClient::mon_command(int rank, const vector& cmd, + bufferlist &inbl, + bufferlist *outbl, string *outs) +{ + Mutex mylock("RadosClient::mon_command::mylock"); + Cond cond; + bool done; + int rval; + lock.Lock(); + monclient.start_mon_command(rank, cmd, inbl, outbl, outs, + new C_SafeCond(&mylock, &cond, &done, &rval)); + lock.Unlock(); + mylock.Lock(); + while (!done) + cond.Wait(mylock); + mylock.Unlock(); + return rval; +} + +int librados::RadosClient::mon_command(string name, const vector& cmd, + bufferlist &inbl, + bufferlist *outbl, string *outs) +{ + Mutex mylock("RadosClient::mon_command::mylock"); + Cond cond; + bool done; + int rval; + lock.Lock(); + monclient.start_mon_command(name, cmd, inbl, outbl, outs, + new C_SafeCond(&mylock, &cond, &done, &rval)); + lock.Unlock(); + mylock.Lock(); + while (!done) + cond.Wait(mylock); + mylock.Unlock(); + return rval; +} + int librados::RadosClient::osd_command(int osd, vector& cmd, bufferlist& inbl, bufferlist *poutbl, string *prs) diff --git a/src/librados/RadosClient.h b/src/librados/RadosClient.h index 9374553b0ad2..337beff57503 100644 --- a/src/librados/RadosClient.h +++ b/src/librados/RadosClient.h @@ -108,6 +108,12 @@ public: void watch_notify(MWatchNotify *m); int mon_command(const vector& cmd, bufferlist &inbl, bufferlist *outbl, string *outs); + int mon_command(int rank, + const vector& cmd, bufferlist &inbl, + bufferlist *outbl, string *outs); + int mon_command(string name, + const vector& cmd, bufferlist &inbl, + bufferlist *outbl, string *outs); int osd_command(int osd, vector& cmd, bufferlist& inbl, bufferlist *poutbl, string *prs); int pg_command(pg_t pgid, vector& cmd, bufferlist& inbl, diff --git a/src/librados/librados.cc b/src/librados/librados.cc index 1dda70828fd0..43c2584c3907 100644 --- a/src/librados/librados.cc +++ b/src/librados/librados.cc @@ -1857,6 +1857,45 @@ extern "C" int rados_mon_command(rados_t cluster, const char **cmd, return ret; } +extern "C" int rados_mon_command_target(rados_t cluster, const char *name, + const char **cmd, + size_t cmdlen, + const char *inbuf, size_t inbuflen, + char **outbuf, size_t *outbuflen, + char **outs, size_t *outslen) +{ + librados::RadosClient *client = (librados::RadosClient *)cluster; + bufferlist inbl; + bufferlist outbl; + string outstring; + vector cmdvec; + + // is this a numeric id? + char *endptr; + errno = 0; + long rank = strtol(name, &endptr, 10); + if ((errno == ERANGE && (rank == LONG_MAX || rank == LONG_MIN)) || + (errno != 0 && rank == 0) || + endptr == name || // no digits + *endptr != '\0') { // extra characters + rank = -1; + } + + for (size_t i = 0; i < cmdlen; i++) + cmdvec.push_back(cmd[i]); + + inbl.append(inbuf, inbuflen); + int ret; + if (rank >= 0) + ret = client->mon_command(rank, cmdvec, inbl, &outbl, &outstring); + else + ret = client->mon_command(name, cmdvec, inbl, &outbl, &outstring); + + do_out_buffer(outbl, outbuf, outbuflen); + do_out_buffer(outstring, outs, outslen); + return ret; +} + extern "C" int rados_osd_command(rados_t cluster, int osdid, const char **cmd, size_t cmdlen, const char *inbuf, size_t inbuflen, diff --git a/src/pybind/rados.py b/src/pybind/rados.py index 4a5ed961603b..c40004652727 100644 --- a/src/pybind/rados.py +++ b/src/pybind/rados.py @@ -518,9 +518,9 @@ Rados object in state %s." % (self.state)) raise make_ex(ret, "error opening ioctx '%s'" % ioctx_name) return Ioctx(ioctx_name, self.librados, ioctx) - def mon_command(self, cmd, inbuf, timeout=0): + def mon_command(self, cmd, inbuf, timeout=0, target=None): """ - mon_command(cmd, inbuf, outbuf, outbuflen, outs, outslen) + mon_command[_target](cmd, inbuf, outbuf, outbuflen, outs, outslen) returns (int ret, string outbuf, string outs) """ import sys @@ -531,11 +531,18 @@ Rados object in state %s." % (self.state)) outslen = c_long() cmdarr = (c_char_p * len(cmd))(*cmd) - ret = run_in_thread(self.librados.rados_mon_command, - (self.cluster, cmdarr, len(cmd), - c_char_p(inbuf), len(inbuf), - outbufp, byref(outbuflen), outsp, byref(outslen)), - timeout) + if target: + ret = run_in_thread(self.librados.rados_mon_command_target, + (self.cluster, target, cmdarr, len(cmd), + c_char_p(inbuf), len(inbuf), + outbufp, byref(outbuflen), outsp, byref(outslen)), + timeout) + else: + ret = run_in_thread(self.librados.rados_mon_command, + (self.cluster, cmdarr, len(cmd), + c_char_p(inbuf), len(inbuf), + outbufp, byref(outbuflen), outsp, byref(outslen)), + timeout) if ret == 0: # copy returned memory (ctypes makes a copy, not a reference)