#include "messages/MGetConfig.h"
#include "messages/MMonCommand.h"
#include "common/Formatter.h"
+#include "common/TextTable.h"
+#include "include/stringify.h"
#define dout_subsys ceph_subsys_mon
#undef dout_prefix
bool ConfigMonitor::preprocess_query(MonOpRequestRef op)
{
+ switch (op->get_req()->get_type()) {
+ case MSG_MON_COMMAND:
+ return preprocess_command(op);
+ }
return false;
}
+bool ConfigMonitor::preprocess_command(MonOpRequestRef op)
+{
+ MMonCommand *m = static_cast<MMonCommand*>(op->get_req());
+ stringstream ss;
+ int err = 0;
+
+ map<string, cmd_vartype> cmdmap;
+ if (!cmdmap_from_json(m->cmd, &cmdmap, ss)) {
+ string rs = ss.str();
+ mon->reply_command(op, -EINVAL, rs, get_last_committed());
+ return true;
+ }
+ string format;
+ cmd_getval(g_ceph_context, cmdmap, "format", format, string("plain"));
+ boost::scoped_ptr<Formatter> f(Formatter::create(format));
+
+ string prefix;
+ cmd_getval(g_ceph_context, cmdmap, "prefix", prefix);
+
+ bufferlist odata;
+ if (prefix == "config dump") {
+ list<pair<string,Section*>> sections = {
+ make_pair("global", &config_map.global)
+ };
+ for (auto& i : config_map.by_type) {
+ sections.push_back(make_pair(i.first, &i.second));
+ auto j = config_map.by_id.lower_bound(i.first);
+ while (j != config_map.by_id.end() &&
+ j->first.find(i.first) == 0) {
+ sections.push_back(make_pair(j->first, &j->second));
+ ++j;
+ }
+ }
+ TextTable tbl;
+ if (!f) {
+ tbl.define_column("WHO", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("MASK", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("OPTION", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("VALUE", TextTable::LEFT, TextTable::LEFT);
+ } else {
+ f->open_array_section("config");
+ }
+ for (auto s : sections) {
+ for (auto i : s.second->options) {
+ if (!f) {
+ tbl << s.first;
+ tbl << i.second.mask.to_str();
+ tbl << i.first;
+ tbl << i.second.raw_value;
+ tbl << TextTable::endrow;
+ } else {
+ f->open_object_section("option");
+ f->dump_string("section", s.first);
+ i.second.dump(f.get());
+ f->close_section();
+ }
+ }
+ }
+ if (!f) {
+ odata.append(stringify(tbl));
+ } else {
+ f->close_section();
+ f->flush(odata);
+ }
+ } else if (prefix == "config get") {
+ string who, name;
+ cmd_getval(g_ceph_context, cmdmap, "who", who);
+ cmd_getval(g_ceph_context, cmdmap, "key", name);
+
+ EntityName entity;
+ if (!entity.from_str(who)) {
+ ss << "unrecognized entity '" << who << "'";
+ err = -EINVAL;
+ goto reply;
+ }
+
+ map<string,string> crush_location;
+ string device_class;
+ if (entity.is_osd()) {
+ mon->osdmon()->osdmap.crush->get_full_location(who, &crush_location);
+ int id = atoi(entity.get_id().c_str());
+ const char *c = mon->osdmon()->osdmap.crush->get_item_class(id);
+ if (c) {
+ device_class = c;
+ }
+ dout(10) << __func__ << " crush_location " << crush_location
+ << " class " << device_class << dendl;
+ }
+
+ std::map<std::string,std::string> config;
+ std::map<std::string,pair<std::string,OptionMask>> src;
+ config_map.generate_entity_map(
+ entity,
+ crush_location,
+ mon->osdmon()->osdmap.crush.get(),
+ device_class,
+ &config, &src);
+
+ TextTable tbl;
+ if (!f) {
+ tbl.define_column("WHO", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("MASK", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("OPTION", TextTable::LEFT, TextTable::LEFT);
+ tbl.define_column("VALUE", TextTable::LEFT, TextTable::LEFT);
+ } else {
+ f->open_object_section("config");
+ }
+ auto p = config.begin();
+ auto q = src.begin();
+ for (; p != config.end(); ++p, ++q) {
+ if (name.size() && p->first != name) {
+ continue;
+ }
+ if (!f) {
+ tbl << q->second.first;
+ tbl << q->second.second.to_str();
+ tbl << p->first;
+ tbl << p->second;
+ tbl << TextTable::endrow;
+ } else {
+ f->open_object_section(p->first.c_str());
+ f->dump_string("value", p->second);
+ f->dump_string("section", q->second.first);
+ f->dump_object("mask", q->second.second);
+ f->close_section();
+ }
+ }
+ if (!f) {
+ odata.append(stringify(tbl));
+ } else {
+ f->close_section();
+ f->flush(odata);
+ }
+ } else {
+ return false;
+ }
+
+ reply:
+ mon->reply_command(op, err, ss.str(), odata, get_last_committed());
+ return true;
+}
+
void ConfigMonitor::handle_get_config(MonOpRequestRef op)
{
MGetConfig *m = static_cast<MGetConfig*>(op->get_req());
string prefix;
cmd_getval(g_ceph_context, cmdmap, "prefix", prefix);
- if (prefix == "config set") {
+ if (prefix == "config set" ||
+ prefix == "config rm") {
string who;
string name, value;
cmd_getval(g_ceph_context, cmdmap, "who", who);
key += mask_str + "/";
}
key += name;
- bufferlist bl;
- bl.append(value);
MonitorDBStore::TransactionRef t = paxos->get_pending_transaction();
- t->put(CONFIG_PREFIX, key, bl);
+ if (prefix == "config set") {
+ bufferlist bl;
+ bl.append(value);
+ t->put(CONFIG_PREFIX, key, bl);
+ } else {
+ t->erase(CONFIG_PREFIX, key);
+ }
goto update;
} else {
ss << "unknown command " << prefix;
name = key.substr(last_slash + 1);
who = key.substr(0, last_slash);
}
- string section_name;
Option fake_opt(name, Option::TYPE_STR, Option::LEVEL_DEV);
const Option *opt = g_conf->find_option(name);
<< value << "' for " << name << dendl;
}
+ string section_name;
MaskedOption mopt(*opt);
mopt.raw_value = value;
-
- if (ConfigMap::parse_mask(who, §ion_name, &mopt.mask)) {
+ if (who.size() &&
+ !ConfigMap::parse_mask(who, §ion_name, &mopt.mask)) {
+ derr << __func__ << " ignoring key " << key << dendl;
+ } else {
Section *section = &config_map.global;;
if (section_name.size()) {
if (section_name.find('.') != std::string::npos) {
}
section->options.insert(make_pair(name, mopt));
++num;
- } else {
- derr << __func__ << " ignoring key " << key << dendl;
}
it->next();
}
"name=injected_args,type=CephString,n=N", \
"inject config arguments into monitor", "mon", "rw", "cli,rest",
FLAG(NOFORWARD))
-COMMAND("config set " \
- "name=key,type=CephString name=value,type=CephString",
- "Set a configuration option at runtime (not persistent)",
- "mon", "rw", "cli,rest")
+
COMMAND("status", "show cluster status", "mon", "r", "cli,rest")
COMMAND("health name=detail,type=CephChoices,strings=detail,req=false", \
"show cluster health", "mon", "r", "cli,rest")
" name=who,type=CephString" \
" name=name,type=CephString" \
" name=value,type=CephString", \
- "set a config option",
+ "Set a configuration option for one or more entities",
+ "config", "rw", "cli,rest")
+COMMAND("config rm" \
+ " name=who,type=CephString" \
+ " name=name,type=CephString",
+ "Clear a configuration option for one or more entities",
"config", "rw", "cli,rest")
+COMMAND("config get " \
+ "name=who,type=CephString " \
+ "name=key,type=CephString,req=False",
+ "Show configuration option(s) for an entity",
+ "config", "r", "cli,rest")
+COMMAND("config dump",
+ "Show all configuration option(s)",
+ "mon", "r", "cli,rest")