c = "foo";
break;
}
+ //wrap command with new protocol
+ c = "{\"prefix\": \"" + c + "\"}";
break;
}
} else {
}
}
- 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<string> cmdvec;
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" &&
std::unique_lock l(lock);
decltype(hooks)::iterator p;
- string match = c;
while (match.size()) {
p = hooks.find(match);
if (p != hooks.cend())
}
}
- 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