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