1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2016 John Spray <john.spray@redhat.com>
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.
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"
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
;
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
;
44 void encode(bufferlist
& bl
) const {
45 ENCODE_START(1, 1, bl
);
50 encode(default_value
, bl
);
53 encode(enum_allowed
, bl
);
55 encode(long_desc
, bl
);
60 void decode(bufferlist::const_iterator
& p
) {
66 decode(default_value
, p
);
69 decode(enum_allowed
, p
);
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
);
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
);
98 f
->open_array_section("see_also");
99 for (auto& i
: see_also
) {
100 f
->dump_string("option", i
);
111 std::string error_string
;
112 std::map
<std::string
,ModuleOption
> module_options
;
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
);
120 encode(error_string
, bl
);
121 encode(module_options
, bl
);
125 void decode(bufferlist::const_iterator
&bl
) {
129 decode(error_string
, bl
);
131 decode(module_options
, bl
);
136 bool operator==(const ModuleInfo
&rhs
) const
138 return (name
== rhs
.name
) && (can_run
== rhs
.can_run
);
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
);
160 std::vector
<ModuleInfo
> available_modules
;
162 StandbyInfo(uint64_t gid_
, const std::string
&name_
,
163 const std::vector
<ModuleInfo
>& am
)
164 : gid(gid_
), name(name_
), available_modules(am
)
171 void encode(bufferlist
& bl
) const
173 ENCODE_START(3, 1, bl
);
176 std::set
<std::string
> old_available_modules
;
177 for (const auto &i
: available_modules
) {
178 old_available_modules
.insert(i
.name
);
180 encode(old_available_modules
, bl
); // version 2
181 encode(available_modules
, bl
); // version 3
185 void decode(bufferlist::const_iterator
& p
)
191 std::set
<std::string
> old_available_modules
;
192 decode(old_available_modules
, p
);
194 for (const auto &name
: old_available_modules
) {
195 MgrMap::ModuleInfo info
;
197 available_modules
.push_back(std::move(info
));
202 decode(available_modules
, p
);
207 bool have_module(const std::string
&module_name
) const
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
;
215 return it
!= available_modules
.end();
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
;
232 std::map
<uint64_t, StandbyInfo
> standbys
;
234 // Modules which are enabled
235 std::set
<std::string
> modules
;
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
240 std::map
<uint32_t, std::set
<std::string
>> always_on_modules
;
242 // Modules which are reported to exist
243 std::vector
<ModuleInfo
> available_modules
;
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
;
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
; }
256 bool all_support_module(const std::string
& module
) {
257 if (!have_module(module
)) {
260 for (auto& p
: standbys
) {
261 if (!p
.second
.have_module(module
)) {
268 bool have_module(const std::string
&module_name
) const
270 for (const auto &i
: available_modules
) {
271 if (i
.name
== module_name
) {
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
) {
288 bool can_run_module(const std::string
&module_name
, std::string
*error
) const
290 for (const auto &i
: available_modules
) {
291 if (i
.name
== module_name
) {
292 *error
= i
.error_string
;
297 std::ostringstream oss
;
298 oss
<< "Module '" << module_name
<< "' does not exist";
299 throw std::logic_error(oss
.str());
302 bool module_enabled(const std::string
& module_name
) const
304 return modules
.find(module_name
) != modules
.end();
307 bool any_supports_module(const std::string
& module
) const {
308 if (have_module(module
)) {
311 for (auto& p
: standbys
) {
312 if (p
.second
.have_module(module
)) {
319 bool have_name(const string
& name
) const {
320 if (active_name
== name
) {
323 for (auto& p
: standbys
) {
324 if (p
.second
.name
== name
) {
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
);
336 for (auto& p
: standbys
) {
337 ls
.insert(p
.second
.name
);
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())
349 void encode(bufferlist
& bl
, uint64_t features
) const
351 if (!HAVE_FEATURE(features
, SERVER_NAUTILUS
)) {
352 ENCODE_START(5, 1, 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
);
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
);
367 encode(old_available_modules
, bl
);
369 encode(services
, bl
);
370 encode(available_modules
, bl
);
374 ENCODE_START(8, 6, 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
);
382 encode(services
, bl
);
383 encode(available_modules
, bl
);
384 encode(active_change
, bl
);
385 encode(always_on_modules
, bl
);
390 void decode(bufferlist::const_iterator
& p
)
394 decode(active_addrs
, p
);
395 decode(active_gid
, p
);
396 decode(available
, p
);
397 decode(active_name
, p
);
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
409 for (const auto &i
: module_name_list
) {
410 MgrMap::ModuleInfo info
;
412 available_modules
.push_back(std::move(info
));
421 decode(available_modules
, p
);
424 decode(active_change
, p
);
429 decode(always_on_modules
, p
);
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
) {
455 f
->open_array_section("modules");
456 for (auto& i
: modules
) {
457 f
->dump_string("module", i
);
460 f
->open_array_section("available_modules");
461 for (const auto& j
: available_modules
) {
466 f
->open_object_section("services");
467 for (const auto &i
: services
) {
468 f
->dump_string(i
.first
.c_str(), i
.second
);
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
);
483 static void generate_test_instances(list
<MgrMap
*> &l
) {
484 l
.push_back(new MgrMap
);
487 void print_summary(Formatter
*f
, std::ostream
*ss
) const
489 // One or the other, not both
490 ceph_assert((ss
!= nullptr) != (f
!= nullptr));
494 utime_t now
= ceph_clock_now();
495 if (get_active_gid() != 0) {
496 *ss
<< get_active_name();
498 // If the daemon hasn't gone active yet, indicate that.
499 *ss
<< "(active, starting";
504 *ss
<< ", since " << utimespan_str(now
- active_change
);
508 *ss
<< "no daemons active";
510 *ss
<< " (since " << utimespan_str(now
- active_change
) << ")";
513 if (standbys
.size()) {
514 *ss
<< ", standbys: ";
516 for (const auto &i
: standbys
) {
520 *ss
<< i
.second
.name
;
527 friend ostream
& operator<<(ostream
& out
, const MgrMap
& m
) {
529 m
.print_summary(nullptr, &ss
);
530 return out
<< ss
.str();
533 friend ostream
& operator<<(ostream
& out
, const std::vector
<ModuleInfo
>& mi
) {
534 for (const auto &i
: mi
) {
535 out
<< i
.name
<< " ";
541 WRITE_CLASS_ENCODER_FEATURES(MgrMap
)
542 WRITE_CLASS_ENCODER(MgrMap::StandbyInfo
)
543 WRITE_CLASS_ENCODER(MgrMap::ModuleInfo
);
544 WRITE_CLASS_ENCODER(MgrMap::ModuleOption
);