1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #ifndef CEPH_COMMON_ADMIN_SOCKET_H
16 #define CEPH_COMMON_ADMIN_SOCKET_H
18 #if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
19 #include "crimson/admin/admin_socket.h"
22 #include <condition_variable>
25 #include <string_view>
28 #include "include/buffer.h"
29 #include "include/common_fwd.h"
30 #include "common/ref.h"
31 #include "common/cmdparse.h"
36 inline constexpr auto CEPH_ADMIN_SOCK_VERSION
= std::string_view("2");
38 class AdminSocketHook
{
42 * Handler for admin socket commands, synchronous version
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.
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
55 * @retval 0 Success, errss is ignored and does not contribute to output
56 * @retval <0 Error code, errss is prepended to @c out
58 * @note If @c out is empty, then admin socket will try to flush @c f to out.
61 std::string_view command
,
62 const cmdmap_t
& cmdmap
,
65 ceph::buffer::list
& out
) = 0;
69 * Handler for admin socket commands, asynchronous version
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
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
88 * @note If @c out is empty, then admin socket will try to flush @c f to out.
90 virtual void call_async(
91 std::string_view command
,
92 const cmdmap_t
& cmdmap
,
94 const ceph::buffer::list
& inbl
,
95 std::function
<void(int,const std::string
&,ceph::buffer::list
&)> on_finish
) {
96 // by default, call the synchronous handler and then finish
97 ceph::buffer::list out
;
98 std::ostringstream errss
;
99 int r
= call(command
, cmdmap
, f
, errss
, out
);
100 on_finish(r
, errss
.str(), out
);
102 virtual ~AdminSocketHook() {}
108 AdminSocket(CephContext
*cct
);
111 AdminSocket(const AdminSocket
&) = delete;
112 AdminSocket
& operator =(const AdminSocket
&) = delete;
113 AdminSocket(AdminSocket
&&) = delete;
114 AdminSocket
& operator =(AdminSocket
&&) = delete;
117 * register an admin socket command
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'.
125 * The entire incoming command string is passed to the registered
128 * @param command command string
129 * @param cmddesc command syntax descriptor
130 * @param hook implementation
131 * @param help help text. if empty, command will not be included in 'help' output.
133 * @return 0 for success, -EEXIST if command already registered.
135 int register_command(std::string_view cmddesc
,
136 AdminSocketHook
*hook
,
137 std::string_view help
);
140 * unregister all commands belong to hook.
142 void unregister_commands(const AdminSocketHook
*hook
);
144 bool init(const std::string
& path
);
146 void chown(uid_t uid
, gid_t gid
);
147 void chmod(mode_t mode
);
150 void execute_command(
151 const std::vector
<std::string
>& cmd
,
152 const ceph::buffer::list
& inbl
,
153 std::function
<void(int,const std::string
&,ceph::buffer::list
&)> on_fin
);
155 /// execute (blocking)
157 const std::vector
<std::string
>& cmd
,
158 const ceph::buffer::list
& inbl
,
160 ceph::buffer::list
*outbl
);
162 void queue_tell_command(ceph::cref_t
<MCommand
> m
);
163 void queue_tell_command(ceph::cref_t
<MMonCommand
> m
); // for compat
170 std::string
create_wakeup_pipe(int *pipe_rd
, int *pipe_wr
);
171 std::string
destroy_wakeup_pipe();
172 std::string
bind_and_listen(const std::string
&sock_path
, int *fd
);
175 void entry() noexcept
;
177 void do_tell_queue();
182 int m_wakeup_rd_fd
= -1;
183 int m_wakeup_wr_fd
= -1;
184 bool m_shutdown
= false;
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
;
193 std::mutex tell_lock
;
194 std::list
<ceph::cref_t
<MCommand
>> tell_queue
;
195 std::list
<ceph::cref_t
<MMonCommand
>> tell_legacy_queue
;
198 AdminSocketHook
* hook
;
202 hook_info(AdminSocketHook
* hook
, std::string_view desc
,
203 std::string_view help
)
204 : hook(hook
), desc(desc
), help(help
) {}
207 /// find the first hook which matches the given prefix and cmdmap
208 std::pair
<int, AdminSocketHook
*> find_matched_hook(
210 const cmdmap_t
& cmdmap
);
212 std::multimap
<std::string
, hook_info
, std::less
<>> hooks
;
214 friend class AdminSocketTest
;
215 friend class HelpHook
;
216 friend class GetdescsHook
;