From 8c8d5ce529fa826bc0d453edf5fb5e98e29294d3 Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Mon, 29 Aug 2016 19:53:11 +0800 Subject: [PATCH] tools/ceph_monstore_tool: add "rebuild" command Fixes: http://tracker.ceph.com/issues/17179 Signed-off-by: Kefu Chai (cherry picked from commit d909fa035c8fbbded786b2ca072acc10ea6b6052) --- src/tools/ceph_monstore_tool.cc | 140 ++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/src/tools/ceph_monstore_tool.cc b/src/tools/ceph_monstore_tool.cc index f9b4696c527d1..2141698555bc2 100644 --- a/src/tools/ceph_monstore_tool.cc +++ b/src/tools/ceph_monstore_tool.cc @@ -20,8 +20,11 @@ #include "common/Formatter.h" #include "common/errno.h" +#include "auth/KeyRing.h" +#include "auth/cephx/CephxKeyServer.h" #include "global/global_init.h" #include "include/stringify.h" +#include "mon/AuthMonitor.h" #include "mon/MonitorDBStore.h" #include "mon/Paxos.h" #include "mon/MonMap.h" @@ -217,6 +220,8 @@ void usage(const char *n, po::options_description &d) << " (rewrite-crush -- --help for more info)\n" << " inflate-pgmap [-- options] add given number of pgmaps to store\n" << " (inflate-pgmap -- --help for more info)\n" + << " rebuild rebuild store\n" + << " (rebuild -- --help for more info)\n" << std::endl; std::cerr << d << std::endl; std::cerr @@ -509,6 +514,139 @@ int inflate_pgmap(MonitorDBStore& st, unsigned n, bool can_be_trimmed) { return 0; } +static int update_auth(MonitorDBStore& st, const string& keyring_path) +{ + // import all keyrings stored in the keyring file + KeyRing keyring; + int r = keyring.load(g_ceph_context, keyring_path); + if (r < 0) { + cerr << "unable to load admin keyring: " << keyring_path << std::endl; + return r; + } + + bufferlist bl; + __u8 v = 1; + ::encode(v, bl); + + for (const auto& k : keyring.get_keys()) { + KeyServerData::Incremental auth_inc; + auth_inc.name = k.first; + auth_inc.auth = k.second; + auth_inc.op = KeyServerData::AUTH_INC_ADD; + + AuthMonitor::Incremental inc; + inc.inc_type = AuthMonitor::AUTH_DATA; + ::encode(auth_inc, inc.auth_data); + inc.auth_type = CEPH_AUTH_CEPHX; + + inc.encode(bl, CEPH_FEATURES_ALL); + } + + const string prefix("auth"); + auto last_committed = st.get(prefix, "last_committed") + 1; + auto t = make_shared(); + t->put(prefix, last_committed, bl); + t->put(prefix, "last_committed", last_committed); + auto first_committed = st.get(prefix, "first_committed"); + if (!first_committed) { + t->put(prefix, "first_committed", last_committed); + } + st.apply_transaction(t); + return 0; +} + +static int update_mkfs(MonitorDBStore& st) +{ + MonMap monmap; + int r = monmap.build_initial(g_ceph_context, cerr); + if (r) { + cerr << "no initial monitors" << std::endl; + return -EINVAL; + } + bufferlist bl; + monmap.encode(bl, CEPH_FEATURES_ALL); + monmap.set_epoch(0); + auto t = make_shared(); + t->put("mkfs", "monmap", bl); + st.apply_transaction(t); + return 0; +} + +static int update_monitor(MonitorDBStore& st) +{ + const string prefix("monitor"); + // a stripped-down Monitor::mkfs() + bufferlist bl; + bl.append(CEPH_MON_ONDISK_MAGIC "\n"); + auto t = make_shared(); + t->put(prefix, "magic", bl); + st.apply_transaction(t); + return 0; +} + +static int update_paxos(MonitorDBStore& st) +{ + // build a pending paxos proposal from all non-permanent k/v pairs. once the + // proposal is committed, it will gets applied. on the sync provider side, it + // will be a no-op, but on its peers, the paxos commit will help to build up + // the necessary epochs. + bufferlist pending_proposal; + { + MonitorDBStore::Transaction t; + vector prefixes = {"auth", "osdmap", "pgmap", "pgmap_pg"}; + for (const auto& prefix : prefixes) { + for (auto i = st.get_iterator(prefix); i->valid(); i->next()) { + auto key = i->raw_key(); + auto val = i->value(); + t.put(key.first, key.second, val); + } + } + t.encode(pending_proposal); + } + const string prefix("paxos"); + auto t = make_shared(); + t->put(prefix, "first_committed", 0); + t->put(prefix, "last_committed", 0); + auto pending_v = 1; + t->put(prefix, pending_v, pending_proposal); + t->put(prefix, "pending_v", pending_v); + t->put(prefix, "pending_pn", 400); + st.apply_transaction(t); + return 0; +} + +int rebuild_monstore(const char* progname, + vector& subcmds, + MonitorDBStore& st) +{ + po::options_description op_desc("Allowed 'rebuild' options"); + string keyring_path; + op_desc.add_options() + ("keyring", po::value(&keyring_path), + "path to the client.admin key"); + po::variables_map op_vm; + int r = parse_cmd_args(&op_desc, nullptr, nullptr, subcmds, &op_vm); + if (r) { + return -r; + } + if (op_vm.count("help")) { + usage(progname, op_desc); + return 0; + } + if (!keyring_path.empty()) + update_auth(st, keyring_path); + if ((r = update_paxos(st))) { + return r; + } + if ((r = update_mkfs(st))) { + return r; + } + if ((r = update_monitor(st))) { + return r; + } + return 0; +} + int main(int argc, char **argv) { int err = 0; po::options_description desc("Allowed options"); @@ -1094,6 +1232,8 @@ int main(int argc, char **argv) { goto done; } err = inflate_pgmap(st, n, can_be_trimmed); + } else if (cmd == "rebuild") { + err = rebuild_monstore(argv[0], subcmds, st); } else { std::cerr << "Unrecognized command: " << cmd << std::endl; usage(argv[0], desc); -- 2.39.5