From: Sage Weil Date: Tue, 30 May 2017 12:21:16 +0000 (-0400) Subject: mon: add up|down|in|out filters to 'osd tree' X-Git-Tag: v12.1.0~363^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=0027a3b9be6f4dca7d5441dd92febe87c637d2e8;p=ceph-ci.git mon: add up|down|in|out filters to 'osd tree' For example, 'ceph osd tree down' will show *just* down OSDs and their ancestors. \o/ Signed-off-by: Sage Weil --- diff --git a/qa/workunits/cephtool/test.sh b/qa/workunits/cephtool/test.sh index 07b8df941cb..f9718f4ff00 100755 --- a/qa/workunits/cephtool/test.sh +++ b/qa/workunits/cephtool/test.sh @@ -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 diff --git a/src/crush/CrushTreeDumper.h b/src/crush/CrushTreeDumper.h index 6bd11abeb7a..40691c697d3 100644 --- a/src/crush/CrushTreeDumper.h +++ b/src/crush/CrushTreeDumper.h @@ -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; } diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 2c91d79c5d4..ef4490c6ddd 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -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", \ diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index e28621cffaf..579f048fbba 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -4012,13 +4012,39 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) } rdata.append(ds); } else if (prefix == "osd tree") { + vector 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") { diff --git a/src/osd/OSDMap.cc b/src/osd/OSDMap.cc index cbeb791ff66..0453d5cc2ce 100644 --- a/src/osd/OSDMap.cc +++ b/src/osd/OSDMap.cc @@ -2849,8 +2849,24 @@ void OSDMap::print(ostream& out) const class OSDTreePlainDumper : public CrushTreeDumper::Dumper { public: typedef CrushTreeDumper::Dumper 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; } } diff --git a/src/osd/OSDMap.h b/src/osd/OSDMap.h index 5d1819df332..333543ea37b 100644 --- a/src/osd/OSDMap.h +++ b/src/osd/OSDMap.h @@ -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, diff --git a/src/test/mon/osd-crush.sh b/src/test/mon/osd-crush.sh index ef0c84de0bb..3a873eb60f4 100755 --- a/src/test/mon/osd-crush.sh +++ b/src/test/mon/osd-crush.sh @@ -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