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"
37 using namespace std::literals
;
39 inline constexpr auto CEPH_ADMIN_SOCK_VERSION
= "2"sv
;
41 class AdminSocketHook
{
45 * Handler for admin socket commands, synchronous version
47 * Executes action associated with admin command and returns byte-stream output @c out.
48 * There is no restriction on output. Each handler defines output semantics.
49 * Typically output is textual representation of some ceph's internals.
50 * Handler should use provided formatter @c f if structuralized output is being produced.
52 * @param command[in] String matching constant part of cmddesc in @ref AdminSocket::register_command
53 * @param cmdmap[in] Parameters extracted from argument part of cmddesc in @ref AdminSocket::register_command
54 * @param f[in] Formatter created according to requestor preference, used by `ceph --format`
55 * @param errss[out] Error stream, should contain details in case of execution failure
56 * @param out[out] Produced output
58 * @retval 0 Success, errss is ignored and does not contribute to output
59 * @retval <0 Error code, errss is prepended to @c out
61 * @note If @c out is empty, then admin socket will try to flush @c f to out.
64 std::string_view command
,
65 const cmdmap_t
& cmdmap
,
68 ceph::buffer::list
& out
) = 0;
72 * Handler for admin socket commands, asynchronous version
74 * Executes action associated with admin command and prepares byte-stream response.
75 * When processing is done @c on_finish must be called.
76 * There is no restriction on output. Each handler defines own output semantics.
77 * Typically output is textual representation of some ceph's internals.
78 * Input @c inbl can be passed, see ceph --in-file.
79 * Handler should use provided formatter @c f if structuralized output is being produced.
80 * on_finish handler has following parameters:
81 * - result code of handler (same as @ref AdminSocketHook::call)
82 * - error message, text
85 * @param[in] command String matching constant part of cmddesc in @ref AdminSocket::register_command
86 * @param[in] cmdmap Parameters extracted from argument part of cmddesc in @ref AdminSocket::register_command
87 * @param[in] f Formatter created according to requestor preference, used by `ceph --format`
88 * @param[in] inbl Input content for handler
89 * @param[in] on_finish Function to call when processing is done
91 * @note If @c out is empty, then admin socket will try to flush @c f to out.
93 virtual void call_async(
94 std::string_view command
,
95 const cmdmap_t
& cmdmap
,
97 const bufferlist
& inbl
,
98 std::function
<void(int,const std::string
&,bufferlist
&)> on_finish
) {
99 // by default, call the synchronous handler and then finish
101 std::ostringstream errss
;
102 int r
= call(command
, cmdmap
, f
, errss
, out
);
103 on_finish(r
, errss
.str(), out
);
105 virtual ~AdminSocketHook() {}
111 AdminSocket(CephContext
*cct
);
114 AdminSocket(const AdminSocket
&) = delete;
115 AdminSocket
& operator =(const AdminSocket
&) = delete;
116 AdminSocket(AdminSocket
&&) = delete;
117 AdminSocket
& operator =(AdminSocket
&&) = delete;
120 * register an admin socket command
122 * The command is registered under a command string. Incoming
123 * commands are split by space and matched against the longest
124 * registered command. For example, if 'foo' and 'foo bar' are
125 * registered, and an incoming command is 'foo bar baz', it is
126 * matched with 'foo bar', while 'foo fud' will match 'foo'.
128 * The entire incoming command string is passed to the registered
131 * @param command command string
132 * @param cmddesc command syntax descriptor
133 * @param hook implementation
134 * @param help help text. if empty, command will not be included in 'help' output.
136 * @return 0 for success, -EEXIST if command already registered.
138 int register_command(std::string_view cmddesc
,
139 AdminSocketHook
*hook
,
140 std::string_view help
);
143 * unregister all commands belong to hook.
145 void unregister_commands(const AdminSocketHook
*hook
);
147 bool init(const std::string
& path
);
149 void chown(uid_t uid
, gid_t gid
);
150 void chmod(mode_t mode
);
153 void execute_command(
154 const std::vector
<std::string
>& cmd
,
155 const bufferlist
& inbl
,
156 std::function
<void(int,const std::string
&,bufferlist
&)> on_fin
);
158 /// execute (blocking)
160 const std::vector
<std::string
>& cmd
,
161 const bufferlist
& inbl
,
165 void queue_tell_command(cref_t
<MCommand
> m
);
166 void queue_tell_command(cref_t
<MMonCommand
> m
); // for compat
173 std::string
create_wakeup_pipe(int *pipe_rd
, int *pipe_wr
);
174 std::string
destroy_wakeup_pipe();
175 std::string
bind_and_listen(const std::string
&sock_path
, int *fd
);
178 void entry() noexcept
;
180 void do_tell_queue();
185 int m_wakeup_rd_fd
= -1;
186 int m_wakeup_wr_fd
= -1;
187 bool m_shutdown
= false;
189 bool in_hook
= false;
190 std::condition_variable in_hook_cond
;
191 std::mutex lock
; // protects `hooks`
192 std::unique_ptr
<AdminSocketHook
> version_hook
;
193 std::unique_ptr
<AdminSocketHook
> help_hook
;
194 std::unique_ptr
<AdminSocketHook
> getdescs_hook
;
196 std::mutex tell_lock
;
197 std::list
<cref_t
<MCommand
>> tell_queue
;
198 std::list
<cref_t
<MMonCommand
>> tell_legacy_queue
;
201 AdminSocketHook
* hook
;
205 hook_info(AdminSocketHook
* hook
, std::string_view desc
,
206 std::string_view help
)
207 : hook(hook
), desc(desc
), help(help
) {}
210 /// find the first hook which matches the given prefix and cmdmap
211 std::pair
<int, AdminSocketHook
*> find_matched_hook(
213 const cmdmap_t
& cmdmap
);
215 std::multimap
<std::string
, hook_info
, std::less
<>> hooks
;
217 friend class AdminSocketTest
;
218 friend class HelpHook
;
219 friend class GetdescsHook
;