--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include <vector>
+
+#include "msg/Message.h"
+
+class MMgrCommand : public Message {
+public:
+ uuid_d fsid;
+ std::vector<std::string> cmd;
+
+ MMgrCommand()
+ : Message{MSG_MGR_COMMAND} {}
+ MMgrCommand(const uuid_d &f)
+ : Message{MSG_MGR_COMMAND},
+ fsid(f) { }
+
+private:
+ ~MMgrCommand() override {}
+
+public:
+ std::string_view get_type_name() const override { return "mgr_command"; }
+ void print(std::ostream& o) const override {
+ o << "mgr_command(tid " << get_tid() << ": ";
+ for (unsigned i=0; i<cmd.size(); i++) {
+ if (i) o << ' ';
+ o << cmd[i];
+ }
+ o << ")";
+ }
+
+ void encode_payload(uint64_t features) override {
+ using ceph::encode;
+ encode(fsid, payload);
+ encode(cmd, payload);
+ }
+ void decode_payload() override {
+ using ceph::decode;
+ auto p = payload.cbegin();
+ decode(fsid, p);
+ decode(cmd, p);
+ }
+};
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#pragma once
+
+#include <string_view>
+
+#include "msg/Message.h"
+#include "MMgrCommand.h"
+
+class MMgrCommandReply : public Message {
+public:
+ errorcode32_t r;
+ std::string rs;
+
+ MMgrCommandReply()
+ : Message{MSG_MGR_COMMAND_REPLY} {}
+ MMgrCommandReply(MMgrCommand *m, int _r)
+ : Message{MSG_MGR_COMMAND_REPLY}, r(_r) {
+ header.tid = m->get_tid();
+ }
+ MMgrCommandReply(int _r, std::string_view s)
+ : Message{MSG_MGR_COMMAND_REPLY},
+ r(_r), rs(s) { }
+private:
+ ~MMgrCommandReply() override {}
+
+public:
+ std::string_view get_type_name() const override { return "mgr_command_reply"; }
+ void print(std::ostream& o) const override {
+ o << "mgr_command_reply(tid " << get_tid() << ": " << r << " " << rs << ")";
+ }
+
+ void encode_payload(uint64_t features) override {
+ using ceph::encode;
+ encode(r, payload);
+ encode(rs, payload);
+ }
+ void decode_payload() override {
+ using ceph::decode;
+ auto p = payload.cbegin();
+ decode(r, p);
+ decode(rs, p);
+ }
+};
#include "messages/MMonMgrReport.h"
#include "messages/MCommand.h"
#include "messages/MCommandReply.h"
+#include "messages/MMgrCommand.h"
+#include "messages/MMgrCommandReply.h"
#include "messages/MPGStats.h"
#include "messages/MOSDScrub.h"
#include "messages/MOSDScrub2.h"
return handle_close(ref_cast<MMgrClose>(m));
case MSG_COMMAND:
return handle_command(ref_cast<MCommand>(m));
+ case MSG_MGR_COMMAND:
+ return handle_command(ref_cast<MMgrCommand>(m));
default:
dout(1) << "Unhandled message type " << m->get_type() << dendl;
return false;
*/
class CommandContext {
public:
- ceph::ref_t<MCommand> m;
+ ceph::ref_t<MCommand> m_tell;
+ ceph::ref_t<MMgrCommand> m_mgr;
+ const std::vector<std::string>& cmd; ///< ref into m_tell or m_mgr
+ const bufferlist& data; ///< ref into m_tell or m_mgr
bufferlist odata;
cmdmap_t cmdmap;
explicit CommandContext(ceph::ref_t<MCommand> m)
- : m{std::move(m)} {
+ : m_tell{std::move(m)},
+ cmd(m_tell->cmd),
+ data(m_tell->get_data()) {
+ }
+ explicit CommandContext(ceph::ref_t<MMgrCommand> m)
+ : m_mgr{std::move(m)},
+ cmd(m_mgr->cmd),
+ data(m_mgr->get_data()) {
}
void reply(int r, const std::stringstream &ss) {
void reply(int r, const std::string &rs) {
// Let the connection drop as soon as we've sent our response
- ConnectionRef con = m->get_connection();
+ ConnectionRef con = m_tell ? m_tell->get_connection()
+ : m_mgr->get_connection();
if (con) {
con->mark_disposable();
}
derr << __func__ << " " << cpp_strerror(r) << " " << rs << dendl;
}
if (con) {
- MCommandReply *reply = new MCommandReply(r, rs);
- reply->set_tid(m->get_tid());
- reply->set_data(odata);
- con->send_message(reply);
+ if (m_tell) {
+ MCommandReply *reply = new MCommandReply(r, rs);
+ reply->set_tid(m_tell->get_tid());
+ reply->set_data(odata);
+ con->send_message(reply);
+ } else {
+ MMgrCommandReply *reply = new MMgrCommandReply(r, rs);
+ reply->set_tid(m_mgr->get_tid());
+ reply->set_data(odata);
+ con->send_message(reply);
+ }
}
}
};
std::lock_guard l(lock);
auto cmdctx = std::make_shared<CommandContext>(m);
try {
- return _handle_command(m, cmdctx);
+ return _handle_command(cmdctx);
+ } catch (const bad_cmd_get& e) {
+ cmdctx->reply(-EINVAL, e.what());
+ return true;
+ }
+}
+
+bool DaemonServer::handle_command(const ref_t<MMgrCommand>& m)
+{
+ std::lock_guard l(lock);
+ auto cmdctx = std::make_shared<CommandContext>(m);
+ try {
+ return _handle_command(cmdctx);
} catch (const bad_cmd_get& e) {
cmdctx->reply(-EINVAL, e.what());
return true;
}
bool DaemonServer::_handle_command(
- const ref_t<MCommand>& m,
std::shared_ptr<CommandContext>& cmdctx)
{
+ MessageRef m;
+ if (cmdctx->m_tell) {
+ m = cmdctx->m_tell;
+ } else {
+ m = cmdctx->m_mgr;
+ }
auto priv = m->get_connection()->get_priv();
auto session = static_cast<MgrSession*>(priv.get());
if (!session) {
return true;
}
- if (session->inst.name == entity_name_t())
+ if (session->inst.name == entity_name_t()) {
session->inst.name = m->get_source();
+ }
std::string format;
boost::scoped_ptr<Formatter> f;
std::stringstream ss;
int r = 0;
- if (!cmdmap_from_json(m->cmd, &(cmdctx->cmdmap), ss)) {
+ if (!cmdmap_from_json(cmdctx->cmd, &(cmdctx->cmdmap), ss)) {
cmdctx->reply(-EINVAL, ss);
return true;
}
dout(1) << " access denied" << dendl;
audit_clog->info() << "from='" << session->inst << "' "
<< "entity='" << session->entity_name << "' "
- << "cmd=" << m->cmd << ": access denied";
+ << "cmd=" << cmdctx->cmd << ": access denied";
ss << "access denied: does your client key have mgr caps? "
"See http://docs.ceph.com/docs/master/mgr/administrator/"
"#client-authentication";
audit_clog->debug()
<< "from='" << session->inst << "' "
<< "entity='" << session->entity_name << "' "
- << "cmd=" << m->cmd << ": dispatch";
+ << "cmd=" << cmdctx->cmd << ": dispatch";
// ----------------
// service map commands
}
std::stringstream ds;
- bufferlist inbl = cmdctx->m->get_data();
+ bufferlist inbl = cmdctx->data;
int r = py_modules.handle_command(handler_name, cmdctx->cmdmap, inbl, &ds, &ss);
cmdctx->odata.append(ds);
cmdctx->reply(r, ss);