]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: add an "osd crush tree" command 4840/head
authorKefu Chai <kchai@redhat.com>
Tue, 2 Jun 2015 15:52:22 +0000 (23:52 +0800)
committerKefu Chai <kchai@redhat.com>
Sun, 14 Jun 2015 11:08:32 +0000 (19:08 +0800)
* to print crush buckets/items in a tree

Fixes: #11833
Signed-off-by: Kefu Chai <kchai@redhat.com>
doc/man/8/ceph.rst
src/crush/CrushWrapper.cc
src/crush/CrushWrapper.h
src/mon/MonCommands.h
src/mon/OSDMonitor.cc
src/test/mon/osd-crush-tree.rng [new file with mode: 0644]
src/test/mon/osd-crush.sh

index f9502215a1016fedc6fb866ed34b0eef6a7cf109..70e588eb0d53cba16490b14fc74396fec8502550 100644 (file)
@@ -699,6 +699,12 @@ Usage::
 
        ceph osd crush show-tunables
 
+Subcommand ``tree`` shows the crush buckets and items in a tree view.
+
+Usage::
+
+       ceph osd crush tree
+
 Subcommand ``tunables`` sets crush tunables values to <profile>.
 
 Usage::
index e9a963d3a62fd76dca5aec3e7db1cd60290d0685..c94ed2754be1ac3c065c78f3d6305987b4e106a7 100644 (file)
@@ -1456,6 +1456,56 @@ void CrushWrapper::dump(Formatter *f) const
   f->close_section();
 }
 
+namespace {
+  // depth first walker
+  class TreeDumper {
+    typedef CrushTreeDumper::Item Item;
+    const CrushWrapper *crush;
+  public:
+    TreeDumper(const CrushWrapper *crush)
+      : crush(crush) {}
+
+    void dump(Formatter *f) {
+      set<int> roots;
+      crush->find_roots(roots);
+      for (set<int>::iterator root = roots.begin(); root != roots.end(); ++root) {
+       dump_item(Item(*root, 0, crush->get_bucket_weightf(*root)), f);
+      }
+    }
+
+  private:
+    void dump_item(const Item& qi, Formatter* f) {
+      if (qi.is_bucket()) {
+       f->open_object_section("bucket");
+       CrushTreeDumper::dump_item_fields(crush, qi, f);
+       dump_bucket_children(qi, f);
+       f->close_section();
+      } else {
+       f->open_object_section("device");
+       CrushTreeDumper::dump_item_fields(crush, qi, f);
+       f->close_section();
+      }
+    }
+
+    void dump_bucket_children(const Item& parent, Formatter* f) {
+      f->open_array_section("items");
+      const int max_pos = crush->get_bucket_size(parent.id);
+      for (int pos = 0; pos < max_pos; pos++) {
+       int id = crush->get_bucket_item(parent.id, pos);
+       float weight = crush->get_bucket_item_weightf(parent.id, pos);
+       dump_item(Item(id, parent.depth + 1, weight), f);
+      }
+      f->close_section();
+    }
+  };
+}
+
+void CrushWrapper::dump_tree(Formatter *f) const
+{
+  assert(f);
+  TreeDumper(this).dump(f);
+}
+
 void CrushWrapper::dump_tunables(Formatter *f) const
 {
   f->dump_int("choose_local_tries", get_choose_local_tries());
index 315e543ffccdc0869bc753e81946e7cf8d7e6c71..e3b4c489b39db90e4267720fd453efb4c1e2c298 100644 (file)
@@ -1060,6 +1060,7 @@ public:
   void dump_tunables(Formatter *f) const;
   void list_rules(Formatter *f) const;
   void dump_tree(ostream *out, Formatter *f) const;
+  void dump_tree(Formatter *f) const;
   static void generate_test_instances(list<CrushWrapper*>& o);
 
   int _get_osd_pool_default_crush_replicated_ruleset(CephContext *cct,
index 6e34c5056faf910e1afaa789441f2912559116fe..de3792cec1e5670dee38ca290696f7a047280517 100644 (file)
@@ -531,6 +531,9 @@ COMMAND("osd crush rule create-erasure " \
 COMMAND("osd crush rule rm " \
        "name=name,type=CephString,goodchars=[A-Za-z0-9-_.] ",  \
        "remove crush rule <name>", "osd", "rw", "cli,rest")
+COMMAND("osd crush tree",
+       "dump crush buckets and items in a tree view",
+       "osd", "r", "cli,rest")
 COMMAND("osd setmaxosd " \
        "name=newmax,type=CephInt,range=0", \
        "set new maximum osd value", "osd", "rw", "cli,rest")
index ef68d4689c23f9ed2e1244b83fcff5834677c1c2..0d3905fa9143dd2ab11626f21c14e8a54cabec26 100644 (file)
@@ -3706,6 +3706,12 @@ stats_out:
     f->flush(rs);
     rs << "\n";
     rdata.append(rs.str());
+  } else if (prefix == "osd crush tree") {
+    boost::scoped_ptr<Formatter> f(Formatter::create(format, "json-pretty", "json-pretty"));
+    f->open_array_section("crush_map_roots");
+    osdmap.crush->dump_tree(f.get());
+    f->close_section();
+    f->flush(rdata);
   } else if (prefix == "osd erasure-code-profile ls") {
     const map<string,map<string,string> > &profiles =
       osdmap.get_erasure_code_profiles();
diff --git a/src/test/mon/osd-crush-tree.rng b/src/test/mon/osd-crush-tree.rng
new file mode 100644 (file)
index 0000000..d050ed2
--- /dev/null
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grammar xmlns="http://relaxng.org/ns/structure/1.0">
+  <start>
+    <ref name="crush_map_roots"/>
+  </start>
+  <define name="item">
+    <choice>
+      <ref name="bucket"/>
+      <ref name="device"/>
+    </choice>
+  </define>
+  <define name="device">
+    <element name="device">
+      <element name="id">
+        <text/>
+      </element>
+      <element name="name">
+        <text/>
+      </element>
+      <element name="type">
+        <text/>
+      </element>
+      <element name="type_id">
+        <text/>
+      </element>
+      <element name="crush_weight">
+        <text/>
+      </element>
+      <element name="depth">
+        <text/>
+      </element>
+    </element>
+  </define>
+  <define name="bucket">
+    <element name="bucket">
+      <element name="id">
+        <text/>
+      </element>
+      <element name="name">
+        <text/>
+      </element>
+      <element name="type">
+        <text/>
+      </element>
+      <element name="type_id">
+        <text/>
+      </element>
+      <element name="items">
+        <zeroOrMore>
+          <ref name="item"/>
+        </zeroOrMore>
+      </element>
+    </element>
+  </define>
+  <define name="crush_map_roots">
+    <element name="crush_map_roots">
+      <oneOrMore>
+        <ref name="bucket"/>
+      </oneOrMore>
+    </element>
+  </define>
+</grammar>
index f6c4d5005679234a7f298be446e10243487b0c8a..ec83e8e3b4cd7962d5208423e50a6acda643f66a 100755 (executable)
@@ -218,6 +218,14 @@ function TEST_crush_reject_empty() {
         ./ceph osd setcrushmap -i $empty_map.map || return 1
 }
 
+function TEST_crush_tree() {
+    local dir=$1
+    run_mon $dir a || return 1
+
+    ./ceph osd crush tree --format=xml | \
+        $XMLSTARLET val -e -r test/mon/osd-crush-tree.rng - || return 1
+}
+
 main osd-crush "$@"
 
 # Local Variables: