]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/MonMap.h
update sources to ceph Nautilus 14.2.1
[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
24 #include "include/err.h"
25 #include "include/types.h"
26
27 #include "mon/mon_types.h"
28 #include "msg/Message.h"
29
30
31 #ifdef WITH_SEASTAR
32 namespace ceph::common {
33 class ConfigProxy;
34 }
35 #endif
36
37 namespace ceph {
38 class Formatter;
39 }
40
41 struct mon_info_t {
42 /**
43 * monitor name
44 *
45 * i.e., 'foo' in 'mon.foo'
46 */
47 string name;
48 /**
49 * monitor's public address(es)
50 *
51 * public facing address(es), used to communicate with all clients
52 * and with other monitors.
53 */
54 entity_addrvec_t public_addrs;
55 /**
56 * the priority of the mon, the lower value the more preferred
57 */
58 uint16_t priority{0};
59
60 // <REMOVE ME>
61 mon_info_t(const string& n, const entity_addr_t& p_addr, uint16_t p)
62 : name(n), public_addrs(p_addr), priority(p)
63 {}
64 // </REMOVE ME>
65
66 mon_info_t(const string& n, const entity_addrvec_t& p_addrs, uint16_t p)
67 : name(n), public_addrs(p_addrs), priority(p)
68 {}
69 mon_info_t(const string &n, const entity_addrvec_t& p_addrs)
70 : name(n), public_addrs(p_addrs)
71 { }
72
73 mon_info_t() { }
74
75
76 void encode(bufferlist& bl, uint64_t features) const;
77 void decode(bufferlist::const_iterator& p);
78 void print(ostream& out) const;
79 };
80 WRITE_CLASS_ENCODER_FEATURES(mon_info_t)
81
82 inline ostream& operator<<(ostream& out, const mon_info_t& mon) {
83 mon.print(out);
84 return out;
85 }
86
87 class MonMap {
88 public:
89 epoch_t epoch; // what epoch/version of the monmap
90 uuid_d fsid;
91 utime_t last_changed;
92 utime_t created;
93
94 map<string, mon_info_t> mon_info;
95 map<entity_addr_t, string> addr_mons;
96
97 vector<string> ranks;
98
99 /**
100 * Persistent Features are all those features that once set on a
101 * monmap cannot, and should not, be removed. These will define the
102 * non-negotiable features that a given monitor must support to
103 * properly operate in a given quorum.
104 *
105 * Should be reserved for features that we really want to make sure
106 * are sticky, and are important enough to tolerate not being able
107 * to downgrade a monitor.
108 */
109 mon_feature_t persistent_features;
110 /**
111 * Optional Features are all those features that can be enabled or
112 * disabled following a given criteria -- e.g., user-mandated via the
113 * cli --, and act much like indicators of what the cluster currently
114 * supports.
115 *
116 * They are by no means "optional" in the sense that monitors can
117 * ignore them. Just that they are not persistent.
118 */
119 mon_feature_t optional_features;
120
121 /**
122 * Returns the set of features required by this monmap.
123 *
124 * The features required by this monmap is the union of all the
125 * currently set persistent features and the currently set optional
126 * features.
127 *
128 * @returns the set of features required by this monmap
129 */
130 mon_feature_t get_required_features() const {
131 return (persistent_features | optional_features);
132 }
133
134 // upgrade gate
135 uint8_t min_mon_release = 0;
136
137 void _add_ambiguous_addr(const string& name,
138 entity_addr_t addr,
139 int priority,
140 bool for_mkfs=false);
141
142 public:
143 void calc_legacy_ranks();
144 void calc_addr_mons() {
145 // populate addr_mons
146 addr_mons.clear();
147 for (auto& p : mon_info) {
148 for (auto& a : p.second.public_addrs.v) {
149 addr_mons[a] = p.first;
150 }
151 }
152 }
153
154 MonMap()
155 : epoch(0) {
156 }
157
158 uuid_d& get_fsid() { return fsid; }
159
160 unsigned size() const {
161 return mon_info.size();
162 }
163
164 unsigned min_quorum_size(unsigned total_mons=0) const {
165 if (total_mons == 0) {
166 total_mons = size();
167 }
168 return total_mons / 2 + 1;
169 }
170
171 epoch_t get_epoch() const { return epoch; }
172 void set_epoch(epoch_t e) { epoch = e; }
173
174 /**
175 * Obtain list of public facing addresses
176 *
177 * @param ls list to populate with the monitors' addresses
178 */
179 void list_addrs(list<entity_addr_t>& ls) const {
180 for (auto& i : mon_info) {
181 for (auto& j : i.second.public_addrs.v) {
182 ls.push_back(j);
183 }
184 }
185 }
186
187 /**
188 * Add new monitor to the monmap
189 *
190 * @param m monitor info of the new monitor
191 */
192 void add(const mon_info_t& m) {
193 ceph_assert(mon_info.count(m.name) == 0);
194 for (auto& a : m.public_addrs.v) {
195 ceph_assert(addr_mons.count(a) == 0);
196 }
197 mon_info[m.name] = m;
198 if (get_required_features().contains_all(
199 ceph::features::mon::FEATURE_NAUTILUS)) {
200 ranks.push_back(m.name);
201 ceph_assert(ranks.size() == mon_info.size());
202 } else {
203 calc_legacy_ranks();
204 }
205 calc_addr_mons();
206 }
207
208 /**
209 * Add new monitor to the monmap
210 *
211 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
212 * @param addr Monitor's public address
213 */
214 void add(const string &name, const entity_addrvec_t &addrv,
215 int priority=0) {
216 add(mon_info_t(name, addrv, priority));
217 }
218
219 /**
220 * Remove monitor from the monmap
221 *
222 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
223 */
224 void remove(const string &name) {
225 ceph_assert(mon_info.count(name));
226 mon_info.erase(name);
227 ceph_assert(mon_info.count(name) == 0);
228 if (get_required_features().contains_all(
229 ceph::features::mon::FEATURE_NAUTILUS)) {
230 ranks.erase(std::find(ranks.begin(), ranks.end(), name));
231 ceph_assert(ranks.size() == mon_info.size());
232 } else {
233 calc_legacy_ranks();
234 }
235 calc_addr_mons();
236 }
237
238 /**
239 * Rename monitor from @p oldname to @p newname
240 *
241 * @param oldname monitor's current name (i.e., 'foo' in 'mon.foo')
242 * @param newname monitor's new name (i.e., 'bar' in 'mon.bar')
243 */
244 void rename(string oldname, string newname) {
245 ceph_assert(contains(oldname));
246 ceph_assert(!contains(newname));
247 mon_info[newname] = mon_info[oldname];
248 mon_info.erase(oldname);
249 mon_info[newname].name = newname;
250 if (get_required_features().contains_all(
251 ceph::features::mon::FEATURE_NAUTILUS)) {
252 *std::find(ranks.begin(), ranks.end(), oldname) = newname;
253 ceph_assert(ranks.size() == mon_info.size());
254 } else {
255 calc_legacy_ranks();
256 }
257 calc_addr_mons();
258 }
259
260 int set_rank(const string& name, int rank) {
261 int oldrank = get_rank(name);
262 if (oldrank < 0) {
263 return -ENOENT;
264 }
265 if (rank < 0 || rank >= (int)ranks.size()) {
266 return -EINVAL;
267 }
268 if (oldrank != rank) {
269 ranks.erase(ranks.begin() + oldrank);
270 ranks.insert(ranks.begin() + rank, name);
271 }
272 return 0;
273 }
274
275 bool contains(const string& name) const {
276 return mon_info.count(name);
277 }
278
279 /**
280 * Check if monmap contains a monitor with address @p a
281 *
282 * @note checks for all addresses a monitor may have, public or otherwise.
283 *
284 * @param a monitor address
285 * @returns true if monmap contains a monitor with address @p;
286 * false otherwise.
287 */
288 bool contains(const entity_addr_t &a, string *name=nullptr) const {
289 for (auto& i : mon_info) {
290 for (auto& j : i.second.public_addrs.v) {
291 if (j == a) {
292 if (name) {
293 *name = i.first;
294 }
295 return true;
296 }
297 }
298 }
299 return false;
300 }
301 bool contains(const entity_addrvec_t &av, string *name=nullptr) const {
302 for (auto& i : mon_info) {
303 for (auto& j : i.second.public_addrs.v) {
304 for (auto& k : av.v) {
305 if (j == k) {
306 if (name) {
307 *name = i.first;
308 }
309 return true;
310 }
311 }
312 }
313 }
314 return false;
315 }
316
317 string get_name(unsigned n) const {
318 ceph_assert(n < ranks.size());
319 return ranks[n];
320 }
321 string get_name(const entity_addr_t& a) const {
322 map<entity_addr_t,string>::const_iterator p = addr_mons.find(a);
323 if (p == addr_mons.end())
324 return string();
325 else
326 return p->second;
327 }
328 string get_name(const entity_addrvec_t& av) const {
329 for (auto& i : av.v) {
330 map<entity_addr_t,string>::const_iterator p = addr_mons.find(i);
331 if (p != addr_mons.end())
332 return p->second;
333 }
334 return string();
335 }
336
337 int get_rank(const string& n) const {
338 if (auto found = std::find(ranks.begin(), ranks.end(), n);
339 found != ranks.end()) {
340 return std::distance(ranks.begin(), found);
341 } else {
342 return -1;
343 }
344 }
345 int get_rank(const entity_addr_t& a) const {
346 string n = get_name(a);
347 if (!n.empty()) {
348 return get_rank(n);
349 }
350 return -1;
351 }
352 int get_rank(const entity_addrvec_t& av) const {
353 string n = get_name(av);
354 if (!n.empty()) {
355 return get_rank(n);
356 }
357 return -1;
358 }
359 bool get_addr_name(const entity_addr_t& a, string& name) {
360 if (addr_mons.count(a) == 0)
361 return false;
362 name = addr_mons[a];
363 return true;
364 }
365
366 const entity_addrvec_t& get_addrs(const string& n) const {
367 ceph_assert(mon_info.count(n));
368 map<string,mon_info_t>::const_iterator p = mon_info.find(n);
369 return p->second.public_addrs;
370 }
371 const entity_addrvec_t& get_addrs(unsigned m) const {
372 ceph_assert(m < ranks.size());
373 return get_addrs(ranks[m]);
374 }
375 void set_addrvec(const string& n, const entity_addrvec_t& a) {
376 ceph_assert(mon_info.count(n));
377 mon_info[n].public_addrs = a;
378 calc_addr_mons();
379 }
380
381 void encode(bufferlist& blist, uint64_t con_features) const;
382 void decode(bufferlist& blist) {
383 auto p = std::cbegin(blist);
384 decode(p);
385 }
386 void decode(bufferlist::const_iterator& p);
387
388 void generate_fsid() {
389 fsid.generate_random();
390 }
391
392 // read from/write to a file
393 int write(const char *fn);
394 int read(const char *fn);
395
396 /**
397 * build an initial bootstrap monmap from conf
398 *
399 * Build an initial bootstrap monmap from the config. This will
400 * try, in this order:
401 *
402 * 1 monmap -- an explicitly provided monmap
403 * 2 mon_host -- list of monitors
404 * 3 config [mon.*] sections, and 'mon addr' fields in those sections
405 *
406 * @param cct context (and associated config)
407 * @param errout ostream to send error messages too
408 */
409 #ifdef WITH_SEASTAR
410 seastar::future<> build_initial(const ceph::common::ConfigProxy& conf, bool for_mkfs);
411 #else
412 int build_initial(CephContext *cct, bool for_mkfs, ostream& errout);
413 #endif
414 /**
415 * filter monmap given a set of initial members.
416 *
417 * Remove mons that aren't in the initial_members list. Add missing
418 * mons and give them dummy IPs (blank IPv4, with a non-zero
419 * nonce). If the name matches my_name, then my_addr will be used in
420 * place of a dummy addr.
421 *
422 * @param initial_members list of initial member names
423 * @param my_name name of self, can be blank
424 * @param my_addr my addr
425 * @param removed optional pointer to set to insert removed mon addrs to
426 */
427 void set_initial_members(CephContext *cct,
428 list<std::string>& initial_members,
429 string my_name,
430 const entity_addrvec_t& my_addrs,
431 set<entity_addrvec_t> *removed);
432
433 void print(ostream& out) const;
434 void print_summary(ostream& out) const;
435 void dump(ceph::Formatter *f) const;
436
437 static void generate_test_instances(list<MonMap*>& o);
438 protected:
439 /**
440 * build a monmap from a list of ips
441 *
442 * Give mons dummy names.
443 *
444 * @param hosts list of ips, space or comma separated
445 * @param prefix prefix to prepend to generated mon names
446 * @return 0 for success, -errno on error
447 */
448 int init_with_ips(const std::string& ips,
449 bool for_mkfs,
450 const std::string &prefix);
451 /**
452 * build a monmap from a list of hostnames
453 *
454 * Give mons dummy names.
455 *
456 * @param hosts list of ips, space or comma separated
457 * @param prefix prefix to prepend to generated mon names
458 * @return 0 for success, -errno on error
459 */
460 int init_with_hosts(const std::string& hostlist,
461 bool for_mkfs,
462 const std::string& prefix);
463 int init_with_config_file(const ConfigProxy& conf, std::ostream& errout);
464 #if WITH_SEASTAR
465 seastar::future<> read_monmap(const std::string& monmap);
466 /// try to build monmap with different settings, like
467 /// mon_host, mon* sections, and mon_dns_srv_name
468 seastar::future<> build_monmap(const ceph::common::ConfigProxy& conf, bool for_mkfs);
469 /// initialize monmap by resolving given service name
470 seastar::future<> init_with_dns_srv(bool for_mkfs, const std::string& name);
471 #else
472 /// read from encoded monmap file
473 int init_with_monmap(const std::string& monmap, std::ostream& errout);
474 int init_with_dns_srv(CephContext* cct, std::string srv_name, bool for_mkfs,
475 std::ostream& errout);
476 #endif
477 };
478 WRITE_CLASS_ENCODER_FEATURES(MonMap)
479
480 inline ostream& operator<<(ostream &out, const MonMap &m) {
481 m.print_summary(out);
482 return out;
483 }
484
485 #endif