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