]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/mon/Monitor.h
import ceph quincy 17.2.6
[ceph.git] / ceph / src / mon / Monitor.h
index fc9772601cb9871f4eb3a39d024bab3616d02a56..41fde178a97e264c50473131aa757b803f0091b6 100644 (file)
@@ -1,4 +1,4 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
 // vim: ts=8 sw=2 smarttab
 /*
  * Ceph - scalable distributed file system
@@ -7,16 +7,16 @@
  *
  * 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 
+ * License version 2.1, as published by the Free Software
  * Foundation.  See file COPYING.
- * 
+ *
  */
 
-/* 
- * This is the top level monitor. It runs on each machine in the Monitor   
- * Cluster. The election of a leader for the paxos algorithm only happens 
- * once per machine via the elector. There is a separate paxos instance (state) 
- * kept for each of the system components: Object Store Device (OSD) Monitor, 
+/*
+ * This is the top level monitor. It runs on each machine in the Monitor
+ * Cluster. The election of a leader for the paxos algorithm only happens
+ * once per machine via the elector. There is a separate paxos instance (state)
+ * kept for each of the system components: Object Store Device (OSD) Monitor,
  * Placement Group (PG) Monitor, Metadata Server (MDS) Monitor, and Client Monitor.
  */
 
@@ -25,6 +25,8 @@
 
 #include <errno.h>
 #include <cmath>
+#include <string>
+#include <array>
 
 #include "include/types.h"
 #include "include/health.h"
 #include "Elector.h"
 #include "Paxos.h"
 #include "Session.h"
-#include "PGStatService.h"
 #include "MonCommand.h"
 
+
+#include "common/config_obs.h"
 #include "common/LogClient.h"
+#include "auth/AuthClient.h"
+#include "auth/AuthServer.h"
 #include "auth/cephx/CephxKeyServer.h"
 #include "auth/AuthMethodList.h"
 #include "auth/KeyRing.h"
+#include "include/common_fwd.h"
 #include "messages/MMonCommand.h"
 #include "mon/MonitorDBStore.h"
-#include "include/memory.h"
 #include "mgr/MgrClient.h"
 
 #include "mon/MonOpRequest.h"
 #include "common/WorkQueue.h"
 
+using namespace TOPNSPC::common;
 
 #define CEPH_MON_PROTOCOL     13 /* cluster internal */
 
@@ -77,10 +83,6 @@ enum {
   l_cluster_num_object_misplaced,
   l_cluster_num_object_unfound,
   l_cluster_num_bytes,
-  l_cluster_num_mds_up,
-  l_cluster_num_mds_in,
-  l_cluster_num_mds_failed,
-  l_cluster_mds_epoch,
   l_cluster_last,
 };
 
@@ -97,47 +99,32 @@ enum {
   l_mon_last,
 };
 
-class QuorumService;
 class PaxosService;
 
-class PerfCounters;
 class AdminSocketHook;
 
-class MMonGetMap;
-class MMonGetVersion;
-class MMonMetadata;
-class MMonSync;
-class MMonScrub;
-class MMonProbe;
-struct MMonSubscribe;
-struct MRoute;
-struct MForward;
-struct MTimeCheck;
-struct MMonHealth;
-
 #define COMPAT_SET_LOC "feature_set"
 
-class C_MonContext final : public FunctionContext {
-  const Monitor *mon;
-public:
-  explicit C_MonContext(Monitor *m, boost::function<void(int)>&& callback)
-    : FunctionContext(std::move(callback)), mon(m) {}
-  void finish(int r) override;
-};
-
 class Monitor : public Dispatcher,
+               public AuthClient,
+               public AuthServer,
                 public md_config_obs_t {
 public:
+  int orig_argc = 0;
+  const char **orig_argv = nullptr;
+
   // me
-  string name;
+  std::string name;
   int rank;
   Messenger *messenger;
   ConnectionRef con_self;
-  Mutex lock;
+  ceph::mutex lock = ceph::make_mutex("Monitor::lock");
   SafeTimer timer;
   Finisher finisher;
   ThreadPool cpu_tp;  ///< threadpool for CPU intensive work
-  
+
+  ceph::mutex auth_lock = ceph::make_mutex("Monitor::auth_lock");
+
   /// true if we have ever joined a quorum.  if false, we are either a
   /// new cluster, a newly joining monitor, or a just-upgraded
   /// monitor.
@@ -152,7 +139,7 @@ public:
   MonMap *monmap;
   uuid_d fingerprint;
 
-  set<entity_addr_t> extra_probe_peers;
+  std::set<entity_addrvec_t> extra_probe_peers;
 
   LogClient log_client;
   LogChannelRef clog;
@@ -165,19 +152,17 @@ public:
 
   CompatSet features;
 
-  vector<MonCommand> leader_mon_commands; // quorum leader's commands
-  vector<MonCommand> local_mon_commands;  // commands i support
-  bufferlist local_mon_commands_bl;       // encoded version of above
+  std::vector<MonCommand> leader_mon_commands; // quorum leader's commands
+  std::vector<MonCommand> local_mon_commands;  // commands i support
+  ceph::buffer::list local_mon_commands_bl;       // encoded version of above
 
-  // for upgrading mon cluster that still uses PGMonitor
-  vector<MonCommand> local_upgrading_mon_commands;  // mixed mon cluster commands
-  bufferlist local_upgrading_mon_commands_bl;       // encoded version of above
+  std::vector<MonCommand> prenautilus_local_mon_commands;
+  ceph::buffer::list prenautilus_local_mon_commands_bl;
 
   Messenger *mgr_messenger;
   MgrClient mgr_client;
   uint64_t mgr_proxy_bytes = 0;  // in-flight proxied mgr command message bytes
-
-  const MonPGStatService *pgservice;
+  std::string gss_ktfile_client{};
 
 private:
   void new_tick();
@@ -185,20 +170,21 @@ private:
   // -- local storage --
 public:
   MonitorDBStore *store;
-  static const string MONITOR_NAME;
-  static const string MONITOR_STORE_PREFIX;
+  static const std::string MONITOR_NAME;
+  static const std::string MONITOR_STORE_PREFIX;
 
   // -- monitor state --
 private:
   enum {
-    STATE_PROBING = 1,
+    STATE_INIT = 1,
+    STATE_PROBING,
     STATE_SYNCHRONIZING,
     STATE_ELECTING,
     STATE_LEADER,
     STATE_PEON,
     STATE_SHUTDOWN
   };
-  int state;
+  int state = STATE_INIT;
 
 public:
   static const char *get_state_name(int s) {
@@ -216,6 +202,7 @@ public:
     return get_state_name(state);
   }
 
+  bool is_init() const { return state == STATE_INIT; }
   bool is_shutdown() const { return state == STATE_SHUTDOWN; }
   bool is_probing() const { return state == STATE_PROBING; }
   bool is_synchronizing() const { return state == STATE_SYNCHRONIZING; }
@@ -227,9 +214,24 @@ public:
 
   void prepare_new_fingerprint(MonitorDBStore::TransactionRef t);
 
+  std::vector<DaemonHealthMetric> get_health_metrics();
+
+  int quorum_age() const {
+    auto age = std::chrono::duration_cast<std::chrono::seconds>(
+      ceph::mono_clock::now() - quorum_since);
+    return age.count();
+  }
+
+  bool is_mon_down() const {
+    int max = monmap->size();
+    int actual = get_quorum().size();
+    auto now = ceph::real_clock::now();
+    return actual < max && now > monmap->created.to_real_time();
+  }
+
   // -- elector --
 private:
-  Paxos *paxos;
+  std::unique_ptr<Paxos> paxos;
   Elector elector;
   friend class Elector;
 
@@ -237,13 +239,14 @@ private:
   uint64_t required_features;
   
   int leader;            // current leader (to best of knowledge)
-  set<int> quorum;       // current active set of monitors (if !starting)
+  std::set<int> quorum;       // current active set of monitors (if !starting)
+  ceph::mono_clock::time_point quorum_since;  // when quorum formed
   utime_t leader_since;  // when this monitor became the leader, if it is the leader
   utime_t exited_quorum; // time detected as not in quorum; 0 if in
 
   // map of counts of connected clients, by type and features, for
   // each quorum mon
-  map<int,FeatureMap> quorum_feature_map;
+  std::map<int,FeatureMap> quorum_feature_map;
 
   /**
    * Intersection of quorum member's connection feature bits.
@@ -254,14 +257,62 @@ private:
    */
   mon_feature_t quorum_mon_features;
 
-  set<string> outside_quorum;
+  ceph_release_t quorum_min_mon_release{ceph_release_t::unknown};
+
+  std::set<std::string> outside_quorum;
+
+  bool stretch_mode_engaged{false};
+  bool degraded_stretch_mode{false};
+  bool recovering_stretch_mode{false};
+  std::string stretch_bucket_divider;
+  std::map<std::string, std::set<std::string>> dead_mon_buckets; // bucket->mon ranks, locations with no live mons
+  std::set<std::string> up_mon_buckets; // locations with a live mon
+  void do_stretch_mode_election_work();
+
+  bool session_stretch_allowed(MonSession *s, MonOpRequestRef& op);
+  void disconnect_disallowed_stretch_sessions();
+  void set_elector_disallowed_leaders(bool allow_election);
+
+  std::map<std::string,std::string> crush_loc;
+  bool need_set_crush_loc{false};
+public:
+  bool is_stretch_mode() { return stretch_mode_engaged; }
+  bool is_degraded_stretch_mode() { return degraded_stretch_mode; }
+  bool is_recovering_stretch_mode() { return recovering_stretch_mode; }
+
+  /**
+   * This set of functions maintains the in-memory stretch state
+   * and sets up transitions of the map states by calling in to
+   * MonmapMonitor and OSDMonitor.
+   *
+   * The [maybe_]go_* functions are called on the leader to
+   * decide if transitions should happen; the trigger_* functions
+   * set up the map transitions; and the set_* functions actually
+   * change the memory state -- but these are only called
+   * via OSDMonitor::update_from_paxos, to guarantee consistent
+   * updates across the entire cluster.
+   */
+  void try_engage_stretch_mode();
+  void maybe_go_degraded_stretch_mode();
+  void trigger_degraded_stretch_mode(const std::set<std::string>& dead_mons,
+                                    const std::set<int>& dead_buckets);
+  void set_degraded_stretch_mode();
+  void go_recovery_stretch_mode();
+  void set_recovery_stretch_mode();
+  void trigger_healthy_stretch_mode();
+  void set_healthy_stretch_mode();
+  void enable_stretch_mode();
+  void set_mon_crush_location(const std::string& loc);
+
+  
+private:
 
   /**
    * @defgroup Monitor_h_scrub
    * @{
    */
   version_t scrub_version;            ///< paxos version we are scrubbing
-  map<int,ScrubResult> scrub_result;  ///< results so far
+  std::map<int,ScrubResult> scrub_result;  ///< results so far
 
   /**
    * trigger a cross-mon scrub
@@ -272,13 +323,13 @@ private:
   int scrub();
   void handle_scrub(MonOpRequestRef op);
   bool _scrub(ScrubResult *r,
-              pair<string,string> *start,
+              std::pair<std::string,std::string> *start,
               int *num_keys);
   void scrub_check_results();
   void scrub_timeout();
   void scrub_finish();
   void scrub_reset();
-  void scrub_update_interval(int secs);
+  void scrub_update_interval(ceph::timespan interval);
 
   Context *scrub_event;       ///< periodic event to trigger scrub (leader)
   Context *scrub_timeout_event;  ///< scrub round timeout (leader)
@@ -288,13 +339,13 @@ private:
   void scrub_cancel_timeout();
 
   struct ScrubState {
-    pair<string,string> last_key; ///< last scrubbed key
+    std::pair<std::string,std::string> last_key; ///< last scrubbed key
     bool finished;
 
     ScrubState() : finished(false) { }
     virtual ~ScrubState() { }
   };
-  ceph::shared_ptr<ScrubState> scrub_state; ///< keeps track of current scrub
+  std::shared_ptr<ScrubState> scrub_state; ///< keeps track of current scrub
 
   /**
    * @defgroup Monitor_h_sync Synchronization
@@ -304,11 +355,11 @@ private:
    * @} // provider state
    */
   struct SyncProvider {
-    entity_inst_t entity;  ///< who
+    entity_addrvec_t addrs;
     uint64_t cookie;       ///< unique cookie for this sync attempt
     utime_t timeout;       ///< when we give up and expire this attempt
     version_t last_committed; ///< last paxos version on peer
-    pair<string,string> last_key; ///< last key sent to (or on) peer
+    std::pair<std::string,std::string> last_key; ///< last key sent to (or on) peer
     bool full;             ///< full scan?
     MonitorDBStore::Synchronizer synchronizer;   ///< iterator
 
@@ -320,13 +371,13 @@ private:
     }
   };
 
-  map<uint64_t, SyncProvider> sync_providers;  ///< cookie -> SyncProvider for those syncing from us
+  std::map<std::uint64_t, SyncProvider> sync_providers;  ///< cookie -> SyncProvider for those syncing from us
   uint64_t sync_provider_count;   ///< counter for issued cookies to keep them unique
 
   /**
    * @} // requester state
    */
-  entity_inst_t sync_provider;   ///< who we are syncing from
+  entity_addrvec_t sync_provider;  ///< who we are syncing from
   uint64_t sync_cookie;          ///< 0 if we are starting, non-zero otherwise
   bool sync_full;                ///< true if we are a full sync, false for recent catch-up
   version_t sync_start_version;  ///< last_committed at sync start
@@ -370,7 +421,7 @@ private:
    *
    * @returns a set of strings referring to the prefixes being synchronized
    */
-  set<string> get_sync_targets_names();
+  std::set<std::string> get_sync_targets_names();
 
   /**
    * Reset the monitor's sync-related data structures for syncing *from* a peer
@@ -390,7 +441,7 @@ private:
   /**
    * Get the latest monmap for backup purposes during sync
    */
-  void sync_obtain_latest_monmap(bufferlist &bl);
+  void sync_obtain_latest_monmap(ceph::buffer::list &bl);
 
   /**
    * Start sync process
@@ -400,13 +451,13 @@ private:
    * @param entity where to pull committed state from
    * @param full whether to do a full sync or just catch up on recent paxos
    */
-  void sync_start(entity_inst_t &entity, bool full);
+  void sync_start(entity_addrvec_t &addrs, bool full);
 
 public:
   /**
    * force a sync on next mon restart
    */
-  void sync_force(Formatter *f, ostream& ss);
+  void sync_force(ceph::Formatter *f);
 
 private:
   /**
@@ -467,8 +518,8 @@ private:
    * @} // Synchronization
    */
 
-  list<Context*> waitfor_quorum;
-  list<Context*> maybe_wait_for_quorum;
+  std::list<Context*> waitfor_quorum;
+  std::list<Context*> maybe_wait_for_quorum;
 
   /**
    * @defgroup Monitor_h_TimeCheck Monitor Clock Drift Early Warning System
@@ -494,9 +545,9 @@ private:
    *  - Once all the quorum members have pong'ed, the leader will share the
    *    clock skew and latency maps with all the monitors in the quorum.
    */
-  map<entity_inst_t, utime_t> timecheck_waiting;
-  map<entity_inst_t, double> timecheck_skews;
-  map<entity_inst_t, double> timecheck_latencies;
+  std::map<int, utime_t> timecheck_waiting;
+  std::map<int, double> timecheck_skews;
+  std::map<int, double> timecheck_latencies;
   // odd value means we are mid-round; even value means the round has
   // finished.
   version_t timecheck_round;
@@ -527,7 +578,7 @@ private:
   void timecheck_check_skews();
   void timecheck_report();
   void timecheck();
-  health_status_t timecheck_status(ostringstream &ss,
+  health_status_t timecheck_status(std::ostringstream &ss,
                                    const double skew_bound,
                                    const double latency);
   void handle_timecheck_leader(MonOpRequestRef op);
@@ -541,7 +592,7 @@ private:
     double abs_skew = std::fabs(skew_bound);
     if (abs)
       *abs = abs_skew;
-    return (abs_skew > g_conf->mon_clock_drift_allowed);
+    return (abs_skew > g_conf()->mon_clock_drift_allowed);
   }
 
   /**
@@ -563,13 +614,13 @@ private:
 public:
   epoch_t get_epoch();
   int get_leader() const { return leader; }
-  string get_leader_name() {
-    return quorum.empty() ? string() : monmap->get_name(*quorum.begin());
+  std::string get_leader_name() {
+    return quorum.empty() ? std::string() : monmap->get_name(leader);
   }
-  const set<int>& get_quorum() const { return quorum; }
-  list<string> get_quorum_names() {
-    list<string> q;
-    for (set<int>::iterator p = quorum.begin(); p != quorum.end(); ++p)
+  const std::set<int>& get_quorum() const { return quorum; }
+  std::list<std::string> get_quorum_names() {
+    std::list<std::string> q;
+    for (auto p = quorum.begin(); p != quorum.end(); ++p)
       q.push_back(monmap->get_name(*p));
     return q;
   }
@@ -595,19 +646,22 @@ private:
   void _reset();   ///< called from bootstrap, start_, or join_election
   void wait_for_paxos_write();
   void _finish_svc_election(); ///< called by {win,lose}_election
+  void respawn();
 public:
   void bootstrap();
   void join_election();
   void start_election();
   void win_standalone_election();
   // end election (called by Elector)
-  void win_election(epoch_t epoch, set<int>& q,
+  void win_election(epoch_t epoch, const std::set<int>& q,
                    uint64_t features,
                     const mon_feature_t& mon_features,
-                   const map<int,Metadata>& metadata);
-  void lose_election(epoch_t epoch, set<int>& q, int l,
+                   ceph_release_t min_mon_release,
+                   const std::map<int,Metadata>& metadata);
+  void lose_election(epoch_t epoch, std::set<int>& q, int l,
                     uint64_t features,
-                     const mon_feature_t& mon_features);
+                     const mon_feature_t& mon_features,
+                    ceph_release_t min_mon_release);
   // end election (called by Elector)
   void finish_election();
 
@@ -616,63 +670,63 @@ public:
   /**
    * Vector holding the Services serviced by this Monitor.
    */
-  vector<PaxosService*> paxos_service;
-
-  class PGMonitor *pgmon() {
-    return (class PGMonitor *)paxos_service[PAXOS_PGMAP];
-  }
+  std::array<std::unique_ptr<PaxosService>, PAXOS_NUM> paxos_service;
 
   class MDSMonitor *mdsmon() {
-    return (class MDSMonitor *)paxos_service[PAXOS_MDSMAP];
+    return (class MDSMonitor *)paxos_service[PAXOS_MDSMAP].get();
   }
 
   class MonmapMonitor *monmon() {
-    return (class MonmapMonitor *)paxos_service[PAXOS_MONMAP];
+    return (class MonmapMonitor *)paxos_service[PAXOS_MONMAP].get();
   }
 
   class OSDMonitor *osdmon() {
-    return (class OSDMonitor *)paxos_service[PAXOS_OSDMAP];
+    return (class OSDMonitor *)paxos_service[PAXOS_OSDMAP].get();
   }
 
   class AuthMonitor *authmon() {
-    return (class AuthMonitor *)paxos_service[PAXOS_AUTH];
+    return (class AuthMonitor *)paxos_service[PAXOS_AUTH].get();
   }
 
   class LogMonitor *logmon() {
-    return (class LogMonitor*) paxos_service[PAXOS_LOG];
+    return (class LogMonitor*) paxos_service[PAXOS_LOG].get();
   }
 
   class MgrMonitor *mgrmon() {
-    return (class MgrMonitor*) paxos_service[PAXOS_MGR];
+    return (class MgrMonitor*) paxos_service[PAXOS_MGR].get();
   }
 
   class MgrStatMonitor *mgrstatmon() {
-    return (class MgrStatMonitor*) paxos_service[PAXOS_MGRSTAT];
+    return (class MgrStatMonitor*) paxos_service[PAXOS_MGRSTAT].get();
+  }
+
+  class HealthMonitor *healthmon() {
+    return (class HealthMonitor*) paxos_service[PAXOS_HEALTH].get();
+  }
+
+  class ConfigMonitor *configmon() {
+    return (class ConfigMonitor*) paxos_service[PAXOS_CONFIG].get();
   }
 
-  class MgrStatMonitor *healthmon() {
-    return (class MgrStatMonitor*) paxos_service[PAXOS_MGRSTAT];
+  class KVMonitor *kvmon() {
+    return (class KVMonitor*) paxos_service[PAXOS_KV].get();
   }
 
   friend class Paxos;
   friend class OSDMonitor;
   friend class MDSMonitor;
   friend class MonmapMonitor;
-  friend class PGMonitor;
   friend class LogMonitor;
-  friend class ConfigKeyService;
-
-  QuorumService *health_monitor;
-  QuorumService *config_key_service;
+  friend class KVMonitor;
 
   // -- sessions --
   MonSessionMap session_map;
-  Mutex session_map_lock{"Monitor::session_map_lock"};
+  ceph::mutex session_map_lock = ceph::make_mutex("Monitor::session_map_lock");
   AdminSocketHook *admin_hook;
 
   template<typename Func, typename...Args>
   void with_session_map(Func&& func) {
-    Mutex::Locker l(session_map_lock);
+    std::lock_guard l(session_map_lock);
     std::forward<Func>(func)(session_map);
   }
   void send_latest_monmap(Connection *con);
@@ -682,35 +736,37 @@ public:
   void handle_subscribe(MonOpRequestRef op);
   void handle_mon_get_map(MonOpRequestRef op);
 
-  static void _generate_command_map(map<string,cmd_vartype>& cmdmap,
-                                    map<string,string> &param_str_map);
+  static void _generate_command_map(cmdmap_t& cmdmap,
+                                    std::map<std::string,std::string> &param_str_map);
   static const MonCommand *_get_moncommand(
-    const string &cmd_prefix,
-    const vector<MonCommand>& cmds);
-  bool _allowed_command(MonSession *s, string &module, string &prefix,
-                        const map<string,cmd_vartype>& cmdmap,
-                        const map<string,string>& param_str_map,
+    const std::string &cmd_prefix,
+    const std::vector<MonCommand>& cmds);
+  bool _allowed_command(MonSession *s, const std::string& module,
+                       const std::string& prefix,
+                        const cmdmap_t& cmdmap,
+                        const std::map<std::string,std::string>& param_str_map,
                         const MonCommand *this_cmd);
-  void get_mon_status(Formatter *f, ostream& ss);
-  void _quorum_status(Formatter *f, ostream& ss);
-  bool _add_bootstrap_peer_hint(string cmd, cmdmap_t& cmdmap, ostream& ss);
+  void get_mon_status(ceph::Formatter *f);
+  void _quorum_status(ceph::Formatter *f, std::ostream& ss);
+  bool _add_bootstrap_peer_hint(std::string_view cmd, const cmdmap_t& cmdmap,
+                               std::ostream& ss);
+  void handle_tell_command(MonOpRequestRef op);
   void handle_command(MonOpRequestRef op);
   void handle_route(MonOpRequestRef op);
 
-  void handle_mon_metadata(MonOpRequestRef op);
-  int get_mon_metadata(int mon, Formatter *f, ostream& err);
-  int print_nodes(Formatter *f, ostream& err);
+  int get_mon_metadata(int mon, ceph::Formatter *f, std::ostream& err);
+  int print_nodes(ceph::Formatter *f, std::ostream& err);
 
-  // Accumulate metadata across calls to update_mon_metadata
-  map<int, Metadata> mon_metadata;
-  map<int, Metadata> pending_metadata;
+  // track metadata reported by win_election()
+  std::map<int, Metadata> mon_metadata;
+  std::map<int, Metadata> pending_metadata;
 
   /**
    *
    */
   struct health_cache_t {
     health_status_t overall;
-    string summary;
+    std::string summary;
 
     void reset() {
       // health_status_t doesn't really have a NONE value and we're not
@@ -725,7 +781,7 @@ public:
 
   void health_tick_start();
   void health_tick_stop();
-  utime_t health_interval_calc_next_update();
+  ceph::real_clock::time_point health_interval_calc_next_update();
   void health_interval_start();
   void health_interval_stop();
   void health_events_cleanup();
@@ -735,27 +791,13 @@ public:
   void do_health_to_clog_interval();
   void do_health_to_clog(bool force = false);
 
-  /**
-   * Generate health report
-   *
-   * @param status one-line status summary
-   * @param detailbl optional bufferlist* to fill with a detailed report
-   * @returns health status
-   */
-  health_status_t get_health(list<string>& status, bufferlist *detailbl,
-                             Formatter *f);
-
-  health_status_t get_health_status(
-    bool want_detail,
-    Formatter *f,
-    std::string *plain,
-    const char *sep1 = " ",
-    const char *sep2 = "; ");
   void log_health(
     const health_check_map_t& updated,
     const health_check_map_t& previous,
     MonitorDBStore::TransactionRef t);
 
+  void update_pending_metadata();
+
 protected:
 
   class HealthCheckLogStatus {
@@ -775,10 +817,14 @@ protected:
 
 public:
 
-  void get_cluster_status(stringstream &ss, Formatter *f);
+  void get_cluster_status(std::stringstream &ss, ceph::Formatter *f,
+                         MonSession *session);
+
+  void reply_command(MonOpRequestRef op, int rc, const std::string &rs, version_t version);
+  void reply_command(MonOpRequestRef op, int rc, const std::string &rs, ceph::buffer::list& rdata, version_t version);
+
+  void reply_tell_command(MonOpRequestRef op, int rc, const std::string &rs);
 
-  void reply_command(MonOpRequestRef op, int rc, const string &rs, version_t version);
-  void reply_command(MonOpRequestRef op, int rc, const string &rs, bufferlist& rdata, version_t version);
 
 
   void handle_probe(MonOpRequestRef op);
@@ -802,11 +848,10 @@ public:
   // request routing
   struct RoutedRequest {
     uint64_t tid;
-    bufferlist request_bl;
+    ceph::buffer::list request_bl;
     MonSession *session;
     ConnectionRef con;
     uint64_t con_features;
-    entity_inst_t client_inst;
     MonOpRequestRef op;
 
     RoutedRequest() : tid(0), session(NULL), con_features(0) {}
@@ -816,11 +861,10 @@ public:
     }
   };
   uint64_t routed_request_tid;
-  map<uint64_t, RoutedRequest*> routed_requests;
-  
+  std::map<uint64_t, RoutedRequest*> routed_requests;
+
   void forward_request_leader(MonOpRequestRef op);
   void handle_forward(MonOpRequestRef op);
-  void try_send_message(Message *m, const entity_inst_t& to);
   void send_reply(MonOpRequestRef op, Message *reply);
   void no_reply(MonOpRequestRef op);
   void resend_routed_requests();
@@ -828,25 +872,28 @@ public:
   void remove_all_sessions();
   void waitlist_or_zap_client(MonOpRequestRef op);
 
-  void send_command(const entity_inst_t& inst,
-                   const vector<string>& com);
+  void send_mon_message(Message *m, int rank);
+  /** can_change_external_state if we can do things like
+   *  call elections as a result of the new map.
+   */
+  void notify_new_monmap(bool can_change_external_state=false, bool remove_rank_elector=true);
 
 public:
   struct C_Command : public C_MonOp {
-    Monitor *mon;
+    Monitor &mon;
     int rc;
-    string rs;
-    bufferlist rdata;
+    std::string rs;
+    ceph::buffer::list rdata;
     version_t version;
-    C_Command(Monitor *_mm, MonOpRequestRef _op, int r, string s, version_t v) :
+    C_Command(Monitor &_mm, MonOpRequestRef _op, int r, std::string s, version_t v) :
       C_MonOp(_op), mon(_mm), rc(r), rs(s), version(v){}
-    C_Command(Monitor *_mm, MonOpRequestRef _op, int r, string s, bufferlist rd, version_t v) :
+    C_Command(Monitor &_mm, MonOpRequestRef _op, int r, std::string s, ceph::buffer::list rd, version_t v) :
       C_MonOp(_op), mon(_mm), rc(r), rs(s), rdata(rd), version(v){}
 
     void _finish(int r) override {
-      MMonCommand *m = static_cast<MMonCommand*>(op->get_req());
+      auto m = op->get_req<MMonCommand>();
       if (r >= 0) {
-        ostringstream ss;
+       std::ostringstream ss;
         if (!op->get_req()->get_connection()) {
           ss << "connection dropped for command ";
         } else {
@@ -854,23 +901,29 @@ public:
 
           // if client drops we may not have a session to draw information from.
           if (s) {
-            ss << "from='" << s->inst << "' "
+            ss << "from='" << s->name << " " << s->addrs << "' "
               << "entity='" << s->entity_name << "' ";
           } else {
             ss << "session dropped for command ";
           }
         }
-        ss << "cmd='" << m->cmd << "': finished";
-
-        mon->audit_clog->info() << ss.str();
-       mon->reply_command(op, rc, rs, rdata, version);
+        cmdmap_t cmdmap;
+        std::ostringstream ds;
+        std::string prefix;
+        cmdmap_from_json(m->cmd, &cmdmap, ds);
+        cmd_getval(cmdmap, "prefix", prefix);
+        if (prefix != "config set" && prefix != "config-key set")
+          ss << "cmd='" << m->cmd << "': finished";
+
+        mon.audit_clog->info() << ss.str();
+        mon.reply_command(op, rc, rs, rdata, version);
       }
       else if (r == -ECANCELED)
         return;
       else if (r == -EAGAIN)
-       mon->dispatch_op(op);
+        mon.dispatch_op(op);
       else
-       assert(0 == "bad C_Command return value");
+       ceph_abort_msg("bad C_Command return value");
     }
   };
 
@@ -887,7 +940,7 @@ public:
       else if (r == -ECANCELED)
         return;
       else
-       assert(0 == "bad C_RetryMessage return value");
+       ceph_abort_msg("bad C_RetryMessage return value");
     }
   };
 
@@ -895,30 +948,70 @@ public:
   //on forwarded messages, so we create a non-locking version for this class
   void _ms_dispatch(Message *m);
   bool ms_dispatch(Message *m) override {
-    lock.Lock();
+    std::lock_guard l{lock};
     _ms_dispatch(m);
-    lock.Unlock();
     return true;
   }
   void dispatch_op(MonOpRequestRef op);
   //mon_caps is used for un-connected messages from monitors
-  MonCap * mon_caps;
-  bool ms_get_authorizer(int dest_type, AuthAuthorizer **authorizer, bool force_new) override;
-  bool ms_verify_authorizer(Connection *con, int peer_type,
-                           int protocol, bufferlist& authorizer_data, bufferlist& authorizer_reply,
-                           bool& isvalid, CryptoKey& session_key) override;
+  MonCap mon_caps;
+  bool get_authorizer(int dest_type, AuthAuthorizer **authorizer);
+public: // for AuthMonitor msgr1:
+  int ms_handle_authentication(Connection *con) override;
+private:
+  void ms_handle_accept(Connection *con) override;
   bool ms_handle_reset(Connection *con) override;
   void ms_handle_remote_reset(Connection *con) override {}
   bool ms_handle_refused(Connection *con) override;
 
-  int write_default_keyring(bufferlist& bl);
+  // AuthClient
+  int get_auth_request(
+    Connection *con,
+    AuthConnectionMeta *auth_meta,
+    uint32_t *method,
+    std::vector<uint32_t> *preferred_modes,
+    ceph::buffer::list *out) override;
+  int handle_auth_reply_more(
+    Connection *con,
+    AuthConnectionMeta *auth_meta,
+   const ceph::buffer::list& bl,
+    ceph::buffer::list *reply) override;
+  int handle_auth_done(
+    Connection *con,
+    AuthConnectionMeta *auth_meta,
+    uint64_t global_id,
+    uint32_t con_mode,
+    const ceph::buffer::list& bl,
+    CryptoKey *session_key,
+    std::string *connection_secret) override;
+  int handle_auth_bad_method(
+    Connection *con,
+    AuthConnectionMeta *auth_meta,
+    uint32_t old_auth_method,
+    int result,
+    const std::vector<uint32_t>& allowed_methods,
+    const std::vector<uint32_t>& allowed_modes) override;
+  // /AuthClient
+  // AuthServer
+  int handle_auth_request(
+    Connection *con,
+    AuthConnectionMeta *auth_meta,
+    bool more,
+    uint32_t auth_method,
+    const ceph::buffer::list& bl,
+    ceph::buffer::list *reply) override;
+  // /AuthServer
+
+  int write_default_keyring(ceph::buffer::list& bl);
   void extract_save_mon_key(KeyRing& keyring);
 
   void collect_metadata(Metadata *m);
-  void update_mon_metadata(int from, Metadata&& m);
   int load_metadata();
-  void count_metadata(const string& field, Formatter *f);
-  void count_metadata(const string& field, map<string,int> *out);
+  void count_metadata(const std::string& field, ceph::Formatter *f);
+  void count_metadata(const std::string& field, std::map<std::string,int> *out);
+  // get_all_versions() gathers version information from daemons for health check
+  void get_all_versions(std::map<std::string, std::list<std::string>> &versions);
+  void get_versions(std::map<std::string, std::list<std::string>> &versions);
 
   // features
   static CompatSet get_initial_supported_features();
@@ -932,7 +1025,7 @@ public:
   OpTracker op_tracker;
 
  public:
-  Monitor(CephContext *cct_, string nm, MonitorDBStore *s,
+  Monitor(CephContext *cct_, std::string nm, MonitorDBStore *s,
          Messenger *m, Messenger *mgr_m, MonMap *map);
   ~Monitor() override;
 
@@ -940,7 +1033,7 @@ public:
 
   // config observer
   const char** get_tracked_conf_keys() const override;
-  void handle_conf_change(const struct md_config_t *conf,
+  void handle_conf_change(const ConfigProxy& conf,
                           const std::set<std::string> &changed) override;
 
   void update_log_clients();
@@ -954,7 +1047,7 @@ public:
 
   void handle_signal(int sig);
 
-  int mkfs(bufferlist& osdmapbl);
+  int mkfs(ceph::buffer::list& osdmapbl);
 
   /**
    * check cluster_fsid file
@@ -971,8 +1064,10 @@ public:
   int write_fsid();
   int write_fsid(MonitorDBStore::TransactionRef t);
 
-  void do_admin_command(std::string command, cmdmap_t& cmdmap,
-                       std::string format, ostream& ss);
+  int do_admin_command(std::string_view command, const cmdmap_t& cmdmap,
+                      ceph::Formatter *f,
+                      std::ostream& err,
+                      std::ostream& out);
 
 private:
   // don't allow copying
@@ -981,27 +1076,29 @@ private:
 
 public:
   static void format_command_descriptions(const std::vector<MonCommand> &commands,
-                                         Formatter *f,
-                                         bufferlist *rdata,
-                                         bool hide_mgr_flag=false);
+                                         ceph::Formatter *f,
+                                         uint64_t features,
+                                         ceph::buffer::list *rdata);
 
   const std::vector<MonCommand> &get_local_commands(mon_feature_t f) {
-    if (f.contains_all(ceph::features::mon::FEATURE_LUMINOUS))
+    if (f.contains_all(ceph::features::mon::FEATURE_NAUTILUS)) {
       return local_mon_commands;
-    else
-      return local_upgrading_mon_commands;
+    } else {
+      return prenautilus_local_mon_commands;
+    }
   }
-  const bufferlist& get_local_commands_bl(mon_feature_t f) {
-    if (f.contains_all(ceph::features::mon::FEATURE_LUMINOUS))
+  const ceph::buffer::list& get_local_commands_bl(mon_feature_t f) {
+    if (f.contains_all(ceph::features::mon::FEATURE_NAUTILUS)) {
       return local_mon_commands_bl;
-    else
-      return local_upgrading_mon_commands_bl;
+    } else {
+      return prenautilus_local_mon_commands_bl;
+    }
   }
   void set_leader_commands(const std::vector<MonCommand>& cmds) {
     leader_mon_commands = cmds;
   }
 
-  static bool is_keyring_required();
+  bool is_keyring_required();
 };
 
 #define CEPH_MON_FEATURE_INCOMPAT_BASE CompatSet::Feature (1, "initial feature set (~v.18)")
@@ -1013,8 +1110,40 @@ public:
 #define CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V3 CompatSet::Feature(7, "support shec erasure code")
 #define CEPH_MON_FEATURE_INCOMPAT_KRAKEN CompatSet::Feature(8, "support monmap features")
 #define CEPH_MON_FEATURE_INCOMPAT_LUMINOUS CompatSet::Feature(9, "luminous ondisk layout")
+#define CEPH_MON_FEATURE_INCOMPAT_MIMIC CompatSet::Feature(10, "mimic ondisk layout")
+#define CEPH_MON_FEATURE_INCOMPAT_NAUTILUS CompatSet::Feature(11, "nautilus ondisk layout")
+#define CEPH_MON_FEATURE_INCOMPAT_OCTOPUS CompatSet::Feature(12, "octopus ondisk layout")
+#define CEPH_MON_FEATURE_INCOMPAT_PACIFIC CompatSet::Feature(13, "pacific ondisk layout")
+#define CEPH_MON_FEATURE_INCOMPAT_QUINCY CompatSet::Feature(14, "quincy ondisk layout")
 // make sure you add your feature to Monitor::get_supported_features
 
 
+/* Callers use:
+ *
+ *      new C_MonContext{...}
+ *
+ * instead of
+ *
+ *      new C_MonContext(...)
+ *
+ * because of gcc bug [1].
+ *
+ * [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85883
+ */
+template<typename T>
+class C_MonContext : public LambdaContext<T> {
+public:
+  C_MonContext(const Monitor* m, T&& f) :
+      LambdaContext<T>(std::forward<T>(f)),
+      mon(m)
+  {}
+  void finish(int r) override {
+    if (mon->is_shutdown())
+      return;
+    LambdaContext<T>::finish(r);
+  }
+private:
+  const Monitor* mon;
+};
 
 #endif