]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/OSDMonitor: extend "set-device-class" for multiple osds
authorxie xingguo <xie.xingguo@zte.com.cn>
Fri, 30 Jun 2017 05:56:21 +0000 (13:56 +0800)
committerxie xingguo <xie.xingguo@zte.com.cn>
Mon, 10 Jul 2017 00:45:36 +0000 (08:45 +0800)
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 <xie.xingguo@zte.com.cn>
src/mon/MonCommands.h
src/mon/OSDMonitor.cc
src/osd/OSD.cc
src/test/crush/crush-classes.sh

index 679166864749c9f4aa661045fae30fe09d6df12e..bfdf0041ebafe2634452f930608f2c45ffc605d2 100644 (file)
@@ -527,9 +527,10 @@ COMMAND("osd crush add " \
        "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 " \
index 4fc7c09fafe9e4c78ff9d1add6aff49096c51cba..31ba54670d8118fa0731a4a410a4eed537dfd99c 100644 (file)
@@ -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<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>
index 1392be7a01cc5411b6f907387d62eeb68bcda8ec..7a42528c3d0d8d9b1e9f2c8669e87b92d0c28642 100644 (file)
@@ -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);
 }
index ac8ec2052dd9b3a3cefe5b35ed1df1ba0609f3ea..5dd9553dd674531d601c1b8c198600b9a6797ab3 100755 (executable)
@@ -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