]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
7c673cae FG |
2 | // vim: ts=8 sw=2 smarttab |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2011 New Dream Network | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
11fdf7f2 | 10 | * License version 2.1, as published by the Free Software |
7c673cae | 11 | * Foundation. See file COPYING. |
11fdf7f2 | 12 | * |
7c673cae FG |
13 | */ |
14 | ||
15 | #ifndef CEPH_COMMON_ADMIN_SOCKET_H | |
16 | #define CEPH_COMMON_ADMIN_SOCKET_H | |
17 | ||
9f95a23c TL |
18 | #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN) |
19 | #include "crimson/admin/admin_socket.h" | |
20 | #else | |
21 | ||
11fdf7f2 TL |
22 | #include <condition_variable> |
23 | #include <mutex> | |
24 | #include <string> | |
25 | #include <string_view> | |
26 | #include <thread> | |
27 | ||
28 | #include "include/buffer.h" | |
9f95a23c TL |
29 | #include "include/common_fwd.h" |
30 | #include "common/ref.h" | |
11fdf7f2 | 31 | #include "common/cmdparse.h" |
7c673cae | 32 | |
9f95a23c TL |
33 | class MCommand; |
34 | class MMonCommand; | |
7c673cae | 35 | |
f67539c2 | 36 | inline constexpr auto CEPH_ADMIN_SOCK_VERSION = std::string_view("2"); |
7c673cae FG |
37 | |
38 | class AdminSocketHook { | |
39 | public: | |
9f95a23c TL |
40 | /** |
41 | * @brief | |
42 | * Handler for admin socket commands, synchronous version | |
43 | * | |
44 | * Executes action associated with admin command and returns byte-stream output @c out. | |
45 | * There is no restriction on output. Each handler defines output semantics. | |
46 | * Typically output is textual representation of some ceph's internals. | |
47 | * Handler should use provided formatter @c f if structuralized output is being produced. | |
48 | * | |
49 | * @param command[in] String matching constant part of cmddesc in @ref AdminSocket::register_command | |
50 | * @param cmdmap[in] Parameters extracted from argument part of cmddesc in @ref AdminSocket::register_command | |
51 | * @param f[in] Formatter created according to requestor preference, used by `ceph --format` | |
52 | * @param errss[out] Error stream, should contain details in case of execution failure | |
53 | * @param out[out] Produced output | |
54 | * | |
55 | * @retval 0 Success, errss is ignored and does not contribute to output | |
56 | * @retval <0 Error code, errss is prepended to @c out | |
57 | * | |
58 | * @note If @c out is empty, then admin socket will try to flush @c f to out. | |
59 | */ | |
60 | virtual int call( | |
61 | std::string_view command, | |
62 | const cmdmap_t& cmdmap, | |
f67539c2 | 63 | ceph::Formatter *f, |
9f95a23c TL |
64 | std::ostream& errss, |
65 | ceph::buffer::list& out) = 0; | |
66 | ||
67 | /** | |
68 | * @brief | |
69 | * Handler for admin socket commands, asynchronous version | |
70 | * | |
71 | * Executes action associated with admin command and prepares byte-stream response. | |
72 | * When processing is done @c on_finish must be called. | |
73 | * There is no restriction on output. Each handler defines own output semantics. | |
74 | * Typically output is textual representation of some ceph's internals. | |
75 | * Input @c inbl can be passed, see ceph --in-file. | |
76 | * Handler should use provided formatter @c f if structuralized output is being produced. | |
77 | * on_finish handler has following parameters: | |
78 | * - result code of handler (same as @ref AdminSocketHook::call) | |
79 | * - error message, text | |
80 | * - output | |
81 | * | |
82 | * @param[in] command String matching constant part of cmddesc in @ref AdminSocket::register_command | |
83 | * @param[in] cmdmap Parameters extracted from argument part of cmddesc in @ref AdminSocket::register_command | |
84 | * @param[in] f Formatter created according to requestor preference, used by `ceph --format` | |
85 | * @param[in] inbl Input content for handler | |
86 | * @param[in] on_finish Function to call when processing is done | |
87 | * | |
88 | * @note If @c out is empty, then admin socket will try to flush @c f to out. | |
89 | */ | |
90 | virtual void call_async( | |
91 | std::string_view command, | |
92 | const cmdmap_t& cmdmap, | |
f67539c2 TL |
93 | ceph::Formatter *f, |
94 | const ceph::buffer::list& inbl, | |
95 | std::function<void(int,const std::string&,ceph::buffer::list&)> on_finish) { | |
9f95a23c | 96 | // by default, call the synchronous handler and then finish |
f67539c2 | 97 | ceph::buffer::list out; |
9f95a23c TL |
98 | std::ostringstream errss; |
99 | int r = call(command, cmdmap, f, errss, out); | |
100 | on_finish(r, errss.str(), out); | |
101 | } | |
7c673cae FG |
102 | virtual ~AdminSocketHook() {} |
103 | }; | |
104 | ||
11fdf7f2 | 105 | class AdminSocket |
7c673cae FG |
106 | { |
107 | public: | |
108 | AdminSocket(CephContext *cct); | |
11fdf7f2 TL |
109 | ~AdminSocket(); |
110 | ||
111 | AdminSocket(const AdminSocket&) = delete; | |
112 | AdminSocket& operator =(const AdminSocket&) = delete; | |
113 | AdminSocket(AdminSocket&&) = delete; | |
114 | AdminSocket& operator =(AdminSocket&&) = delete; | |
7c673cae FG |
115 | |
116 | /** | |
117 | * register an admin socket command | |
118 | * | |
119 | * The command is registered under a command string. Incoming | |
120 | * commands are split by space and matched against the longest | |
121 | * registered command. For example, if 'foo' and 'foo bar' are | |
122 | * registered, and an incoming command is 'foo bar baz', it is | |
123 | * matched with 'foo bar', while 'foo fud' will match 'foo'. | |
124 | * | |
11fdf7f2 | 125 | * The entire incoming command string is passed to the registered |
7c673cae FG |
126 | * hook. |
127 | * | |
128 | * @param command command string | |
129 | * @param cmddesc command syntax descriptor | |
11fdf7f2 | 130 | * @param hook implementation |
7c673cae FG |
131 | * @param help help text. if empty, command will not be included in 'help' output. |
132 | * | |
133 | * @return 0 for success, -EEXIST if command already registered. | |
134 | */ | |
9f95a23c | 135 | int register_command(std::string_view cmddesc, |
11fdf7f2 TL |
136 | AdminSocketHook *hook, |
137 | std::string_view help); | |
7c673cae | 138 | |
11fdf7f2 TL |
139 | /* |
140 | * unregister all commands belong to hook. | |
141 | */ | |
142 | void unregister_commands(const AdminSocketHook *hook); | |
7c673cae | 143 | |
11fdf7f2 | 144 | bool init(const std::string& path); |
7c673cae FG |
145 | |
146 | void chown(uid_t uid, gid_t gid); | |
147 | void chmod(mode_t mode); | |
9f95a23c TL |
148 | |
149 | /// execute (async) | |
150 | void execute_command( | |
151 | const std::vector<std::string>& cmd, | |
f67539c2 TL |
152 | const ceph::buffer::list& inbl, |
153 | std::function<void(int,const std::string&,ceph::buffer::list&)> on_fin); | |
9f95a23c TL |
154 | |
155 | /// execute (blocking) | |
156 | int execute_command( | |
157 | const std::vector<std::string>& cmd, | |
f67539c2 | 158 | const ceph::buffer::list& inbl, |
9f95a23c | 159 | std::ostream& errss, |
f67539c2 | 160 | ceph::buffer::list *outbl); |
9f95a23c | 161 | |
f67539c2 TL |
162 | void queue_tell_command(ceph::cref_t<MCommand> m); |
163 | void queue_tell_command(ceph::cref_t<MMonCommand> m); // for compat | |
7c673cae FG |
164 | |
165 | private: | |
7c673cae FG |
166 | |
167 | void shutdown(); | |
9f95a23c | 168 | void wakeup(); |
7c673cae | 169 | |
9f95a23c TL |
170 | std::string create_wakeup_pipe(int *pipe_rd, int *pipe_wr); |
171 | std::string destroy_wakeup_pipe(); | |
7c673cae FG |
172 | std::string bind_and_listen(const std::string &sock_path, int *fd); |
173 | ||
11fdf7f2 TL |
174 | std::thread th; |
175 | void entry() noexcept; | |
9f95a23c TL |
176 | void do_accept(); |
177 | void do_tell_queue(); | |
7c673cae FG |
178 | |
179 | CephContext *m_cct; | |
180 | std::string m_path; | |
11fdf7f2 | 181 | int m_sock_fd = -1; |
9f95a23c TL |
182 | int m_wakeup_rd_fd = -1; |
183 | int m_wakeup_wr_fd = -1; | |
184 | bool m_shutdown = false; | |
11fdf7f2 TL |
185 | |
186 | bool in_hook = false; | |
187 | std::condition_variable in_hook_cond; | |
188 | std::mutex lock; // protects `hooks` | |
189 | std::unique_ptr<AdminSocketHook> version_hook; | |
190 | std::unique_ptr<AdminSocketHook> help_hook; | |
191 | std::unique_ptr<AdminSocketHook> getdescs_hook; | |
192 | ||
9f95a23c | 193 | std::mutex tell_lock; |
f67539c2 TL |
194 | std::list<ceph::cref_t<MCommand>> tell_queue; |
195 | std::list<ceph::cref_t<MMonCommand>> tell_legacy_queue; | |
9f95a23c | 196 | |
11fdf7f2 TL |
197 | struct hook_info { |
198 | AdminSocketHook* hook; | |
199 | std::string desc; | |
200 | std::string help; | |
201 | ||
202 | hook_info(AdminSocketHook* hook, std::string_view desc, | |
203 | std::string_view help) | |
204 | : hook(hook), desc(desc), help(help) {} | |
205 | }; | |
206 | ||
f91f0fd5 TL |
207 | /// find the first hook which matches the given prefix and cmdmap |
208 | std::pair<int, AdminSocketHook*> find_matched_hook( | |
209 | std::string& prefix, | |
210 | const cmdmap_t& cmdmap); | |
211 | ||
9f95a23c | 212 | std::multimap<std::string, hook_info, std::less<>> hooks; |
7c673cae FG |
213 | |
214 | friend class AdminSocketTest; | |
215 | friend class HelpHook; | |
216 | friend class GetdescsHook; | |
217 | }; | |
218 | ||
219 | #endif | |
9f95a23c | 220 | #endif |