-// -*- 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
*
* 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.
*/
#include <errno.h>
#include <cmath>
+#include <string>
+#include <array>
#include "include/types.h"
+#include "include/health.h"
#include "msg/Messenger.h"
#include "common/Timer.h"
+#include "health_check.h"
#include "MonMap.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 */
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,
};
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;
-struct MonCommand;
-
#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.
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;
CompatSet features;
- const MonCommand *leader_supported_mon_commands;
- int leader_supported_mon_commands_size;
+ 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
+
+ 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();
// -- 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) {
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; }
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;
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.
* Intersection of quorum members mon-specific feature bits
*/
mon_feature_t quorum_mon_features;
- bufferlist supported_commands_bl; // encoded MonCommands we support
- 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
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)
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
* @} // 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
}
};
- 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
*
* @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
/**
* 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
* @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:
/**
* @} // 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
* - 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;
unsigned int timecheck_acks;
utime_t timecheck_round_start;
+ friend class HealthMonitor;
/* When we hit a skew we will start a new round based off of
* 'mon_timecheck_skew_interval'. Each new round will be backed off
* until we hit 'mon_timecheck_interval' -- which is the typical
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);
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);
}
/**
public:
epoch_t get_epoch();
int get_leader() const { return 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)
+ std::string get_leader_name() {
+ return quorum.empty() ? std::string() : monmap->get_name(leader);
+ }
+ 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;
}
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 MonCommand *cmdset, int cmdsize);
- 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();
- const bufferlist& get_supported_commands_bl() {
- return supported_commands_bl;
- }
-
void update_logger();
/**
* Vector holding the Services serviced by this Monitor.
*/
- vector<PaxosService*> paxos_service;
-
- PaxosService *get_paxos_service_by_name(const string& name);
-
- 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 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);
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> ¶m_str_map);
- static const MonCommand *_get_moncommand(const string &cmd_prefix,
- MonCommand *cmds, int cmds_size);
- bool _allowed_command(MonSession *s, string &module, string &prefix,
- const map<string,cmd_vartype>& cmdmap,
- const map<string,string>& param_str_map,
+ static void _generate_command_map(cmdmap_t& cmdmap,
+ std::map<std::string,std::string> ¶m_str_map);
+ static const MonCommand *_get_moncommand(
+ 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> 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
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();
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);
- void get_cluster_status(stringstream &ss, Formatter *f);
+ 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 {
+ public:
+ health_status_t severity;
+ std::string last_message;
+ utime_t updated_at = 0;
+ HealthCheckLogStatus(health_status_t severity_,
+ const std::string &last_message_,
+ utime_t updated_at_)
+ : severity(severity_),
+ last_message(last_message_),
+ updated_at(updated_at_)
+ {}
+ };
+ std::map<std::string, HealthCheckLogStatus> health_check_log_times;
+
+public:
+
+ 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);
// 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) {}
}
};
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();
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 {
// 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");
}
};
else if (r == -ECANCELED)
return;
else
- assert(0 == "bad C_RetryMessage return value");
+ ceph_abort_msg("bad C_RetryMessage return value");
}
};
//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 update_mon_metadata(int from, Metadata&& m);
- int load_metadata(map<int, Metadata>& m);
- void count_metadata(const string& field, Formatter *f);
+ void collect_metadata(Metadata *m);
+ int load_metadata();
+ 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();
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;
// 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();
void handle_signal(int sig);
- int mkfs(bufferlist& osdmapbl);
+ int mkfs(ceph::buffer::list& osdmapbl);
/**
* check cluster_fsid file
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
Monitor& operator=(const Monitor &rhs);
public:
- static void format_command_descriptions(const MonCommand *commands,
- unsigned commands_size,
- Formatter *f,
- bufferlist *rdata,
- bool hide_mgr_flag=false);
- void get_locally_supported_monitor_commands(const MonCommand **cmds, int *count);
- /// the Monitor owns this pointer once you pass it in
- void set_leader_supported_commands(const MonCommand *cmds, int size);
- static bool is_keyring_required();
+ static void format_command_descriptions(const std::vector<MonCommand> &commands,
+ 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_NAUTILUS)) {
+ return local_mon_commands;
+ } else {
+ return prenautilus_local_mon_commands;
+ }
+ }
+ 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 prenautilus_local_mon_commands_bl;
+ }
+ }
+ void set_leader_commands(const std::vector<MonCommand>& cmds) {
+ leader_mon_commands = cmds;
+ }
+
+ bool is_keyring_required();
};
#define CEPH_MON_FEATURE_INCOMPAT_BASE CompatSet::Feature (1, "initial feature set (~v.18)")
#define CEPH_MON_FEATURE_INCOMPAT_ERASURE_CODE_PLUGINS_V2 CompatSet::Feature(6, "support isa/lrc erasure code")
#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
-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);
+/* 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;
};
-WRITE_CLASS_ENCODER(MonCommand)
#endif