From 85736b784a56f09b172eb5f999555519294b70a4 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Fri, 6 Sep 2019 09:42:28 -0500 Subject: [PATCH] librados: add rados_mgr_command_target This variant lets you specify which mgr to talk to. Signed-off-by: Sage Weil --- src/include/rados/librados.h | 32 ++++++++++++++++++++++++++++++ src/librados/RadosClient.cc | 24 +++++++++++++++++++++++ src/librados/RadosClient.h | 4 ++++ src/librados/librados_c.cc | 34 ++++++++++++++++++++++++++++++++ src/pybind/rados/rados.pyx | 32 +++++++++++++++++++++++------- src/tracing/librados.tp | 38 ++++++++++++++++++++++++++++++++++++ 6 files changed, 157 insertions(+), 7 deletions(-) diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h index 11d5d991d10..d8dc69ca8d2 100644 --- a/src/include/rados/librados.h +++ b/src/include/rados/librados.h @@ -3808,6 +3808,38 @@ CEPH_RADOS_API int rados_mgr_command(rados_t cluster, const char **cmd, size_t *outbuflen, char **outs, size_t *outslen); +/** + * Send ceph-mgr tell command. + * + * @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 mgr name to target + * @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 inbuflen input buffer length + * @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 + */ +CEPH_RADOS_API int rados_mgr_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); + /** * Send monitor command to a specific monitor. * diff --git a/src/librados/RadosClient.cc b/src/librados/RadosClient.cc index f1184abf6ec..2a441a9f1a1 100644 --- a/src/librados/RadosClient.cc +++ b/src/librados/RadosClient.cc @@ -868,6 +868,30 @@ int librados::RadosClient::mgr_command(const vector& cmd, return r; } +int librados::RadosClient::mgr_command( + const string& name, + const vector& cmd, + const bufferlist &inbl, + bufferlist *outbl, string *outs) +{ + std::lock_guard l(lock); + + C_SaferCond cond; + int r = mgrclient.start_tell_command(name, cmd, inbl, outbl, outs, &cond); + if (r < 0) + return r; + + lock.unlock(); + if (conf->rados_mon_op_timeout) { + r = cond.wait_for(conf->rados_mon_op_timeout); + } else { + r = cond.wait(); + } + lock.lock(); + + return r; +} + int librados::RadosClient::mon_command(int rank, const vector& cmd, const bufferlist &inbl, diff --git a/src/librados/RadosClient.h b/src/librados/RadosClient.h index 4d5dfa27542..0f2b153def4 100644 --- a/src/librados/RadosClient.h +++ b/src/librados/RadosClient.h @@ -150,6 +150,10 @@ public: bufferlist *outbl, string *outs); int mgr_command(const vector& cmd, const bufferlist &inbl, bufferlist *outbl, string *outs); + int mgr_command( + const string& name, + const vector& cmd, const bufferlist &inbl, + bufferlist *outbl, string *outs); int osd_command(int osd, vector& cmd, const bufferlist& inbl, bufferlist *poutbl, string *prs); int pg_command(pg_t pgid, vector& cmd, const bufferlist& inbl, diff --git a/src/librados/librados_c.cc b/src/librados/librados_c.cc index 9ace39da43f..5369aef6af1 100644 --- a/src/librados/librados_c.cc +++ b/src/librados/librados_c.cc @@ -884,6 +884,40 @@ extern "C" int _rados_mgr_command(rados_t cluster, const char **cmd, } LIBRADOS_C_API_BASE_DEFAULT(rados_mgr_command); +extern "C" int _rados_mgr_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) +{ + tracepoint(librados, rados_mgr_command_target_enter, cluster, name, cmdlen, + inbuf, inbuflen); + + librados::RadosClient *client = (librados::RadosClient *)cluster; + bufferlist inbl; + bufferlist outbl; + string outstring; + vector cmdvec; + + for (size_t i = 0; i < cmdlen; i++) { + tracepoint(librados, rados_mgr_command_target_cmd, cmd[i]); + cmdvec.push_back(cmd[i]); + } + + inbl.append(inbuf, inbuflen); + int ret = client->mgr_command(name, cmdvec, inbl, &outbl, &outstring); + + do_out_buffer(outbl, outbuf, outbuflen); + do_out_buffer(outstring, outs, outslen); + tracepoint(librados, rados_mgr_command_target_exit, ret, outbuf, outbuflen, + outs, outslen); + return ret; +} +LIBRADOS_C_API_BASE_DEFAULT(rados_mgr_command_target); + extern "C" int _rados_pg_command(rados_t cluster, const char *pgstr, const char **cmd, size_t cmdlen, const char *inbuf, size_t inbuflen, diff --git a/src/pybind/rados/rados.pyx b/src/pybind/rados/rados.pyx index 9123a11691e..6f4828b0be9 100644 --- a/src/pybind/rados/rados.pyx +++ b/src/pybind/rados/rados.pyx @@ -176,6 +176,12 @@ cdef extern from "rados/librados.h" nogil: const char *inbuf, size_t inbuflen, char **outbuf, size_t *outbuflen, char **outs, size_t *outslen) + int rados_mgr_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) 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, @@ -1403,7 +1409,7 @@ Rados object in state %s." % self.state) finally: free(_cmd) - def mgr_command(self, cmd, inbuf, timeout=0): + def mgr_command(self, cmd, inbuf, timeout=0, target=None): """ :return: (int ret, string outbuf, string outs) """ @@ -1413,8 +1419,11 @@ Rados object in state %s." % self.state) cmd = cstr_list(cmd, 'cmd') inbuf = cstr(inbuf, 'inbuf') + target = cstr(target, 'target', opt=True) cdef: + char *_target = opt_str(target) + char **_cmd = to_bytes_array(cmd) size_t _cmdlen = len(cmd) @@ -1427,12 +1436,21 @@ Rados object in state %s." % self.state) size_t _outs_len try: - with nogil: - ret = rados_mgr_command(self.cluster, - _cmd, _cmdlen, - _inbuf, _inbuf_len, - &_outbuf, &_outbuf_len, - &_outs, &_outs_len) + if target is not None: + with nogil: + ret = rados_mgr_command_target(self.cluster, + _target, + _cmd, _cmdlen, + _inbuf, _inbuf_len, + &_outbuf, &_outbuf_len, + &_outs, &_outs_len) + else: + with nogil: + ret = rados_mgr_command(self.cluster, + _cmd, _cmdlen, + _inbuf, _inbuf_len, + &_outbuf, &_outbuf_len, + &_outs, &_outs_len) my_outs = decode_cstr(_outs[:_outs_len]) my_outbuf = _outbuf[:_outbuf_len] diff --git a/src/tracing/librados.tp b/src/tracing/librados.tp index 4b2c55e06f7..dfbd98b6b8a 100644 --- a/src/tracing/librados.tp +++ b/src/tracing/librados.tp @@ -578,6 +578,44 @@ TRACEPOINT_EVENT(librados, rados_mgr_command_exit, ) ) +TRACEPOINT_EVENT(librados, rados_mgr_command_target_enter, + TP_ARGS( + rados_t, cluster, + const char *, name, + size_t, cmdlen, + const char*, inbuf, + size_t, inbuflen), + TP_FIELDS( + ctf_integer_hex(rados_t, cluster, cluster) + ctf_string(name, name) + ctf_integer(size_t, cmdlen, cmdlen) + ceph_ctf_sequence(unsigned char, inbuf, inbuf, size_t, inbuflen) + ) +) + +TRACEPOINT_EVENT(librados, rados_mgr_command_target_cmd, + TP_ARGS( + const char*, cmd), + TP_FIELDS( + ctf_string(cmd, cmd) + ) +) + +TRACEPOINT_EVENT(librados, rados_mgr_command_target_exit, + TP_ARGS( + int, retval, + char**, outbuf, + size_t*, outbuflen, + char**, outs, + size_t*, outslen), + TP_FIELDS( + ctf_integer(int, retval, retval) + ceph_ctf_stringp(outs, outs) + ceph_ctf_sequencep(unsigned char, outbuf, outbuf, size_t, outbuflen) + ceph_ctf_integerp(size_t, outslen, outslen) + ) +) + TRACEPOINT_EVENT(librados, rados_pg_command_enter, TP_ARGS( rados_t, cluster, -- 2.39.5