]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: add 'node ls {all,mds,mon,osd}' asok 4227/head
authorKefu Chai <kchai@redhat.com>
Tue, 31 Mar 2015 15:41:53 +0000 (23:41 +0800)
committerKefu Chai <kchai@redhat.com>
Thu, 7 May 2015 14:29:39 +0000 (07:29 -0700)
Fixes: #10904
Signed-off-by: Kefu Chai <kchai@redhat.com>
qa/workunits/cephtool/test.sh
src/common/util.cc
src/include/util.h
src/mon/MDSMonitor.cc
src/mon/MDSMonitor.h
src/mon/MonCommands.h
src/mon/Monitor.cc
src/mon/Monitor.h
src/mon/OSDMonitor.cc
src/mon/OSDMonitor.h

index b4b41f83a9066c0365f3b39c9b33643ab4ad3ae5..2784eabadab0c522196a70676decfd2e33fa9e38 100755 (executable)
@@ -559,6 +559,11 @@ function test_mon_misc()
   ceph health --format json-pretty
   ceph health detail --format xml-pretty
 
+  ceph node ls
+  for t in mon osd mds ; do
+      ceph node ls $t
+  done
+
   ceph_watch_start
   mymsg="this is a test log message $$.$(date)"
   ceph log "$mymsg"
index 13132f5e8f9fd1ca9a364a03d62331d870ef53f4..3c3a304c22fcb558e9836c8f83fc74282dc2d303 100644 (file)
@@ -235,3 +235,21 @@ void collect_sys_info(map<string, string> *m, CephContext *cct)
   // distro info
   lsb_release_parse(m, cct);
 }
+
+void dump_services(Formatter* f, const map<string, list<int> >& services, const char* type)
+{
+  assert(f);
+
+  f->open_object_section(type);
+  for (map<string, list<int> >::const_iterator host = services.begin();
+       host != services.end(); ++host) {
+    f->open_array_section(host->first.c_str());
+    const list<int>& hosted = host->second;
+    for (list<int>::const_iterator s = hosted.begin();
+        s != hosted.end(); ++s) {
+      f->dump_int(type, *s);
+    }
+    f->close_section();
+  }
+  f->close_section();
+}
index c3a28bc443eec1dd525e56d2b73dc401bedad1e1..c453440dc1b646a2504cf0c529e9476403e29a22 100644 (file)
@@ -79,4 +79,10 @@ int get_fs_stats(ceph_data_stats_t &stats, const char *path);
 /// collect info from @p uname(2), @p /proc/meminfo and @p /proc/cpuinfo
 void collect_sys_info(map<string, string> *m, CephContext *cct);
 
+/// dump service ids grouped by their host to the specified formatter
+/// @param f formatter for the output
+/// @param services a map from hostname to a list of service id hosted by this host
+/// @param type the service type of given @p services, for example @p osd or @p mon.
+void dump_services(Formatter* f, const map<string, list<int> >& services, const char* type);
+
 #endif /* CEPH_UTIL_H */
index c79094a45f03ca9f695ba930ad4c1ef00420c2f4..34d18d5bfb78b4599a827b15e42f286f4d018478 100644 (file)
@@ -1792,6 +1792,34 @@ int MDSMonitor::dump_metadata(const std::string &who, Formatter *f, ostream& err
   return 0;
 }
 
+int MDSMonitor::print_nodes(Formatter *f)
+{
+  assert(f);
+
+  map<mds_gid_t, Metadata> metadata;
+  if (int r = load_metadata(metadata)) {
+    return r;
+  }
+
+  map<string, list<int> > mdses; // hostname => rank
+  for (map<mds_gid_t, Metadata>::iterator it = metadata.begin();
+       it != metadata.end(); ++it) {
+    const Metadata& m = it->second;
+    Metadata::const_iterator hostname = m.find("hostname");
+    if (hostname == m.end()) {
+      // not likely though
+      continue;
+    }
+    const mds_gid_t gid = it->first;
+    assert(mdsmap.get_state_gid(gid) != MDSMap::STATE_NULL);
+    const MDSMap::mds_info_t& mds_info = mdsmap.get_info_gid(gid);
+    mdses[hostname->second].push_back(mds_info.rank);
+  }
+
+  dump_services(f, mdses, "mds");
+  return 0;
+}
+
 void MDSMonitor::tick()
 {
   // make sure mds's are still alive
index 9b5ccd013721b01c82b503405352b161a3eff0fe..88bf69a48fc7de89c2a1237beed637500d8fb87e 100644 (file)
@@ -131,6 +131,7 @@ public:
 
   void dump_info(Formatter *f);
   int dump_metadata(const string& who, Formatter *f, ostream& err);
+  int print_nodes(Formatter *f);
 
   void check_subs();
   void check_sub(Subscription *sub);
index 8a8bb320a7bc6621545a4cc6af9d0dc4d991dfa7..4bde698fb04d300b962c1dea9a12486cf1e5f80d 100644 (file)
@@ -257,7 +257,9 @@ COMMAND("tell " \
        "send a command to a specific daemon", "mon", "rw", "cli,rest")
 COMMAND_WITH_FLAG("version", "show mon daemon version", "mon", "r", "cli,rest",
             NOFORWARD)
-
+COMMAND("node ls " \
+       "name=type,type=CephChoices,strings=all|osd|mon|mds,req=false",
+       "list all nodes in cluster [type]", "mon", "r", "cli,rest")
 /*
  * MDS commands (MDSMonitor.cc)
  */
index 456dff5a5786284942e4cf17a49517c6a78e2b66..74ba6a11211efe2c51392c6639c9063dd060dfad 100644 (file)
@@ -2844,6 +2844,28 @@ void Monitor::handle_command(MMonCommand *m)
     ss2 << "report " << rdata.crc32c(6789);
     rs = ss2.str();
     r = 0;
+  } else if (prefix == "node ls") {
+    string node_type("all");
+    cmd_getval(g_ceph_context, cmdmap, "type", node_type);
+    if (!f)
+      f.reset(Formatter::create("json-pretty"));
+    if (node_type == "all") {
+      f->open_object_section("nodes");
+      print_nodes(f.get(), ds);
+      osdmon()->print_nodes(f.get());
+      mdsmon()->print_nodes(f.get());
+      f->close_section();
+    } else if (node_type == "mon") {
+      print_nodes(f.get(), ds);
+    } else if (node_type == "osd") {
+      osdmon()->print_nodes(f.get());
+    } else if (node_type == "mds") {
+      mdsmon()->print_nodes(f.get());
+    }
+    f->flush(ds);
+    rdata.append(ds);
+    rs = "";
+    r = 0;
   } else if (prefix == "mon_metadata") {
     string name;
     cmd_getval(g_ceph_context, cmdmap, "id", name);
@@ -4271,6 +4293,30 @@ int Monitor::get_mon_metadata(int mon, Formatter *f, ostream& err)
   return 0;
 }
 
+int Monitor::print_nodes(Formatter *f, ostream& err)
+{
+  map<int, Metadata> metadata;
+  if (int r = load_metadata(metadata)) {
+    err << "Unable to load metadata.\n";
+    return r;
+  }
+
+  map<string, list<int> > mons;        // hostname => mon
+  for (map<int, Metadata>::iterator it = metadata.begin();
+       it != metadata.end(); ++it) {
+    const Metadata& m = it->second;
+    Metadata::const_iterator hostname = m.find("hostname");
+    if (hostname == m.end()) {
+      // not likely though
+      continue;
+    }
+    mons[hostname->second].push_back(it->first);
+  }
+
+  dump_services(f, mons, "mon");
+  return 0;
+}
+
 // ----------------------------------------------
 // scrub
 
index 1654bb815c93167975047df6184c776ef3542cbe..d031115167bf9600dbe95789be5014b56e728c66 100644 (file)
@@ -655,6 +655,7 @@ public:
 
   void handle_mon_metadata(MMonMetadata *m);
   int get_mon_metadata(int mon, Formatter *f, ostream& err);
+  int print_nodes(Formatter *f, ostream& err);
   map<int, Metadata> metadata;
 
   /**
index 9f44a479ed6a0169be53881c40f4704b4d477d52..c586b41ba20b71e3871a8d6b03e516c210c38db1 100644 (file)
@@ -1124,13 +1124,12 @@ void OSDMonitor::encode_pending(MonitorDBStore::TransactionRef t)
   pending_metadata_rm.clear();
 }
 
-int OSDMonitor::dump_osd_metadata(int osd, Formatter *f, ostream *err)
+int OSDMonitor::load_metadata(int osd, map<string, string>& m, ostream *err)
 {
   bufferlist bl;
   int r = mon->store->get(OSD_METADATA_PREFIX, stringify(osd), bl);
   if (r < 0)
     return r;
-  map<string,string> m;
   try {
     bufferlist::iterator p = bl.begin();
     ::decode(m, p);
@@ -1140,11 +1139,39 @@ int OSDMonitor::dump_osd_metadata(int osd, Formatter *f, ostream *err)
       *err << "osd." << osd << " metadata is corrupt";
     return -EIO;
   }
+  return 0;
+}
+
+int OSDMonitor::dump_osd_metadata(int osd, Formatter *f, ostream *err)
+{
+  map<string,string> m;
+  if (int r = load_metadata(osd, m, err))
+    return r;
   for (map<string,string>::iterator p = m.begin(); p != m.end(); ++p)
     f->dump_string(p->first.c_str(), p->second);
   return 0;
 }
 
+void OSDMonitor::print_nodes(Formatter *f)
+{
+  // group OSDs by their hosts
+  map<string, list<int> > osds; // hostname => osd
+  for (int osd = 0; osd <= osdmap.get_max_osd(); osd++) {
+    map<string, string> m;
+    if (load_metadata(osd, m, NULL)) {
+      continue;
+    }
+    map<string, string>::iterator hostname = m.find("hostname");
+    if (hostname == m.end()) {
+      // not likely though
+      continue;
+    }
+    osds[hostname->second].push_back(osd);
+  }
+
+  dump_services(f, osds, "osd");
+}
+
 void OSDMonitor::share_map_with_random_osd()
 {
   if (osdmap.get_num_up_osds() == 0) {
index 1e7f8f0bcff3f0255a4faa13d59dd86bec8f602f..41cd805a7e2d42590e6cc1258395953dfa622cc4 100644 (file)
@@ -386,6 +386,8 @@ private:
   bool preprocess_remove_snaps(struct MRemoveSnaps *m);
   bool prepare_remove_snaps(struct MRemoveSnaps *m);
 
+  int load_metadata(int osd, map<string, string>& m, ostream *err);
+
  public:
   OSDMonitor(Monitor *mn, Paxos *p, string service_name)
   : PaxosService(mn, p, service_name),
@@ -418,6 +420,7 @@ private:
 
   void dump_info(Formatter *f);
   int dump_osd_metadata(int osd, Formatter *f, ostream *err);
+  void print_nodes(Formatter *f);
 
   void check_subs();
   void check_sub(Subscription *sub);