]>
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; | |
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 |