// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- // vim: ts=8 sw=2 smarttab #pragma once #include #include #include #include #include #include #include #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 using Ref = boost::intrusive_ptr; 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 active_con; std::vector> pending_conns; seastar::timer 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>; ceph_tid_t last_version_req_id = 0; std::map version_reqs; ceph_tid_t last_mon_command_id = 0; using command_result_t = seastar::future>; struct mon_command_t { MURef req; typename command_result_t::promise_type result; mon_command_t(MURef req); }; std::vector 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> get_supported_auth_methods(int peer_type) final; uint32_t pick_con_mode(int peer_type, uint32_t auth_method, const std::vector& 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& allowed_methods, const std::vector& allowed_modes) final; private: void tick(); std::optional> 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 m); seastar::future<> handle_auth_reply(crimson::net::Connection &conn, Ref m); seastar::future<> handle_subscribe_ack(Ref m); seastar::future<> handle_get_version_reply(Ref m); seastar::future<> handle_mon_command_ack(Ref m); seastar::future<> handle_log_ack(Ref m); seastar::future<> handle_config(Ref 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 reopen_session(int rank); std::vector 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_messages; std::optional> 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 : fmt::ostream_formatter {}; #endif