summaryrefslogtreecommitdiffstats
path: root/src/test/admin_socket_output.cc
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 18:24:20 +0000
commit483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch)
treee5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/test/admin_socket_output.cc
parentInitial commit. (diff)
downloadceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.tar.xz
ceph-483eb2f56657e8e7f419ab1a4fab8dce9ade8609.zip
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/admin_socket_output.cc')
-rw-r--r--src/test/admin_socket_output.cc241
1 files changed, 241 insertions, 0 deletions
diff --git a/src/test/admin_socket_output.cc b/src/test/admin_socket_output.cc
new file mode 100644
index 00000000..76e6e567
--- /dev/null
+++ b/src/test/admin_socket_output.cc
@@ -0,0 +1,241 @@
+// -*- 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 <regex> // For regex, regex_search
+#include <experimental/filesystem> // For extension
+
+#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;
+ std::string socket_regex = R"(\..*\.asok)";
+ for (const auto &x : fs::recursive_directory_iterator(socketdir)) {
+ std::cout << x.path() << std::endl;
+ if (x.path().extension() == ".asok") {
+ for (auto target = targets.cbegin(); target != targets.cend();) {
+ std::regex reg(prefix + *target + socket_regex);
+ if (std::regex_search(x.path().filename().string(), reg)) {
+ std::cout << "Found " << *target << " socket " << x.path()
+ << std::endl;
+ sockets.insert(std::make_pair(*target, x.path().string()));
+ target = targets.erase(target);
+ }
+ else {
+ ++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 + "\"}";
+ }
+ std::string err = client.do_request(command, &output);
+ if (!err.empty()) {
+ std::cerr << __func__ << " AdminSocketClient::do_request errored with: "
+ << err << std::endl;
+ ceph_abort();
+ }
+ 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;
+ std::string err = client.do_request("{\"prefix\":\"help\"}", &response);
+ if (!err.empty()) {
+ std::cerr << __func__ << " AdminSocketClient::do_request errored with: "
+ << err << std::endl;
+ return false;
+ }
+ 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());
+}