]> git.proxmox.com Git - ceph.git/blob - ceph/src/test/admin_socket_output.cc
update sources to v12.1.0
[ceph.git] / ceph / src / test / admin_socket_output.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
3 /*
4 * Ceph - scalable distributed file system
5 *
6 * Copyright (C) 2017 Red Hat
7 *
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.
12 *
13 */
14
15 #include <iostream>
16 #include <boost/filesystem/convenience.hpp> // For extension
17 #include <boost/regex.hpp> // For regex, regex_search
18
19 #include "common/admin_socket_client.h" // For AdminSocketClient
20 #include "common/ceph_json.h" // For JSONParser, JSONObjIter
21 #include "include/buffer.h" // For bufferlist
22
23 #include "admin_socket_output.h"
24
25 void AdminSocketOutput::add_target(const std::string& target) {
26 if (target == "all") {
27 add_target("osd");
28 add_target("mon");
29 add_target("mgr");
30 add_target("mds");
31 add_target("client");
32 return;
33 }
34 targets.insert(target);
35 }
36
37 void AdminSocketOutput::add_command(const std::string& target,
38 const std::string& command) {
39 auto seek = custom_commands.find(target);
40 if (seek != custom_commands.end()) {
41 seek->second.push_back(command);
42 } else {
43 std::vector<std::string> vec;
44 vec.push_back(command);
45 custom_commands.insert(std::make_pair(target, vec));
46 }
47
48 }
49
50 void AdminSocketOutput::add_test(const std::string &target,
51 const std::string &command,
52 bool (*test)(std::string &)) {
53 auto seek = tests.find(target);
54 if (seek != tests.end()) {
55 seek->second.push_back(std::make_pair(command, test));
56 } else {
57 std::vector<std::pair<std::string, bool (*)(std::string &)>> vec;
58 vec.push_back(std::make_pair(command, test));
59 tests.insert(std::make_pair(target, vec));
60 }
61 }
62
63 void AdminSocketOutput::postpone(const std::string &target,
64 const std::string& command) {
65 auto seek = postponed_commands.find(target);
66 if (seek != postponed_commands.end()) {
67 seek->second.push_back(command);
68 } else {
69 std::vector<string> vec;
70 vec.push_back(command);
71 postponed_commands.insert(std::make_pair(target, vec));
72 }
73 }
74
75 bool AdminSocketOutput::init_sockets() {
76 std::cout << "Initialising sockets" << std::endl;
77 for (const auto &x : bfs::directory_iterator(socketdir)) {
78 std::cout << x.path() << std::endl;
79 if (bfs::extension(x.path()) == ".asok") {
80 for (auto &target : targets) {
81 if (boost::regex_search(x.path().filename().string(),
82 boost::regex(prefix + target + R"(\..*\.asok)"))) {
83 std::cout << "Found " << target << " socket " << x.path()
84 << std::endl;
85 sockets.insert(std::make_pair(target, x.path().string()));
86 targets.erase(target);
87 }
88 }
89 if (targets.empty()) {
90 std::cout << "Found all required sockets" << std::endl;
91 break;
92 }
93 }
94 }
95
96 return !sockets.empty() && targets.empty();
97 }
98
99 std::pair<std::string, std::string>
100 AdminSocketOutput::run_command(AdminSocketClient &client,
101 const std::string raw_command,
102 bool send_untouched) {
103 std::cout << "Sending command \"" << raw_command << "\"" << std::endl;
104 std::string command;
105 std::string output;
106 if (send_untouched) {
107 command = raw_command;
108 } else {
109 command = "{\"prefix\":\"" + raw_command + "\"}";
110 }
111 client.do_request(command, &output);
112 return std::make_pair(command, output);
113 }
114
115 bool AdminSocketOutput::gather_socket_output() {
116
117 std::cout << "Gathering socket output" << std::endl;
118 for (const auto& socket : sockets) {
119 std::string response;
120 AdminSocketClient client(socket.second);
121 std::cout << std::endl
122 << "Sending request to " << socket << std::endl
123 << std::endl;
124 client.do_request("{\"prefix\":\"help\"}", &response);
125 std::cout << response << '\n';
126
127 JSONParser parser;
128 bool ret = parser.parse(response.c_str(), response.size());
129 if (!ret) {
130 cerr << "parse error" << std::endl;
131 return false;
132 }
133
134 socket_results sresults;
135 JSONObjIter iter = parser.find_first();
136 const auto postponed_iter = postponed_commands.find(socket.first);
137 std::vector<std::string> postponed;
138 if (postponed_iter != postponed_commands.end()) {
139 postponed = postponed_iter->second;
140 }
141 std::cout << "Sending commands to " << socket.first << " socket"
142 << std::endl;
143 for (; !iter.end(); ++iter) {
144 if (std::find(postponed.begin(), postponed.end(), (*iter)->get_name())
145 != std::end(postponed)) {
146 std::cout << "Command \"" << (*iter)->get_name() << "\" postponed"
147 << std::endl;
148 continue;
149 }
150 sresults.insert(run_command(client, (*iter)->get_name()));
151 }
152
153 if (sresults.empty()) {
154 return false;
155 }
156
157 // Custom commands
158 const auto seek = custom_commands.find(socket.first);
159 if (seek != custom_commands.end()) {
160 std::cout << std::endl << "Sending custom commands:" << std::endl;
161 for (const auto& raw_command : seek->second) {
162 sresults.insert(run_command(client, raw_command, true));
163 }
164 }
165
166 // Postponed commands
167 if (!postponed.empty())
168 std::cout << std::endl << "Sending postponed commands" << std::endl;
169 for (const auto& command : postponed) {
170 sresults.insert(run_command(client, command));
171 }
172
173 results.insert(
174 std::pair<std::string, socket_results>(socket.first, sresults));
175
176 }
177
178 return true;
179 }
180
181 std::string AdminSocketOutput::get_result(const std::string target,
182 const std::string command) const {
183 const auto& target_results = results.find(target);
184 if (target_results == results.end())
185 return std::string("");
186 else {
187 const auto& result = target_results->second.find(command);
188 if (result == target_results->second.end())
189 return std::string("");
190 else
191 return result->second;
192 }
193 }
194
195 bool AdminSocketOutput::run_tests() const {
196 for (const auto& socket : sockets) {
197 const auto& seek = tests.find(socket.first);
198 if (seek != tests.end()) {
199 std::cout << std::endl;
200 std::cout << "Running tests for " << socket.first << " socket" << std::endl;
201 for (const auto& test : seek->second) {
202 auto result = get_result(socket.first, test.first);
203 if(result.empty()) {
204 std::cout << "Failed to find result for command: " << test.first << std::endl;
205 return false;
206 } else {
207 std::cout << "Running test for command: " << test.first << std::endl;
208 const auto& test_func = test.second;
209 bool res = test_func(result);
210 if (res == false)
211 return false;
212 else
213 std::cout << "Test passed" << std::endl;
214 }
215 }
216 }
217 }
218
219 return true;
220 }
221
222 void AdminSocketOutput::exec() {
223 ceph_assert(init_directories());
224 ceph_assert(init_sockets());
225 ceph_assert(gather_socket_output());
226 ceph_assert(run_tests());
227 }