]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/MonMap.h
52b4e232fed2dd59ef7018b112d0bf292b68d096
[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 #include "include/err.h"
19
20 #include "msg/Message.h"
21 #include "include/types.h"
22 #include "mon/mon_types.h"
23
24 namespace ceph {
25 class Formatter;
26 }
27
28 struct mon_info_t {
29 /**
30 * monitor name
31 *
32 * i.e., 'foo' in 'mon.foo'
33 */
34 string name;
35 /**
36 * monitor's public address
37 *
38 * public facing address, traditionally used to communicate with all clients
39 * and other monitors.
40 */
41 entity_addr_t public_addr;
42
43 mon_info_t(string &n, entity_addr_t& p_addr)
44 : name(n), public_addr(p_addr)
45 { }
46
47 mon_info_t() { }
48
49
50 void encode(bufferlist& bl, uint64_t features) const;
51 void decode(bufferlist::iterator& p);
52 void print(ostream& out) const;
53 };
54 WRITE_CLASS_ENCODER_FEATURES(mon_info_t)
55
56 inline ostream& operator<<(ostream& out, const mon_info_t& mon) {
57 mon.print(out);
58 return out;
59 }
60
61 class MonMap {
62 public:
63 epoch_t epoch; // what epoch/version of the monmap
64 uuid_d fsid;
65 utime_t last_changed;
66 utime_t created;
67
68 map<string, mon_info_t> mon_info;
69 map<entity_addr_t, string> addr_mons;
70
71 vector<string> ranks;
72
73 /**
74 * Persistent Features are all those features that once set on a
75 * monmap cannot, and should not, be removed. These will define the
76 * non-negotiable features that a given monitor must support to
77 * properly operate in a given quorum.
78 *
79 * Should be reserved for features that we really want to make sure
80 * are sticky, and are important enough to tolerate not being able
81 * to downgrade a monitor.
82 */
83 mon_feature_t persistent_features;
84 /**
85 * Optional Features are all those features that can be enabled or
86 * disabled following a given criteria -- e.g., user-mandated via the
87 * cli --, and act much like indicators of what the cluster currently
88 * supports.
89 *
90 * They are by no means "optional" in the sense that monitors can
91 * ignore them. Just that they are not persistent.
92 */
93 mon_feature_t optional_features;
94
95 /**
96 * Returns the set of features required by this monmap.
97 *
98 * The features required by this monmap is the union of all the
99 * currently set persistent features and the currently set optional
100 * features.
101 *
102 * @returns the set of features required by this monmap
103 */
104 mon_feature_t get_required_features() const {
105 return (persistent_features | optional_features);
106 }
107
108 public:
109 void sanitize_mons(map<string,entity_addr_t>& o);
110 void calc_ranks();
111
112 MonMap()
113 : epoch(0) {
114 memset(&fsid, 0, sizeof(fsid));
115 }
116
117 uuid_d& get_fsid() { return fsid; }
118
119 unsigned size() const {
120 return mon_info.size();
121 }
122
123 epoch_t get_epoch() const { return epoch; }
124 void set_epoch(epoch_t e) { epoch = e; }
125
126 /**
127 * Obtain list of public facing addresses
128 *
129 * @param ls list to populate with the monitors' addresses
130 */
131 void list_addrs(list<entity_addr_t>& ls) const {
132 for (map<string,mon_info_t>::const_iterator p = mon_info.begin();
133 p != mon_info.end();
134 ++p) {
135 ls.push_back(p->second.public_addr);
136 }
137 }
138
139 /**
140 * Add new monitor to the monmap
141 *
142 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
143 * @param addr Monitor's public address
144 */
145 void add(const string &name, const entity_addr_t &addr) {
146 assert(mon_info.count(name) == 0);
147 assert(addr_mons.count(addr) == 0);
148 mon_info_t &m = mon_info[name];
149 m.name = name;
150 m.public_addr = addr;
151 calc_ranks();
152 }
153
154 /**
155 * Remove monitor from the monmap
156 *
157 * @param name Monitor name (i.e., 'foo' in 'mon.foo')
158 */
159 void remove(const string &name) {
160 assert(mon_info.count(name));
161 mon_info.erase(name);
162 assert(mon_info.count(name) == 0);
163 calc_ranks();
164 }
165
166 /**
167 * Rename monitor from @p oldname to @p newname
168 *
169 * @param oldname monitor's current name (i.e., 'foo' in 'mon.foo')
170 * @param newname monitor's new name (i.e., 'bar' in 'mon.bar')
171 */
172 void rename(string oldname, string newname) {
173 assert(contains(oldname));
174 assert(!contains(newname));
175 mon_info[newname] = mon_info[oldname];
176 mon_info.erase(oldname);
177 mon_info[newname].name = newname;
178 calc_ranks();
179 }
180
181 bool contains(const string& name) const {
182 return mon_info.count(name);
183 }
184
185 /**
186 * Check if monmap contains a monitor with address @p a
187 *
188 * @note checks for all addresses a monitor may have, public or otherwise.
189 *
190 * @param a monitor address
191 * @returns true if monmap contains a monitor with address @p;
192 * false otherwise.
193 */
194 bool contains(const entity_addr_t &a) const {
195 for (map<string,mon_info_t>::const_iterator p = mon_info.begin();
196 p != mon_info.end();
197 ++p) {
198 if (p->second.public_addr == a)
199 return true;
200 }
201 return false;
202 }
203
204 string get_name(unsigned n) const {
205 assert(n < ranks.size());
206 return ranks[n];
207 }
208 string get_name(const entity_addr_t& a) const {
209 map<entity_addr_t,string>::const_iterator p = addr_mons.find(a);
210 if (p == addr_mons.end())
211 return string();
212 else
213 return p->second;
214 }
215
216 int get_rank(const string& n) {
217 for (unsigned i = 0; i < ranks.size(); i++)
218 if (ranks[i] == n)
219 return i;
220 return -1;
221 }
222 int get_rank(const entity_addr_t& a) {
223 string n = get_name(a);
224 if (n.empty())
225 return -1;
226
227 for (unsigned i = 0; i < ranks.size(); i++)
228 if (ranks[i] == n)
229 return i;
230 return -1;
231 }
232 bool get_addr_name(const entity_addr_t& a, string& name) {
233 if (addr_mons.count(a) == 0)
234 return false;
235 name = addr_mons[a];
236 return true;
237 }
238
239 const entity_addr_t& get_addr(const string& n) const {
240 assert(mon_info.count(n));
241 map<string,mon_info_t>::const_iterator p = mon_info.find(n);
242 return p->second.public_addr;
243 }
244 const entity_addr_t& get_addr(unsigned m) const {
245 assert(m < ranks.size());
246 return get_addr(ranks[m]);
247 }
248 void set_addr(const string& n, const entity_addr_t& a) {
249 assert(mon_info.count(n));
250 mon_info[n].public_addr = a;
251 calc_ranks();
252 }
253 entity_inst_t get_inst(const string& n) {
254 assert(mon_info.count(n));
255 int m = get_rank(n);
256 assert(m >= 0); // vector can't take negative indicies
257 return get_inst(m);
258 }
259 entity_inst_t get_inst(unsigned m) const {
260 assert(m < ranks.size());
261 entity_inst_t i;
262 i.addr = get_addr(m);
263 i.name = entity_name_t::MON(m);
264 return i;
265 }
266
267 void encode(bufferlist& blist, uint64_t con_features) const;
268 void decode(bufferlist& blist) {
269 bufferlist::iterator p = blist.begin();
270 decode(p);
271 }
272 void decode(bufferlist::iterator &p);
273
274 void generate_fsid() {
275 fsid.generate_random();
276 }
277
278 // read from/write to a file
279 int write(const char *fn);
280 int read(const char *fn);
281
282 /**
283 * build an initial bootstrap monmap from conf
284 *
285 * Build an initial bootstrap monmap from the config. This will
286 * try, in this order:
287 *
288 * 1 monmap -- an explicitly provided monmap
289 * 2 mon_host -- list of monitors
290 * 3 config [mon.*] sections, and 'mon addr' fields in those sections
291 *
292 * @param cct context (and associated config)
293 * @param errout ostream to send error messages too
294 */
295 int build_initial(CephContext *cct, ostream& errout);
296
297 /**
298 * build a monmap from a list of hosts or ips
299 *
300 * Resolve dns as needed. Give mons dummy names.
301 *
302 * @param hosts list of hosts, space or comma separated
303 * @param prefix prefix to prepend to generated mon names
304 * @return 0 for success, -errno on error
305 */
306 int build_from_host_list(std::string hosts, std::string prefix);
307
308 /**
309 * filter monmap given a set of initial members.
310 *
311 * Remove mons that aren't in the initial_members list. Add missing
312 * mons and give them dummy IPs (blank IPv4, with a non-zero
313 * nonce). If the name matches my_name, then my_addr will be used in
314 * place of a dummy addr.
315 *
316 * @param initial_members list of initial member names
317 * @param my_name name of self, can be blank
318 * @param my_addr my addr
319 * @param removed optional pointer to set to insert removed mon addrs to
320 */
321 void set_initial_members(CephContext *cct,
322 list<std::string>& initial_members,
323 string my_name, const entity_addr_t& my_addr,
324 set<entity_addr_t> *removed);
325
326 void print(ostream& out) const;
327 void print_summary(ostream& out) const;
328 void dump(ceph::Formatter *f) const;
329
330 static void generate_test_instances(list<MonMap*>& o);
331 };
332 WRITE_CLASS_ENCODER_FEATURES(MonMap)
333
334 inline ostream& operator<<(ostream &out, const MonMap &m) {
335 m.print_summary(out);
336 return out;
337 }
338
339 #endif