]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
tools/ceph_monstore_tool: add "rebuild" command
authorKefu Chai <kchai@redhat.com>
Mon, 29 Aug 2016 11:53:11 +0000 (19:53 +0800)
committerKefu Chai <kchai@redhat.com>
Tue, 18 Oct 2016 02:49:42 +0000 (10:49 +0800)
Fixes: http://tracker.ceph.com/issues/17179
Signed-off-by: Kefu Chai <kchai@redhat.com>
(cherry picked from commit d909fa035c8fbbded786b2ca072acc10ea6b6052)

src/tools/ceph_monstore_tool.cc

index f9b4696c527d1c6e1d2362801f950f9a019d9de4..2141698555bc28e1288b84751f87c48b98e56e0b 100644 (file)
 #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<MonitorDBStore::Transaction>();
+  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<MonitorDBStore::Transaction>();
+  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<MonitorDBStore::Transaction>();
+  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<string> 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<MonitorDBStore::Transaction>();
+  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<string>& subcmds,
+                    MonitorDBStore& st)
+{
+  po::options_description op_desc("Allowed 'rebuild' options");
+  string keyring_path;
+  op_desc.add_options()
+    ("keyring", po::value<string>(&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);