]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
erasure-code: create default profile if necessary 2178/head
authorLoic Dachary <loic@dachary.org>
Wed, 18 Jun 2014 22:49:13 +0000 (00:49 +0200)
committerLoic Dachary <loic@dachary.org>
Thu, 31 Jul 2014 12:47:06 +0000 (18:32 +0545)
After an upgrade to firefly, the existing Ceph clusters do not have the
default erasure code profile. Although it may be created with

   ceph osd erasure-code-profile set default

it was not included in the release notes and is confusing for the
administrator.

The *osd pool create* and *osd crush rule create-erasure* commands are
modified to implicitly create the default erasure code profile if it is
not found.

In order to avoid code duplication, the default erasure code profile
code creation that happens when a new firefly ceph cluster is created is
encapsulated in the OSDMap::get_erasure_code_profile_default method.

Conversely, handling the pending change in OSDMonitor is not
encapsulated in a function but duplicated instead. If it was a function
the caller would need a switch to distinguish between the case when goto
wait is needed, or goto reply or proceed because nothing needs to be
done. It is unclear if having a function would lead to smaller or more
maintainable code.

http://tracker.ceph.com/issues/8601 Fixes: #8601

Backport: firefly
Signed-off-by: Loic Dachary <loic@dachary.org>
(cherry picked from commit 4e1405e7720eda71a872c991045ac8ead6f3e7d8)

src/mon/OSDMonitor.cc
src/osd/OSDMap.cc
src/osd/OSDMap.h
src/test/mon/osd-crush.sh
src/test/mon/osd-pool-create.sh

index eab5122cc1f33acf4544d8f3667dd2a7a8d34e1f..b12dfa19043169c59869144cc0e7bca1c775b8b6 100644 (file)
@@ -4172,6 +4172,24 @@ bool OSDMonitor::prepare_command_impl(MMonCommand *m,
     cmd_getval(g_ceph_context, cmdmap, "profile", profile);
     if (profile == "")
       profile = "default";
+    if (profile == "default") {
+      if (!osdmap.has_erasure_code_profile(profile)) {
+       if (pending_inc.has_erasure_code_profile(profile)) {
+         dout(20) << "erasure code profile " << 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 " << profile << " set" << dendl;
+       pending_inc.set_erasure_code_profile(profile, profile_map);
+       goto wait;
+      }
+    }
 
     int ruleset;
     err = crush_ruleset_create_erasure(name, profile, &ruleset, ss);
@@ -4847,6 +4865,25 @@ done:
     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,
+                                                     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 (ruleset_name == "") {
       if (erasure_code_profile == "default") {
        ruleset_name = "erasure-code";
index 8c66c76760dd0b9e0056b94ef85899c659e3e4bb..886463ed3e74767991432a32d2c80cf53063658d 100644 (file)
@@ -2551,13 +2551,25 @@ int OSDMap::build_simple(CephContext *cct, epoch_t e, uuid_d &fsid,
     set_weight(i, CEPH_OSD_OUT);
   }
 
-  map<string,string> erasure_code_profile_map;
-  r = get_str_map(cct->_conf->osd_pool_default_erasure_code_profile,
-                 ss,
-                 &erasure_code_profile_map);
-  erasure_code_profile_map["directory"] =
+  map<string,string> profile_map;
+  r = get_erasure_code_profile_default(cct, profile_map, &ss);
+  if (r < 0) {
+    lderr(cct) << ss.str() << dendl;
+    return r;
+  }
+  set_erasure_code_profile("default", profile_map);
+  return 0;
+}
+
+int OSDMap::get_erasure_code_profile_default(CephContext *cct,
+                                            map<string,string> &profile_map,
+                                            ostream *ss)
+{
+  int r = get_str_map(cct->_conf->osd_pool_default_erasure_code_profile,
+                     *ss,
+                     &profile_map);
+  profile_map["directory"] =
     cct->_conf->osd_pool_default_erasure_code_directory;
-  set_erasure_code_profile("default", erasure_code_profile_map);
   return r;
 }
 
index 08064f8bb54f81d70bf2e76bdeb9ccbc8bb7f0b5..a34758369ed328a47d11a9d0c6f466ee08c197ad 100644 (file)
@@ -380,6 +380,9 @@ public:
       erasure_code_profiles.find(name);
     return i != erasure_code_profiles.end();
   }
+  int get_erasure_code_profile_default(CephContext *cct,
+                                      map<string,string> &profile_map,
+                                      ostream *ss);
   void set_erasure_code_profile(const string &name,
                                const map<string,string> &profile) {
     erasure_code_profiles[name] = profile;
index 5f32f8cdf5464742faee2d6a916a8f50a6ecbe08..ceb1efb1b82220a1495dcb1af2e27b9039be656e 100755 (executable)
@@ -90,6 +90,9 @@ function TEST_crush_rule_create_simple_exists() {
 function TEST_crush_rule_create_erasure() {
     local dir=$1
     local ruleset=ruleset3
+    #
+    # create a new ruleset with the default profile, implicitly
+    #
     ./ceph osd crush rule create-erasure $ruleset || return 1
     ./ceph osd crush rule create-erasure $ruleset 2>&1 | \
         grep "$ruleset already exists" || return 1
@@ -98,9 +101,24 @@ function TEST_crush_rule_create_erasure() {
         grep '<op>chooseleaf_indep</op><num>0</num><type>host</type>' || return 1
     ./ceph osd crush rule rm $ruleset || return 1
     ! ./ceph osd crush rule ls | grep $ruleset || return 1
+    #
+    # create a new ruleset with the default profile, explicitly
+    #
     ./ceph osd crush rule create-erasure $ruleset default || return 1
     ./ceph osd crush rule ls | grep $ruleset || return 1
     ./ceph osd crush rule rm $ruleset || return 1
+    ! ./ceph osd crush rule ls | grep $ruleset || return 1
+    #
+    # create a new ruleset and the default profile, implicitly
+    #
+    ./ceph osd erasure-code-profile rm default || return 1
+    ! ./ceph osd erasure-code-profile ls | grep default || return 1
+    ./ceph osd crush rule create-erasure $ruleset || return 1
+    CEPH_ARGS='' ./ceph --admin-daemon $dir/a/ceph-mon.a.asok log flush || return 1
+    grep 'profile default set' $dir/a/log || return 1
+    ./ceph osd erasure-code-profile ls | grep default || return 1
+    ./ceph osd crush rule rm $ruleset || return 1
+    ! ./ceph osd crush rule ls | grep $ruleset || return 1
 }
 
 function TEST_crush_rule_create_erasure_exists() {
@@ -114,6 +132,21 @@ function TEST_crush_rule_create_erasure_exists() {
     ./ceph osd crush rule rm $ruleset || return 1
 }
 
+function TEST_crush_rule_create_erasure_profile_default_exists() {
+    local dir=$1
+    local ruleset=ruleset6
+    ./ceph osd erasure-code-profile rm default || return 1
+    ! ./ceph osd erasure-code-profile ls | grep default || return 1
+    # add to the pending OSD map without triggering a paxos proposal
+    result=$(echo '{"prefix":"osdmonitor_prepare_command","prepare":"osd erasure-code-profile set","name":"default"}' | nc -U $dir/a/ceph-mon.a.asok | cut --bytes=5-)
+    test $result = true || return 1
+    ./ceph osd crush rule create-erasure $ruleset || return 1
+    CEPH_ARGS='' ./ceph --admin-daemon $dir/a/ceph-mon.a.asok log flush || return 1
+    grep 'profile default already pending' $dir/a/log || return 1
+    ./ceph osd crush rule rm $ruleset || return 1
+    ./ceph osd erasure-code-profile ls | grep default || return 1
+}
+
 main osd-crush
 
 # Local Variables:
index 97bde0946db1934b11ea3c43aba8fea98f4cdaef..b8fa67c2d60145faa7df726ce808da1c7c6b12cc 100755 (executable)
@@ -109,6 +109,28 @@ function TEST_erasure_crush_rule_pending() {
     grep "$crush_ruleset 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
+    ./ceph osd erasure-code-profile rm default || return 1
+    ! ./ceph osd erasure-code-profile ls | grep default || return 1
+    ./ceph osd pool create $poolname 12 12 erasure default
+    ./ceph osd erasure-code-profile ls | grep default || return 1
+}
+
+function TEST_erasure_code_profile_default_pending() {
+    local dir=$1
+    run_mon $dir a --public-addr 127.0.0.1
+    ./ceph osd erasure-code-profile rm default || return 1
+    ! ./ceph osd erasure-code-profile ls | grep default || return 1
+    # add to the pending OSD map without triggering a paxos proposal
+    result=$(echo '{"prefix":"osdmonitor_prepare_command","prepare":"osd erasure-code-profile set","name":"default"}' | nc -U $dir/a/ceph-mon.a.asok | cut --bytes=5-)
+    test $result = true || return 1
+    ./ceph osd pool create pool_erasure 12 12 erasure default || return 1
+    CEPH_ARGS='' ./ceph --admin-daemon $dir/a/ceph-mon.a.asok log flush || return 1
+    grep 'profile default already pending' $dir/a/log || return 1
+}
+
 function TEST_erasure_crush_stripe_width() {
     local dir=$1
     # the default stripe width is used to initialize the pool