1 #include "auth/cephx/CephxKeyServer.h"
2 #include "common/errno.h"
3 #include "mon/AuthMonitor.h"
4 #include "mon/MonitorDBStore.h"
5 #include "os/ObjectStore.h"
8 static int update_auth(const string& keyring_path,
9 const OSDSuperblock& sb,
11 static int update_monitor(const OSDSuperblock& sb, MonitorDBStore& ms);
12 static int update_osdmap(ObjectStore& fs,
15 static int update_pgmap_pg(ObjectStore& fs, MonitorDBStore& ms);
17 int update_mon_db(ObjectStore& fs, OSDSuperblock& sb,
18 const string& keyring,
19 const string& store_path)
21 MonitorDBStore ms(store_path);
22 int r = ms.create_and_open(cerr);
24 cerr << "unable to open mon store: " << store_path << std::endl;
27 if ((r = update_auth(keyring, sb, ms)) < 0) {
30 if ((r = update_osdmap(fs, sb, ms)) < 0) {
33 if ((r = update_pgmap_pg(fs, ms)) < 0) {
36 if ((r = update_monitor(sb, ms)) < 0) {
44 static void add_auth(KeyServerData::Incremental& auth_inc,
47 AuthMonitor::Incremental inc;
48 inc.inc_type = AuthMonitor::AUTH_DATA;
49 ::encode(auth_inc, inc.auth_data);
50 inc.auth_type = CEPH_AUTH_CEPHX;
55 inc.encode(bl, CEPH_FEATURES_ALL);
57 const string prefix("auth");
58 auto last_committed = ms.get(prefix, "last_committed") + 1;
59 auto t = make_shared<MonitorDBStore::Transaction>();
60 t->put(prefix, last_committed, bl);
61 t->put(prefix, "last_committed", last_committed);
62 auto first_committed = ms.get(prefix, "first_committed");
63 if (!first_committed) {
64 t->put(prefix, "first_committed", last_committed);
66 ms.apply_transaction(t);
69 static int get_auth_inc(const string& keyring_path,
70 const OSDSuperblock& sb,
71 KeyServerData::Incremental* auth_inc)
73 auth_inc->op = KeyServerData::AUTH_INC_ADD;
77 // assuming the entity name of OSD is "osd.<osd_id>"
78 entity.set(CEPH_ENTITY_TYPE_OSD, std::to_string(sb.whoami));
79 auth_inc->name = entity;
81 // read keyring from disk
86 int r = bl.read_file(keyring_path.c_str(), &error);
89 cout << "ignoring keyring (" << keyring_path << ")"
90 << ": " << error << std::endl;
93 cerr << "unable to read keyring (" << keyring_path << ")"
94 << ": " << error << std::endl;
97 } else if (bl.length() == 0) {
98 cout << "ignoring empty keyring: " << keyring_path << std::endl;
101 auto bp = bl.begin();
103 ::decode(keyring, bp);
104 } catch (const buffer::error& e) {
105 cerr << "error decoding keyring: " << keyring_path << std::endl;
112 if (!keyring.get_auth(auth_inc->name, new_inc)) {
113 cerr << "key for " << auth_inc->name << " not found in keyring: "
114 << keyring_path << std::endl;
117 auth_inc->auth.key = new_inc.key;
120 map<string,bufferlist> caps;
121 if (new_inc.caps.empty()) {
122 // fallback to default caps for an OSD
123 // osd 'allow *' mon 'allow rwx'
124 // as suggested by document.
125 ::encode(string("allow *"), caps["osd"]);
126 ::encode(string("allow rwx"), caps["mon"]);
130 auth_inc->auth.caps = caps;
136 // - auth/first_committed
137 // - auth/last_committed
138 static int update_auth(const string& keyring_path,
139 const OSDSuperblock& sb,
142 // stolen from AuthMonitor::prepare_command(), where prefix is "auth add"
143 KeyServerData::Incremental auth_inc;
145 if ((r = get_auth_inc(keyring_path, sb, &auth_inc))) {
148 add_auth(auth_inc, ms);
152 // stolen from Monitor::check_fsid()
153 static int check_fsid(const uuid_d& fsid, MonitorDBStore& ms)
156 int r = ms.get("monitor", "cluster_uuid", bl);
159 string uuid(bl.c_str(), bl.length());
160 auto end = uuid.find_first_of('\n');
161 if (end != uuid.npos) {
165 if (!existing.parse(uuid.c_str())) {
166 cerr << "error: unable to parse uuid" << std::endl;
169 if (fsid != existing) {
170 cerr << "error: cluster_uuid " << existing << " != " << fsid << std::endl;
177 // - monitor/cluster_uuid
178 int update_monitor(const OSDSuperblock& sb, MonitorDBStore& ms)
180 switch (check_fsid(sb.cluster_fsid, ms)) {
192 string uuid = stringify(sb.cluster_fsid) + "\n";
195 auto t = make_shared<MonitorDBStore::Transaction>();
196 t->put("monitor", "cluster_uuid", bl);
197 ms.apply_transaction(t);
203 // - osdmap/full_${epoch}
204 // - osdmap/full_latest
205 // - osdmap/first_committed
206 // - osdmap/last_committed
207 int update_osdmap(ObjectStore& fs, OSDSuperblock& sb, MonitorDBStore& ms)
209 const string prefix("osdmap");
210 const string first_committed_name("first_committed");
211 const string last_committed_name("last_committed");
212 epoch_t first_committed = ms.get(prefix, first_committed_name);
213 epoch_t last_committed = ms.get(prefix, last_committed_name);
214 auto t = make_shared<MonitorDBStore::Transaction>();
217 unsigned ntrimmed = 0;
218 // osdmap starts at 1. if we have a "0" first_committed, then there is nothing
219 // to trim. and "1 osdmaps trimmed" in the output message is misleading. so
220 // let's make it an exception.
221 for (auto e = first_committed; first_committed && e < sb.oldest_map; e++) {
223 t->erase(prefix, ms.combine_strings("full", e));
226 // make sure we have a non-zero first_committed. OSDMonitor relies on this.
227 // because PaxosService::put_last_committed() set it to last_committed, if it
228 // is zero. which breaks OSDMonitor::update_from_paxos(), in which we believe
229 // that latest_full should always be greater than last_committed.
230 if (first_committed == 0 && sb.oldest_map < sb.newest_map) {
232 } else if (ntrimmed) {
233 first_committed += ntrimmed;
235 if (first_committed) {
236 t->put(prefix, first_committed_name, first_committed);
237 ms.apply_transaction(t);
238 t = make_shared<MonitorDBStore::Transaction>();
244 for (auto e = max(last_committed+1, sb.oldest_map);
245 e <= sb.newest_map; e++) {
246 bool have_crc = false;
248 uint64_t features = 0;
251 const auto oid = OSD::get_inc_osdmap_pobject_name(e);
253 int nread = fs.read(coll_t::meta(), oid, 0, 0, bl);
255 cerr << "missing " << oid << std::endl;
258 t->put(prefix, e, bl);
260 OSDMap::Incremental inc;
263 features = inc.encode_features | CEPH_FEATURE_RESERVED;
264 if (osdmap.get_epoch() && e > 1) {
265 if (osdmap.apply_incremental(inc)) {
267 << osdmap.get_fsid() << " != " << inc.fsid << std::endl;
270 have_crc = inc.have_crc;
274 osdmap.encode(fbl, features);
275 if (osdmap.get_crc() != inc.full_crc) {
276 cerr << "mismatched inc crc: "
277 << osdmap.get_crc() << " != " << inc.full_crc << std::endl;
280 // inc.decode() verifies `inc_crc`, so it's been taken care of.
286 const auto oid = OSD::get_osdmap_pobject_name(e);
288 int nread = fs.read(coll_t::meta(), oid, 0, 0, bl);
290 cerr << "missing " << oid << std::endl;
293 t->put(prefix, ms.combine_strings("full", e), bl);
297 if (osdmap.have_crc()) {
298 if (have_crc && osdmap.get_crc() != crc) {
299 cerr << "mismatched full/inc crc: "
300 << osdmap.get_crc() << " != " << crc << std::endl;
303 uint32_t saved_crc = osdmap.get_crc();
305 osdmap.encode(fbl, features);
306 if (osdmap.get_crc() != saved_crc) {
307 cerr << "mismatched full crc: "
308 << saved_crc << " != " << osdmap.get_crc() << std::endl;
316 t->put(prefix, last_committed_name, e);
318 t->put(prefix, ms.combine_strings("full", "latest"), e);
320 // this number comes from the default value of osd_target_transaction_size,
321 // so we won't OOM or stuff too many maps in a single transaction if OSD is
322 // keeping a large series of osdmap
323 static constexpr unsigned TRANSACTION_SIZE = 30;
324 if (t->size() >= TRANSACTION_SIZE) {
325 ms.apply_transaction(t);
326 t = make_shared<MonitorDBStore::Transaction>();
330 ms.apply_transaction(t);
334 string osd_name("osd.");
335 osd_name += std::to_string(sb.whoami);
336 cout << std::left << setw(8)
338 << ntrimmed << " osdmaps trimmed, "
339 << nadded << " osdmaps added." << std::endl;
344 // - pgmap_pg/${pgid}
345 int update_pgmap_pg(ObjectStore& fs, MonitorDBStore& ms)
347 // pgmap/${epoch} is the incremental of: stamp, pgmap_pg, pgmap_osd
348 // if PGMonitor fails to read it, it will fall back to the pgmap_pg, i.e.
350 vector<coll_t> collections;
351 int r = fs.list_collections(collections);
353 cerr << "failed to list pgs: " << cpp_strerror(r) << std::endl;
356 const string prefix("pgmap_pg");
357 // in general, there are less than 100 PGs per OSD, so no need to apply
358 // transaction in batch.
359 auto t = make_shared<MonitorDBStore::Transaction>();
361 for (const auto& coll : collections) {
363 if (!coll.is_pg(&pgid))
366 pg_info_t info(pgid);
367 PastIntervals past_intervals;
369 r = PG::read_info(&fs, pgid, coll, bl, info, past_intervals, struct_v);
371 cerr << "failed to read_info: " << cpp_strerror(r) << std::endl;
374 if (struct_v < PG::cur_struct_v) {
375 cerr << "incompatible pg_info: v" << struct_v << std::endl;
378 version_t latest_epoch = 0;
379 r = ms.get(prefix, stringify(pgid.pgid), bl);
382 auto bp = bl.begin();
383 ::decode(pg_stat, bp);
384 latest_epoch = pg_stat.reported_epoch;
386 if (info.stats.reported_epoch > latest_epoch) {
388 ::encode(info.stats, bl);
389 t->put(prefix, stringify(pgid.pgid), bl);
393 ms.apply_transaction(t);
394 cout << std::left << setw(10)
395 << " " << npg << " pgs added." << std::endl;