]> git.proxmox.com Git - ceph.git/blame - ceph/src/mgr/ServiceMap.cc
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / mgr / ServiceMap.cc
CommitLineData
224ce89b
WB
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include "mgr/ServiceMap.h"
5
f67539c2
TL
6#include <experimental/iterator>
7#include <fmt/format.h>
8#include <regex>
9
224ce89b
WB
10#include "common/Formatter.h"
11
9f95a23c
TL
12using ceph::bufferlist;
13using ceph::Formatter;
14
224ce89b
WB
15// Daemon
16
17void ServiceMap::Daemon::encode(bufferlist& bl, uint64_t features) const
18{
9f95a23c 19 ENCODE_START(2, 1, bl);
11fdf7f2
TL
20 encode(gid, bl);
21 encode(addr, bl, features);
22 encode(start_epoch, bl);
23 encode(start_stamp, bl);
24 encode(metadata, bl);
9f95a23c 25 encode(task_status, bl);
224ce89b
WB
26 ENCODE_FINISH(bl);
27}
28
11fdf7f2 29void ServiceMap::Daemon::decode(bufferlist::const_iterator& p)
224ce89b 30{
9f95a23c 31 DECODE_START(2, p);
11fdf7f2
TL
32 decode(gid, p);
33 decode(addr, p);
34 decode(start_epoch, p);
35 decode(start_stamp, p);
36 decode(metadata, p);
9f95a23c
TL
37 if (struct_v >= 2) {
38 decode(task_status, p);
39 }
224ce89b
WB
40 DECODE_FINISH(p);
41}
42
43void ServiceMap::Daemon::dump(Formatter *f) const
44{
45 f->dump_unsigned("start_epoch", start_epoch);
46 f->dump_stream("start_stamp") << start_stamp;
47 f->dump_unsigned("gid", gid);
11fdf7f2 48 f->dump_string("addr", addr.get_legacy_str());
224ce89b
WB
49 f->open_object_section("metadata");
50 for (auto& p : metadata) {
51 f->dump_string(p.first.c_str(), p.second);
52 }
53 f->close_section();
9f95a23c
TL
54 f->open_object_section("task_status");
55 for (auto& p : task_status) {
56 f->dump_string(p.first.c_str(), p.second);
57 }
58 f->close_section();
224ce89b
WB
59}
60
61void ServiceMap::Daemon::generate_test_instances(std::list<Daemon*>& ls)
62{
63 ls.push_back(new Daemon);
64 ls.push_back(new Daemon);
65 ls.back()->gid = 222;
66 ls.back()->metadata["this"] = "that";
9f95a23c 67 ls.back()->task_status["task1"] = "running";
224ce89b
WB
68}
69
70// Service
71
f67539c2
TL
72std::string ServiceMap::Service::get_summary() const
73{
74 if (!summary.empty()) {
75 return summary;
76 }
77 if (daemons.empty()) {
78 return "no daemons active";
79 }
80
81 // If "daemon_type" is present, this will be used in place of "daemon" when
82 // reporting the count (e.g., "${N} daemons").
83 //
84 // We will additional break down the count by various groupings, based
85 // on the following keys:
86 //
87 // "hostname" -> host(s)
88 // "zone_id" -> zone(s)
89 //
90 // The `ceph -s` will be something likes:
91 // iscsi: 3 portals active (3 hosts)
92 // rgw: 3 gateways active (3 hosts, 1 zone)
93
94 std::map<std::string, std::set<std::string>> groupings;
95 std::string type("daemon");
96 int num = 0;
97 for (auto& d : daemons) {
98 ++num;
99 if (auto p = d.second.metadata.find("daemon_type");
100 p != d.second.metadata.end()) {
101 type = p->second;
102 }
103 for (auto k : {make_pair("zone", "zone_id"),
104 make_pair("host", "hostname")}) {
105 auto p = d.second.metadata.find(k.second);
106 if (p != d.second.metadata.end()) {
107 groupings[k.first].insert(p->second);
108 }
109 }
110 }
111
112 std::ostringstream ss;
113 ss << num << " " << type << (num > 1 ? "s" : "") << " active";
114 if (groupings.size()) {
115 ss << " (";
116 for (auto i = groupings.begin(); i != groupings.end(); ++i) {
117 if (i != groupings.begin()) {
118 ss << ", ";
119 }
120 ss << i->second.size() << " " << i->first << (i->second.size() ? "s" : "");
121 }
122 ss << ")";
123 }
124
125 return ss.str();
126}
127
128bool ServiceMap::Service::has_running_tasks() const
129{
130 return std::any_of(daemons.begin(), daemons.end(), [](auto& daemon) {
131 return !daemon.second.task_status.empty();
132 });
133}
134
135std::string ServiceMap::Service::get_task_summary(const std::string_view task_prefix) const
136{
137 // contruct a map similar to:
138 // {"service1 status" -> {"service1.0" -> "running"}}
139 // {"service2 status" -> {"service2.0" -> "idle"},
140 // {"service2.1" -> "running"}}
141 std::map<std::string, std::map<std::string, std::string>> by_task;
142 for (const auto& [service_id, daemon] : daemons) {
143 for (const auto& [task_name, status] : daemon.task_status) {
144 by_task[task_name].emplace(fmt::format("{}.{}", task_prefix, service_id),
145 status);
146 }
147 }
148 std::stringstream ss;
149 for (const auto &[task_name, status_by_service] : by_task) {
150 ss << "\n " << task_name << ":";
151 for (auto& [service, status] : status_by_service) {
152 ss << "\n " << service << ": " << status;
153 }
154 }
155 return ss.str();
156}
157
158void ServiceMap::Service::count_metadata(const std::string& field,
159 std::map<std::string,int> *out) const
160{
161 for (auto& p : daemons) {
162 auto q = p.second.metadata.find(field);
163 if (q == p.second.metadata.end()) {
164 (*out)["unknown"]++;
165 } else {
166 (*out)[q->second]++;
167 }
168 }
169}
170
224ce89b
WB
171void ServiceMap::Service::encode(bufferlist& bl, uint64_t features) const
172{
173 ENCODE_START(1, 1, bl);
11fdf7f2
TL
174 encode(daemons, bl, features);
175 encode(summary, bl);
224ce89b
WB
176 ENCODE_FINISH(bl);
177}
178
11fdf7f2 179void ServiceMap::Service::decode(bufferlist::const_iterator& p)
224ce89b
WB
180{
181 DECODE_START(1, p);
11fdf7f2
TL
182 decode(daemons, p);
183 decode(summary, p);
224ce89b
WB
184 DECODE_FINISH(p);
185}
186
187void ServiceMap::Service::dump(Formatter *f) const
188{
189 f->open_object_section("daemons");
190 f->dump_string("summary", summary);
191 for (auto& p : daemons) {
192 f->dump_object(p.first.c_str(), p.second);
193 }
194 f->close_section();
195}
196
197void ServiceMap::Service::generate_test_instances(std::list<Service*>& ls)
198{
199 ls.push_back(new Service);
200 ls.push_back(new Service);
201 ls.back()->daemons["one"].gid = 1;
202 ls.back()->daemons["two"].gid = 2;
203}
204
205// ServiceMap
206
207void ServiceMap::encode(bufferlist& bl, uint64_t features) const
208{
209 ENCODE_START(1, 1, bl);
11fdf7f2
TL
210 encode(epoch, bl);
211 encode(modified, bl);
212 encode(services, bl, features);
224ce89b
WB
213 ENCODE_FINISH(bl);
214}
215
11fdf7f2 216void ServiceMap::decode(bufferlist::const_iterator& p)
224ce89b
WB
217{
218 DECODE_START(1, p);
11fdf7f2
TL
219 decode(epoch, p);
220 decode(modified, p);
221 decode(services, p);
224ce89b
WB
222 DECODE_FINISH(p);
223}
224
225void ServiceMap::dump(Formatter *f) const
226{
227 f->dump_unsigned("epoch", epoch);
228 f->dump_stream("modified") << modified;
229 f->open_object_section("services");
230 for (auto& p : services) {
231 f->dump_object(p.first.c_str(), p.second);
232 }
233 f->close_section();
234}
235
236void ServiceMap::generate_test_instances(std::list<ServiceMap*>& ls)
237{
238 ls.push_back(new ServiceMap);
239 ls.push_back(new ServiceMap);
240 ls.back()->epoch = 123;
241 ls.back()->services["rgw"].daemons["one"].gid = 123;
242 ls.back()->services["rgw"].daemons["two"].gid = 344;
243 ls.back()->services["iscsi"].daemons["foo"].gid = 3222;
244}