]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/OSDMonitor: add "ceph osd ls-tree" command
authorxie xingguo <xie.xingguo@zte.com.cn>
Thu, 8 Jun 2017 12:16:17 +0000 (20:16 +0800)
committerxie xingguo <xie.xingguo@zte.com.cn>
Mon, 12 Jun 2017 02:08:33 +0000 (10:08 +0800)
E.g.:
~# ceph osd tree
ID WEIGHT  TYPE NAME                                        UP/DOWN REWEIGHT PRIMARY-AFFINITY
-5 3.00000 root foo
-4 2.00000     rack foo-rack-1
-3 1.00000         host foo-host-192-8-8-91
 1 1.00000             osd.1                                     up  1.00000          1.00000
-6 1.00000         host foo-host-192-8-8-92
 2 1.00000             osd.2                                     up  1.00000          1.00000
-8 1.00000     rack foo-rack-2
-7 1.00000         host foo-host-192-8-8-93
 0 1.00000             osd.0                                     up  1.00000          1.00000
-1       0 root default
-2       0     host gitbuilder-ceph-rpm-centos7-amd64-basic

~# ceph osd ls-tree foo
0
1
2

~# ceph osd ls-tree foo-rack-1
1
2

~# ceph osd ls-tree foo-rack-2
0

~# ceph osd ls-tree foo-host-192-8-8-92
2

Signed-off-by: xie xingguo <xie.xingguo@zte.com.cn>
qa/workunits/cephtool/test.sh
src/crush/CrushWrapper.cc
src/crush/CrushWrapper.h
src/mon/MonCommands.h
src/mon/OSDMonitor.cc
src/osd/OSDMap.cc
src/osd/OSDMap.h

index 296c93d7af4a7c25774ede3296a4818cadaf420b..2df6e57d0f8f300b49971cc6c9498f6c08a51ccf 100755 (executable)
@@ -1440,6 +1440,19 @@ function test_mon_osd()
   ceph osd rm-nodown all
   ! ceph health detail | grep 'nodown osd(s).*0.*1'
 
+  ids=`ceph osd ls-tree default`
+  for osd in $ids
+  do
+    ceph osd add-noout $osd
+    ceph osd add-nodown $osd
+  done
+  ceph -s | grep 'noout osd(s)'
+  ceph -s | grep 'nodown osd(s)'
+  ceph osd rm-noout any
+  ceph osd rm-nodown any
+  ! ceph -s | grep 'noout osd(s)'
+  ! ceph -s | grep 'nodown osd(s)'
+
   # make sure mark out preserves weight
   ceph osd reweight osd.0 .5
   ceph osd dump | grep ^osd.0 | grep 'weight 0.5'
index 1e84904ba4f4007f06fc1e4f784badb3712f51d8..0def97e1b37f4dc1f1445f27841c1d2152f7908c 100644 (file)
@@ -677,6 +677,64 @@ int CrushWrapper::get_children(int id, list<int> *children)
   return b->size;
 }
 
+int CrushWrapper::_get_leaves(int id, list<int> *leaves)
+{
+  assert(leaves);
+
+  // Already leaf?
+  if (id >= 0) {
+    leaves->push_back(id);
+    return 0;
+  }
+
+  crush_bucket *b = get_bucket(id);
+  if (IS_ERR(b)) {
+    return -ENOENT;
+  }
+
+  for (unsigned n = 0; n < b->size; n++) {
+    if (b->items[n] >= 0) {
+      leaves->push_back(b->items[n]);
+    } else {
+      // is a bucket, do recursive call
+      int r = _get_leaves(b->items[n], leaves);
+      if (r < 0) {
+        return r;
+      }
+    }
+  }
+
+  return 0; // all is well
+}
+
+int CrushWrapper::get_leaves(const string &name, set<int> *leaves)
+{
+  assert(leaves);
+  leaves->clear();
+
+  if (!name_exists(name)) {
+    return -ENOENT;
+  }
+
+  int id = get_item_id(name);
+  if (id >= 0) {
+    // already leaf
+    leaves->insert(id);
+    return 0;
+  }
+
+  list<int> unordered;
+  int r = _get_leaves(id, &unordered);
+  if (r < 0) {
+    return r;
+  }
+
+  for (auto &p : unordered) {
+    leaves->insert(p);
+  }
+
+  return 0;
+}
 
 int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string name,
                              const map<string,string>& loc)  // typename -> bucketname
index baf5ceba13f6f9a2b323643fe681cf7daa885f18..a06c38227c5acb8d8883f2742bbe221d64bdadc8 100644 (file)
@@ -636,6 +636,15 @@ public:
    */
   int get_children(int id, list<int> *children);
 
+  /**
+    * enumerate leaves(devices) of given node
+    *
+    * @param name parent bucket name
+    * @return 0 on success or a negative errno on error.
+    */
+  int get_leaves(const string &name, set<int> *leaves);
+  int _get_leaves(int id, list<int> *leaves); // worker
+
   /**
    * insert an item into the map at a specific position
    *
index 9d574ede878ac5db3b2f930344464588953347fe..0569c78a5569c79945a74b8eba52a561e46fbfb6 100644 (file)
@@ -437,6 +437,11 @@ COMMAND("osd getcrushmap " \
        "name=epoch,type=CephInt,range=0,req=false", \
        "get CRUSH map", "osd", "r", "cli,rest")
 COMMAND("osd getmaxosd", "show largest OSD id", "osd", "r", "cli,rest")
+COMMAND("osd ls-tree " \
+        "name=epoch,type=CephInt,range=0,req=false "
+        "name=name,type=CephString,req=true", \
+        "show OSD ids under bucket <name> in the CRUSH map", \
+        "osd", "r", "cli,rest")
 COMMAND("osd find " \
        "name=id,type=CephOsdName", \
        "find osd <id> in the CRUSH map and show its location", \
index 5108e16fef1defeb27b2b52384d80edf1adb523b..c5c1cb25ff479bacbf8be73643b95a9b3b07621b 100644 (file)
@@ -4076,7 +4076,8 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op)
           prefix == "osd tree" ||
           prefix == "osd ls" ||
           prefix == "osd getmap" ||
-          prefix == "osd getcrushmap") {
+          prefix == "osd getcrushmap" ||
+          prefix == "osd ls-tree") {
     string val;
 
     epoch_t epoch = 0;
@@ -4179,6 +4180,41 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op)
     } else if (prefix == "osd getcrushmap") {
       p->crush->encode(rdata, mon->get_quorum_con_features());
       ss << "got crush map from osdmap epoch " << p->get_epoch();
+    } else if (prefix == "osd ls-tree") {
+      string bucket_name;
+      cmd_getval(g_ceph_context, cmdmap, "name", bucket_name);
+      set<int> osds;
+      r = p->get_osds_by_bucket_name(bucket_name, &osds);
+      if (r == -ENOENT) {
+        ss << "\"" << bucket_name << "\" does not exist";
+        goto reply;
+      } else if (r < 0) {
+        ss << "can not parse bucket name:\"" << bucket_name << "\"";
+        goto reply;
+      }
+
+      if (f) {
+        f->open_array_section("osds");
+        for (auto &i : osds) {
+          if (osdmap.exists(i)) {
+            f->dump_int("osd", i);
+          }
+        }
+        f->close_section();
+        f->flush(ds);
+      } else {
+        bool first = true;
+        for (auto &i : osds) {
+          if (osdmap.exists(i)) {
+            if (!first)
+              ds << "\n";
+            first = false;
+            ds << i;
+          }
+        }
+      }
+
+      rdata.append(ds);
     }
     if (p != &osdmap)
       delete p;
index 7a712901a4cd94515d8ad1ecc7da3a65a56a8ce1..ced120c592a3258717b835bb1d76dd3cf7b861ff 100644 (file)
@@ -3895,3 +3895,8 @@ int OSDMap::calc_pg_upmaps(
   ldout(cct, 10) << " end deviation " << end_deviation << dendl;
   return num_changed;
 }
+
+int OSDMap::get_osds_by_bucket_name(const string &name, set<int> *osds) const
+{
+  return crush->get_leaves(name, osds);
+}
index 18e8df7674bed742308c750cfb8585b915bcce0d..df58787a37c98e9d701201fe842d9452f544b70f 100644 (file)
@@ -1221,6 +1221,8 @@ public:
     Incremental *pending_inc
     );
 
+  int get_osds_by_bucket_name(const string &name, set<int> *osds) const;
+
   /*
    * handy helpers to build simple maps...
    */