diff options
Diffstat (limited to 'src/crimson/mon/MonClient.h')
-rw-r--r-- | src/crimson/mon/MonClient.h | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/crimson/mon/MonClient.h b/src/crimson/mon/MonClient.h new file mode 100644 index 000000000..1228ecd0b --- /dev/null +++ b/src/crimson/mon/MonClient.h @@ -0,0 +1,218 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include <memory> +#include <vector> + +#include <seastar/core/future.hh> +#include <seastar/core/gate.hh> +#include <seastar/core/lowres_clock.hh> +#include <seastar/core/shared_ptr.hh> +#include <seastar/core/timer.hh> + +#include "auth/AuthRegistry.h" +#include "auth/KeyRing.h" +#include "common/ceph_context.h" + +#include "crimson/auth/AuthClient.h" +#include "crimson/auth/AuthServer.h" +#include "crimson/common/auth_handler.h" +#include "crimson/common/gated.h" +#include "crimson/net/Dispatcher.h" +#include "crimson/net/Fwd.h" + +#include "mon/MonMap.h" + +#include "mon/MonSub.h" + +template<typename Message> using Ref = boost::intrusive_ptr<Message>; +namespace crimson::net { + class Messenger; +} + +class LogClient; + +struct AuthAuthorizeHandler; +class MAuthReply; +struct MMonMap; +struct MMonSubscribeAck; +struct MMonGetVersionReply; +struct MMonCommand; +struct MMonCommandAck; +struct MLogAck; +struct MConfig; + +enum class log_flushing_t; + +namespace crimson::mon { + +class Connection; + +class Client : public crimson::net::Dispatcher, + public crimson::auth::AuthClient, + public crimson::auth::AuthServer +{ + EntityName entity_name; + KeyRing keyring; + const uint32_t want_keys; + + MonMap monmap; + bool ready_to_send = false; + seastar::shared_ptr<Connection> active_con; + std::vector<seastar::shared_ptr<Connection>> pending_conns; + seastar::timer<seastar::lowres_clock> timer; + + crimson::net::Messenger& msgr; + + LogClient *log_client; + bool more_log_pending = false; + utime_t last_send_log; + + seastar::future<> send_log(log_flushing_t flush_flag); + seastar::future<> wait_for_send_log(); + + // commands + using get_version_t = seastar::future<std::tuple<version_t, version_t>>; + + ceph_tid_t last_version_req_id = 0; + std::map<ceph_tid_t, typename get_version_t::promise_type> version_reqs; + + ceph_tid_t last_mon_command_id = 0; + using command_result_t = + seastar::future<std::tuple<std::int32_t, std::string, ceph::bufferlist>>; + struct mon_command_t { + MURef<MMonCommand> req; + typename command_result_t::promise_type result; + mon_command_t(MURef<MMonCommand> req); + }; + std::vector<mon_command_t> mon_commands; + + MonSub sub; + +public: + Client(crimson::net::Messenger&, crimson::common::AuthHandler&); + Client(Client&&); + ~Client(); + seastar::future<> start(); + seastar::future<> stop(); + + void set_log_client(LogClient *clog) { + log_client = clog; + } + + const uuid_d& get_fsid() const { + return monmap.fsid; + } + get_version_t get_version(const std::string& map); + command_result_t run_command(std::string&& cmd, + bufferlist&& bl); + seastar::future<> send_message(MessageURef); + bool sub_want(const std::string& what, version_t start, unsigned flags); + void sub_got(const std::string& what, version_t have); + void sub_unwant(const std::string& what); + bool sub_want_increment(const std::string& what, version_t start, unsigned flags); + seastar::future<> renew_subs(); + seastar::future<> wait_for_config(); + + void print(std::ostream&) const; +private: + // AuthServer methods + std::pair<std::vector<uint32_t>, std::vector<uint32_t>> + get_supported_auth_methods(int peer_type) final; + uint32_t pick_con_mode(int peer_type, + uint32_t auth_method, + const std::vector<uint32_t>& preferred_modes) final; + AuthAuthorizeHandler* get_auth_authorize_handler(int peer_type, + int auth_method) final; + int handle_auth_request(crimson::net::Connection &conn, + AuthConnectionMeta &auth_meta, + bool more, + uint32_t auth_method, + const ceph::bufferlist& payload, + uint64_t *p_peer_global_id, + ceph::bufferlist *reply) final; + + crimson::common::CephContext cct; // for auth_registry + AuthRegistry auth_registry; + crimson::common::AuthHandler& auth_handler; + + // AuthClient methods + crimson::auth::AuthClient::auth_request_t + get_auth_request(crimson::net::Connection &conn, + AuthConnectionMeta &auth_meta) final; + + // Handle server's request to continue the handshake + ceph::bufferlist handle_auth_reply_more(crimson::net::Connection &conn, + AuthConnectionMeta &auth_meta, + const bufferlist& bl) final; + + // Handle server's indication that authentication succeeded + int handle_auth_done(crimson::net::Connection &conn, + AuthConnectionMeta &auth_meta, + uint64_t global_id, + uint32_t con_mode, + const bufferlist& bl) final; + + // Handle server's indication that the previous auth attempt failed + int handle_auth_bad_method(crimson::net::Connection &conn, + AuthConnectionMeta &auth_meta, + uint32_t old_auth_method, + int result, + const std::vector<uint32_t>& allowed_methods, + const std::vector<uint32_t>& allowed_modes) final; + +private: + void tick(); + + std::optional<seastar::future<>> ms_dispatch(crimson::net::ConnectionRef conn, + MessageRef m) override; + void ms_handle_reset(crimson::net::ConnectionRef conn, bool is_replace) override; + + seastar::future<> handle_monmap(crimson::net::Connection &conn, + Ref<MMonMap> m); + seastar::future<> handle_auth_reply(crimson::net::Connection &conn, + Ref<MAuthReply> m); + seastar::future<> handle_subscribe_ack(Ref<MMonSubscribeAck> m); + seastar::future<> handle_get_version_reply(Ref<MMonGetVersionReply> m); + seastar::future<> handle_mon_command_ack(Ref<MMonCommandAck> m); + seastar::future<> handle_log_ack(Ref<MLogAck> m); + seastar::future<> handle_config(Ref<MConfig> m); + + seastar::future<> on_session_opened(); +private: + seastar::future<> load_keyring(); + seastar::future<> authenticate(); + + bool is_hunting() const; + // @param rank, rank of the monitor to be connected, if it is less than 0, + // try to connect to all monitors in monmap, until one of them + // is connected. + // @return true if a connection to monitor is established + seastar::future<bool> reopen_session(int rank); + std::vector<unsigned> get_random_mons(unsigned n) const; + seastar::future<> _add_conn(unsigned rank, uint64_t global_id); + void _finish_auth(const entity_addr_t& peer); + crimson::common::Gated gate; + + // messages that are waiting for the active_con to be available + struct pending_msg_t { + pending_msg_t(MessageURef m) : msg(std::move(m)) {} + MessageURef msg; + seastar::promise<> pr; + }; + std::deque<pending_msg_t> pending_messages; + std::optional<seastar::promise<>> config_updated; +}; + +inline std::ostream& operator<<(std::ostream& out, const Client& client) { + client.print(out); + return out; +} + +} // namespace crimson::mon + +#if FMT_VERSION >= 90000 +template <> struct fmt::formatter<crimson::mon::Client> : fmt::ostream_formatter {}; +#endif |