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'
return b->size;
}
+int CrushWrapper::_get_leaves(int id, list<int> *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<int> *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<int> 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<string,string>& loc) // typename -> bucketname
*/
int get_children(int id, list<int> *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<int> *leaves);
+ int _get_leaves(int id, list<int> *leaves); // worker
+
/**
* insert an item into the map at a specific position
*
"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 <name> in the CRUSH map", \
+ "osd", "r", "cli,rest")
COMMAND("osd find " \
"name=id,type=CephOsdName", \
"find osd <id> in the CRUSH map and show its location", \
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;
} 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<int> 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;
ldout(cct, 10) << " end deviation " << end_deviation << dendl;
return num_changed;
}
+
+int OSDMap::get_osds_by_bucket_name(const string &name, set<int> *osds) const
+{
+ return crush->get_leaves(name, osds);
+}
Incremental *pending_inc
);
+ int get_osds_by_bucket_name(const string &name, set<int> *osds) const;
+
/*
* handy helpers to build simple maps...
*/