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:
: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
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:
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
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
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: