X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fceph%2Fsrc%2Fmon%2FMgrMonitor.cc;fp=src%2Fceph%2Fsrc%2Fmon%2FMgrMonitor.cc;h=0000000000000000000000000000000000000000;hb=7da45d65be36d36b880cc55c5036e96c24b53f00;hp=a307dd4df5ce1cadd0128d01ba942e0723e0dbf7;hpb=691462d09d0987b47e112d6ee8740375df3c51b2;p=stor4nfv.git diff --git a/src/ceph/src/mon/MgrMonitor.cc b/src/ceph/src/mon/MgrMonitor.cc deleted file mode 100644 index a307dd4..0000000 --- a/src/ceph/src/mon/MgrMonitor.cc +++ /dev/null @@ -1,1023 +0,0 @@ -// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- -// vim: ts=8 sw=2 smarttab -/* - * Ceph - scalable distributed file system - * - * Copyright (C) 2016 John Spray - * - * This is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License version 2.1, as published by the Free Software - * Foundation. See file COPYING. - */ - -#include - -#include "messages/MMgrBeacon.h" -#include "messages/MMgrMap.h" -#include "messages/MMgrDigest.h" - -#include "PGStatService.h" -#include "include/stringify.h" -#include "mgr/MgrContext.h" -#include "mgr/mgr_commands.h" -#include "OSDMonitor.h" - -#include "MgrMonitor.h" - -#define MGR_METADATA_PREFIX "mgr_metadata" - -#define dout_subsys ceph_subsys_mon -#undef dout_prefix -#define dout_prefix _prefix(_dout, mon, map) -static ostream& _prefix(std::ostream *_dout, Monitor *mon, - const MgrMap& mgrmap) { - return *_dout << "mon." << mon->name << "@" << mon->rank - << "(" << mon->get_state_name() - << ").mgr e" << mgrmap.get_epoch() << " "; -} - -// Prefix for mon store of active mgr's command descriptions -const static std::string command_descs_prefix = "mgr_command_descs"; - - -void MgrMonitor::create_initial() -{ - // Take a local copy of initial_modules for tokenizer to iterate over. - auto initial_modules = g_conf->get_val("mgr_initial_modules"); - boost::tokenizer<> tok(initial_modules); - for (auto& m : tok) { - pending_map.modules.insert(m); - } - pending_command_descs = mgr_commands; - dout(10) << __func__ << " initial modules " << pending_map.modules - << ", " << pending_command_descs.size() << " commands" - << dendl; -} - -void MgrMonitor::get_store_prefixes(std::set& s) -{ - s.insert(service_name); - s.insert(command_descs_prefix); - s.insert(MGR_METADATA_PREFIX); -} - -void MgrMonitor::update_from_paxos(bool *need_bootstrap) -{ - version_t version = get_last_committed(); - if (version != map.epoch) { - dout(4) << "loading version " << version << dendl; - - bufferlist bl; - 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); - - dout(4) << "active server: " << map.active_addr - << "(" << map.active_gid << ")" << dendl; - - ever_had_active_mgr = get_value("ever_had_active_mgr"); - - load_health(); - - if (map.available) { - first_seen_inactive = utime_t(); - } else { - first_seen_inactive = ceph_clock_now(); - } - - check_subs(); - - if (version == 1 - || command_descs.empty() - || (map.get_available() - && (!old_available || old_gid != map.get_active_gid()))) { - dout(4) << "mkfs or 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 - mon->mgr_client.ms_dispatch(new MMgrMap(map)); -} - -void MgrMonitor::create_pending() -{ - pending_map = map; - pending_map.epoch++; - - if (map.get_epoch() == 1 && - command_descs.empty() && - pending_command_descs.empty()) { - // we've been through the initial map and we haven't populated the - // command_descs vector. This likely means we came from kraken, where - // we wouldn't populate the vector, nor would we write it to disk, on - // create_initial(). - create_initial(); - } -} - -health_status_t MgrMonitor::should_warn_about_mgr_down() -{ - utime_t now = ceph_clock_now(); - // we warn if - // - we've ever had an active mgr, or - // - we have osds AND we've exceeded the grace period - // which means a new mon cluster and be HEALTH_OK indefinitely as long as - // no OSDs are ever created. - if (ever_had_active_mgr || - (mon->osdmon()->osdmap.get_num_osds() > 0 && - now > mon->monmap->created + g_conf->get_val("mon_mgr_mkfs_grace"))) { - health_status_t level = HEALTH_WARN; - if (first_seen_inactive != utime_t() && - now - first_seen_inactive > g_conf->get_val("mon_mgr_inactive_grace")) { - level = HEALTH_ERR; - } - return level; - } - return HEALTH_OK; -} - -void MgrMonitor::encode_pending(MonitorDBStore::TransactionRef t) -{ - dout(10) << __func__ << " " << pending_map << dendl; - bufferlist bl; - pending_map.encode(bl, mon->get_quorum_con_features()); - put_version(t, pending_map.epoch, bl); - put_last_committed(t, pending_map.epoch); - - for (auto& p : pending_metadata) { - dout(10) << __func__ << " set metadata for " << p.first << dendl; - t->put(MGR_METADATA_PREFIX, p.first, p.second); - } - for (auto& name : pending_metadata_rm) { - dout(10) << __func__ << " rm metadata for " << name << dendl; - t->erase(MGR_METADATA_PREFIX, name); - } - pending_metadata.clear(); - pending_metadata_rm.clear(); - - health_check_map_t next; - if (pending_map.active_gid == 0) { - auto level = should_warn_about_mgr_down(); - if (level != HEALTH_OK) { - next.add("MGR_DOWN", level, "no active mgr"); - } else { - dout(10) << __func__ << " no health warning (never active and new cluster)" - << dendl; - } - } else { - 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; - for (auto& p : pending_command_descs) { - p.set_flag(MonCommand::FLAG_MGR); - } - 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) -{ - // check permissions - MonSession *session = op->get_session(); - if (!session) - return false; - if (!session->is_capable("mgr", MON_CAP_X)) { - dout(1) << __func__ << " insufficient caps " << session->caps << dendl; - return false; - } - if (fsid != mon->monmap->fsid) { - dout(1) << __func__ << " op fsid " << fsid - << " != " << mon->monmap->fsid << dendl; - return false; - } - return true; -} - -bool MgrMonitor::preprocess_query(MonOpRequestRef op) -{ - PaxosServiceMessage *m = static_cast(op->get_req()); - switch (m->get_type()) { - case MSG_MGR_BEACON: - return preprocess_beacon(op); - case MSG_MON_COMMAND: - return preprocess_command(op); - default: - mon->no_reply(op); - derr << "Unhandled message type " << m->get_type() << dendl; - return true; - } -} - -bool MgrMonitor::prepare_update(MonOpRequestRef op) -{ - PaxosServiceMessage *m = static_cast(op->get_req()); - switch (m->get_type()) { - case MSG_MGR_BEACON: - return prepare_beacon(op); - - case MSG_MON_COMMAND: - return prepare_command(op); - - default: - mon->no_reply(op); - derr << "Unhandled message type " << m->get_type() << dendl; - return true; - } -} - - - -class C_Updated : public Context { - MgrMonitor *mm; - MonOpRequestRef op; -public: - C_Updated(MgrMonitor *a, MonOpRequestRef c) : - mm(a), op(c) {} - void finish(int r) override { - if (r >= 0) { - // Success - } else if (r == -ECANCELED) { - mm->mon->no_reply(op); - } else { - mm->dispatch(op); // try again - } - } -}; - -bool MgrMonitor::preprocess_beacon(MonOpRequestRef op) -{ - MMgrBeacon *m = static_cast(op->get_req()); - dout(4) << "beacon from " << m->get_gid() << dendl; - - if (!check_caps(op, m->get_fsid())) { - // drop it on the floor - return true; - } - - // always send this to the leader's prepare_beacon() - return false; -} - -bool MgrMonitor::prepare_beacon(MonOpRequestRef op) -{ - MMgrBeacon *m = static_cast(op->get_req()); - dout(4) << "beacon from " << m->get_gid() << dendl; - - // See if we are seeing same name, new GID for the active daemon - if (m->get_name() == pending_map.active_name - && m->get_gid() != pending_map.active_gid) - { - dout(4) << "Active daemon restart (mgr." << m->get_name() << ")" << dendl; - mon->clog->info() << "Active manager daemon " << m->get_name() - << " restarted"; - drop_active(); - } - - // See if we are seeing same name, new GID for any standbys - for (const auto &i : pending_map.standbys) { - const StandbyInfo &s = i.second; - if (s.name == m->get_name() && s.gid != m->get_gid()) { - dout(4) << "Standby daemon restart (mgr." << m->get_name() << ")" << dendl; - mon->clog->debug() << "Standby manager daemon " << m->get_name() - << " restarted"; - drop_standby(i.first); - break; - } - } - - last_beacon[m->get_gid()] = ceph::coarse_mono_clock::now(); - - // Track whether we modified pending_map - bool updated = false; - - if (pending_map.active_gid == m->get_gid()) { - if (pending_map.services != m->get_services()) { - dout(4) << "updated services from mgr." << m->get_name() - << ": " << m->get_services() << dendl; - pending_map.services = m->get_services(); - updated = true; - } - - // A beacon from the currently active daemon - if (pending_map.active_addr != m->get_server_addr()) { - dout(4) << "learned address " << m->get_server_addr() - << " (was " << pending_map.active_addr << ")" << dendl; - pending_map.active_addr = m->get_server_addr(); - updated = true; - } - - if (pending_map.get_available() != m->get_available()) { - 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; - } - if (pending_map.available_modules != m->get_available_modules()) { - dout(4) << "available_modules " << m->get_available_modules() - << " (was " << pending_map.available_modules << ")" << dendl; - pending_map.available_modules = m->get_available_modules(); - updated = true; - } - } else if (pending_map.active_gid == 0) { - // There is no currently active daemon, select this one. - if (pending_map.standbys.count(m->get_gid())) { - drop_standby(m->get_gid(), false); - } - dout(4) << "selecting new active " << m->get_gid() - << " " << m->get_name() - << " (was " << pending_map.active_gid << " " - << pending_map.active_name << ")" << dendl; - pending_map.active_gid = m->get_gid(); - pending_map.active_name = m->get_name(); - pending_map.available_modules = m->get_available_modules(); - ::encode(m->get_metadata(), pending_metadata[m->get_name()]); - pending_metadata_rm.erase(m->get_name()); - - mon->clog->info() << "Activating manager daemon " - << pending_map.active_name; - - updated = true; - } else { - if (pending_map.standbys.count(m->get_gid()) > 0) { - dout(10) << "from existing standby " << m->get_gid() << dendl; - if (pending_map.standbys[m->get_gid()].available_modules != - m->get_available_modules()) { - dout(10) << "existing standby " << m->get_gid() << " available_modules " - << m->get_available_modules() << " (was " - << pending_map.standbys[m->get_gid()].available_modules << ")" - << dendl; - pending_map.standbys[m->get_gid()].available_modules = - m->get_available_modules(); - updated = true; - } - } else { - dout(10) << "new standby " << m->get_gid() << dendl; - mon->clog->debug() << "Standby manager daemon " << m->get_name() - << " started"; - pending_map.standbys[m->get_gid()] = {m->get_gid(), m->get_name(), - m->get_available_modules()}; - ::encode(m->get_metadata(), pending_metadata[m->get_name()]); - pending_metadata_rm.erase(m->get_name()); - updated = true; - } - } - - if (updated) { - dout(4) << "updating map" << dendl; - wait_for_finished_proposal(op, new C_Updated(this, op)); - } else { - dout(10) << "no change" << dendl; - } - - return updated; -} - -void MgrMonitor::check_subs() -{ - const std::string type = "mgrmap"; - if (mon->session_map.subs.count(type) == 0) - return; - for (auto sub : *(mon->session_map.subs[type])) { - check_sub(sub); - } -} - -void MgrMonitor::check_sub(Subscription *sub) -{ - if (sub->type == "mgrmap") { - if (sub->next <= map.get_epoch()) { - dout(20) << "Sending map to subscriber " << sub->session->con - << " " << sub->session->con->get_peer_addr() << dendl; - sub->session->con->send_message(new MMgrMap(map)); - if (sub->onetime) { - mon->session_map.remove_sub(sub); - } else { - sub->next = map.get_epoch() + 1; - } - } - } else { - assert(sub->type == "mgrdigest"); - if (sub->next == 0) { - // new registration; cancel previous timer - cancel_timer(); - } - if (digest_event == nullptr) { - send_digests(); - } - } -} - -/** - * Handle digest subscriptions separately (outside of check_sub) because - * they are going to be periodic rather than version-driven. - */ -void MgrMonitor::send_digests() -{ - cancel_timer(); - - if (!is_active()) { - return; - } - dout(10) << __func__ << dendl; - - const std::string type = "mgrdigest"; - if (mon->session_map.subs.count(type) == 0) - return; - - for (auto sub : *(mon->session_map.subs[type])) { - dout(10) << __func__ << " sending digest to subscriber " << sub->session->con - << " " << sub->session->con->get_peer_addr() << dendl; - MMgrDigest *mdigest = new MMgrDigest; - - JSONFormatter f; - mon->get_health_status(true, &f, nullptr, nullptr, nullptr); - f.flush(mdigest->health_json); - f.reset(); - - std::ostringstream ss; - mon->get_mon_status(&f, ss); - f.flush(mdigest->mon_status_json); - f.reset(); - - sub->session->con->send_message(mdigest); - } - - digest_event = mon->timer.add_event_after( - g_conf->get_val("mon_mgr_digest_period"), - new C_MonContext(mon, [this](int) { - send_digests(); - })); -} - -void MgrMonitor::cancel_timer() -{ - if (digest_event) { - mon->timer.cancel_event(digest_event); - digest_event = nullptr; - } -} - -void MgrMonitor::on_active() -{ - if (mon->is_leader()) { - mon->clog->debug() << "mgrmap e" << map.epoch << ": " << map; - } -} - -void MgrMonitor::get_health( - list >& summary, - list > *detail, - CephContext *cct) const -{ - // start mgr warnings as soon as the mons and osds are all upgraded, - // but before the require_luminous osdmap flag is set. this way the - // user gets some warning before the osd flag is set and mgr is - // actually *required*. - if (!mon->monmap->get_required_features().contains_all( - ceph::features::mon::FEATURE_LUMINOUS) || - !HAVE_FEATURE(mon->osdmon()->osdmap.get_up_osd_features(), - SERVER_LUMINOUS)) { - return; - } - - if (map.active_gid == 0) { - auto level = HEALTH_WARN; - // do not escalate to ERR if they are still upgrading to jewel. - if (mon->osdmon()->osdmap.require_osd_release >= CEPH_RELEASE_LUMINOUS) { - utime_t now = ceph_clock_now(); - if (first_seen_inactive != utime_t() && - now - first_seen_inactive > g_conf->get_val("mon_mgr_inactive_grace")) { - level = HEALTH_ERR; - } - } - summary.push_back(make_pair(level, "no active mgr")); - } -} - -void MgrMonitor::tick() -{ - if (!is_active() || !mon->is_leader()) - return; - - const auto now = ceph::coarse_mono_clock::now(); - - const auto mgr_beacon_grace = std::chrono::seconds( - g_conf->get_val("mon_mgr_beacon_grace")); - - // Note that this is the mgr daemon's tick period, not ours (the - // beacon is sent with this period). - const auto mgr_tick_period = std::chrono::seconds( - g_conf->get_val("mgr_tick_period")); - - if (last_tick != ceph::coarse_mono_clock::time_point::min() - && (now - last_tick > (mgr_beacon_grace - mgr_tick_period))) { - // This case handles either local slowness (calls being delayed - // for whatever reason) or cluster election slowness (a long gap - // between calls while an election happened) - dout(4) << __func__ << ": resetting beacon timeouts due to mon delay " - "(slow election?) of " << now - last_tick << " seconds" << dendl; - for (auto &i : last_beacon) { - i.second = now; - } - } - - last_tick = now; - - // Populate any missing beacons (i.e. no beacon since MgrMonitor - // instantiation) with the current time, so that they will - // eventually look laggy if they fail to give us a beacon. - if (pending_map.active_gid != 0 - && last_beacon.count(pending_map.active_gid) == 0) { - last_beacon[pending_map.active_gid] = now; - } - for (auto s : pending_map.standbys) { - if (last_beacon.count(s.first) == 0) { - last_beacon[s.first] = now; - } - } - - // Cull standbys first so that any remaining standbys - // will be eligible to take over from the active if we cull him. - std::list dead_standbys; - const auto cutoff = now - mgr_beacon_grace; - for (const auto &i : pending_map.standbys) { - auto last_beacon_time = last_beacon.at(i.first); - if (last_beacon_time < cutoff) { - dead_standbys.push_back(i.first); - } - } - - bool propose = false; - - for (auto i : dead_standbys) { - dout(4) << "Dropping laggy standby " << i << dendl; - drop_standby(i); - propose = true; - } - - if (pending_map.active_gid != 0 - && last_beacon.at(pending_map.active_gid) < cutoff) { - const std::string old_active_name = pending_map.active_name; - drop_active(); - propose = true; - dout(4) << "Dropping active" << pending_map.active_gid << dendl; - if (promote_standby()) { - dout(4) << "Promoted standby " << pending_map.active_gid << dendl; - mon->clog->info() << "Manager daemon " << old_active_name - << " is unresponsive, replacing it with standby" - << " daemon " << pending_map.active_name; - } else { - dout(4) << "Active is laggy but have no standbys to replace it" << dendl; - mon->clog->warn() << "Manager daemon " << old_active_name - << " is unresponsive. No standby daemons available."; - } - } else if (pending_map.active_gid == 0) { - if (promote_standby()) { - dout(4) << "Promoted standby " << pending_map.active_gid << dendl; - mon->clog->info() << "Activating manager daemon " - << pending_map.active_name; - propose = true; - } - } - - if (!pending_map.available && - !ever_had_active_mgr && - should_warn_about_mgr_down() != HEALTH_OK) { - dout(10) << " exceeded mon_mgr_mkfs_grace " - << g_conf->get_val("mon_mgr_mkfs_grace") - << " seconds" << dendl; - propose = true; - } - - if (propose) { - propose_pending(); - } -} - -void MgrMonitor::on_restart() -{ - // Clear out the leader-specific state. - last_beacon.clear(); - last_tick = ceph::coarse_mono_clock::now(); -} - - -bool MgrMonitor::promote_standby() -{ - assert(pending_map.active_gid == 0); - if (pending_map.standbys.size()) { - // Promote a replacement (arbitrary choice of standby) - auto replacement_gid = pending_map.standbys.begin()->first; - pending_map.active_gid = replacement_gid; - pending_map.active_name = pending_map.standbys.at(replacement_gid).name; - pending_map.available = false; - pending_map.active_addr = entity_addr_t(); - - drop_standby(replacement_gid, false); - - return true; - } else { - return false; - } -} - -void MgrMonitor::drop_active() -{ - if (last_beacon.count(pending_map.active_gid) > 0) { - last_beacon.erase(pending_map.active_gid); - } - - pending_metadata_rm.insert(pending_map.active_name); - pending_metadata.erase(pending_map.active_name); - pending_map.active_name = ""; - pending_map.active_gid = 0; - pending_map.available = false; - pending_map.active_addr = entity_addr_t(); - pending_map.services.clear(); - - // So that when new active mgr subscribes to mgrdigest, it will - // get an immediate response instead of waiting for next timer - cancel_timer(); -} - -void MgrMonitor::drop_standby(uint64_t gid, bool drop_meta) -{ - if (drop_meta) { - pending_metadata_rm.insert(pending_map.standbys[gid].name); - pending_metadata.erase(pending_map.standbys[gid].name); - } - pending_map.standbys.erase(gid); - if (last_beacon.count(gid) > 0) { - last_beacon.erase(gid); - } -} - -bool MgrMonitor::preprocess_command(MonOpRequestRef op) -{ - MMonCommand *m = static_cast(op->get_req()); - std::stringstream ss; - bufferlist rdata; - - std::map 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 = m->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("json-pretty")); - boost::scoped_ptr f(Formatter::create(format)); - - string prefix; - cmd_getval(g_ceph_context, cmdmap, "prefix", prefix); - int r = 0; - - if (prefix == "mgr dump") { - int64_t epoch = 0; - cmd_getval(g_ceph_context, cmdmap, "epoch", epoch, (int64_t)map.get_epoch()); - if (epoch == (int64_t)map.get_epoch()) { - f->dump_object("mgrmap", map); - } else { - bufferlist bl; - int err = get_version(epoch, bl); - if (err == -ENOENT) { - r = -ENOENT; - ss << "there is no map for epoch " << epoch; - goto reply; - } - MgrMap m; - auto p = bl.begin(); - m.decode(p); - f->dump_object("mgrmap", m); - } - f->flush(rdata); - } else if (prefix == "mgr module ls") { - f->open_object_section("modules"); - { - f->open_array_section("enabled_modules"); - for (auto& p : map.modules) { - f->dump_string("module", p); - } - f->close_section(); - f->open_array_section("disabled_modules"); - for (auto& p : map.available_modules) { - if (map.modules.count(p) == 0) { - f->dump_string("module", p); - } - } - f->close_section(); - } - f->close_section(); - f->flush(rdata); - } else if (prefix == "mgr services") { - f->open_object_section("services"); - for (const auto &i : map.services) { - f->dump_string(i.first.c_str(), i.second); - } - f->close_section(); - f->flush(rdata); - } else if (prefix == "mgr metadata") { - string name; - cmd_getval(g_ceph_context, cmdmap, "id", name); - if (name.size() > 0 && !map.have_name(name)) { - ss << "mgr." << name << " does not exist"; - r = -ENOENT; - goto reply; - } - string format; - cmd_getval(g_ceph_context, cmdmap, "format", format); - boost::scoped_ptr f(Formatter::create(format, "json-pretty", "json-pretty")); - if (name.size()) { - f->open_object_section("mgr_metadata"); - f->dump_string("id", name); - r = dump_metadata(name, f.get(), &ss); - if (r < 0) - goto reply; - f->close_section(); - } else { - r = 0; - f->open_array_section("mgr_metadata"); - for (auto& i : map.get_all_names()) { - f->open_object_section("mgr"); - f->dump_string("id", i); - r = dump_metadata(i, f.get(), NULL); - if (r == -EINVAL || r == -ENOENT) { - // Drop error, continue to get other daemons' metadata - dout(4) << "No metadata for mgr." << i << dendl; - r = 0; - } else if (r < 0) { - // Unexpected error - goto reply; - } - f->close_section(); - } - f->close_section(); - } - f->flush(rdata); - } else if (prefix == "mgr versions") { - if (!f) - f.reset(Formatter::create("json-pretty")); - count_metadata("ceph_version", f.get()); - f->flush(rdata); - r = 0; - } else if (prefix == "mgr count-metadata") { - if (!f) - f.reset(Formatter::create("json-pretty")); - string field; - cmd_getval(g_ceph_context, cmdmap, "property", field); - count_metadata(field, f.get()); - f->flush(rdata); - r = 0; - } else { - return false; - } - -reply: - string rs; - getline(ss, rs); - mon->reply_command(op, r, rs, rdata, get_last_committed()); - return true; -} - -bool MgrMonitor::prepare_command(MonOpRequestRef op) -{ - MMonCommand *m = static_cast(op->get_req()); - - std::stringstream ss; - bufferlist rdata; - - std::map 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 = m->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 == "mgr fail") { - string who; - cmd_getval(g_ceph_context, cmdmap, "who", who); - - std::string err; - uint64_t gid = strict_strtol(who.c_str(), 10, &err); - bool changed = false; - if (!err.empty()) { - // Does not parse as a gid, treat it as a name - if (pending_map.active_name == who) { - drop_active(); - changed = true; - } else { - gid = 0; - for (const auto &i : pending_map.standbys) { - if (i.second.name == who) { - gid = i.first; - break; - } - } - if (gid != 0) { - drop_standby(gid); - changed = true; - } else { - ss << "Daemon not found '" << who << "', already failed?"; - } - } - } else { - if (pending_map.active_gid == gid) { - drop_active(); - changed = true; - } else if (pending_map.standbys.count(gid) > 0) { - drop_standby(gid); - changed = true; - } else { - ss << "Daemon not found '" << gid << "', already failed?"; - } - } - - if (changed && pending_map.active_gid == 0) { - promote_standby(); - } - } else if (prefix == "mgr module enable") { - string module; - cmd_getval(g_ceph_context, cmdmap, "module", module); - if (module.empty()) { - r = -EINVAL; - goto out; - } - string force; - cmd_getval(g_ceph_context, cmdmap, "force", force); - if (!pending_map.all_support_module(module) && - force != "--force") { - ss << "all mgr daemons do not support module '" << module << "', pass " - << "--force to force enablement"; - r = -ENOENT; - goto out; - } - pending_map.modules.insert(module); - } else if (prefix == "mgr module disable") { - string module; - cmd_getval(g_ceph_context, cmdmap, "module", module); - if (module.empty()) { - r = -EINVAL; - goto out; - } - pending_map.modules.erase(module); - } 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; - } -} - -void MgrMonitor::init() -{ - if (digest_event == nullptr) { - send_digests(); // To get it to schedule its own event - } -} - -void MgrMonitor::on_shutdown() -{ - cancel_timer(); -} - -int MgrMonitor::load_metadata(const string& name, std::map& m, - ostream *err) -{ - bufferlist bl; - int r = mon->store->get(MGR_METADATA_PREFIX, name, bl); - if (r < 0) - return r; - try { - bufferlist::iterator p = bl.begin(); - ::decode(m, p); - } - catch (buffer::error& e) { - if (err) - *err << "mgr." << name << " metadata is corrupt"; - return -EIO; - } - return 0; -} - -void MgrMonitor::count_metadata(const string& field, std::map *out) -{ - std::set ls = map.get_all_names(); - for (auto& name : ls) { - std::map meta; - load_metadata(name, meta, nullptr); - auto p = meta.find(field); - if (p == meta.end()) { - (*out)["unknown"]++; - } else { - (*out)[p->second]++; - } - } -} - -void MgrMonitor::count_metadata(const string& field, Formatter *f) -{ - std::map by_val; - count_metadata(field, &by_val); - f->open_object_section(field.c_str()); - for (auto& p : by_val) { - f->dump_int(p.first.c_str(), p.second); - } - f->close_section(); -} - -int MgrMonitor::dump_metadata(const string& name, Formatter *f, ostream *err) -{ - std::map m; - if (int r = load_metadata(name, m, err)) - return r; - for (auto& p : m) { - f->dump_string(p.first.c_str(), p.second); - } - return 0; -} - -const std::vector &MgrMonitor::get_command_descs() const -{ - if (command_descs.empty()) { - // must have just upgraded; fallback to static commands - return mgr_commands; - } else { - return command_descs; - } -}