}
+// Prefix for mon store of active mgr's command descriptions
+const static std::string command_descs_prefix = "mgr_command_descs";
+
+
void MgrMonitor::create_initial()
{
boost::tokenizer<> tok(g_conf->mgr_initial_modules);
int err = get_version(version, bl);
assert(err == 0);
+ bool old_available = map.get_available();
+ uint64_t old_gid = map.get_active_gid();
+
bufferlist::iterator p = bl.begin();
map.decode(p);
}
check_subs();
+
+ if (map.get_available()
+ && (!old_available || old_gid != map.get_active_gid()))
+ {
+ dout(4) << "daemon transitioned to available, loading commands" << dendl;
+ bufferlist loaded_commands;
+ int r = mon->store->get(command_descs_prefix, "", loaded_commands);
+ if (r < 0) {
+ derr << "Failed to load mgr commands: " << cpp_strerror(r) << dendl;
+ } else {
+ auto p = loaded_commands.begin();
+ ::decode(command_descs, p);
+ }
+ }
}
// feed our pet MgrClient
put_value(t, "ever_had_active_mgr", 1);
}
encode_health(next, t);
+
+ if (pending_command_descs.size()) {
+ dout(4) << __func__ << " encoding " << pending_command_descs.size()
+ << " command_descs" << dendl;
+ bufferlist bl;
+ ::encode(pending_command_descs, bl);
+ t->put(command_descs_prefix, "", bl);
+ pending_command_descs.clear();
+ }
}
bool MgrMonitor::check_caps(MonOpRequestRef op, const uuid_d& fsid)
dout(4) << "available " << m->get_gid() << dendl;
mon->clog->info() << "Manager daemon " << pending_map.active_name
<< " is now available";
+
+ // This beacon should include command descriptions
+ pending_command_descs = m->get_command_descs();
+ if (pending_command_descs.empty()) {
+ // This should not happen, but it also isn't fatal: we just
+ // won't successfully update our list of commands.
+ dout(4) << "First available beacon from " << pending_map.active_name
+ << "(" << m->get_gid() << ") does not include command descs"
+ << dendl;
+ } else {
+ dout(4) << "First available beacon from " << pending_map.active_name
+ << "(" << m->get_gid() << ") includes "
+ << pending_command_descs.size() << " command descs" << dendl;
+ }
+
pending_map.available = m->get_available();
updated = true;
}
#include "include/Context.h"
#include "MgrMap.h"
#include "PaxosService.h"
+#include "MonCommand.h"
class MgrMonitor: public PaxosService
{
health_status_t should_warn_about_mgr_down();
+ // Command descriptions we've learned from the active mgr
+ std::vector<MonCommand> command_descs;
+ std::vector<MonCommand> pending_command_descs;
+
public:
MgrMonitor(Monitor *mn, Paxos *p, const string& service_name)
: PaxosService(mn, p, service_name)
void print_summary(Formatter *f, std::ostream *ss) const;
+ const std::vector<MonCommand> &get_command_descs() const {
+ return command_descs;
+ }
+
friend class C_Updated;
};
#include <mon/MonCommands.h>
#undef COMMAND
#undef COMMAND_WITH_FLAG
-
- // FIXME: slurp up the Mgr commands too
-
-#define COMMAND(parsesig, helptext, modulename, req_perms, avail) \
- {parsesig, helptext, modulename, req_perms, avail, FLAG(MGR)},
-#define COMMAND_WITH_FLAG(parsesig, helptext, modulename, req_perms, avail, flags) \
- {parsesig, helptext, modulename, req_perms, avail, flags | FLAG(MGR)},
-#include <mgr/MgrCommands.h>
-#undef COMMAND
-#undef COMMAND_WITH_FLAG
-
};
return capable;
}
-void Monitor::format_command_descriptions(const MonCommand *commands,
- unsigned commands_size,
+void Monitor::format_command_descriptions(const std::vector<MonCommand> &commands,
Formatter *f,
bufferlist *rdata,
bool hide_mgr_flag)
{
int cmdnum = 0;
f->open_object_section("command_descriptions");
- for (const MonCommand *cp = commands;
- cp < &commands[commands_size]; cp++) {
-
- unsigned flags = cp->flags;
+ for (const auto &cmd : commands) {
+ unsigned flags = cmd.flags;
if (hide_mgr_flag) {
flags &= ~MonCommand::FLAG_MGR;
}
ostringstream secname;
secname << "cmd" << setfill('0') << std::setw(3) << cmdnum;
dump_cmddesc_to_json(f, secname.str(),
- cp->cmdstring, cp->helpstring, cp->module,
- cp->req_perms, cp->availability, flags);
+ cmd.cmdstring, cmd.helpstring, cmd.module,
+ cmd.req_perms, cmd.availability, flags);
cmdnum++;
}
f->close_section(); // command_descriptions
// hide mgr commands until luminous upgrade is complete
bool hide_mgr_flag =
osdmon()->osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS;
- format_command_descriptions(leader_supported_mon_commands,
- leader_supported_mon_commands_size, f, &rdata,
- hide_mgr_flag);
+
+ std::vector<MonCommand> commands;
+ commands = static_cast<MgrMonitor*>(
+ paxos_service[PAXOS_MGR])->get_command_descs();
+
+ for (int i = 0 ; i < leader_supported_mon_commands_size; ++i) {
+ commands.push_back(leader_supported_mon_commands[i]);
+ }
+
+ format_command_descriptions(commands, f, &rdata, hide_mgr_flag);
delete f;
reply_command(op, 0, "", rdata, 0);
return;
#include "Paxos.h"
#include "Session.h"
#include "PGStatService.h"
+#include "MonCommand.h"
#include "common/LogClient.h"
#include "auth/cephx/CephxKeyServer.h"
struct MForward;
struct MTimeCheck;
struct MMonHealth;
-struct MonCommand;
#define COMPAT_SET_LOC "feature_set"
Monitor& operator=(const Monitor &rhs);
public:
- static void format_command_descriptions(const MonCommand *commands,
- unsigned commands_size,
+ static void format_command_descriptions(const std::vector<MonCommand> &commands,
Formatter *f,
bufferlist *rdata,
bool hide_mgr_flag=false);
#define CEPH_MON_FEATURE_INCOMPAT_KRAKEN CompatSet::Feature(8, "support monmap features")
// make sure you add your feature to Monitor::get_supported_features
-struct MonCommand {
- string cmdstring;
- string helpstring;
- string module;
- string req_perms;
- string availability;
- uint64_t flags;
-
- // MonCommand flags
- static const uint64_t FLAG_NONE = 0;
- static const uint64_t FLAG_NOFORWARD = 1 << 0;
- static const uint64_t FLAG_OBSOLETE = 1 << 1;
- static const uint64_t FLAG_DEPRECATED = 1 << 2;
- static const uint64_t FLAG_MGR = 1 << 3;
-
- bool has_flag(uint64_t flag) const { return (flags & flag) != 0; }
- void set_flag(uint64_t flag) { flags |= flag; }
- void unset_flag(uint64_t flag) { flags &= ~flag; }
-
- void encode(bufferlist &bl) const {
- /*
- * very naughty: deliberately unversioned because individual commands
- * shouldn't be encoded standalone, only as a full set (which we do
- * version, see encode_array() below).
- */
- ::encode(cmdstring, bl);
- ::encode(helpstring, bl);
- ::encode(module, bl);
- ::encode(req_perms, bl);
- ::encode(availability, bl);
- }
- void decode(bufferlist::iterator &bl) {
- ::decode(cmdstring, bl);
- ::decode(helpstring, bl);
- ::decode(module, bl);
- ::decode(req_perms, bl);
- ::decode(availability, bl);
- }
- bool is_compat(const MonCommand* o) const {
- return cmdstring == o->cmdstring &&
- module == o->module && req_perms == o->req_perms &&
- availability == o->availability;
- }
-
- bool is_noforward() const {
- return has_flag(MonCommand::FLAG_NOFORWARD);
- }
-
- bool is_obsolete() const {
- return has_flag(MonCommand::FLAG_OBSOLETE);
- }
-
- bool is_deprecated() const {
- return has_flag(MonCommand::FLAG_DEPRECATED);
- }
- bool is_mgr() const {
- return has_flag(MonCommand::FLAG_MGR);
- }
-
- static void encode_array(const MonCommand *cmds, int size, bufferlist &bl) {
- ENCODE_START(2, 1, bl);
- uint16_t s = size;
- ::encode(s, bl);
- ::encode_array_nohead(cmds, size, bl);
- for (int i = 0; i < size; i++)
- ::encode(cmds[i].flags, bl);
- ENCODE_FINISH(bl);
- }
- static void decode_array(MonCommand **cmds, int *size,
- bufferlist::iterator &bl) {
- DECODE_START(2, bl);
- uint16_t s = 0;
- ::decode(s, bl);
- *size = s;
- *cmds = new MonCommand[*size];
- ::decode_array_nohead(*cmds, *size, bl);
- if (struct_v >= 2) {
- for (int i = 0; i < *size; i++)
- ::decode((*cmds)[i].flags, bl);
- } else {
- for (int i = 0; i < *size; i++)
- (*cmds)[i].flags = 0;
- }
- DECODE_FINISH(bl);
- }
-
- bool requires_perm(char p) const {
- return (req_perms.find(p) != string::npos);
- }
-};
-WRITE_CLASS_ENCODER(MonCommand)
#endif
out << " get_command_descriptions --pull585\n";
}
-static void json_print(const MonCommand *mon_commands, int size)
+static void json_print(const std::vector<MonCommand> &mon_commands)
{
bufferlist rdata;
Formatter *f = Formatter::create("json");
- Monitor::format_command_descriptions(mon_commands, size, f, &rdata);
+ Monitor::format_command_descriptions(mon_commands, f, &rdata);
delete f;
string data(rdata.c_str(), rdata.length());
cout << data << std::endl;
#undef FLAG
#undef COMMAND
#undef COMMAND_WITH_FLAG
- MonCommand mon_commands[] = {
+ std::vector<MonCommand> mon_commands = {
#define FLAG(f) (MonCommand::FLAG_##f)
#define COMMAND(parsesig, helptext, modulename, req_perms, avail) \
{parsesig, helptext, modulename, req_perms, avail, 0},
#undef COMMAND
#undef COMMAND_WITH_FLAG
- // FIXME: slurp up the Mgr commands too
-
#define COMMAND(parsesig, helptext, modulename, req_perms, avail) \
{parsesig, helptext, modulename, req_perms, avail, FLAG(MGR)},
#define COMMAND_WITH_FLAG(parsesig, helptext, modulename, req_perms, avail, flags) \
#undef COMMAND_WITH_FLAG
};
- json_print(mon_commands, ARRAY_SIZE(mon_commands));
+ json_print(mon_commands);
}
// syntax error https://github.com/ceph/ceph/pull/585
static void pull585()
{
- MonCommand mon_commands[] = {
+ std::vector<MonCommand> mon_commands = {
{ "osd pool create "
"name=pool,type=CephPoolname "
"name=pg_num,type=CephInt,range=0 "
"create pool", "osd", "rw", "cli,rest" }
};
- json_print(mon_commands, ARRAY_SIZE(mon_commands));
+ json_print(mon_commands);
}
int main(int argc, char **argv) {