]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/common/admin_socket.h
Import ceph 15.2.8
[ceph.git] / ceph / src / common / admin_socket.h
index 9f2c5ee87e233da0a0c9d0ae493b579d5c399df2..2e4e153f4de8c7a68dfbff9a86ae665484259c87 100644 (file)
 #ifndef CEPH_COMMON_ADMIN_SOCKET_H
 #define CEPH_COMMON_ADMIN_SOCKET_H
 
+#if defined(WITH_SEASTAR) && !defined(WITH_ALIEN)
+#include "crimson/admin/admin_socket.h"
+#else
+
 #include <condition_variable>
 #include <mutex>
 #include <string>
 #include <thread>
 
 #include "include/buffer.h"
+#include "include/common_fwd.h"
+#include "common/ref.h"
 #include "common/cmdparse.h"
 
 class AdminSocket;
-class CephContext;
+class MCommand;
+class MMonCommand;
 
 using namespace std::literals;
 
@@ -33,8 +40,68 @@ inline constexpr auto CEPH_ADMIN_SOCK_VERSION = "2"sv;
 
 class AdminSocketHook {
 public:
-  virtual bool call(std::string_view command, const cmdmap_t& cmdmap,
-                   std::string_view format, bufferlist& out) = 0;
+  /**
+   * @brief
+   * Handler for admin socket commands, synchronous version
+   *
+   * Executes action associated with admin command and returns byte-stream output @c out.
+   * There is no restriction on output. Each handler defines output semantics.
+   * Typically output is textual representation of some ceph's internals.
+   * Handler should use provided formatter @c f if structuralized output is being produced.
+   *
+   * @param command[in] String matching constant part of cmddesc in @ref AdminSocket::register_command
+   * @param cmdmap[in]  Parameters extracted from argument part of cmddesc in @ref AdminSocket::register_command
+   * @param f[in]       Formatter created according to requestor preference, used by `ceph --format`
+   * @param errss[out]  Error stream, should contain details in case of execution failure
+   * @param out[out]    Produced output
+   *
+   * @retval 0 Success, errss is ignored and does not contribute to output
+   * @retval <0 Error code, errss is prepended to @c out
+   *
+   * @note If @c out is empty, then admin socket will try to flush @c f to out.
+   */
+  virtual int call(
+    std::string_view command,
+    const cmdmap_t& cmdmap,
+    Formatter *f,
+    std::ostream& errss,
+    ceph::buffer::list& out) = 0;
+
+  /**
+   * @brief
+   * Handler for admin socket commands, asynchronous version
+   *
+   * Executes action associated with admin command and prepares byte-stream response.
+   * When processing is done @c on_finish must be called.
+   * There is no restriction on output. Each handler defines own output semantics.
+   * Typically output is textual representation of some ceph's internals.
+   * Input @c inbl can be passed, see ceph --in-file.
+   * Handler should use provided formatter @c f if structuralized output is being produced.
+   * on_finish handler has following parameters:
+   * - result code of handler (same as @ref AdminSocketHook::call)
+   * - error message, text
+   * - output
+   *
+   * @param[in] command String matching constant part of cmddesc in @ref AdminSocket::register_command
+   * @param[in] cmdmap  Parameters extracted from argument part of cmddesc in @ref AdminSocket::register_command
+   * @param[in] f       Formatter created according to requestor preference, used by `ceph --format`
+   * @param[in] inbl    Input content for handler
+   * @param[in] on_finish Function to call when processing is done
+   *
+   * @note If @c out is empty, then admin socket will try to flush @c f to out.
+   */
+  virtual void call_async(
+    std::string_view command,
+    const cmdmap_t& cmdmap,
+    Formatter *f,
+    const bufferlist& inbl,
+    std::function<void(int,const std::string&,bufferlist&)> on_finish) {
+    // by default, call the synchronous handler and then finish
+    bufferlist out;
+    std::ostringstream errss;
+    int r = call(command, cmdmap, f, errss, out);
+    on_finish(r, errss.str(), out);
+  }
   virtual ~AdminSocketHook() {}
 };
 
@@ -68,23 +135,10 @@ public:
    *
    * @return 0 for success, -EEXIST if command already registered.
    */
-  int register_command(std::string_view command,
-                      std::string_view cmddesc,
+  int register_command(std::string_view cmddesc,
                       AdminSocketHook *hook,
                       std::string_view help);
 
-  /**
-   * unregister an admin socket command.
-   *
-   * If a command is currently in progress, this will block until it
-   * is done.  For that reason, you must not hold any locks required
-   * by your hook while you call this.
-   *
-   * @param command command string
-   * @return 0 on succest, -ENOENT if command dne.
-   */
-  int unregister_command(std::string_view command);
-
   /*
    * unregister all commands belong to hook.
    */
@@ -95,26 +149,42 @@ public:
   void chown(uid_t uid, gid_t gid);
   void chmod(mode_t mode);
 
+  /// execute (async)
+  void execute_command(
+    const std::vector<std::string>& cmd,
+    const bufferlist& inbl,
+    std::function<void(int,const std::string&,bufferlist&)> on_fin);
+
+  /// execute (blocking)
+  int execute_command(
+    const std::vector<std::string>& cmd,
+    const bufferlist& inbl,
+    std::ostream& errss,
+    bufferlist *outbl);
+
+  void queue_tell_command(cref_t<MCommand> m);
+  void queue_tell_command(cref_t<MMonCommand> m); // for compat
+
 private:
 
   void shutdown();
+  void wakeup();
 
-  std::string create_shutdown_pipe(int *pipe_rd, int *pipe_wr);
-  std::string destroy_shutdown_pipe();
+  std::string create_wakeup_pipe(int *pipe_rd, int *pipe_wr);
+  std::string destroy_wakeup_pipe();
   std::string bind_and_listen(const std::string &sock_path, int *fd);
 
   std::thread th;
   void entry() noexcept;
-  bool do_accept();
-  bool validate(const std::string& command,
-               const cmdmap_t& cmdmap,
-               bufferlist& out) const;
+  void do_accept();
+  void do_tell_queue();
 
   CephContext *m_cct;
   std::string m_path;
   int m_sock_fd = -1;
-  int m_shutdown_rd_fd = -1;
-  int m_shutdown_wr_fd = -1;
+  int m_wakeup_rd_fd = -1;
+  int m_wakeup_wr_fd = -1;
+  bool m_shutdown = false;
 
   bool in_hook = false;
   std::condition_variable in_hook_cond;
@@ -123,6 +193,10 @@ private:
   std::unique_ptr<AdminSocketHook> help_hook;
   std::unique_ptr<AdminSocketHook> getdescs_hook;
 
+  std::mutex tell_lock;
+  std::list<cref_t<MCommand>> tell_queue;
+  std::list<cref_t<MMonCommand>> tell_legacy_queue;
+
   struct hook_info {
     AdminSocketHook* hook;
     std::string desc;
@@ -133,7 +207,12 @@ private:
       : hook(hook), desc(desc), help(help) {}
   };
 
-  std::map<std::string, hook_info, std::less<>> hooks;
+  /// find the first hook which matches the given prefix and cmdmap
+  std::pair<int, AdminSocketHook*> find_matched_hook(
+    std::string& prefix,
+    const cmdmap_t& cmdmap);
+
+  std::multimap<std::string, hook_info, std::less<>> hooks;
 
   friend class AdminSocketTest;
   friend class HelpHook;
@@ -141,3 +220,4 @@ private:
 };
 
 #endif
+#endif