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