From: Xiaoxi Chen Date: Tue, 5 Aug 2014 08:12:22 +0000 (+0800) Subject: mon/OSDMonitor : Use user provided ruleset for replicated pool X-Git-Tag: v0.80.8~49 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=cf4e30095e8149d1df0f2c9b4c93c9df0779ec84;p=ceph.git mon/OSDMonitor : Use user provided ruleset for replicated pool 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 (cherry picked from commit bf9726a294abd32b429170284ac328a592802648) --- diff --git a/doc/rados/operations/pools.rst b/doc/rados/operations/pools.rst index 3f9757547050..07822c7db75d 100644 --- a/doc/rados/operations/pools.rst +++ b/doc/rados/operations/pools.rst @@ -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 diff --git a/src/mon/OSDMonitor.cc b/src/mon/OSDMonitor.cc index 7e469b2dfda8..560c8ecd3142 100644 --- a/src/mon/OSDMonitor.cc +++ b/src/mon/OSDMonitor.cc @@ -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 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 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 diff --git a/src/test/mon/osd-pool-create.sh b/src/test/mon/osd-pool-create.sh index b8fa67c2d601..0e4811b41d73 100755 --- a/src/test/mon/osd-pool-create.sh +++ b/src/test/mon/osd-pool-create.sh @@ -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: