]>
git.proxmox.com Git - ceph.git/blob - ceph/src/tools/rebuild_mondb.cc
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
,
16 int update_mon_db(ObjectStore
& fs
, OSDSuperblock
& sb
,
17 const string
& keyring
,
18 const string
& store_path
)
20 MonitorDBStore
ms(store_path
);
21 int r
= ms
.create_and_open(cerr
);
23 cerr
<< "unable to open mon store: " << store_path
<< std::endl
;
26 if ((r
= update_auth(keyring
, sb
, ms
)) < 0) {
29 if ((r
= update_osdmap(fs
, sb
, ms
)) < 0) {
32 if ((r
= update_monitor(sb
, ms
)) < 0) {
40 static void add_auth(KeyServerData::Incremental
& auth_inc
,
43 AuthMonitor::Incremental inc
;
44 inc
.inc_type
= AuthMonitor::AUTH_DATA
;
45 encode(auth_inc
, inc
.auth_data
);
46 inc
.auth_type
= CEPH_AUTH_CEPHX
;
51 inc
.encode(bl
, CEPH_FEATURES_ALL
);
53 const string
prefix("auth");
54 auto last_committed
= ms
.get(prefix
, "last_committed") + 1;
55 auto t
= make_shared
<MonitorDBStore::Transaction
>();
56 t
->put(prefix
, last_committed
, bl
);
57 t
->put(prefix
, "last_committed", last_committed
);
58 auto first_committed
= ms
.get(prefix
, "first_committed");
59 if (!first_committed
) {
60 t
->put(prefix
, "first_committed", last_committed
);
62 ms
.apply_transaction(t
);
65 static int get_auth_inc(const string
& keyring_path
,
66 const OSDSuperblock
& sb
,
67 KeyServerData::Incremental
* auth_inc
)
69 auth_inc
->op
= KeyServerData::AUTH_INC_ADD
;
73 // assuming the entity name of OSD is "osd.<osd_id>"
74 entity
.set(CEPH_ENTITY_TYPE_OSD
, std::to_string(sb
.whoami
));
75 auth_inc
->name
= entity
;
77 // read keyring from disk
82 int r
= bl
.read_file(keyring_path
.c_str(), &error
);
85 cout
<< "ignoring keyring (" << keyring_path
<< ")"
86 << ": " << error
<< std::endl
;
89 cerr
<< "unable to read keyring (" << keyring_path
<< ")"
90 << ": " << error
<< std::endl
;
93 } else if (bl
.length() == 0) {
94 cout
<< "ignoring empty keyring: " << keyring_path
<< std::endl
;
97 auto bp
= bl
.cbegin();
100 } catch (const buffer::error
& e
) {
101 cerr
<< "error decoding keyring: " << keyring_path
<< std::endl
;
108 if (!keyring
.get_auth(auth_inc
->name
, new_inc
)) {
109 cerr
<< "key for " << auth_inc
->name
<< " not found in keyring: "
110 << keyring_path
<< std::endl
;
113 auth_inc
->auth
.key
= new_inc
.key
;
116 map
<string
,bufferlist
> caps
;
117 if (new_inc
.caps
.empty()) {
118 // fallback to default caps for an OSD
119 // osd 'allow *' mon 'allow rwx'
120 // as suggested by document.
121 encode(string("allow *"), caps
["osd"]);
122 encode(string("allow rwx"), caps
["mon"]);
126 auth_inc
->auth
.caps
= caps
;
132 // - auth/first_committed
133 // - auth/last_committed
134 static int update_auth(const string
& keyring_path
,
135 const OSDSuperblock
& sb
,
138 // stolen from AuthMonitor::prepare_command(), where prefix is "auth add"
139 KeyServerData::Incremental auth_inc
;
141 if ((r
= get_auth_inc(keyring_path
, sb
, &auth_inc
))) {
144 add_auth(auth_inc
, ms
);
148 // stolen from Monitor::check_fsid()
149 static int check_fsid(const uuid_d
& fsid
, MonitorDBStore
& ms
)
152 int r
= ms
.get("monitor", "cluster_uuid", bl
);
155 string
uuid(bl
.c_str(), bl
.length());
156 auto end
= uuid
.find_first_of('\n');
157 if (end
!= uuid
.npos
) {
161 if (!existing
.parse(uuid
.c_str())) {
162 cerr
<< "error: unable to parse uuid" << std::endl
;
165 if (fsid
!= existing
) {
166 cerr
<< "error: cluster_uuid " << existing
<< " != " << fsid
<< std::endl
;
173 // - monitor/cluster_uuid
174 int update_monitor(const OSDSuperblock
& sb
, MonitorDBStore
& ms
)
176 switch (check_fsid(sb
.cluster_fsid
, ms
)) {
188 string uuid
= stringify(sb
.cluster_fsid
) + "\n";
191 auto t
= make_shared
<MonitorDBStore::Transaction
>();
192 t
->put("monitor", "cluster_uuid", bl
);
193 ms
.apply_transaction(t
);
199 // - osdmap/full_${epoch}
200 // - osdmap/full_latest
201 // - osdmap/first_committed
202 // - osdmap/last_committed
203 int update_osdmap(ObjectStore
& fs
, OSDSuperblock
& sb
, MonitorDBStore
& ms
)
205 const string
prefix("osdmap");
206 const string
first_committed_name("first_committed");
207 const string
last_committed_name("last_committed");
208 epoch_t first_committed
= ms
.get(prefix
, first_committed_name
);
209 epoch_t last_committed
= ms
.get(prefix
, last_committed_name
);
210 auto t
= make_shared
<MonitorDBStore::Transaction
>();
213 unsigned ntrimmed
= 0;
214 // osdmap starts at 1. if we have a "0" first_committed, then there is nothing
215 // to trim. and "1 osdmaps trimmed" in the output message is misleading. so
216 // let's make it an exception.
217 for (auto e
= first_committed
; first_committed
&& e
< sb
.oldest_map
; e
++) {
219 t
->erase(prefix
, ms
.combine_strings("full", e
));
222 // make sure we have a non-zero first_committed. OSDMonitor relies on this.
223 // because PaxosService::put_last_committed() set it to last_committed, if it
224 // is zero. which breaks OSDMonitor::update_from_paxos(), in which we believe
225 // that latest_full should always be greater than last_committed.
226 if (first_committed
== 0 && sb
.oldest_map
< sb
.newest_map
) {
228 } else if (ntrimmed
) {
229 first_committed
+= ntrimmed
;
231 if (first_committed
) {
232 t
->put(prefix
, first_committed_name
, first_committed
);
233 ms
.apply_transaction(t
);
234 t
= make_shared
<MonitorDBStore::Transaction
>();
239 auto ch
= fs
.open_collection(coll_t::meta());
241 for (auto e
= std::max(last_committed
+1, sb
.oldest_map
);
242 e
<= sb
.newest_map
; e
++) {
243 bool have_crc
= false;
245 uint64_t features
= 0;
248 const auto oid
= OSD::get_inc_osdmap_pobject_name(e
);
250 int nread
= fs
.read(ch
, oid
, 0, 0, bl
);
252 cerr
<< "missing " << oid
<< std::endl
;
255 t
->put(prefix
, e
, bl
);
257 OSDMap::Incremental inc
;
258 auto p
= bl
.cbegin();
260 features
= inc
.encode_features
| CEPH_FEATURE_RESERVED
;
261 if (osdmap
.get_epoch() && e
> 1) {
262 if (osdmap
.apply_incremental(inc
)) {
264 << osdmap
.get_fsid() << " != " << inc
.fsid
<< std::endl
;
267 have_crc
= inc
.have_crc
;
271 osdmap
.encode(fbl
, features
);
272 if (osdmap
.get_crc() != inc
.full_crc
) {
273 cerr
<< "mismatched inc crc: "
274 << osdmap
.get_crc() << " != " << inc
.full_crc
<< std::endl
;
277 // inc.decode() verifies `inc_crc`, so it's been taken care of.
283 const auto oid
= OSD::get_osdmap_pobject_name(e
);
285 int nread
= fs
.read(ch
, oid
, 0, 0, bl
);
287 cerr
<< "missing " << oid
<< std::endl
;
290 t
->put(prefix
, ms
.combine_strings("full", e
), bl
);
292 auto p
= bl
.cbegin();
294 if (osdmap
.have_crc()) {
295 if (have_crc
&& osdmap
.get_crc() != crc
) {
296 cerr
<< "mismatched full/inc crc: "
297 << osdmap
.get_crc() << " != " << crc
<< std::endl
;
300 uint32_t saved_crc
= osdmap
.get_crc();
302 osdmap
.encode(fbl
, features
);
303 if (osdmap
.get_crc() != saved_crc
) {
304 cerr
<< "mismatched full crc: "
305 << saved_crc
<< " != " << osdmap
.get_crc() << std::endl
;
313 t
->put(prefix
, last_committed_name
, e
);
315 t
->put(prefix
, ms
.combine_strings("full", "latest"), e
);
317 // this number comes from the default value of osd_target_transaction_size,
318 // so we won't OOM or stuff too many maps in a single transaction if OSD is
319 // keeping a large series of osdmap
320 static constexpr unsigned TRANSACTION_SIZE
= 30;
321 if (t
->size() >= TRANSACTION_SIZE
) {
322 ms
.apply_transaction(t
);
323 t
= make_shared
<MonitorDBStore::Transaction
>();
327 ms
.apply_transaction(t
);
331 string
osd_name("osd.");
332 osd_name
+= std::to_string(sb
.whoami
);
333 cout
<< std::left
<< setw(8)
335 << ntrimmed
<< " osdmaps trimmed, "
336 << nadded
<< " osdmaps added." << std::endl
;