"add or update crushmap position and weight for <name> with <weight> and location <args>", \
"osd", "rw", "cli,rest")
COMMAND("osd crush set-device-class " \
- "name=id,type=CephOsdName " \
- "name=class,type=CephString ", \
- "set the <class> of the device <name>", \
+ "name=class,type=CephString " \
+ "name=ids,type=CephString,n=N", \
+ "set the <class> of the osd(s) <id> [<id>...]," \
+ "or use <all|any|*> to set all.", \
"osd", "rw", "cli,rest")
COMMAND("osd crush create-or-move " \
"name=id,type=CephOsdName " \
} else if (prefix == "osd crush set-device-class") {
if (osdmap.require_osd_release < CEPH_RELEASE_LUMINOUS) {
ss << "you must complete the upgrade and 'ceph osd require-osd-release "
- << "luminous' before using crush device classes";
+ << "luminous' before using crush device classes";
err = -EPERM;
goto reply;
}
- if (!osdmap.exists(osdid)) {
- err = -ENOENT;
- ss << name << " does not exist. create it before updating the crush map";
- goto reply;
- }
string device_class;
if (!cmd_getval(g_ceph_context, cmdmap, "class", device_class)) {
goto reply;
}
+ bool stop = false;
+ vector<string> idvec;
+ cmd_getval(g_ceph_context, cmdmap, "ids", idvec);
CrushWrapper newcrush;
_get_pending_crush(newcrush);
+ set<int> updated;
+ for (unsigned j = 0; j < idvec.size() && !stop; j++) {
+ set<int> osds;
+ // wildcard?
+ if (j == 0 &&
+ (idvec[0] == "any" || idvec[0] == "all" || idvec[0] == "*")) {
+ osdmap.get_all_osds(osds);
+ stop = true;
+ } else {
+ // try traditional single osd way
+ long osd = parse_osd_id(idvec[j].c_str(), &ss);
+ if (osd < 0) {
+ // ss has reason for failure
+ ss << ", unable to parse osd id:\"" << idvec[j] << "\". ";
+ err = -EINVAL;
+ continue;
+ }
+ osds.insert(osd);
+ }
- string action;
- if (newcrush.item_exists(osdid)) {
- action = "updating";
- } else {
- action = "creating";
- newcrush.set_item_name(osdid, name);
- }
+ for (auto &osd : osds) {
+ if (!osdmap.exists(osd)) {
+ ss << "osd." << osd << " does not exist. ";
+ continue;
+ }
- dout(5) << action << " crush item id " << osdid << " name '"
- << name << "' device_class " << device_class << dendl;
- err = newcrush.update_device_class(osdid, device_class, name, &ss);
- if (err < 0)
- goto reply;
+ ostringstream oss;
+ oss << "osd." << osd;
+ string name = oss.str();
- if (err == 0 && !_have_pending_crush()) {
- ss << "set-device-class item id " << osdid << " name '" << name << "' device_class "
- << device_class << " : no change";
- goto reply;
+ string action;
+ if (newcrush.item_exists(osd)) {
+ action = "updating";
+ } else {
+ action = "creating";
+ newcrush.set_item_name(osd, name);
+ }
+
+ dout(5) << action << " crush item id " << osd << " name '" << name
+ << "' device_class '" << device_class << "'"
+ << dendl;
+ err = newcrush.update_device_class(osd, device_class, name, &ss);
+ if (err < 0) {
+ goto reply;
+ }
+ if (err == 0 && !_have_pending_crush()) {
+ if (!stop) {
+ // for single osd only, wildcard makes too much noise
+ ss << "set-device-class item id " << osd << " name '" << name
+ << "' device_class '" << device_class << "': no change";
+ }
+ } else {
+ updated.insert(osd);
+ }
+ }
}
- pending_inc.crush.clear();
- newcrush.encode(pending_inc.crush, mon->get_quorum_con_features());
- ss << "set-device-class item id " << osdid << " name '" << name << "' device_class "
- << device_class;
- getline(ss, rs);
- wait_for_finished_proposal(op, new Monitor::C_Command(mon, op, 0, rs,
- get_last_committed() + 1));
- return true;
+ if (!updated.empty()) {
+ pending_inc.crush.clear();
+ newcrush.encode(pending_inc.crush, mon->get_quorum_con_features());
+ ss << "set osd(s) " << updated << " to class '" << device_class << "'";
+ getline(ss, rs);
+ wait_for_finished_proposal(op,
+ new Monitor::C_Command(mon,op, 0, rs, get_last_committed() + 1));
+ return true;
+ }
} else if (prefix == "osd crush add-bucket") {
// os crush add-bucket <name> <type>