1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
6 A Crimson-wise version of the src/common/admin_socket.h
8 Note: assumed to be running on a single core.
12 #include <string_view>
14 #include <seastar/core/future.hh>
15 #include <seastar/core/gate.hh>
16 #include <seastar/core/iostream.hh>
17 #include <seastar/core/shared_mutex.hh>
18 #include <seastar/core/shared_ptr.hh>
19 #include <seastar/net/api.hh>
21 #include "common/cmdparse.h"
23 using namespace std::literals
;
25 namespace crimson::admin
{
30 * A specific hook must implement exactly one of the two interfaces:
31 * (1) call(command, cmdmap, format, out)
33 * (2) exec_command(formatter, command, cmdmap, format, out)
35 * The default implementation of (1) above calls exec_command() after handling
36 * most of the boiler-plate choirs:
37 * - setting up the formatter, with an appropiate 'section' already opened;
38 * - handling possible failures (exceptions or future_exceptions) returned
40 * - flushing the output to the outgoing bufferlist.
42 class AdminSocketHook
{
44 AdminSocketHook(std::string_view prefix
,
45 std::string_view desc
,
46 std::string_view help
) :
47 prefix
{prefix
}, desc
{desc
}, help
{help
}
50 * \retval 'false' for hook execution errors
52 virtual seastar::future
<ceph::bufferlist
>
53 call(std::string_view command
,
54 std::string_view format
,
55 const cmdmap_t
& cmdmap
) const = 0;
56 virtual ~AdminSocketHook() {}
57 const std::string_view prefix
;
58 const std::string_view desc
;
59 const std::string_view help
;
62 class AdminSocket
: public seastar::enable_lw_shared_from_this
<AdminSocket
> {
64 AdminSocket() = default;
65 ~AdminSocket() = default;
67 AdminSocket(const AdminSocket
&) = delete;
68 AdminSocket
& operator=(const AdminSocket
&) = delete;
69 AdminSocket(AdminSocket
&&) = delete;
70 AdminSocket
& operator=(AdminSocket
&&) = delete;
72 using hook_server_tag
= const void*;
75 * create the async Seastar thread that handles asok commands arriving
78 seastar::future
<> start(const std::string
& path
);
80 seastar::future
<> stop();
83 * register an admin socket hooks server
85 * The server registers a set of APIs under a common hook_server_tag.
87 * Commands (APIs) are registered under a command string. Incoming
88 * commands are split by spaces and matched against the longest
89 * registered command. For example, if 'foo' and 'foo bar' are
90 * registered, and an incoming command is 'foo bar baz', it is
91 * matched with 'foo bar', while 'foo fud' will match 'foo'.
93 * The entire incoming command string is passed to the registered
96 * \param server_tag a tag identifying the server registering the hook
97 * \param apis_served a vector of the commands served by this server. Each
98 * command registration includes its identifying command string, the
99 * expected call syntax, and some help text.
101 * A note regarding the help text: if empty, command will not be
102 * included in 'help' output.
104 * \retval a shared ptr to the asok server itself, or nullopt if
105 * a block with same tag is already registered.
107 seastar::future
<> register_command(std::unique_ptr
<AdminSocketHook
>&& hook
);
110 * Registering the APIs that are served directly by the admin_socket server.
112 seastar::future
<> register_admin_commands();
116 * the result of analyzing an incoming command, and locating it in
117 * the registered APIs collection.
119 struct parsed_command_t
{
122 const AdminSocketHook
& hook
;
124 // and the shorthand:
125 using maybe_parsed_t
= std::optional
<AdminSocket::parsed_command_t
>;
127 seastar::future
<> handle_client(seastar::input_stream
<char>& inp
,
128 seastar::output_stream
<char>& out
);
130 seastar::future
<> execute_line(std::string cmdline
,
131 seastar::output_stream
<char>& out
);
133 seastar::future
<> finalize_response(seastar::output_stream
<char>& out
,
134 ceph::bufferlist
&& msgs
);
136 bool validate_command(const parsed_command_t
& parsed
,
137 const std::string
& command_text
,
138 ceph::bufferlist
& out
) const;
140 std::optional
<seastar::server_socket
> server_sock
;
141 std::optional
<seastar::connected_socket
> connected_sock
;
144 * stopping incoming ASOK requests at shutdown
146 seastar::gate stop_gate
;
149 * parse the incoming command line into the sequence of words that identifies
150 * the API, and into its arguments. Locate the command string in the
153 maybe_parsed_t
parse_cmd(std::string command_text
, bufferlist
& out
);
156 * The servers table is protected by a rw-lock, to be acquired exclusively
157 * only when registering or removing a server.
158 * The lock is locked-shared when executing any hook.
160 mutable seastar::shared_mutex servers_tbl_rwlock
;
161 using hooks_t
= std::map
<std::string_view
, std::unique_ptr
<AdminSocketHook
>>;
168 hooks_t::const_iterator
begin() const {
169 return hooks
.cbegin();
171 hooks_t::const_iterator
end() const {
175 friend class AdminSocketTest
;
176 friend class HelpHook
;
177 friend class GetdescsHook
;
180 } // namespace crimson::admin