]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
mon: test the crush ruleset when creating a pool
authorLoic Dachary <ldachary@redhat.com>
Thu, 16 Jul 2015 16:02:02 +0000 (18:02 +0200)
committerKen Dreyer <kdreyer@redhat.com>
Wed, 4 Nov 2015 21:42:39 +0000 (14:42 -0700)
We want to fix the following scenario:

 * an erasure code plugin (or another part of the code) creates a
   ruleset
 * the ruleset crashes during mapping (for whatever reason)
 * ceph osd pool create uses the bugous ruleset
 * the monitors try to do mapping a crash

Having a bugous ruleset in the crush map is very difficult prevent. The
catastrophic event of using it with a newly created pool can however be
prevented by calling the CrushTester just before creating the pool and
after all implicit or explicit crush ruleset creation happened.

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

Signed-off-by: Loic Dachary <ldachary@redhat.com>
(cherry picked from commit f1e86be589803596e86acc964ac5c5c03b4038d8)

Conflicts:
src/test/mon/osd-crush.sh
          removed the run_mon because in hammer it is shared
          between all tests
        src/mon/OSDMonitor.cc
          prepare_new_pool changed stringstream to *ostream

(cherry picked from commit f47ba4b1a1029a55f8bc4ab393a7fa3712cd4e00)

src/mon/OSDMonitor.cc
src/test/mon/osd-crush.sh

index 730702e7ca83b544e4223fe5e41b0adbe6cc0c39..fe3a0851caadd25bb916fa27a1ebf968250a0a68 100644 (file)
@@ -3874,6 +3874,7 @@ int OSDMonitor::prepare_pool_crush_ruleset(const unsigned pool_type,
                                           int *crush_ruleset,
                                           stringstream &ss)
 {
+
   if (*crush_ruleset < 0) {
     switch (pool_type) {
     case pg_pool_t::TYPE_REPLICATED:
@@ -3985,6 +3986,14 @@ int OSDMonitor::prepare_new_pool(string& name, uint64_t auid,
                                 crush_ruleset_name, &crush_ruleset, ss);
   if (r)
     return r;
+  CrushWrapper newcrush;
+  _get_pending_crush(newcrush);
+  CrushTester tester(newcrush, ss);
+  r = tester.test_with_crushtool(g_conf->crushtool.c_str(),
+                                osdmap.get_max_osd(),
+                                g_conf->mon_lease);
+  if (r)
+    return r;
   unsigned size, min_size;
   r = prepare_pool_size(pool_type, erasure_code_profile, &size, &min_size, ss);
   if (r)
index 2242e9c957ce3bcee2416b64718b71565050d281..db607f106c82c39935009e2d8365b37558a81f1b 100755 (executable)
@@ -78,6 +78,9 @@ function TEST_crush_rule_rm() {
 
 function TEST_crush_rule_create_erasure() {
     local dir=$1
+    # should have at least one OSD
+    run_osd $dir 0 || return 1
+
     local ruleset=ruleset3
     #
     # create a new ruleset with the default profile, implicitly
@@ -108,6 +111,15 @@ function TEST_crush_rule_create_erasure() {
     ./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
+    #
+    # create a bugous ruleset and verify it cannot be used
+    # to create a pool.
+    #
+    ceph osd erasure-code-profile set myprofile plugin=lrc mapping=__DD__DD layers='[[ "_cDD_cDD", "" ],[ "cDDD____", "" ],[ "____cDDD", "" ],]' ruleset-steps='[ [ "choose", "datacenter", 3 ], [ "chooseleaf", "osd", 0] ]'
+    expect_failure $dir "Error EINVAL" \
+        ./ceph osd pool create mypool 1 1 erasure myprofile || return 1
+    ./ceph osd crush rule rm mypool || return 1
+    ./ceph osd erasure-code-profile rm myprofile || return 1
 }
 
 function check_ruleset_id_match_rule_id() {