From: Adam Kupczyk Date: Tue, 30 Jul 2019 11:54:58 +0000 (+0200) Subject: common/admin_socket: Add 'execute_command' that allows for self-reflection. X-Git-Tag: v15.1.0~1945^2~4 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=838320a9b22c1749f609433843542690fccdfaee;p=ceph-ci.git common/admin_socket: Add 'execute_command' that allows for self-reflection. Signed-off-by: Adam Kupczyk --- diff --git a/src/common/admin_socket.cc b/src/common/admin_socket.cc index 1fc79d3e034..57b31b4a5b2 100644 --- a/src/common/admin_socket.cc +++ b/src/common/admin_socket.cc @@ -336,23 +336,42 @@ bool AdminSocket::do_accept() } } - bool rval = false; + bool rval; + bufferlist out; + rval = execute_command(c, out); + if (rval) { + uint32_t len = htonl(out.length()); + int ret = safe_write(connection_fd, &len, sizeof(len)); + if (ret < 0) { + lderr(m_cct) << "AdminSocket: error writing response length " + << cpp_strerror(ret) << dendl; + rval = false; + } else { + if (out.write_fd(connection_fd) >= 0) + rval = true; + } + } + retry_sys_call(::close, connection_fd); + return rval; +} + +int AdminSocket::execute_command(const std::string& cmd, ceph::bufferlist& out) +{ cmdmap_t cmdmap; string format; vector cmdvec; stringstream errss; - cmdvec.push_back(c); + cmdvec.push_back(cmd); if (!cmdmap_from_json(cmdvec, &cmdmap, errss)) { ldout(m_cct, 0) << "AdminSocket: " << errss.str() << dendl; - retry_sys_call(::close, connection_fd); return false; } + string match; try { cmd_getval(m_cct, cmdmap, "format", format); - cmd_getval(m_cct, cmdmap, "prefix", c); + cmd_getval(m_cct, cmdmap, "prefix", match); } catch (const bad_cmd_get& e) { - retry_sys_call(::close, connection_fd); return false; } if (format != "json" && format != "json-pretty" && @@ -361,7 +380,6 @@ bool AdminSocket::do_accept() std::unique_lock l(lock); decltype(hooks)::iterator p; - string match = c; while (match.size()) { p = hooks.find(match); if (p != hooks.cend()) @@ -377,53 +395,41 @@ bool AdminSocket::do_accept() } } - bufferlist out; if (p == hooks.cend()) { - lderr(m_cct) << "AdminSocket: request '" << c << "' not defined" << dendl; - } else { - string args; - if (match != c) { - args = c.substr(match.length() + 1); - } - - // Drop lock to avoid cycles in cases where the hook takes - // the same lock that was held during calls to register/unregister, - // and set in_hook to allow unregister to wait for us before - // removing this hook. - in_hook = true; - auto match_hook = p->second.hook; - l.unlock(); - bool success = (validate(match, cmdmap, out) && - match_hook->call(match, cmdmap, format, out)); - l.lock(); - in_hook = false; - in_hook_cond.notify_all(); - - if (!success) { - ldout(m_cct, 0) << "AdminSocket: request '" << match << "' args '" << args - << "' to " << match_hook << " failed" << dendl; - out.append("failed"); - } else { - ldout(m_cct, 5) << "AdminSocket: request '" << match << "' '" << args - << "' to " << match_hook - << " returned " << out.length() << " bytes" << dendl; - } - uint32_t len = htonl(out.length()); - int ret = safe_write(connection_fd, &len, sizeof(len)); - if (ret < 0) { - lderr(m_cct) << "AdminSocket: error writing response length " - << cpp_strerror(ret) << dendl; - } else { - if (out.write_fd(connection_fd) >= 0) - rval = true; - } + lderr(m_cct) << "AdminSocket: request '" << cmd << "' not defined" << dendl; + return false; + } + string args; + if (match != cmd) { + args = cmd.substr(match.length() + 1); } - l.unlock(); - retry_sys_call(::close, connection_fd); - return rval; + // Drop lock to avoid cycles in cases where the hook takes + // the same lock that was held during calls to register/unregister, + // and set in_hook to allow unregister to wait for us before + // removing this hook. + in_hook = true; + auto match_hook = p->second.hook; + l.unlock(); + bool success = (validate(match, cmdmap, out) && + match_hook->call(match, cmdmap, format, out)); + l.lock(); + in_hook = false; + in_hook_cond.notify_all(); + if (!success) { + ldout(m_cct, 0) << "AdminSocket: request '" << match << "' args '" << args + << "' to " << match_hook << " failed" << dendl; + out.append("failed"); + } else { + ldout(m_cct, 5) << "AdminSocket: request '" << match << "' '" << args + << "' to " << match_hook + << " returned " << out.length() << " bytes" << dendl; + } + return true; } + + bool AdminSocket::validate(const std::string& command, const cmdmap_t& cmdmap, bufferlist& out) const diff --git a/src/common/admin_socket.h b/src/common/admin_socket.h index d6361adcfc7..688db292739 100644 --- a/src/common/admin_socket.h +++ b/src/common/admin_socket.h @@ -94,6 +94,7 @@ public: void chown(uid_t uid, gid_t gid); void chmod(mode_t mode); + int execute_command(const std::string& cmd, ceph::bufferlist& out); private: