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

Fixes: #11833
Signed-off-by: Kefu Chai <kchai@redhat.com>
(cherry picked from commit 5436c290f3622feb8d4b279ed6552b2510e0cee9)

Conflicts:
src/test/mon/osd-crush.sh:
do not start mon as run() takes care of it already

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 08d06bae38782326be5ae8298ce39893480815af..97c98ada8214fcae76730806ec16854c277aa71c 100644 (file)
@@ -669,6 +669,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 497c2196958a2f2404b8d9b1c511885da8b177f8..48945b95fdd9b4c8cce005e8d8f00116c22b73aa 100644 (file)
@@ -1409,6 +1409,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 cfafab067dee29a8a1992212f6ad2aa625509001..ec4f57a7c9e357767a216171ab53f0ce300c655f 100644 (file)
@@ -1054,6 +1054,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 a72aa4b02d4a3b28ab713954b06046369c31188a..c6d0f85f4c24bf392431296ec69960493b1787d7 100644 (file)
@@ -521,6 +521,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 2857e585994917abd4756082fef7b9d95a0fd4fb..3fdcd17969cec47edee9d5001fc1394379c6a835 100644 (file)
@@ -3367,6 +3367,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 1c6347f48e4aa77500f293d32f4b27a7b2bd3a5f..2242e9c957ce3bcee2416b64718b71565050d281 100755 (executable)
@@ -200,7 +200,12 @@ function TEST_crush_reject_empty() {
         ./ceph osd setcrushmap -i $empty_map.map || return 1
 }
 
-main osd-crush
+function TEST_crush_tree() {
+    ./ceph osd crush tree --format=xml | \
+        $XMLSTARLET val -e -r test/mon/osd-crush-tree.rng - || return 1
+}
+
+main osd-crush 
 
 # Local Variables:
 # compile-command: "cd ../.. ; make -j4 && test/mon/osd-crush.sh"