]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: add up|down|in|out filters to 'osd tree' 15294/head
authorSage Weil <sage@redhat.com>
Tue, 30 May 2017 12:21:16 +0000 (08:21 -0400)
committerSage Weil <sage@redhat.com>
Tue, 30 May 2017 12:21:16 +0000 (08:21 -0400)
For example, 'ceph osd tree down' will show *just* down OSDs and their
ancestors.  \o/

Signed-off-by: Sage Weil <sage@redhat.com>
qa/workunits/cephtool/test.sh
src/crush/CrushTreeDumper.h
src/mon/MonCommands.h
src/mon/OSDMonitor.cc
src/osd/OSDMap.cc
src/osd/OSDMap.h
src/test/mon/osd-crush.sh

index 07b8df941cb70c1946fa9b2197fde51add503a59..f9718f4ff00d8b58d14f543db6d8cc75f1144f72 100755 (executable)
@@ -1312,6 +1312,19 @@ function test_mon_osd()
   ceph osd unpause
 
   ceph osd tree
+  ceph osd tree up
+  ceph osd tree down
+  ceph osd tree in
+  ceph osd tree out
+  ceph osd tree up in
+  ceph osd tree up out
+  ceph osd tree down in
+  ceph osd tree down out
+  ceph osd tree out down
+  expect_false ceph osd tree up down
+  expect_false ceph osd tree in out
+  expect_false ceph osd tree up foo
+
   ceph osd perf
   ceph osd blocked-by
 
index 6bd11abeb7acfacb3a0a5e9926326971e4837e9a..40691c697d3a75487eb0414ded0470b597b5ec4c 100644 (file)
@@ -76,10 +76,10 @@ namespace CrushTreeDumper {
       clear();
     }
 
-    virtual bool should_dump_leaf(int i) {
+    virtual bool should_dump_leaf(int i) const {
       return true;
     }
-    virtual bool should_dump_empty_bucket() {
+    virtual bool should_dump_empty_bucket() const {
       return true;
     }
 
index 2c91d79c5d4cab5a8d9ca2f8ab7e463455080437..ef4490c6ddd7bd8e9da7596c166c9d54933c65d4 100644 (file)
@@ -421,7 +421,8 @@ COMMAND("osd dump " \
        "name=epoch,type=CephInt,range=0,req=false",
        "print summary of OSD map", "osd", "r", "cli,rest")
 COMMAND("osd tree " \
-       "name=epoch,type=CephInt,range=0,req=false", \
+       "name=epoch,type=CephInt,range=0,req=false " \
+       "name=states,type=CephChoices,strings=up|down|in|out,n=N,req=false", \
        "print OSD tree", "osd", "r", "cli,rest")
 COMMAND("osd ls " \
        "name=epoch,type=CephInt,range=0,req=false", \
index e28621cffafda6770fdd6600f5232e85c7307fa7..579f048fbba4d12d48b92b4564c88f3ae17f0b60 100644 (file)
@@ -4012,13 +4012,39 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op)
       }
       rdata.append(ds);
     } else if (prefix == "osd tree") {
+      vector<string> states;
+      cmd_getval(g_ceph_context, cmdmap, "states", states);
+      unsigned filter = 0;
+      for (auto& s : states) {
+       if (s == "up") {
+         filter |= OSDMap::DUMP_UP;
+       } else if (s == "down") {
+         filter |= OSDMap::DUMP_DOWN;
+       } else if (s == "in") {
+         filter |= OSDMap::DUMP_IN;
+       } else if (s == "out") {
+         filter |= OSDMap::DUMP_OUT;
+       } else {
+         ss << "unrecognized state '" << s << "'";
+         r = -EINVAL;
+         goto reply;
+       }
+      }
+      if ((filter & (OSDMap::DUMP_IN|OSDMap::DUMP_OUT)) ==
+         (OSDMap::DUMP_IN|OSDMap::DUMP_OUT) ||
+         (filter & (OSDMap::DUMP_UP|OSDMap::DUMP_DOWN)) ==
+         (OSDMap::DUMP_UP|OSDMap::DUMP_DOWN)) {
+       ss << "cannot specify both up and down or both in and out";
+       r = -EINVAL;
+       goto reply;
+      }
       if (f) {
        f->open_object_section("tree");
-       p->print_tree(f.get(), NULL);
+       p->print_tree(f.get(), NULL, filter);
        f->close_section();
        f->flush(ds);
       } else {
-       p->print_tree(NULL, &ds);
+       p->print_tree(NULL, &ds, filter);
       }
       rdata.append(ds);
     } else if (prefix == "osd getmap") {
index cbeb791ff668d5ef6ecf2f029717b507e7ab04f0..0453d5cc2ce1f5f6c2f75d25e7e7edb56332b182 100644 (file)
@@ -2849,8 +2849,24 @@ void OSDMap::print(ostream& out) const
 class OSDTreePlainDumper : public CrushTreeDumper::Dumper<TextTable> {
 public:
   typedef CrushTreeDumper::Dumper<TextTable> Parent;
-  OSDTreePlainDumper(const CrushWrapper *crush, const OSDMap *osdmap_)
-    : Parent(crush), osdmap(osdmap_) {}
+
+  OSDTreePlainDumper(const CrushWrapper *crush, const OSDMap *osdmap_,
+                    unsigned f)
+    : Parent(crush), osdmap(osdmap_), filter(f) { }
+
+  bool should_dump_leaf(int i) const override {
+    if (((filter & OSDMap::DUMP_UP) && !osdmap->is_up(i)) ||
+       ((filter & OSDMap::DUMP_DOWN) && !osdmap->is_down(i)) ||
+       ((filter & OSDMap::DUMP_IN) && !osdmap->is_in(i)) ||
+       ((filter & OSDMap::DUMP_OUT) && !osdmap->is_out(i))) {
+      return false;
+    }
+    return true;
+  }
+
+  bool should_dump_empty_bucket() const override {
+    return !filter;
+  }
 
   void dump(TextTable *tbl) {
     tbl->define_column("ID", TextTable::LEFT, TextTable::RIGHT);
@@ -2863,8 +2879,9 @@ public:
     Parent::dump(tbl);
 
     for (int i = 0; i < osdmap->get_max_osd(); i++) {
-      if (osdmap->exists(i) && !is_touched(i))
+      if (osdmap->exists(i) && !is_touched(i) && should_dump_leaf(i)) {
        dump_item(CrushTreeDumper::Item(i, 0, 0), tbl);
+      }
     }
   }
 
@@ -2900,14 +2917,30 @@ protected:
 
 private:
   const OSDMap *osdmap;
+  const unsigned filter;
 };
 
 class OSDTreeFormattingDumper : public CrushTreeDumper::FormattingDumper {
 public:
   typedef CrushTreeDumper::FormattingDumper Parent;
 
-  OSDTreeFormattingDumper(const CrushWrapper *crush, const OSDMap *osdmap_)
-    : Parent(crush), osdmap(osdmap_) {}
+  OSDTreeFormattingDumper(const CrushWrapper *crush, const OSDMap *osdmap_,
+                         unsigned f)
+    : Parent(crush), osdmap(osdmap_), filter(f) { }
+
+  bool should_dump_leaf(int i) const override {
+    if (((filter & OSDMap::DUMP_UP) && !osdmap->is_up(i)) ||
+       ((filter & OSDMap::DUMP_DOWN) && !osdmap->is_down(i)) ||
+       ((filter & OSDMap::DUMP_IN) && !osdmap->is_in(i)) ||
+       ((filter & OSDMap::DUMP_OUT) && !osdmap->is_out(i))) {
+      return false;
+    }
+    return true;
+  }
+
+  bool should_dump_empty_bucket() const override {
+    return !filter;
+  }
 
   void dump(Formatter *f) {
     f->open_array_section("nodes");
@@ -2915,7 +2948,7 @@ public:
     f->close_section();
     f->open_array_section("stray");
     for (int i = 0; i < osdmap->get_max_osd(); i++) {
-      if (osdmap->exists(i) && !is_touched(i))
+      if (osdmap->exists(i) && !is_touched(i) && should_dump_leaf(i))
        dump_item(CrushTreeDumper::Item(i, 0, 0), f);
     }
     f->close_section();
@@ -2935,16 +2968,17 @@ protected:
 
 private:
   const OSDMap *osdmap;
+  const unsigned filter;
 };
 
-void OSDMap::print_tree(Formatter *f, ostream *out) const
+void OSDMap::print_tree(Formatter *f, ostream *out, unsigned filter) const
 {
-  if (f)
-    OSDTreeFormattingDumper(crush.get(), this).dump(f);
-  else {
+  if (f) {
+    OSDTreeFormattingDumper(crush.get(), this, filter).dump(f);
+  else {
     assert(out);
     TextTable tbl;
-    OSDTreePlainDumper(crush.get(), this).dump(&tbl);
+    OSDTreePlainDumper(crush.get(), this, filter).dump(&tbl);
     *out << tbl;
   }
 }
index 5d1819df33275df7e23c1e981f4fd4feff32ceeb..333543ea37bf0571d61ce3925c2d396d80192ded 100644 (file)
@@ -957,7 +957,14 @@ public:
   void print_pools(ostream& out) const;
   void print_summary(Formatter *f, ostream& out) const;
   void print_oneline_summary(ostream& out) const;
-  void print_tree(Formatter *f, ostream *out) const;
+
+  enum {
+    DUMP_IN = 1,     // only 'in' osds
+    DUMP_OUT = 2,    // only 'out' osds
+    DUMP_UP = 4,     // only 'up' osds
+    DUMP_DOWN = 8,   // only 'down' osds
+  };
+  void print_tree(Formatter *f, ostream *out, unsigned dump_flags=0) const;
 
   int summarize_mapping_stats(
     OSDMap *newmap,
index ef0c84de0bbaa0fdb085c57a134907953783a235..3a873eb60f4fb6c62e8f6a04da7eb7708ea9afdc 100755 (executable)
@@ -210,8 +210,10 @@ function TEST_crush_rename_bucket() {
     run_mon $dir a || return 1
 
     ceph osd crush add-bucket host1 host
+    ceph osd tree
     ! ceph osd tree | grep host2 || return 1
     ceph osd crush rename-bucket host1 host2 || return 1
+    ceph osd tree
     ceph osd tree | grep host2 || return 1
     ceph osd crush rename-bucket host1 host2 || return 1 # idempotency
     ceph osd crush rename-bucket nonexistent something 2>&1 | grep "Error ENOENT" || return 1