From: xie xingguo Date: Thu, 17 Aug 2017 02:34:26 +0000 (+0800) Subject: crush, mon: "ceph osd crush rule ls-by-class" support X-Git-Tag: v12.2.0~11^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5687932aa629bfd9ef06f7914d53c44c6129670e;p=ceph.git crush, mon: "ceph osd crush rule ls-by-class" support This command returns all crush rules that are currently referencing the device class specified by user. Signed-off-by: xie xingguo (cherry picked from commit 7c67f95201316a240c7cdf1d8619b7642ff8fc33) --- diff --git a/qa/workunits/mon/crush_ops.sh b/qa/workunits/mon/crush_ops.sh index 41e7d10882f5..44bc70f4e923 100755 --- a/qa/workunits/mon/crush_ops.sh +++ b/qa/workunits/mon/crush_ops.sh @@ -26,6 +26,10 @@ ceph osd crush set-device-class ssd osd.0 ceph osd crush set-device-class hdd osd.1 ceph osd crush rule create-replicated foo-ssd default host ssd ceph osd crush rule create-replicated foo-hdd default host hdd +ceph osd crush rule ls-by-class ssd | grep 'foo-ssd' +ceph osd crush rule ls-by-class ssd | expect_false grep 'foo-hdd' +ceph osd crush rule ls-by-class hdd | grep 'foo-hdd' +ceph osd crush rule ls-by-class hdd | expect_false grep 'foo-ssd' ceph osd erasure-code-profile set ec-foo-ssd crush-device-class=ssd m=2 k=2 ceph osd pool create ec-foo 2 erasure ec-foo-ssd diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc index 1c72454b6473..bf6f3cf5ab8d 100644 --- a/src/crush/CrushWrapper.cc +++ b/src/crush/CrushWrapper.cc @@ -2023,6 +2023,37 @@ int CrushWrapper::device_class_clone( return 0; } +int CrushWrapper::get_rules_by_class(const string &class_name, set *rules) +{ + assert(rules); + rules->clear(); + if (!class_exists(class_name)) { + return -ENOENT; + } + int class_id = get_class_id(class_name); + for (unsigned i = 0; i < crush->max_rules; ++i) { + crush_rule *r = crush->rules[i]; + if (!r) + continue; + for (unsigned j = 0; j < r->len; ++j) { + if (r->steps[j].op == CRUSH_RULE_TAKE) { + int step_item = r->steps[j].arg1; + int original_item; + int c; + int res = split_id_class(step_item, &original_item, &c); + if (res < 0) { + return res; + } + if (c != -1 && c == class_id) { + rules->insert(i); + break; + } + } + } + } + return 0; +} + bool CrushWrapper::_class_is_dead(int class_id) { for (auto &p: class_map) { diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h index 5271e1441123..3737d5730023 100644 --- a/src/crush/CrushWrapper.h +++ b/src/crush/CrushWrapper.h @@ -1220,6 +1220,7 @@ public: int rename_class(const string& srcname, const string& dstname); int populate_classes( const std::map>& old_class_bucket); + int get_rules_by_class(const string &class_name, set *rules); bool _class_is_dead(int class_id); void cleanup_dead_classes(); int rebuild_roots_with_classes(); diff --git a/src/mon/MonCommands.h b/src/mon/MonCommands.h index 5756f967769a..e463986bc870 100644 --- a/src/mon/MonCommands.h +++ b/src/mon/MonCommands.h @@ -509,6 +509,10 @@ COMMAND("osd lspools " \ COMMAND_WITH_FLAG("osd crush rule list", "list crush rules", "osd", "r", "cli,rest", FLAG(DEPRECATED)) COMMAND("osd crush rule ls", "list crush rules", "osd", "r", "cli,rest") +COMMAND("osd crush rule ls-by-class " \ + "name=class,type=CephString,goodchars=[A-Za-z0-9-_.],req=false", \ + "list all crush rules that reference the same ", \ + "osd", "r", "cli,rest") COMMAND("osd crush rule dump " \ "name=name,type=CephString,goodchars=[A-Za-z0-9-_.],req=false", \ "dump crush rule (default all)", \ diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index b97e3dc00962..995c0a561d94 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -4930,6 +4930,34 @@ bool OSDMonitor::preprocess_command(MonOpRequestRef op) osdmap.crush->list_rules(&ss); rdata.append(ss.str()); } + } else if (prefix == "osd crush rule ls-by-class") { + string class_name; + cmd_getval(g_ceph_context, cmdmap, "class", class_name); + if (class_name.empty()) { + ss << "no class specified"; + r = -EINVAL; + goto reply; + } + set rules; + r = osdmap.crush->get_rules_by_class(class_name, &rules); + if (r < 0) { + ss << "failed to get rules by class '" << class_name << "'"; + goto reply; + } + if (f) { + f->open_array_section("rules"); + for (auto &rule: rules) { + f->dump_string("name", osdmap.crush->get_rule_name(rule)); + } + f->close_section(); + f->flush(rdata); + } else { + ostringstream rs; + for (auto &rule: rules) { + rs << osdmap.crush->get_rule_name(rule) << "\n"; + } + rdata.append(rs.str()); + } } else if (prefix == "osd crush rule dump") { string name; cmd_getval(g_ceph_context, cmdmap, "name", name);