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