initial code repo
[stor4nfv.git] / src / ceph / src / test / admin_socket_output.cc
diff --git a/src/ceph/src/test/admin_socket_output.cc b/src/ceph/src/test/admin_socket_output.cc
new file mode 100644 (file)
index 0000000..50fa966
--- /dev/null
@@ -0,0 +1,227 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2017 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#include <iostream>
+#include <boost/filesystem/convenience.hpp> // For extension
+#include <boost/regex.hpp>                 // For regex, regex_search
+
+#include "common/admin_socket_client.h"     // For AdminSocketClient
+#include "common/ceph_json.h"               // For JSONParser, JSONObjIter
+#include "include/buffer.h"                 // For bufferlist
+
+#include "admin_socket_output.h"
+
+void AdminSocketOutput::add_target(const std::string& target) {
+  if (target == "all") {
+    add_target("osd");
+    add_target("mon");
+    add_target("mgr");
+    add_target("mds");
+    add_target("client");
+    return;
+  }
+  targets.insert(target);
+}
+
+void AdminSocketOutput::add_command(const std::string& target,
+                                    const std::string& command) {
+  auto seek = custom_commands.find(target);
+  if (seek != custom_commands.end()) {
+    seek->second.push_back(command);
+  } else {
+    std::vector<std::string> vec;
+    vec.push_back(command);
+    custom_commands.insert(std::make_pair(target, vec));
+  }
+
+}
+
+void AdminSocketOutput::add_test(const std::string &target,
+                                 const std::string &command,
+                                 bool (*test)(std::string &)) {
+  auto seek = tests.find(target);
+  if (seek != tests.end()) {
+    seek->second.push_back(std::make_pair(command, test));
+  } else {
+    std::vector<std::pair<std::string, bool (*)(std::string &)>> vec;
+    vec.push_back(std::make_pair(command, test));
+    tests.insert(std::make_pair(target, vec));
+  }
+}
+
+void AdminSocketOutput::postpone(const std::string &target,
+                                 const std::string& command) {
+  auto seek = postponed_commands.find(target);
+  if (seek != postponed_commands.end()) {
+    seek->second.push_back(command);
+  } else {
+    std::vector<string> vec;
+    vec.push_back(command);
+    postponed_commands.insert(std::make_pair(target, vec));
+  }
+}
+
+bool AdminSocketOutput::init_sockets() {
+  std::cout << "Initialising sockets" << std::endl;
+  for (const auto &x : bfs::directory_iterator(socketdir)) {
+    std::cout << x.path() << std::endl;
+    if (bfs::extension(x.path()) == ".asok") {
+      for (auto &target : targets) {
+        if (boost::regex_search(x.path().filename().string(),
+            boost::regex(prefix + target + R"(\..*\.asok)"))) {
+          std::cout << "Found " << target << " socket " << x.path()
+                    << std::endl;
+          sockets.insert(std::make_pair(target, x.path().string()));
+          targets.erase(target);
+        }
+      }
+      if (targets.empty()) {
+        std::cout << "Found all required sockets" << std::endl;
+        break;
+      }
+    }
+  }
+
+  return !sockets.empty() && targets.empty();
+}
+
+std::pair<std::string, std::string>
+AdminSocketOutput::run_command(AdminSocketClient &client,
+                               const std::string raw_command,
+                               bool send_untouched) {
+  std::cout << "Sending command \"" << raw_command << "\"" << std::endl;
+  std::string command;
+  std::string output;
+  if (send_untouched) {
+    command = raw_command;
+  } else {
+    command = "{\"prefix\":\"" + raw_command + "\"}";
+  }
+  client.do_request(command, &output);
+  return std::make_pair(command, output);
+}
+
+bool AdminSocketOutput::gather_socket_output() {
+
+  std::cout << "Gathering socket output" << std::endl;
+  for (const auto& socket : sockets) {
+    std::string response;
+    AdminSocketClient client(socket.second);
+    std::cout << std::endl
+              << "Sending request to " << socket << std::endl
+              << std::endl;
+    client.do_request("{\"prefix\":\"help\"}", &response);
+    std::cout << response << '\n';
+
+    JSONParser parser;
+    bool ret = parser.parse(response.c_str(), response.size());
+    if (!ret) {
+      cerr << "parse error" << std::endl;
+      return false;
+    }
+
+    socket_results sresults;
+    JSONObjIter iter = parser.find_first();
+    const auto postponed_iter = postponed_commands.find(socket.first);
+    std::vector<std::string> postponed;
+    if (postponed_iter != postponed_commands.end()) {
+      postponed = postponed_iter->second;
+    }
+    std::cout << "Sending commands to " << socket.first << " socket"
+              << std::endl;
+    for (; !iter.end(); ++iter) {
+      if (std::find(postponed.begin(), postponed.end(), (*iter)->get_name())
+          != std::end(postponed)) {
+        std::cout << "Command \"" << (*iter)->get_name() << "\" postponed"
+                  << std::endl;
+        continue;
+      }
+      sresults.insert(run_command(client, (*iter)->get_name()));
+    }
+
+    if (sresults.empty()) {
+      return false;
+    }
+
+    // Custom commands
+    const auto seek = custom_commands.find(socket.first);
+    if (seek != custom_commands.end()) {
+      std::cout << std::endl << "Sending custom commands:" << std::endl;
+      for (const auto& raw_command : seek->second) {
+        sresults.insert(run_command(client, raw_command, true));
+      }
+    }
+
+    // Postponed commands
+    if (!postponed.empty())
+      std::cout << std::endl << "Sending postponed commands" << std::endl;
+    for (const auto& command : postponed) {
+      sresults.insert(run_command(client, command));
+    }
+
+    results.insert(
+        std::pair<std::string, socket_results>(socket.first, sresults));
+
+  }
+
+  return true;
+}
+
+std::string AdminSocketOutput::get_result(const std::string target,
+                                          const std::string command) const {
+  const auto& target_results = results.find(target);
+  if (target_results == results.end())
+    return std::string("");
+  else {
+    const auto& result = target_results->second.find(command);
+    if (result == target_results->second.end())
+      return std::string("");
+    else
+      return result->second;
+  }
+}
+
+bool AdminSocketOutput::run_tests() const {
+  for (const auto& socket : sockets) {
+    const auto& seek = tests.find(socket.first);
+    if (seek != tests.end()) {
+      std::cout << std::endl;
+      std::cout << "Running tests for " << socket.first << " socket" << std::endl;
+      for (const auto& test : seek->second) {
+          auto result = get_result(socket.first, test.first);
+          if(result.empty()) {
+            std::cout << "Failed to find result for command: " << test.first << std::endl;
+            return false;
+          } else {
+            std::cout << "Running test for command: " << test.first << std::endl;
+            const auto& test_func = test.second;
+            bool res = test_func(result);
+            if (res == false)
+              return false;
+            else
+              std::cout << "Test passed" << std::endl;
+          }
+        }
+      }
+    }
+
+  return true;
+}
+
+void AdminSocketOutput::exec() {
+  ceph_assert(init_directories());
+  ceph_assert(init_sockets());
+  ceph_assert(gather_socket_output());
+  ceph_assert(run_tests());
+}