From b00d4ca0854e1193425f7081fc801b499148b8a5 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 30 Jul 2019 11:30:15 -0500 Subject: [PATCH] mon/HealthMonitor: implement mute and unmount commands Signed-off-by: Sage Weil --- src/mon/HealthMonitor.cc | 144 ++++++++++++++++++++++++++++++++++++++- src/mon/HealthMonitor.h | 3 + src/mon/MonCommands.h | 4 ++ 3 files changed, 150 insertions(+), 1 deletion(-) diff --git a/src/mon/HealthMonitor.cc b/src/mon/HealthMonitor.cc index c10670f56de..53325ddf7e9 100644 --- a/src/mon/HealthMonitor.cc +++ b/src/mon/HealthMonitor.cc @@ -167,7 +167,25 @@ version_t HealthMonitor::get_trim_to() const bool HealthMonitor::preprocess_query(MonOpRequestRef op) { - return false; + PaxosServiceMessage *m = static_cast(op->get_req()); + switch (m->get_type()) { + case MSG_MON_COMMAND: + try { + return preprocess_command(op); + } catch (const bad_cmd_get& e) { + bufferlist bl; + mon->reply_command(op, -EINVAL, e.what(), bl, get_last_committed()); + return true; + } + + case MSG_MON_HEALTH_CHECKS: + return false; + + default: + mon->no_reply(op); + derr << "Unhandled message type " << m->get_type() << dendl; + return true; + } } bool HealthMonitor::prepare_update(MonOpRequestRef op) @@ -178,11 +196,135 @@ bool HealthMonitor::prepare_update(MonOpRequestRef op) switch (m->get_type()) { case MSG_MON_HEALTH_CHECKS: return prepare_health_checks(op); + case MSG_MON_COMMAND: + return prepare_command(op); default: return false; } } +bool HealthMonitor::preprocess_command(MonOpRequestRef op) +{ + MMonCommand *m = static_cast(op->get_req()); + std::stringstream ss; + bufferlist rdata; + + cmdmap_t cmdmap; + if (!cmdmap_from_json(m->cmd, &cmdmap, ss)) { + string rs = ss.str(); + mon->reply_command(op, -EINVAL, rs, rdata, get_last_committed()); + return true; + } + + MonSession *session = op->get_session(); + if (!session) { + mon->reply_command(op, -EACCES, "access denied", rdata, + get_last_committed()); + return true; + } + + string format; + cmd_getval(g_ceph_context, cmdmap, "format", format); + boost::scoped_ptr f(Formatter::create(format, "json-pretty", + "json-pretty")); + + string prefix; + cmd_getval(g_ceph_context, cmdmap, "prefix", prefix); + int r = 0; + +//} else { + return false; +//} + +reply: + string rs; + getline(ss, rs); + mon->reply_command(op, r, rs, rdata, get_last_committed()); + return true; +} + +bool HealthMonitor::prepare_command(MonOpRequestRef op) +{ + MMonCommand *m = static_cast(op->get_req()); + + std::stringstream ss; + bufferlist rdata; + + cmdmap_t cmdmap; + if (!cmdmap_from_json(m->cmd, &cmdmap, ss)) { + string rs = ss.str(); + mon->reply_command(op, -EINVAL, rs, rdata, get_last_committed()); + return true; + } + + MonSession *session = op->get_session(); + if (!session) { + mon->reply_command(op, -EACCES, "access denied", rdata, get_last_committed()); + return true; + } + + string format; + cmd_getval(g_ceph_context, cmdmap, "format", format, string("plain")); + boost::scoped_ptr f(Formatter::create(format)); + + string prefix; + cmd_getval(g_ceph_context, cmdmap, "prefix", prefix); + + int r = 0; + + if (prefix == "health mute") { + string code; + if (!cmd_getval(g_ceph_context, cmdmap, "code", code) || + code == "") { + r = -EINVAL; + ss << "must specify an alert code to mute"; + goto out; + } + string ttl_str; + utime_t ttl; + if (cmd_getval(g_ceph_context, cmdmap, "ttl", ttl_str)) { + auto secs = parse_timespan(ttl_str); + if (secs == 0s) { + r = -EINVAL; + ss << "not a valid duration: " << ttl_str; + goto out; + } + ttl = ceph_clock_now(); + ttl += std::chrono::duration(secs).count(); + } + auto& m = pending_mutes[code]; + m.code = code; + m.ttl = ttl; + } else if (prefix == "health unmute") { + string code; + if (cmd_getval(g_ceph_context, cmdmap, "code", code)) { + pending_mutes.erase(code); + } else { + pending_mutes.clear(); + } + } else { + ss << "Command '" << prefix << "' not implemented!"; + r = -ENOSYS; + } + +out: + dout(4) << __func__ << " done, r=" << r << dendl; + /* Compose response */ + string rs; + getline(ss, rs); + + if (r >= 0) { + // success.. delay reply + wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, r, rs, + get_last_committed() + 1)); + return true; + } else { + // reply immediately + mon->reply_command(op, r, rs, rdata, get_last_committed()); + return false; + } +} + bool HealthMonitor::prepare_health_checks(MonOpRequestRef op) { MMonHealthChecks *m = static_cast(op->get_req()); diff --git a/src/mon/HealthMonitor.h b/src/mon/HealthMonitor.h index e4b4ee484f2..113d261a187 100644 --- a/src/mon/HealthMonitor.h +++ b/src/mon/HealthMonitor.h @@ -39,6 +39,9 @@ public: bool preprocess_query(MonOpRequestRef op) override; bool prepare_update(MonOpRequestRef op) override; + bool preprocess_command(MonOpRequestRef op); + bool prepare_command(MonOpRequestRef op); + bool prepare_health_checks(MonOpRequestRef op); bool check_leader_health(); diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index f22f62e37e3..b51979ed87d 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -211,6 +211,10 @@ COMMAND_WITH_FLAG("injectargs " \ COMMAND("status", "show cluster status", "mon", "r") COMMAND("health name=detail,type=CephChoices,strings=detail,req=false", \ "show cluster health", "mon", "r") +COMMAND("health mute name=code,type=CephString name=ttl,type=CephString,req=false", + "mute health alert", "mon", "w") +COMMAND("health unmute name=code,type=CephString,req=false", + "unmute existing health alert mute(s)", "mon", "w") COMMAND("time-sync-status", "show time sync status", "mon", "r") COMMAND("df name=detail,type=CephChoices,strings=detail,req=false", \ "show cluster free space stats", "mon", "r") -- 2.39.5