]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/MgrMap.h
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / mon / MgrMap.h
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) 2016 John Spray <john.spray@redhat.com>
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 #ifndef MGR_MAP_H_
15 #define MGR_MAP_H_
16
17 #include <sstream>
18 #include <set>
19
20 #include "msg/msg_types.h"
21 #include "common/Formatter.h"
22 #include "include/encoding.h"
23 #include "include/utime.h"
24 #include "common/version.h"
25 #include "common/options.h"
26 #include "common/Clock.h"
27
28
29 class MgrMap
30 {
31 public:
32 struct ModuleOption {
33 std::string name;
34 uint8_t type = Option::TYPE_STR; // Option::type_t TYPE_*
35 uint8_t level = Option::LEVEL_ADVANCED; // Option::level_t LEVEL_*
36 uint32_t flags = 0; // Option::flag_t FLAG_*
37 std::string default_value;
38 std::string min, max;
39 std::set<std::string> enum_allowed;
40 std::string desc, long_desc;
41 std::set<std::string> tags;
42 std::set<std::string> see_also;
43
44 void encode(bufferlist& bl) const {
45 ENCODE_START(1, 1, bl);
46 encode(name, bl);
47 encode(type, bl);
48 encode(level, bl);
49 encode(flags, bl);
50 encode(default_value, bl);
51 encode(min, bl);
52 encode(max, bl);
53 encode(enum_allowed, bl);
54 encode(desc, bl);
55 encode(long_desc, bl);
56 encode(tags, bl);
57 encode(see_also, bl);
58 ENCODE_FINISH(bl);
59 }
60 void decode(bufferlist::const_iterator& p) {
61 DECODE_START(1, p);
62 decode(name, p);
63 decode(type, p);
64 decode(level, p);
65 decode(flags, p);
66 decode(default_value, p);
67 decode(min, p);
68 decode(max, p);
69 decode(enum_allowed, p);
70 decode(desc, p);
71 decode(long_desc, p);
72 decode(tags, p);
73 decode(see_also, p);
74 DECODE_FINISH(p);
75 }
76 void dump(Formatter *f) const {
77 f->dump_string("name", name);
78 f->dump_string("type", Option::type_to_str(
79 static_cast<Option::type_t>(type)));
80 f->dump_string("level", Option::level_to_str(
81 static_cast<Option::level_t>(level)));
82 f->dump_unsigned("flags", flags);
83 f->dump_string("default_value", default_value);
84 f->dump_string("min", min);
85 f->dump_string("max", max);
86 f->open_array_section("enum_allowed");
87 for (auto& i : enum_allowed) {
88 f->dump_string("value", i);
89 }
90 f->close_section();
91 f->dump_string("desc", desc);
92 f->dump_string("long_desc", long_desc);
93 f->open_array_section("tags");
94 for (auto& i : tags) {
95 f->dump_string("tag", i);
96 }
97 f->close_section();
98 f->open_array_section("see_also");
99 for (auto& i : see_also) {
100 f->dump_string("option", i);
101 }
102 f->close_section();
103 }
104 };
105
106 class ModuleInfo
107 {
108 public:
109 std::string name;
110 bool can_run = true;
111 std::string error_string;
112 std::map<std::string,ModuleOption> module_options;
113
114 // We do not include the module's `failed` field in the beacon,
115 // because it is exposed via health checks.
116 void encode(bufferlist &bl) const {
117 ENCODE_START(2, 1, bl);
118 encode(name, bl);
119 encode(can_run, bl);
120 encode(error_string, bl);
121 encode(module_options, bl);
122 ENCODE_FINISH(bl);
123 }
124
125 void decode(bufferlist::const_iterator &bl) {
126 DECODE_START(1, bl);
127 decode(name, bl);
128 decode(can_run, bl);
129 decode(error_string, bl);
130 if (struct_v >= 2) {
131 decode(module_options, bl);
132 }
133 DECODE_FINISH(bl);
134 }
135
136 bool operator==(const ModuleInfo &rhs) const
137 {
138 return (name == rhs.name) && (can_run == rhs.can_run);
139 }
140
141 void dump(Formatter *f) const {
142 f->open_object_section("module");
143 f->dump_string("name", name);
144 f->dump_bool("can_run", can_run);
145 f->dump_string("error_string", error_string);
146 f->open_object_section("module_options");
147 for (auto& i : module_options) {
148 f->dump_object(i.first.c_str(), i.second);
149 }
150 f->close_section();
151 f->close_section();
152 }
153 };
154
155 class StandbyInfo
156 {
157 public:
158 uint64_t gid;
159 std::string name;
160 std::vector<ModuleInfo> available_modules;
161
162 StandbyInfo(uint64_t gid_, const std::string &name_,
163 const std::vector<ModuleInfo>& am)
164 : gid(gid_), name(name_), available_modules(am)
165 {}
166
167 StandbyInfo()
168 : gid(0)
169 {}
170
171 void encode(bufferlist& bl) const
172 {
173 ENCODE_START(3, 1, bl);
174 encode(gid, bl);
175 encode(name, bl);
176 std::set<std::string> old_available_modules;
177 for (const auto &i : available_modules) {
178 old_available_modules.insert(i.name);
179 }
180 encode(old_available_modules, bl); // version 2
181 encode(available_modules, bl); // version 3
182 ENCODE_FINISH(bl);
183 }
184
185 void decode(bufferlist::const_iterator& p)
186 {
187 DECODE_START(3, p);
188 decode(gid, p);
189 decode(name, p);
190 if (struct_v >= 2) {
191 std::set<std::string> old_available_modules;
192 decode(old_available_modules, p);
193 if (struct_v < 3) {
194 for (const auto &name : old_available_modules) {
195 MgrMap::ModuleInfo info;
196 info.name = name;
197 available_modules.push_back(std::move(info));
198 }
199 }
200 }
201 if (struct_v >= 3) {
202 decode(available_modules, p);
203 }
204 DECODE_FINISH(p);
205 }
206
207 bool have_module(const std::string &module_name) const
208 {
209 auto it = std::find_if(available_modules.begin(),
210 available_modules.end(),
211 [module_name](const ModuleInfo &m) -> bool {
212 return m.name == module_name;
213 });
214
215 return it != available_modules.end();
216 }
217 };
218
219 epoch_t epoch = 0;
220
221 /// global_id of the ceph-mgr instance selected as a leader
222 uint64_t active_gid = 0;
223 /// server address reported by the leader once it is active
224 entity_addrvec_t active_addrs;
225 /// whether the nominated leader is active (i.e. has initialized its server)
226 bool available = false;
227 /// the name (foo in mgr.<foo>) of the active daemon
228 std::string active_name;
229 /// when the active mgr became active, or we lost the active mgr
230 utime_t active_change;
231
232 std::map<uint64_t, StandbyInfo> standbys;
233
234 // Modules which are enabled
235 std::set<std::string> modules;
236
237 // Modules which should always be enabled. A manager daemon will enable
238 // modules from the union of this set and the `modules` set above, latest
239 // active version.
240 std::map<uint32_t, std::set<std::string>> always_on_modules;
241
242 // Modules which are reported to exist
243 std::vector<ModuleInfo> available_modules;
244
245 // Map of module name to URI, indicating services exposed by
246 // running modules on the active mgr daemon.
247 std::map<std::string, std::string> services;
248
249 epoch_t get_epoch() const { return epoch; }
250 entity_addrvec_t get_active_addrs() const { return active_addrs; }
251 uint64_t get_active_gid() const { return active_gid; }
252 bool get_available() const { return available; }
253 const std::string &get_active_name() const { return active_name; }
254 const utime_t& get_active_change() const { return active_change; }
255
256 bool all_support_module(const std::string& module) {
257 if (!have_module(module)) {
258 return false;
259 }
260 for (auto& p : standbys) {
261 if (!p.second.have_module(module)) {
262 return false;
263 }
264 }
265 return true;
266 }
267
268 bool have_module(const std::string &module_name) const
269 {
270 for (const auto &i : available_modules) {
271 if (i.name == module_name) {
272 return true;
273 }
274 }
275
276 return false;
277 }
278
279 const ModuleInfo *get_module_info(const std::string &module_name) const {
280 for (const auto &i : available_modules) {
281 if (i.name == module_name) {
282 return &i;
283 }
284 }
285 return nullptr;
286 }
287
288 bool can_run_module(const std::string &module_name, std::string *error) const
289 {
290 for (const auto &i : available_modules) {
291 if (i.name == module_name) {
292 *error = i.error_string;
293 return i.can_run;
294 }
295 }
296
297 std::ostringstream oss;
298 oss << "Module '" << module_name << "' does not exist";
299 throw std::logic_error(oss.str());
300 }
301
302 bool module_enabled(const std::string& module_name) const
303 {
304 return modules.find(module_name) != modules.end();
305 }
306
307 bool any_supports_module(const std::string& module) const {
308 if (have_module(module)) {
309 return true;
310 }
311 for (auto& p : standbys) {
312 if (p.second.have_module(module)) {
313 return true;
314 }
315 }
316 return false;
317 }
318
319 bool have_name(const string& name) const {
320 if (active_name == name) {
321 return true;
322 }
323 for (auto& p : standbys) {
324 if (p.second.name == name) {
325 return true;
326 }
327 }
328 return false;
329 }
330
331 std::set<std::string> get_all_names() const {
332 std::set<std::string> ls;
333 if (active_name.size()) {
334 ls.insert(active_name);
335 }
336 for (auto& p : standbys) {
337 ls.insert(p.second.name);
338 }
339 return ls;
340 }
341
342 std::set<std::string> get_always_on_modules() const {
343 auto it = always_on_modules.find(ceph_release());
344 if (it == always_on_modules.end())
345 return {};
346 return it->second;
347 }
348
349 void encode(bufferlist& bl, uint64_t features) const
350 {
351 if (!HAVE_FEATURE(features, SERVER_NAUTILUS)) {
352 ENCODE_START(5, 1, bl);
353 encode(epoch, bl);
354 encode(active_addrs.legacy_addr(), bl, features);
355 encode(active_gid, bl);
356 encode(available, bl);
357 encode(active_name, bl);
358 encode(standbys, bl);
359 encode(modules, bl);
360
361 // Pre-version 4 string list of available modules
362 // (replaced by direct encode of ModuleInfo below)
363 std::set<std::string> old_available_modules;
364 for (const auto &i : available_modules) {
365 old_available_modules.insert(i.name);
366 }
367 encode(old_available_modules, bl);
368
369 encode(services, bl);
370 encode(available_modules, bl);
371 ENCODE_FINISH(bl);
372 return;
373 }
374 ENCODE_START(8, 6, bl);
375 encode(epoch, bl);
376 encode(active_addrs, bl, features);
377 encode(active_gid, bl);
378 encode(available, bl);
379 encode(active_name, bl);
380 encode(standbys, bl);
381 encode(modules, bl);
382 encode(services, bl);
383 encode(available_modules, bl);
384 encode(active_change, bl);
385 encode(always_on_modules, bl);
386 ENCODE_FINISH(bl);
387 return;
388 }
389
390 void decode(bufferlist::const_iterator& p)
391 {
392 DECODE_START(7, p);
393 decode(epoch, p);
394 decode(active_addrs, p);
395 decode(active_gid, p);
396 decode(available, p);
397 decode(active_name, p);
398 decode(standbys, p);
399 if (struct_v >= 2) {
400 decode(modules, p);
401
402 if (struct_v < 6) {
403 // Reconstitute ModuleInfos from names
404 std::set<std::string> module_name_list;
405 decode(module_name_list, p);
406 // Only need to unpack this field if we won't have the full
407 // MgrMap::ModuleInfo structures added in v4
408 if (struct_v < 4) {
409 for (const auto &i : module_name_list) {
410 MgrMap::ModuleInfo info;
411 info.name = i;
412 available_modules.push_back(std::move(info));
413 }
414 }
415 }
416 }
417 if (struct_v >= 3) {
418 decode(services, p);
419 }
420 if (struct_v >= 4) {
421 decode(available_modules, p);
422 }
423 if (struct_v >= 7) {
424 decode(active_change, p);
425 } else {
426 active_change = {};
427 }
428 if (struct_v >= 8) {
429 decode(always_on_modules, p);
430 }
431 DECODE_FINISH(p);
432 }
433
434 void dump(Formatter *f) const {
435 f->dump_int("epoch", epoch);
436 f->dump_int("active_gid", get_active_gid());
437 f->dump_string("active_name", get_active_name());
438 f->dump_object("active_addrs", active_addrs);
439 f->dump_stream("active_addr") << active_addrs.get_legacy_str();
440 f->dump_stream("active_change") << active_change;
441 f->dump_bool("available", available);
442 f->open_array_section("standbys");
443 for (const auto &i : standbys) {
444 f->open_object_section("standby");
445 f->dump_int("gid", i.second.gid);
446 f->dump_string("name", i.second.name);
447 f->open_array_section("available_modules");
448 for (const auto& j : i.second.available_modules) {
449 j.dump(f);
450 }
451 f->close_section();
452 f->close_section();
453 }
454 f->close_section();
455 f->open_array_section("modules");
456 for (auto& i : modules) {
457 f->dump_string("module", i);
458 }
459 f->close_section();
460 f->open_array_section("available_modules");
461 for (const auto& j : available_modules) {
462 j.dump(f);
463 }
464 f->close_section();
465
466 f->open_object_section("services");
467 for (const auto &i : services) {
468 f->dump_string(i.first.c_str(), i.second);
469 }
470 f->close_section();
471
472 f->open_object_section("always_on_modules");
473 for (auto& v : always_on_modules) {
474 f->open_array_section(ceph_release_name(v.first));
475 for (auto& m : v.second) {
476 f->dump_string("module", m);
477 }
478 f->close_section();
479 }
480 f->close_section();
481 }
482
483 static void generate_test_instances(list<MgrMap*> &l) {
484 l.push_back(new MgrMap);
485 }
486
487 void print_summary(Formatter *f, std::ostream *ss) const
488 {
489 // One or the other, not both
490 ceph_assert((ss != nullptr) != (f != nullptr));
491 if (f) {
492 dump(f);
493 } else {
494 utime_t now = ceph_clock_now();
495 if (get_active_gid() != 0) {
496 *ss << get_active_name();
497 if (!available) {
498 // If the daemon hasn't gone active yet, indicate that.
499 *ss << "(active, starting";
500 } else {
501 *ss << "(active";
502 }
503 if (active_change) {
504 *ss << ", since " << utimespan_str(now - active_change);
505 }
506 *ss << ")";
507 } else {
508 *ss << "no daemons active";
509 if (active_change) {
510 *ss << " (since " << utimespan_str(now - active_change) << ")";
511 }
512 }
513 if (standbys.size()) {
514 *ss << ", standbys: ";
515 bool first = true;
516 for (const auto &i : standbys) {
517 if (!first) {
518 *ss << ", ";
519 }
520 *ss << i.second.name;
521 first = false;
522 }
523 }
524 }
525 }
526
527 friend ostream& operator<<(ostream& out, const MgrMap& m) {
528 ostringstream ss;
529 m.print_summary(nullptr, &ss);
530 return out << ss.str();
531 }
532
533 friend ostream& operator<<(ostream& out, const std::vector<ModuleInfo>& mi) {
534 for (const auto &i : mi) {
535 out << i.name << " ";
536 }
537 return out;
538 }
539 };
540
541 WRITE_CLASS_ENCODER_FEATURES(MgrMap)
542 WRITE_CLASS_ENCODER(MgrMap::StandbyInfo)
543 WRITE_CLASS_ENCODER(MgrMap::ModuleInfo);
544 WRITE_CLASS_ENCODER(MgrMap::ModuleOption);
545
546 #endif
547