]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon/OSDMonitor : Use user provided ruleset for replicated pool
authorXiaoxi Chen <xiaoxi.chen@intel.com>
Tue, 5 Aug 2014 08:12:22 +0000 (16:12 +0800)
committerSage Weil <sage@redhat.com>
Tue, 14 Oct 2014 18:17:14 +0000 (11:17 -0700)
When creating a replicated pool, currently ceph ignore the ruleset
name provided by user but use a global default ruleset.

This patch fix this bug, so the rulset specified by
ceph osd pool create replicated
can be properly set.

Signed-off-by: Xiaoxi Chen <xiaoxi.chen@intel.com>
(cherry picked from commit bf9726a294abd32b429170284ac328a592802648)

doc/rados/operations/pools.rst
src/mon/OSDMonitor.cc
src/test/mon/osd-pool-create.sh

index 3f9757547050c21350f5fa08c87f1fac5b97d9c3..07822c7db75da2e11671f5feed86991139b1a672 100644 (file)
@@ -61,9 +61,10 @@ For example::
 
 To create a pool, execute:: 
 
-       ceph osd pool create {pool-name} {pg-num} [{pgp-num}] [replicated]
+       ceph osd pool create {pool-name} {pg-num} [{pgp-num}] [replicated] \
+             [crush-ruleset-name]
        ceph osd pool create {pool-name} {pg-num}  {pgp-num}   erasure \
-             {erasure-code-profile}
+             [erasure-code-profile] [crush-ruleset-name]
 
 Where: 
 
@@ -107,7 +108,18 @@ Where:
 :Required: No. 
 :Default: replicated
 
-``{erasure-code-profile=profile}``
+``[crush-ruleset-name]``
+
+:Description: The name of the crush ruleset for this pool. If specified ruleset doesn't
+              exists, the creation of **replicated** pool will fail with -ENOENT. But
+              **replicated** pool will create a new erasure ruleset with specified name.
+
+:Type: String
+:Required: No.
+:Default: "erasure-code" for **erasure pool**. Pick up Ceph configuraion variable
+**osd_pool_default_crush_replicated_ruleset** for **replicated** pool.
+
+``[erasure-code-profile=profile]``
 
 :Description: For **erasure** pools only. Use the erasure code
               **profile**. It must be an existing profile as
index 7e469b2dfda87214d197e8927a40a81897a34e13..560c8ecd314237581a93704f759f3c297e8b4fd3 100644 (file)
@@ -3279,11 +3279,38 @@ int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type,
   if (*crush_ruleset < 0) {
     switch (pool_type) {
     case pg_pool_t::TYPE_REPLICATED:
-      *crush_ruleset = osdmap.crush->get_osd_pool_default_crush_replicated_ruleset(g_ceph_context);
-      if (*crush_ruleset < 0) {
-        // Errors may happen e.g. if no valid ruleset is available
-        ss << "No suitable CRUSH ruleset exists";
-        return *crush_ruleset;
+      {
+       if (ruleset_name == "") {
+         //Use default ruleset
+         *crush_ruleset = osdmap.crush->get_osd_pool_default_crush_replicated_ruleset(g_ceph_context);
+         if (*crush_ruleset < 0) {
+           // Errors may happen e.g. if no valid ruleset is available
+           ss << "No suitable CRUSH ruleset exists";
+           return *crush_ruleset;
+         }
+       } else {
+         int ret;
+         ret = osdmap.crush->get_rule_id(ruleset_name);
+         if (ret != -ENOENT) {
+           // found it, use it
+           *crush_ruleset = ret;
+         } else {
+           CrushWrapper newcrush;
+           _get_pending_crush(newcrush);
+
+           ret = newcrush.get_rule_id(ruleset_name);
+           if (ret != -ENOENT) {
+             // found it, wait for it to be proposed
+             dout(20) << "prepare_pool_crush_ruleset: ruleset "
+                  << ruleset_name << " is pending, try again" << dendl;
+             return -EAGAIN;
+           } else {
+             //Cannot find it , return error
+             ss << "Specified ruleset " << ruleset_name << " doesn't exist";
+             return ret;
+           }
+         }
+       }
       }
       break;
     case pg_pool_t::TYPE_ERASURE:
@@ -5004,35 +5031,41 @@ done:
     cmd_getval(g_ceph_context, cmdmap, "ruleset", ruleset_name);
     string erasure_code_profile;
     cmd_getval(g_ceph_context, cmdmap, "erasure_code_profile", erasure_code_profile);
-    if (erasure_code_profile == "")
-      erasure_code_profile = "default";
-    if (erasure_code_profile == "default") {
-      if (!osdmap.has_erasure_code_profile(erasure_code_profile)) {
-       if (pending_inc.has_erasure_code_profile(erasure_code_profile)) {
-         dout(20) << "erasure code profile " << erasure_code_profile << " already pending" << dendl;
-         goto wait;
-       }
 
-       map<string,string> profile_map;
-       err = osdmap.get_erasure_code_profile_default(g_ceph_context,
+    if (pool_type == pg_pool_t::TYPE_ERASURE) {
+      if (erasure_code_profile == "")
+       erasure_code_profile = "default";
+      //handle the erasure code profile
+      if (erasure_code_profile == "default") {
+       if (!osdmap.has_erasure_code_profile(erasure_code_profile)) {
+         if (pending_inc.has_erasure_code_profile(erasure_code_profile)) {
+           dout(20) << "erasure code profile " << erasure_code_profile << " already pending" << dendl;
+           goto wait;
+         }
+
+         map<string,string> profile_map;
+         err = osdmap.get_erasure_code_profile_default(g_ceph_context,
                                                      profile_map,
                                                      &ss);
-       if (err)
-         goto reply;
-       dout(20) << "erasure code profile " << erasure_code_profile << " set" << dendl;
-       pending_inc.set_erasure_code_profile(erasure_code_profile, profile_map);
-       goto wait;
+         if (err)
+           goto reply;
+         dout(20) << "erasure code profile " << erasure_code_profile << " set" << dendl;
+         pending_inc.set_erasure_code_profile(erasure_code_profile, profile_map);
+         goto wait;
+       }
       }
-    }
-
-    if (ruleset_name == "") {
-      if (erasure_code_profile == "default") {
-       ruleset_name = "erasure-code";
-      } else {
-       dout(1) << "implicitly use ruleset named after the pool: "
+      if (ruleset_name == "") {
+       if (erasure_code_profile == "default") {
+         ruleset_name = "erasure-code";
+       } else {
+         dout(1) << "implicitly use ruleset named after the pool: "
                << poolstr << dendl;
-       ruleset_name = poolstr;
+         ruleset_name = poolstr;
+       }
       }
+    } else {
+      //NOTE:for replicated pool,cmd_map will put ruleset_name to erasure_code_profile field
+      ruleset_name = erasure_code_profile;
     }
 
     err = prepare_new_pool(poolstr, 0, // auid=0 for admin created pool
index b8fa67c2d60145faa7df726ce808da1c7c6b12cc..0e4811b41d732445dceb7229e2a45fc75fc6a77d 100755 (executable)
@@ -109,6 +109,20 @@ function TEST_erasure_crush_rule_pending() {
     grep "$crush_ruleset try again" $dir/a/log || return 1
 }
 
+function TEST_simple_crush_rule_pending() {
+    local dir=$1
+    run_mon $dir a --public-addr 127.0.0.1
+    # try again if the ruleset creation is pending
+    crush_ruleset=simple_ruleset
+    ./ceph osd crush add-bucket host1 host
+    # add to the pending OSD map without triggering a paxos proposal
+    result=$(echo '{"prefix":"osdmonitor_prepare_command","prepare":"osd crush rule create-simple","name":"'$crush_ruleset'","root":"host1","type":"host"}' | nc -U $dir/a/ceph-mon.a.asok | cut --bytes=5-)
+    test $result = true || return 1
+    ./ceph osd pool create pool_simple 12 12 replicated $crush_ruleset || return 1
+    CEPH_ARGS='' ./ceph --admin-daemon $dir/a/ceph-mon.a.asok log flush || return 1
+    grep "$crush_ruleset is pending, try again" $dir/a/log || return 1
+}
+
 function TEST_erasure_code_profile_default() {
     local dir=$1
     run_mon $dir a --public-addr 127.0.0.1
@@ -177,18 +191,44 @@ function TEST_erasure_code_pool() {
         grep 'cannot change to type replicated' || return 1
 }
 
+function TEST_replicated_pool_with_ruleset() {
+    local dir=$1
+    run_mon $dir a --public-addr 127.0.0.1
+    local ruleset=ruleset0
+    local root=host1
+    ./ceph osd crush add-bucket $root host
+    local failure_domain=osd
+    local poolname=mypool
+    ./ceph osd crush rule create-simple $ruleset $root $failure_domain || return 1
+    ./ceph osd crush rule ls | grep $ruleset
+    ./ceph osd pool create $poolname 12 12 replicated $ruleset 2>&1 | \
+        grep "pool 'mypool' created" || return 1
+    rule_id=`./ceph osd crush rule dump $ruleset | grep "rule_id" | awk -F[' ':,] '{print $4}'`
+    ./ceph osd pool get $poolname crush_ruleset  2>&1 | \
+        grep "crush_ruleset: $rule_id" || return 1
+    #non-existent crush ruleset
+    ./ceph osd pool create newpool 12 12 replicated non-existent 2>&1 | \
+        grep "doesn't exist" || return 1
+}
+
 function TEST_replicated_pool() {
     local dir=$1
     run_mon $dir a --public-addr 127.0.0.1
-    ./ceph osd pool create replicated 12 12 replicated
+    ./ceph osd pool create replicated 12 12 replicated 2>&1 | \
+        grep "pool 'replicated' created" || return 1
     ./ceph osd pool create replicated 12 12 replicated 2>&1 | \
         grep 'already exists' || return 1
-    ./ceph osd pool create replicated 12 12 # default is replicated
-    ./ceph osd pool create replicated 12    # default is replicated, pgp_num = pg_num
+    # default is replicated
+    ./ceph osd pool create replicated1 12 12 2>&1 | \
+        grep "pool 'replicated1' created" || return 1
+    # default is replicated, pgp_num = pg_num
+    ./ceph osd pool create replicated2 12 2>&1 | \
+        grep "pool 'replicated2' created" || return 1
     ./ceph osd pool create replicated 12 12 erasure 2>&1 | \
         grep 'cannot change to type erasure' || return 1
 }
 
+
 main osd-pool-create
 
 # Local Variables: