From: xie xingguo Date: Thu, 8 Jun 2017 12:16:17 +0000 (+0800) Subject: mon/OSDMonitor: add "ceph osd ls-tree" command X-Git-Tag: v12.1.0~143^2~2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=905ad73c33d3827b6b3c073b48072a9a4b073c12;p=ceph.git mon/OSDMonitor: add "ceph osd ls-tree" command 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 --- diff --git a/qa/workunits/cephtool/test.sh b/qa/workunits/cephtool/test.sh index 296c93d7af4a..2df6e57d0f8f 100755 --- a/qa/workunits/cephtool/test.sh +++ b/qa/workunits/cephtool/test.sh @@ -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' diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 1e84904ba4f4..0def97e1b37f 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -677,6 +677,64 @@ int CrushWrapper::get_children(int id, list *children) return b->size; } +int CrushWrapper::_get_leaves(int id, list *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 *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 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& loc) // typename -> bucketname diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index baf5ceba13f6..a06c38227c5a 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -636,6 +636,15 @@ public: */ int get_children(int id, list *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 *leaves); + int _get_leaves(int id, list *leaves); // worker + /** * insert an item into the map at a specific position * diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 9d574ede878a..0569c78a5569 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -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 in the CRUSH map", \ + "osd", "r", "cli,rest") COMMAND("osd find " \ "name=id,type=CephOsdName", \ "find osd in the CRUSH map and show its location", \ diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 5108e16fef1d..c5c1cb25ff47 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -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 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; diff --git a/src/osd/OSDMap.cc b/src/osd/OSDMap.cc index 7a712901a4cd..ced120c592a3 100644 --- a/src/osd/OSDMap.cc +++ b/src/osd/OSDMap.cc @@ -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 *osds) const +{ + return crush->get_leaves(name, osds); +} diff --git a/src/osd/OSDMap.h b/src/osd/OSDMap.h index 18e8df7674be..df58787a37c9 100644 --- a/src/osd/OSDMap.h +++ b/src/osd/OSDMap.h @@ -1221,6 +1221,8 @@ public: Incremental *pending_inc ); + int get_osds_by_bucket_name(const string &name, set *osds) const; + /* * handy helpers to build simple maps... */