]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/MonMap.h
d28046c2d97c7249ea69e902cd0d6c7ecb03e923
[ceph.git] / ceph / src / mon / MonMap.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) 2004-2006 Sage Weil <sage@newdream.net>
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
15 #ifndef CEPH_MONMAP_H
16 #define CEPH_MONMAP_H
17
18 #ifdef WITH_SEASTAR
19 #include <seastar/core/future.hh>
20 #endif
21
22 #include "common/config_fwd.h"
23 #include "common/ceph_releases.h"
24
25 #include "include/err.h"
26 #include "include/types.h"
27
28 #include "mon/mon_types.h"
29 #include "msg/Message.h"
30
31
32 #ifdef WITH_SEASTAR
33 namespace crimson::common {
34 class ConfigProxy;
35 }
36 #endif
37
38 namespace ceph {
39 class Formatter;
40 }
41
42 struct mon_info_t {
43 /**
44 * monitor name
45 *
46 * i.e., 'foo' in 'mon.foo'
47 */
48 std::string name;
49 /**
50 * monitor's public address(es)
51 *
52 * public facing address(es), used to communicate with all clients
53 * and with other monitors.
54 */
55 entity_addrvec_t public_addrs;
56 /**
57 * the priority of the mon, the lower value the more preferred
58 */
59 uint16_t priority{0};
60 uint16_t weight{0};
61
62 // <REMOVE ME>
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)
65 {}
66 // </REMOVE ME>
67
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)
71 {}
72 mon_info_t(const std::string &n, const entity_addrvec_t& p_addrs)
73 : name(n), public_addrs(p_addrs)
74 { }
75
76 mon_info_t() { }
77
78
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;
82 };
83 WRITE_CLASS_ENCODER_FEATURES(mon_info_t)
84
85 inline std::ostream& operator<<(std::ostream& out, const mon_info_t& mon) {
86 mon.print(out);
87 return out;
88 }
89
90 class MonMap {
91 public:
92 epoch_t epoch; // what epoch/version of the monmap
93 uuid_d fsid;
94 utime_t last_changed;
95 utime_t created;
96
97 std::map<std::string, mon_info_t> mon_info;
98 std::map<entity_addr_t, std::string> addr_mons;
99
100 std::vector<std::string> ranks;
101
102 /**
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.
107 *
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.
111 */
112 mon_feature_t persistent_features;
113 /**
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
117 * supports.
118 *
119 * They are by no means "optional" in the sense that monitors can
120 * ignore them. Just that they are not persistent.
121 */
122 mon_feature_t optional_features;
123
124 /**
125 * Returns the set of features required by this monmap.
126 *
127 * The features required by this monmap is the union of all the
128 * currently set persistent features and the currently set optional
129 * features.
130 *
131 * @returns the set of features required by this monmap
132 */
133 mon_feature_t get_required_features() const {
134 return (persistent_features | optional_features);
135 }
136
137 // upgrade gate
138 ceph_release_t min_mon_release{ceph_release_t::unknown};
139
140 void _add_ambiguous_addr(const std::string& name,
141 entity_addr_t addr,
142 int priority,
143 int weight,
144 bool for_mkfs);
145
146 public:
147 void calc_legacy_ranks();
148 void calc_addr_mons() {
149 // populate addr_mons
150 addr_mons.clear();
151 for (auto& p : mon_info) {
152 for (auto& a : p.second.public_addrs.v) {
153 addr_mons[a] = p.first;
154 }
155 }
156 }
157
158 MonMap()
159 : epoch(0) {
160 }
161
162 uuid_d& get_fsid() { return fsid; }
163
164 unsigned size() const {
165 return mon_info.size();
166 }
167
168 unsigned min_quorum_size(unsigned total_mons=0) const {
169 if (total_mons == 0) {
170 total_mons = size();
171 }
172 return total_mons / 2 + 1;
173 }
174
175 epoch_t get_epoch() const { return epoch; }
176 void set_epoch(epoch_t e) { epoch = e; }
177
178 /**
179 * Obtain list of public facing addresses
180 *
181 * @param ls list to populate with the monitors' addresses
182 */
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) {
186 ls.push_back(j);
187 }
188 }
189 }
190
191 /**
192 * Add new monitor to the monmap
193 *
194 * @param m monitor info of the new monitor
195 */
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);
200 }
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());
206 } else {
207 calc_legacy_ranks();
208 }
209 calc_addr_mons();
210 }
211
212 /**
213 * Add new monitor to the monmap
214 *
215 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
216 * @param addr Monitor's public address
217 */
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));
221 }
222
223 /**
224 * Remove monitor from the monmap
225 *
226 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
227 */
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());
236 } else {
237 calc_legacy_ranks();
238 }
239 calc_addr_mons();
240 }
241
242 /**
243 * Rename monitor from @p oldname to @p newname
244 *
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')
247 */
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());
258 } else {
259 calc_legacy_ranks();
260 }
261 calc_addr_mons();
262 }
263
264 int set_rank(const std::string& name, int rank) {
265 int oldrank = get_rank(name);
266 if (oldrank < 0) {
267 return -ENOENT;
268 }
269 if (rank < 0 || rank >= (int)ranks.size()) {
270 return -EINVAL;
271 }
272 if (oldrank != rank) {
273 ranks.erase(ranks.begin() + oldrank);
274 ranks.insert(ranks.begin() + rank, name);
275 }
276 return 0;
277 }
278
279 bool contains(const std::string& name) const {
280 return mon_info.count(name);
281 }
282
283 /**
284 * Check if monmap contains a monitor with address @p a
285 *
286 * @note checks for all addresses a monitor may have, public or otherwise.
287 *
288 * @param a monitor address
289 * @returns true if monmap contains a monitor with address @p;
290 * false otherwise.
291 */
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) {
295 if (j == a) {
296 if (name) {
297 *name = i.first;
298 }
299 return true;
300 }
301 }
302 }
303 return false;
304 }
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) {
309 if (j == k) {
310 if (name) {
311 *name = i.first;
312 }
313 return true;
314 }
315 }
316 }
317 }
318 return false;
319 }
320
321 std::string get_name(unsigned n) const {
322 ceph_assert(n < ranks.size());
323 return ranks[n];
324 }
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();
329 else
330 return p->second;
331 }
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())
336 return p->second;
337 }
338 return std::string();
339 }
340
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);
345 } else {
346 return -1;
347 }
348 }
349 int get_rank(const entity_addr_t& a) const {
350 std::string n = get_name(a);
351 if (!n.empty()) {
352 return get_rank(n);
353 }
354 return -1;
355 }
356 int get_rank(const entity_addrvec_t& av) const {
357 std::string n = get_name(av);
358 if (!n.empty()) {
359 return get_rank(n);
360 }
361 return -1;
362 }
363 bool get_addr_name(const entity_addr_t& a, std::string& name) {
364 if (addr_mons.count(a) == 0)
365 return false;
366 name = addr_mons[a];
367 return true;
368 }
369
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;
374 }
375 const entity_addrvec_t& get_addrs(unsigned m) const {
376 ceph_assert(m < ranks.size());
377 return get_addrs(ranks[m]);
378 }
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;
382 calc_addr_mons();
383 }
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;
388 }
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;
393 }
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;
398 }
399
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);
403 decode(p);
404 }
405 void decode(ceph::buffer::list::const_iterator& p);
406
407 void generate_fsid() {
408 fsid.generate_random();
409 }
410
411 // read from/write to a file
412 int write(const char *fn);
413 int read(const char *fn);
414
415 /**
416 * build an initial bootstrap monmap from conf
417 *
418 * Build an initial bootstrap monmap from the config. This will
419 * try, in this order:
420 *
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
424 *
425 * @param cct context (and associated config)
426 * @param errout std::ostream to send error messages too
427 */
428 #ifdef WITH_SEASTAR
429 seastar::future<> build_initial(const crimson::common::ConfigProxy& conf, bool for_mkfs);
430 #else
431 int build_initial(CephContext *cct, bool for_mkfs, std::ostream& errout);
432 #endif
433 /**
434 * filter monmap given a set of initial members.
435 *
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.
440 *
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
445 */
446 void set_initial_members(CephContext *cct,
447 std::list<std::string>& initial_members,
448 std::string my_name,
449 const entity_addrvec_t& my_addrs,
450 std::set<entity_addrvec_t> *removed);
451
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;
456
457 static void generate_test_instances(std::list<MonMap*>& o);
458 protected:
459 /**
460 * build a monmap from a list of entity_addrvec_t's
461 *
462 * Give mons dummy names.
463 *
464 * @param addrs list of entity_addrvec_t's
465 * @param prefix prefix to prepend to generated mon names
466 */
467 void init_with_addrs(const std::vector<entity_addrvec_t>& addrs,
468 bool for_mkfs,
469 std::string_view prefix);
470 /**
471 * build a monmap from a list of ips
472 *
473 * Give mons dummy names.
474 *
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
478 */
479 int init_with_ips(const std::string& ips,
480 bool for_mkfs,
481 std::string_view prefix);
482 /**
483 * build a monmap from a list of hostnames
484 *
485 * Give mons dummy names.
486 *
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
490 */
491 int init_with_hosts(const std::string& hostlist,
492 bool for_mkfs,
493 std::string_view prefix);
494 int init_with_config_file(const ConfigProxy& conf, std::ostream& errout);
495 #if WITH_SEASTAR
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);
502 #else
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);
507 #endif
508 };
509 WRITE_CLASS_ENCODER_FEATURES(MonMap)
510
511 inline std::ostream& operator<<(std::ostream &out, const MonMap &m) {
512 m.print_summary(out);
513 return out;
514 }
515
516 #endif