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) 2004-2006 Sage Weil <sage@newdream.net>
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.
19 #include <seastar/core/future.hh>
22 #include "common/config_fwd.h"
23 #include "common/ceph_releases.h"
25 #include "include/err.h"
26 #include "include/types.h"
28 #include "mon/mon_types.h"
29 #include "msg/Message.h"
33 namespace crimson::common
{
46 * i.e., 'foo' in 'mon.foo'
50 * monitor's public address(es)
52 * public facing address(es), used to communicate with all clients
53 * and with other monitors.
55 entity_addrvec_t public_addrs
;
57 * the priority of the mon, the lower value the more preferred
63 mon_info_t(const std::string
& n
, const entity_addr_t
& p_addr
, uint16_t p
)
64 : name(n
), public_addrs(p_addr
), priority(p
)
68 mon_info_t(const std::string
& n
, const entity_addrvec_t
& p_addrs
,
69 uint16_t p
, uint16_t w
)
70 : name(n
), public_addrs(p_addrs
), priority(p
), weight(w
)
72 mon_info_t(const std::string
&n
, const entity_addrvec_t
& p_addrs
)
73 : name(n
), public_addrs(p_addrs
)
79 void encode(ceph::buffer::list
& bl
, uint64_t features
) const;
80 void decode(ceph::buffer::list::const_iterator
& p
);
81 void print(std::ostream
& out
) const;
83 WRITE_CLASS_ENCODER_FEATURES(mon_info_t
)
85 inline std::ostream
& operator<<(std::ostream
& out
, const mon_info_t
& mon
) {
92 epoch_t epoch
; // what epoch/version of the monmap
97 std::map
<std::string
, mon_info_t
> mon_info
;
98 std::map
<entity_addr_t
, std::string
> addr_mons
;
100 std::vector
<std::string
> ranks
;
103 * Persistent Features are all those features that once set on a
104 * monmap cannot, and should not, be removed. These will define the
105 * non-negotiable features that a given monitor must support to
106 * properly operate in a given quorum.
108 * Should be reserved for features that we really want to make sure
109 * are sticky, and are important enough to tolerate not being able
110 * to downgrade a monitor.
112 mon_feature_t persistent_features
;
114 * Optional Features are all those features that can be enabled or
115 * disabled following a given criteria -- e.g., user-mandated via the
116 * cli --, and act much like indicators of what the cluster currently
119 * They are by no means "optional" in the sense that monitors can
120 * ignore them. Just that they are not persistent.
122 mon_feature_t optional_features
;
125 * Returns the set of features required by this monmap.
127 * The features required by this monmap is the union of all the
128 * currently set persistent features and the currently set optional
131 * @returns the set of features required by this monmap
133 mon_feature_t
get_required_features() const {
134 return (persistent_features
| optional_features
);
138 ceph_release_t min_mon_release
{ceph_release_t::unknown
};
140 void _add_ambiguous_addr(const std::string
& name
,
147 void calc_legacy_ranks();
148 void calc_addr_mons() {
149 // populate addr_mons
151 for (auto& p
: mon_info
) {
152 for (auto& a
: p
.second
.public_addrs
.v
) {
153 addr_mons
[a
] = p
.first
;
162 uuid_d
& get_fsid() { return fsid
; }
164 unsigned size() const {
165 return mon_info
.size();
168 unsigned min_quorum_size(unsigned total_mons
=0) const {
169 if (total_mons
== 0) {
172 return total_mons
/ 2 + 1;
175 epoch_t
get_epoch() const { return epoch
; }
176 void set_epoch(epoch_t e
) { epoch
= e
; }
179 * Obtain list of public facing addresses
181 * @param ls list to populate with the monitors' addresses
183 void list_addrs(std::list
<entity_addr_t
>& ls
) const {
184 for (auto& i
: mon_info
) {
185 for (auto& j
: i
.second
.public_addrs
.v
) {
192 * Add new monitor to the monmap
194 * @param m monitor info of the new monitor
196 void add(const mon_info_t
& m
) {
197 ceph_assert(mon_info
.count(m
.name
) == 0);
198 for (auto& a
: m
.public_addrs
.v
) {
199 ceph_assert(addr_mons
.count(a
) == 0);
201 mon_info
[m
.name
] = m
;
202 if (get_required_features().contains_all(
203 ceph::features::mon::FEATURE_NAUTILUS
)) {
204 ranks
.push_back(m
.name
);
205 ceph_assert(ranks
.size() == mon_info
.size());
213 * Add new monitor to the monmap
215 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
216 * @param addr Monitor's public address
218 void add(const std::string
&name
, const entity_addrvec_t
&addrv
,
219 uint16_t priority
=0, uint16_t weight
=0) {
220 add(mon_info_t(name
, addrv
, priority
, weight
));
224 * Remove monitor from the monmap
226 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
228 void remove(const std::string
&name
) {
229 ceph_assert(mon_info
.count(name
));
230 mon_info
.erase(name
);
231 ceph_assert(mon_info
.count(name
) == 0);
232 if (get_required_features().contains_all(
233 ceph::features::mon::FEATURE_NAUTILUS
)) {
234 ranks
.erase(std::find(ranks
.begin(), ranks
.end(), name
));
235 ceph_assert(ranks
.size() == mon_info
.size());
243 * Rename monitor from @p oldname to @p newname
245 * @param oldname monitor's current name (i.e., 'foo' in 'mon.foo')
246 * @param newname monitor's new name (i.e., 'bar' in 'mon.bar')
248 void rename(std::string oldname
, std::string newname
) {
249 ceph_assert(contains(oldname
));
250 ceph_assert(!contains(newname
));
251 mon_info
[newname
] = mon_info
[oldname
];
252 mon_info
.erase(oldname
);
253 mon_info
[newname
].name
= newname
;
254 if (get_required_features().contains_all(
255 ceph::features::mon::FEATURE_NAUTILUS
)) {
256 *std::find(ranks
.begin(), ranks
.end(), oldname
) = newname
;
257 ceph_assert(ranks
.size() == mon_info
.size());
264 int set_rank(const std::string
& name
, int rank
) {
265 int oldrank
= get_rank(name
);
269 if (rank
< 0 || rank
>= (int)ranks
.size()) {
272 if (oldrank
!= rank
) {
273 ranks
.erase(ranks
.begin() + oldrank
);
274 ranks
.insert(ranks
.begin() + rank
, name
);
279 bool contains(const std::string
& name
) const {
280 return mon_info
.count(name
);
284 * Check if monmap contains a monitor with address @p a
286 * @note checks for all addresses a monitor may have, public or otherwise.
288 * @param a monitor address
289 * @returns true if monmap contains a monitor with address @p;
292 bool contains(const entity_addr_t
&a
, std::string
*name
=nullptr) const {
293 for (auto& i
: mon_info
) {
294 for (auto& j
: i
.second
.public_addrs
.v
) {
305 bool contains(const entity_addrvec_t
&av
, std::string
*name
=nullptr) const {
306 for (auto& i
: mon_info
) {
307 for (auto& j
: i
.second
.public_addrs
.v
) {
308 for (auto& k
: av
.v
) {
321 std::string
get_name(unsigned n
) const {
322 ceph_assert(n
< ranks
.size());
325 std::string
get_name(const entity_addr_t
& a
) const {
326 std::map
<entity_addr_t
, std::string
>::const_iterator p
= addr_mons
.find(a
);
327 if (p
== addr_mons
.end())
328 return std::string();
332 std::string
get_name(const entity_addrvec_t
& av
) const {
333 for (auto& i
: av
.v
) {
334 std::map
<entity_addr_t
, std::string
>::const_iterator p
= addr_mons
.find(i
);
335 if (p
!= addr_mons
.end())
338 return std::string();
341 int get_rank(const std::string
& n
) const {
342 if (auto found
= std::find(ranks
.begin(), ranks
.end(), n
);
343 found
!= ranks
.end()) {
344 return std::distance(ranks
.begin(), found
);
349 int get_rank(const entity_addr_t
& a
) const {
350 std::string n
= get_name(a
);
356 int get_rank(const entity_addrvec_t
& av
) const {
357 std::string n
= get_name(av
);
363 bool get_addr_name(const entity_addr_t
& a
, std::string
& name
) {
364 if (addr_mons
.count(a
) == 0)
370 const entity_addrvec_t
& get_addrs(const std::string
& n
) const {
371 ceph_assert(mon_info
.count(n
));
372 std::map
<std::string
,mon_info_t
>::const_iterator p
= mon_info
.find(n
);
373 return p
->second
.public_addrs
;
375 const entity_addrvec_t
& get_addrs(unsigned m
) const {
376 ceph_assert(m
< ranks
.size());
377 return get_addrs(ranks
[m
]);
379 void set_addrvec(const std::string
& n
, const entity_addrvec_t
& a
) {
380 ceph_assert(mon_info
.count(n
));
381 mon_info
[n
].public_addrs
= a
;
384 uint16_t get_priority(const std::string
& n
) const {
385 auto it
= mon_info
.find(n
);
386 ceph_assert(it
!= mon_info
.end());
387 return it
->second
.priority
;
389 uint16_t get_weight(const std::string
& n
) const {
390 auto it
= mon_info
.find(n
);
391 ceph_assert(it
!= mon_info
.end());
392 return it
->second
.weight
;
394 void set_weight(const std::string
& n
, uint16_t v
) {
395 auto it
= mon_info
.find(n
);
396 ceph_assert(it
!= mon_info
.end());
397 it
->second
.weight
= v
;
400 void encode(ceph::buffer::list
& blist
, uint64_t con_features
) const;
401 void decode(ceph::buffer::list
& blist
) {
402 auto p
= std::cbegin(blist
);
405 void decode(ceph::buffer::list::const_iterator
& p
);
407 void generate_fsid() {
408 fsid
.generate_random();
411 // read from/write to a file
412 int write(const char *fn
);
413 int read(const char *fn
);
416 * build an initial bootstrap monmap from conf
418 * Build an initial bootstrap monmap from the config. This will
419 * try, in this order:
421 * 1 monmap -- an explicitly provided monmap
422 * 2 mon_host -- list of monitors
423 * 3 config [mon.*] sections, and 'mon addr' fields in those sections
425 * @param cct context (and associated config)
426 * @param errout std::ostream to send error messages too
429 seastar::future
<> build_initial(const crimson::common::ConfigProxy
& conf
, bool for_mkfs
);
431 int build_initial(CephContext
*cct
, bool for_mkfs
, std::ostream
& errout
);
434 * filter monmap given a set of initial members.
436 * Remove mons that aren't in the initial_members list. Add missing
437 * mons and give them dummy IPs (blank IPv4, with a non-zero
438 * nonce). If the name matches my_name, then my_addr will be used in
439 * place of a dummy addr.
441 * @param initial_members list of initial member names
442 * @param my_name name of self, can be blank
443 * @param my_addr my addr
444 * @param removed optional pointer to set to insert removed mon addrs to
446 void set_initial_members(CephContext
*cct
,
447 std::list
<std::string
>& initial_members
,
449 const entity_addrvec_t
& my_addrs
,
450 std::set
<entity_addrvec_t
> *removed
);
452 void print(std::ostream
& out
) const;
453 void print_summary(std::ostream
& out
) const;
454 void dump(ceph::Formatter
*f
) const;
455 void dump_summary(ceph::Formatter
*f
) const;
457 static void generate_test_instances(std::list
<MonMap
*>& o
);
460 * build a monmap from a list of entity_addrvec_t's
462 * Give mons dummy names.
464 * @param addrs list of entity_addrvec_t's
465 * @param prefix prefix to prepend to generated mon names
467 void init_with_addrs(const std::vector
<entity_addrvec_t
>& addrs
,
469 std::string_view prefix
);
471 * build a monmap from a list of ips
473 * Give mons dummy names.
475 * @param hosts list of ips, space or comma separated
476 * @param prefix prefix to prepend to generated mon names
477 * @return 0 for success, -errno on error
479 int init_with_ips(const std::string
& ips
,
481 std::string_view prefix
);
483 * build a monmap from a list of hostnames
485 * Give mons dummy names.
487 * @param hosts list of ips, space or comma separated
488 * @param prefix prefix to prepend to generated mon names
489 * @return 0 for success, -errno on error
491 int init_with_hosts(const std::string
& hostlist
,
493 std::string_view prefix
);
494 int init_with_config_file(const ConfigProxy
& conf
, std::ostream
& errout
);
496 seastar::future
<> read_monmap(const std::string
& monmap
);
497 /// try to build monmap with different settings, like
498 /// mon_host, mon* sections, and mon_dns_srv_name
499 seastar::future
<> build_monmap(const crimson::common::ConfigProxy
& conf
, bool for_mkfs
);
500 /// initialize monmap by resolving given service name
501 seastar::future
<> init_with_dns_srv(bool for_mkfs
, const std::string
& name
);
503 /// read from encoded monmap file
504 int init_with_monmap(const std::string
& monmap
, std::ostream
& errout
);
505 int init_with_dns_srv(CephContext
* cct
, std::string srv_name
, bool for_mkfs
,
506 std::ostream
& errout
);
509 WRITE_CLASS_ENCODER_FEATURES(MonMap
)
511 inline std::ostream
& operator<<(std::ostream
&out
, const MonMap
&m
) {
512 m
.print_summary(out
);