]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
2 | // vim: ts=8 sw=2 smarttab | |
3 | #pragma once | |
4 | ||
5 | /** | |
6 | A Crimson-wise version of the src/common/admin_socket.h | |
7 | ||
8 | Note: assumed to be running on a single core. | |
9 | */ | |
10 | #include <map> | |
11 | #include <string> | |
12 | #include <string_view> | |
13 | ||
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> | |
20 | ||
21 | #include "common/cmdparse.h" | |
f67539c2 TL |
22 | #include "include/buffer.h" |
23 | #include "crimson/net/Fwd.h" | |
9f95a23c | 24 | |
f67539c2 TL |
25 | class MCommand; |
26 | ||
9f95a23c TL |
27 | namespace crimson::admin { |
28 | ||
29 | class AdminSocket; | |
30 | ||
f67539c2 TL |
31 | struct tell_result_t { |
32 | int ret = 0; | |
33 | std::string err; | |
34 | ceph::bufferlist out; | |
35 | tell_result_t() = default; | |
36 | tell_result_t(int ret, std::string&& err); | |
37 | tell_result_t(int ret, std::string&& err, ceph::bufferlist&& out); | |
38 | /** | |
39 | * create a \c tell_result_t indicating the successful completion | |
40 | * of command | |
41 | * | |
42 | * \param formatter the content of formatter will be flushed to the | |
43 | * output buffer | |
44 | */ | |
45 | tell_result_t(std::unique_ptr<Formatter> formatter); | |
46 | }; | |
47 | ||
9f95a23c | 48 | /** |
f67539c2 | 49 | * An abstract class to be inherited by implementations of asock hooks |
9f95a23c TL |
50 | */ |
51 | class AdminSocketHook { | |
52 | public: | |
53 | AdminSocketHook(std::string_view prefix, | |
54 | std::string_view desc, | |
55 | std::string_view help) : | |
56 | prefix{prefix}, desc{desc}, help{help} | |
57 | {} | |
58 | /** | |
f67539c2 TL |
59 | * handle command defined by cmdmap |
60 | * | |
61 | * \param cmdmap dictionary holding the named parameters | |
62 | * \param format the expected format of the output | |
63 | * \param input the binary input of the command | |
64 | * \pre \c cmdmap should be validated with \c desc | |
65 | * \retval an instance of \c tell_result_t | |
66 | * \note a negative \c ret should be set to indicate that the hook fails to | |
67 | * fulfill the command either because of an invalid input or other | |
68 | * failures. in that case, a brief reason of the failure should | |
69 | * noted in \c err in the returned value | |
9f95a23c | 70 | */ |
f67539c2 TL |
71 | virtual seastar::future<tell_result_t> call(const cmdmap_t& cmdmap, |
72 | std::string_view format, | |
73 | ceph::bufferlist&& input) const = 0; | |
9f95a23c TL |
74 | virtual ~AdminSocketHook() {} |
75 | const std::string_view prefix; | |
76 | const std::string_view desc; | |
77 | const std::string_view help; | |
78 | }; | |
79 | ||
80 | class AdminSocket : public seastar::enable_lw_shared_from_this<AdminSocket> { | |
81 | public: | |
82 | AdminSocket() = default; | |
83 | ~AdminSocket() = default; | |
84 | ||
85 | AdminSocket(const AdminSocket&) = delete; | |
86 | AdminSocket& operator=(const AdminSocket&) = delete; | |
87 | AdminSocket(AdminSocket&&) = delete; | |
88 | AdminSocket& operator=(AdminSocket&&) = delete; | |
89 | ||
9f95a23c TL |
90 | /** |
91 | * create the async Seastar thread that handles asok commands arriving | |
92 | * over the socket. | |
93 | */ | |
94 | seastar::future<> start(const std::string& path); | |
95 | ||
96 | seastar::future<> stop(); | |
97 | ||
98 | /** | |
f67539c2 | 99 | * register an admin socket hook |
9f95a23c TL |
100 | * |
101 | * Commands (APIs) are registered under a command string. Incoming | |
102 | * commands are split by spaces and matched against the longest | |
103 | * registered command. For example, if 'foo' and 'foo bar' are | |
104 | * registered, and an incoming command is 'foo bar baz', it is | |
105 | * matched with 'foo bar', while 'foo fud' will match 'foo'. | |
106 | * | |
f67539c2 | 107 | * \param hook a hook which includes its identifying command string, the |
9f95a23c TL |
108 | * expected call syntax, and some help text. |
109 | * | |
110 | * A note regarding the help text: if empty, command will not be | |
111 | * included in 'help' output. | |
9f95a23c | 112 | */ |
20effc67 | 113 | void register_command(std::unique_ptr<AdminSocketHook>&& hook); |
9f95a23c TL |
114 | |
115 | /** | |
116 | * Registering the APIs that are served directly by the admin_socket server. | |
117 | */ | |
20effc67 | 118 | void register_admin_commands(); |
f67539c2 TL |
119 | /** |
120 | * handle a command message by replying an MCommandReply with the same tid | |
121 | * | |
122 | * \param conn connection over which the incoming command message is received | |
123 | * \param m message carrying the command vector and optional input buffer | |
124 | */ | |
125 | seastar::future<> handle_command(crimson::net::ConnectionRef conn, | |
126 | boost::intrusive_ptr<MCommand> m); | |
9f95a23c | 127 | |
f67539c2 | 128 | private: |
9f95a23c TL |
129 | /** |
130 | * the result of analyzing an incoming command, and locating it in | |
131 | * the registered APIs collection. | |
132 | */ | |
133 | struct parsed_command_t { | |
f67539c2 | 134 | cmdmap_t params; |
9f95a23c TL |
135 | std::string format; |
136 | const AdminSocketHook& hook; | |
137 | }; | |
138 | // and the shorthand: | |
9f95a23c TL |
139 | seastar::future<> handle_client(seastar::input_stream<char>& inp, |
140 | seastar::output_stream<char>& out); | |
141 | ||
142 | seastar::future<> execute_line(std::string cmdline, | |
143 | seastar::output_stream<char>& out); | |
144 | ||
145 | seastar::future<> finalize_response(seastar::output_stream<char>& out, | |
146 | ceph::bufferlist&& msgs); | |
147 | ||
f67539c2 TL |
148 | seastar::future<tell_result_t> execute_command(const std::vector<std::string>& cmd, |
149 | ceph::bufferlist&& buf); | |
9f95a23c | 150 | |
f67539c2 | 151 | std::optional<seastar::future<>> task; |
9f95a23c TL |
152 | std::optional<seastar::server_socket> server_sock; |
153 | std::optional<seastar::connected_socket> connected_sock; | |
154 | ||
155 | /** | |
156 | * stopping incoming ASOK requests at shutdown | |
157 | */ | |
158 | seastar::gate stop_gate; | |
159 | ||
160 | /** | |
f67539c2 TL |
161 | * parse the incoming command vector, find a registered hook by looking up by |
162 | * its prefix, perform sanity checks on the parsed parameters with the hook's | |
163 | * command description | |
164 | * | |
165 | * \param cmd a vector of string which presents a command | |
166 | * \retval on success, a \c parsed_command_t is returned, tell_result_t with | |
167 | * detailed error messages is returned otherwise | |
9f95a23c | 168 | */ |
f67539c2 TL |
169 | std::variant<parsed_command_t, tell_result_t> |
170 | parse_cmd(const std::vector<std::string>& cmd); | |
9f95a23c | 171 | |
9f95a23c TL |
172 | using hooks_t = std::map<std::string_view, std::unique_ptr<AdminSocketHook>>; |
173 | hooks_t hooks; | |
174 | ||
20effc67 | 175 | public: |
9f95a23c TL |
176 | /** |
177 | * iterator support | |
178 | */ | |
179 | hooks_t::const_iterator begin() const { | |
180 | return hooks.cbegin(); | |
181 | } | |
182 | hooks_t::const_iterator end() const { | |
183 | return hooks.cend(); | |
184 | } | |
9f95a23c TL |
185 | }; |
186 | ||
187 | } // namespace crimson::admin |