summaryrefslogtreecommitdiffstats
path: root/src/crimson/admin/admin_socket.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/crimson/admin/admin_socket.h')
-rw-r--r--src/crimson/admin/admin_socket.h201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/crimson/admin/admin_socket.h b/src/crimson/admin/admin_socket.h
new file mode 100644
index 000000000..a842b62a2
--- /dev/null
+++ b/src/crimson/admin/admin_socket.h
@@ -0,0 +1,201 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+#pragma once
+
+/**
+ A Crimson-wise version of the src/common/admin_socket.h
+
+ Note: assumed to be running on a single core.
+*/
+#include <map>
+#include <string>
+#include <string_view>
+
+#include <seastar/core/future.hh>
+#include <seastar/core/gate.hh>
+#include <seastar/core/iostream.hh>
+#include <seastar/core/shared_mutex.hh>
+#include <seastar/core/shared_ptr.hh>
+#include <seastar/net/api.hh>
+
+#include "common/cmdparse.h"
+#include "include/buffer.h"
+#include "crimson/net/Fwd.h"
+
+using namespace std::literals;
+
+class MCommand;
+
+namespace crimson::admin {
+
+class AdminSocket;
+
+struct tell_result_t {
+ int ret = 0;
+ std::string err;
+ ceph::bufferlist out;
+ tell_result_t() = default;
+ tell_result_t(int ret, std::string&& err);
+ tell_result_t(int ret, std::string&& err, ceph::bufferlist&& out);
+ /**
+ * create a \c tell_result_t indicating the successful completion
+ * of command
+ *
+ * \param formatter the content of formatter will be flushed to the
+ * output buffer
+ */
+ tell_result_t(std::unique_ptr<Formatter> formatter);
+};
+
+/**
+ * An abstract class to be inherited by implementations of asock hooks
+ */
+class AdminSocketHook {
+ public:
+ AdminSocketHook(std::string_view prefix,
+ std::string_view desc,
+ std::string_view help) :
+ prefix{prefix}, desc{desc}, help{help}
+ {}
+ /**
+ * handle command defined by cmdmap
+ *
+ * \param cmdmap dictionary holding the named parameters
+ * \param format the expected format of the output
+ * \param input the binary input of the command
+ * \pre \c cmdmap should be validated with \c desc
+ * \retval an instance of \c tell_result_t
+ * \note a negative \c ret should be set to indicate that the hook fails to
+ * fulfill the command either because of an invalid input or other
+ * failures. in that case, a brief reason of the failure should
+ * noted in \c err in the returned value
+ */
+ virtual seastar::future<tell_result_t> call(const cmdmap_t& cmdmap,
+ std::string_view format,
+ ceph::bufferlist&& input) const = 0;
+ virtual ~AdminSocketHook() {}
+ const std::string_view prefix;
+ const std::string_view desc;
+ const std::string_view help;
+};
+
+class AdminSocket : public seastar::enable_lw_shared_from_this<AdminSocket> {
+ public:
+ AdminSocket() = default;
+ ~AdminSocket() = default;
+
+ AdminSocket(const AdminSocket&) = delete;
+ AdminSocket& operator=(const AdminSocket&) = delete;
+ AdminSocket(AdminSocket&&) = delete;
+ AdminSocket& operator=(AdminSocket&&) = delete;
+
+ using hook_server_tag = const void*;
+
+ /**
+ * create the async Seastar thread that handles asok commands arriving
+ * over the socket.
+ */
+ seastar::future<> start(const std::string& path);
+
+ seastar::future<> stop();
+
+ /**
+ * register an admin socket hook
+ *
+ * Commands (APIs) are registered under a command string. Incoming
+ * commands are split by spaces and matched against the longest
+ * registered command. For example, if 'foo' and 'foo bar' are
+ * registered, and an incoming command is 'foo bar baz', it is
+ * matched with 'foo bar', while 'foo fud' will match 'foo'.
+ *
+ * \param hook a hook which includes its identifying command string, the
+ * expected call syntax, and some help text.
+ *
+ * A note regarding the help text: if empty, command will not be
+ * included in 'help' output.
+ */
+ seastar::future<> register_command(std::unique_ptr<AdminSocketHook>&& hook);
+
+ /**
+ * Registering the APIs that are served directly by the admin_socket server.
+ */
+ seastar::future<> register_admin_commands();
+ /**
+ * handle a command message by replying an MCommandReply with the same tid
+ *
+ * \param conn connection over which the incoming command message is received
+ * \param m message carrying the command vector and optional input buffer
+ */
+ seastar::future<> handle_command(crimson::net::ConnectionRef conn,
+ boost::intrusive_ptr<MCommand> m);
+
+private:
+ /**
+ * the result of analyzing an incoming command, and locating it in
+ * the registered APIs collection.
+ */
+ struct parsed_command_t {
+ cmdmap_t params;
+ std::string format;
+ const AdminSocketHook& hook;
+ };
+ // and the shorthand:
+ seastar::future<> handle_client(seastar::input_stream<char>& inp,
+ seastar::output_stream<char>& out);
+
+ seastar::future<> execute_line(std::string cmdline,
+ seastar::output_stream<char>& out);
+
+ seastar::future<> finalize_response(seastar::output_stream<char>& out,
+ ceph::bufferlist&& msgs);
+
+ seastar::future<tell_result_t> execute_command(const std::vector<std::string>& cmd,
+ ceph::bufferlist&& buf);
+
+ std::optional<seastar::future<>> task;
+ std::optional<seastar::server_socket> server_sock;
+ std::optional<seastar::connected_socket> connected_sock;
+
+ /**
+ * stopping incoming ASOK requests at shutdown
+ */
+ seastar::gate stop_gate;
+
+ /**
+ * parse the incoming command vector, find a registered hook by looking up by
+ * its prefix, perform sanity checks on the parsed parameters with the hook's
+ * command description
+ *
+ * \param cmd a vector of string which presents a command
+ * \retval on success, a \c parsed_command_t is returned, tell_result_t with
+ * detailed error messages is returned otherwise
+ */
+ std::variant<parsed_command_t, tell_result_t>
+ parse_cmd(const std::vector<std::string>& cmd);
+
+ /**
+ * The servers table is protected by a rw-lock, to be acquired exclusively
+ * only when registering or removing a server.
+ * The lock is locked-shared when executing any hook.
+ */
+ mutable seastar::shared_mutex servers_tbl_rwlock;
+ using hooks_t = std::map<std::string_view, std::unique_ptr<AdminSocketHook>>;
+ hooks_t hooks;
+
+ public:
+ /**
+ * iterator support
+ */
+ hooks_t::const_iterator begin() const {
+ return hooks.cbegin();
+ }
+ hooks_t::const_iterator end() const {
+ return hooks.cend();
+ }
+
+ friend class AdminSocketTest;
+ friend class HelpHook;
+ friend class GetdescsHook;
+};
+
+} // namespace crimson::admin