]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: add "mon_metadata <id>" command
authorKefu Chai <kchai@redhat.com>
Thu, 26 Mar 2015 17:08:04 +0000 (01:08 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 7 May 2015 14:29:39 +0000 (07:29 -0700)
Related: #10904
Signed-off-by: Kefu Chai <kchai@redhat.com>
qa/workunits/cephtool/test.sh
src/include/ceph_fs.h
src/messages/MMonMetadata.h [new file with mode: 0644]
src/mon/MonCommands.h
src/mon/Monitor.cc
src/mon/Monitor.h
src/mon/mon_types.h
src/msg/Message.cc

index fab48b53ce7d2f3e5d86d54f227fffd4e7b62a11..03785ce4d3cb603803fad1b56b669f7730291ffa 100755 (executable)
@@ -563,6 +563,8 @@ function test_mon_misc()
   mymsg="this is a test log message $$.$(date)"
   ceph log "$mymsg"
   ceph_watch_wait "$mymsg"
+
+  ceph mon_metadata a
 }
 
 function check_mds_active()
index 63922f5654b05f3b7089ffe742f5f237f771ffb3..60dedd47d2f54fdc7c961f6210f719c89e3126c3 100644 (file)
@@ -94,6 +94,7 @@ struct ceph_dir_layout {
 #define CEPH_MSG_MON_MAP                4
 #define CEPH_MSG_MON_GET_MAP            5
 #define CEPH_MSG_MON_GET_OSDMAP         6
+#define CEPH_MSG_MON_METADATA           7
 #define CEPH_MSG_STATFS                 13
 #define CEPH_MSG_STATFS_REPLY           14
 #define CEPH_MSG_MON_SUBSCRIBE          15
diff --git a/src/messages/MMonMetadata.h b/src/messages/MMonMetadata.h
new file mode 100644 (file)
index 0000000..6c18966
--- /dev/null
@@ -0,0 +1,52 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2015 Red Hat
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation.  See file COPYING.
+ *
+ */
+
+#ifndef CEPH_MMONMETADATA_H
+#define CEPH_MMONMETADATA_H
+
+#include "mon/mon_types.h"
+#include "msg/Message.h"
+
+class MMonMetadata : public Message {
+public:
+  Metadata data;
+
+private:
+  static const int HEAD_VERSION = 1;
+  ~MMonMetadata() {}
+
+public:
+  MMonMetadata() :
+    Message(CEPH_MSG_MON_METADATA, HEAD_VERSION)
+  {}
+  MMonMetadata(const Metadata& metadata) :
+    Message(CEPH_MSG_MON_METADATA, HEAD_VERSION),
+    data(metadata)
+  {}
+
+  virtual const char *get_type_name() const {
+    return "mon_metadata";
+  }
+
+  virtual void encode_payload(uint64_t features) {
+    ::encode(data, payload);
+  }
+
+  virtual void decode_payload() {
+    bufferlist::iterator p = payload.begin();
+    ::decode(data, p);
+  }
+};
+
+#endif
index 0bfa1fc23e8913215971242f7edba9e6a77be08b..40d26577f092d989bc25db5e96fbbc8871ab48ce 100644 (file)
@@ -235,6 +235,10 @@ COMMAND("report name=tags,type=CephString,n=N,req=false", \
        "mon", "r", "cli,rest")
 COMMAND("quorum_status", "report status of monitor quorum", \
        "mon", "r", "cli,rest")
+COMMAND("mon_metadata name=id,type=CephString",
+       "fetch metadata for mon <id>",
+       "mon", "r", "cli,rest")
+
 COMMAND_WITH_FLAG("mon_status", "report status of monitors", "mon", "r", "cli,rest",
             NOFORWARD)
 COMMAND("sync force " \
@@ -361,7 +365,6 @@ COMMAND("mon remove " \
        "name=name,type=CephString", \
        "remove monitor named <name>", "mon", "rw", "cli,rest")
 
-
 /*
  * OSD commands
  */
index 8d1b3ee786cdddce1f5e7c2b17a89b67872850bc..456dff5a5786284942e4cf17a49517c6a78e2b66 100644 (file)
@@ -36,6 +36,7 @@
 #include "messages/MGenericMessage.h"
 #include "messages/MMonCommand.h"
 #include "messages/MMonCommandAck.h"
+#include "messages/MMonMetadata.h"
 #include "messages/MMonSync.h"
 #include "messages/MMonScrub.h"
 #include "messages/MMonProbe.h"
@@ -287,10 +288,9 @@ void Monitor::do_admin_command(string command, cmdmap_t& cmdmap, string format,
   }
   args = "[" + args + "]";
  
-  bool read_only = false;
-  if (command == "mon_status" || command == "quorum_status") {
-    read_only = true;
-  }
+  bool read_only = (command == "mon_status" ||
+                   command == "mon_metadata" ||
+                   command == "quorum_status");
 
   (read_only ? audit_clog->debug() : audit_clog->info())
     << "from='admin socket' entity='admin socket' "
@@ -738,6 +738,7 @@ int Monitor::init()
   // i'm ready!
   messenger->add_dispatcher_tail(this);
 
+
   bootstrap();
 
   // encode command sets
@@ -1857,6 +1858,7 @@ void Monitor::win_election(epoch_t epoch, set<int>& active, uint64_t features,
     health_tick_start();
     do_health_to_clog_interval();
   }
+  collect_sys_info(&metadata[rank], g_ceph_context);
 }
 
 void Monitor::lose_election(epoch_t epoch, set<int> &q, int l, uint64_t features) 
@@ -1878,6 +1880,11 @@ void Monitor::lose_election(epoch_t epoch, set<int> &q, int l, uint64_t features
   logger->inc(l_mon_election_lose);
 
   finish_election();
+
+  Metadata sys_info;
+  collect_sys_info(&sys_info, g_ceph_context);
+  messenger->send_message(new MMonMetadata(sys_info),
+                         monmap->get_inst(get_leader()));
 }
 
 void Monitor::finish_election()
@@ -2837,6 +2844,23 @@ void Monitor::handle_command(MMonCommand *m)
     ss2 << "report " << rdata.crc32c(6789);
     rs = ss2.str();
     r = 0;
+  } else if (prefix == "mon_metadata") {
+    string name;
+    cmd_getval(g_ceph_context, cmdmap, "id", name);
+    int mon = monmap->get_rank(name);
+    if (mon < 0) {
+      rs = "requested mon not found";
+      r = -ENOENT;
+      goto out;
+    }
+    if (!f)
+      f.reset(Formatter::create("json-pretty"));
+    f->open_object_section("mon_metadata");
+    r = get_mon_metadata(mon, f.get(), ds);
+    f->close_section();
+    f->flush(ds);
+    rdata.append(ds);
+    rs = "";
   } else if (prefix == "quorum_status") {
     // make sure our map is readable and up to date
     if (!is_leader() && !is_peon()) {
@@ -3411,6 +3435,9 @@ void Monitor::dispatch(MonSession *s, Message *m, const bool src_is_mon)
       handle_mon_get_map(static_cast<MMonGetMap*>(m));
       break;
 
+    case CEPH_MSG_MON_METADATA:
+      return handle_mon_metadata(static_cast<MMonMetadata*>(m));
+
     default:
       dealt_with = false;
       break;
@@ -4185,7 +4212,64 @@ void Monitor::handle_mon_get_map(MMonGetMap *m)
   m->put();
 }
 
+void Monitor::handle_mon_metadata(MMonMetadata *m)
+{
+  if (is_leader()) {
+    dout(10) << __func__ << dendl;
+    update_mon_metadata(m->get_source().num(), m->data);
+  }
+  m->put();
+}
+
+void Monitor::update_mon_metadata(int from, const Metadata& m)
+{
+  metadata[from] = m;
 
+  bufferlist bl;
+  int err = store->get(MONITOR_STORE_PREFIX, "last_metadata", bl);
+  map<int, Metadata> last_metadata;
+  if (!err) {
+    bufferlist::iterator iter = bl.begin();
+    ::decode(last_metadata, iter);
+    metadata.insert(last_metadata.begin(), last_metadata.end());
+  }
+
+  MonitorDBStore::TransactionRef t = paxos->get_pending_transaction();
+  bl.clear();
+  ::encode(metadata, bl);
+  t->put(MONITOR_STORE_PREFIX, "last_metadata", bl);
+  paxos->trigger_propose();
+}
+
+int Monitor::load_metadata(map<int, Metadata>& metadata)
+{
+  bufferlist bl;
+  int r = store->get(MONITOR_STORE_PREFIX, "last_metadata", bl);
+  if (r)
+    return r;
+  bufferlist::iterator it = bl.begin();
+  ::decode(metadata, it);
+  return 0;
+}
+
+int Monitor::get_mon_metadata(int mon, Formatter *f, ostream& err)
+{
+  assert(f);
+  map<int, Metadata> last_metadata;
+  if (int r = load_metadata(last_metadata)) {
+    err << "Unable to load metadata";
+    return r;
+  }
+  if (!last_metadata.count(mon)) {
+    err << "mon." << mon << " not found";
+    return -EINVAL;
+  }
+  const Metadata& m = last_metadata[mon];
+  for (Metadata::const_iterator p = m.begin(); p != m.end(); ++p) {
+    f->dump_string(p->first.c_str(), p->second);
+  }
+  return 0;
+}
 
 // ----------------------------------------------
 // scrub
index 72f1307602b4a2dcbf866066d606d8c31feebdbc..1654bb815c93167975047df6184c776ef3542cbe 100644 (file)
@@ -107,6 +107,7 @@ class AdminSocketHook;
 
 class MMonGetMap;
 class MMonGetVersion;
+class MMonMetadata;
 class MMonSync;
 class MMonScrub;
 class MMonProbe;
@@ -637,6 +638,7 @@ public:
   void handle_get_version(MMonGetVersion *m);
   void handle_subscribe(MMonSubscribe *m);
   void handle_mon_get_map(MMonGetMap *m);
+
   static void _generate_command_map(map<string,cmd_vartype>& cmdmap,
                                     map<string,string> &param_str_map);
   static const MonCommand *_get_moncommand(const string &cmd_prefix,
@@ -651,6 +653,10 @@ public:
   void handle_command(class MMonCommand *m);
   void handle_route(MRoute *m);
 
+  void handle_mon_metadata(MMonMetadata *m);
+  int get_mon_metadata(int mon, Formatter *f, ostream& err);
+  map<int, Metadata> metadata;
+
   /**
    *
    */
@@ -847,6 +853,9 @@ public:
   int write_default_keyring(bufferlist& bl);
   void extract_save_mon_key(KeyRing& keyring);
 
+  void update_mon_metadata(int from, const Metadata& m);
+  int load_metadata(map<int, Metadata>& m);
+
   // features
   static CompatSet get_initial_supported_features();
   static CompatSet get_supported_features();
index d7346cf2de43834cf964d43fb659b69875034c59..4fa97d3a80bc77e310d816069af1b1aa07527945 100644 (file)
@@ -203,4 +203,7 @@ static inline ostream& operator<<(ostream& out, const ScrubResult& r) {
   return out << "ScrubResult(keys " << r.prefix_keys << " crc " << r.prefix_crc << ")";
 }
 
+/// for information like os, kernel, hostname, memory info, cpu model.
+typedef map<string, string> Metadata;
+
 #endif
index 23f5179a9e4bd4f188447c199882d195c8b9994c..c29ecefdf51329aa7a4a8e75b07c4a88a8b8a430 100644 (file)
@@ -90,6 +90,7 @@ using namespace std;
 #include "messages/MMonGetVersion.h"
 #include "messages/MMonGetVersionReply.h"
 #include "messages/MMonHealth.h"
+#include "messages/MMonMetadata.h"
 #include "messages/MDataPing.h"
 #include "messages/MAuth.h"
 #include "messages/MAuthReply.h"
@@ -396,6 +397,9 @@ Message *decode_message(CephContext *cct, int crcflags,
   case CEPH_MSG_MON_GET_VERSION_REPLY:
     m = new MMonGetVersionReply();
     break;
+  case CEPH_MSG_MON_METADATA:
+    m = new MMonMetadata();
+    break;
 
   case MSG_OSD_BOOT:
     m = new MOSDBoot();