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