From: xie xingguo Date: Fri, 30 Jun 2017 05:56:21 +0000 (+0800) Subject: mon/OSDMonitor: extend "set-device-class" for multiple osds X-Git-Tag: v12.1.1~42^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cde4ab096d9ed6eaaaebb11ed67b6d9d6025afe3;p=ceph.git mon/OSDMonitor: extend "set-device-class" for multiple osds This is useful for applying changes to entire subtrees. For example: ./bin/ceph osd crush set-device-class hdd `./bin/ceph osd ls-tree default` set osd(s) 0,1,2 to class 'hdd' Signed-off-by: xie xingguo --- diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 679166864749..bfdf0041ebaf 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -527,9 +527,10 @@ COMMAND("osd crush add " \ "add or update crushmap position and weight for with and location ", \ "osd", "rw", "cli,rest") COMMAND("osd crush set-device-class " \ - "name=id,type=CephOsdName " \ - "name=class,type=CephString ", \ - "set the of the device ", \ + "name=class,type=CephString " \ + "name=ids,type=CephString,n=N", \ + "set the of the osd(s) [...]," \ + "or use to set all.", \ "osd", "rw", "cli,rest") COMMAND("osd crush create-or-move " \ "name=id,type=CephOsdName " \ diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 4fc7c09fafe9..31ba54670d81 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -7082,15 +7082,10 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, } 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)) { @@ -7098,37 +7093,77 @@ bool OSDMonitor::prepare_command_impl(MonOpRequestRef op, goto reply; } + bool stop = false; + vector idvec; + cmd_getval(g_ceph_context, cmdmap, "ids", idvec); CrushWrapper newcrush; _get_pending_crush(newcrush); + set updated; + for (unsigned j = 0; j < idvec.size() && !stop; j++) { + set 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 diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc index 1392be7a01cc..7a42528c3d0d 100644 --- a/src/osd/OSD.cc +++ b/src/osd/OSD.cc @@ -3453,8 +3453,8 @@ int OSD::update_crush_device_class() string cmd = string("{\"prefix\": \"osd crush set-device-class\", ") + - string("\"id\": ") + stringify(whoami) + string(", ") + - string("\"class\": \"") + device_class + string("\"}"); + string("\"class\": \"") + device_class + string("\", ") + + string("\"ids\": [\"") + stringify(whoami) + string("\"]}"); return mon_cmd_maybe_osd_create(cmd); } diff --git a/src/test/crush/crush-classes.sh b/src/test/crush/crush-classes.sh index ac8ec2052dd9..5dd9553dd674 100755 --- a/src/test/crush/crush-classes.sh +++ b/src/test/crush/crush-classes.sh @@ -115,8 +115,9 @@ function TEST_set_device_class() { TEST_classes $dir || return 1 - ceph osd crush set-device-class osd.0 ssd || return 1 - ceph osd crush set-device-class osd.1 ssd || return 1 + ceph osd crush set-device-class ssd osd.0 || return 1 + ceph osd crush set-device-class ssd osd.1 || return 1 + ceph osd crush set-device-class ssd 0 1 || return 1 # should be idempotent ok=false for delay in 2 4 8 16 32 64 128 256 ; do