// This should be used as a general guideline for most commands handled
// in this function. Adapt as you see fit, but please bear in mind that
// this is the expected behavior.
-
-
+
+
if (prefix == "osd setcrushmap" ||
(prefix == "osd crush set" && !osdid_present)) {
dout(10) << "prepare_command setting new crush map" << dendl;
err = -EINVAL;
goto reply;
}
+
+ if (prefix == "osd setcrushmap") {
+ const map<int64_t,pg_pool_t> &osdmap_pools = osdmap.get_pools();
+ map<int64_t,pg_pool_t>::const_iterator pit;
+ for (pit = osdmap_pools.begin(); pit != osdmap_pools.end(); ++pit) {
+ const int64_t pool_id = pit->first;
+ const pg_pool_t &pool = pit->second;
+ int ruleno = pool.get_crush_ruleset();
+ if (!crush.rule_exists(ruleno)) {
+ ss << " the crush rule no "<< ruleno << " for pool id " << pool_id << " is in use";
+ err = -EINVAL;
+ goto reply;
+ }
+ }
+ }
// sanity check: test some inputs to make sure this map isn't totally broken
dout(10) << " testing map" << dendl;
local crushtool_path_old=`ceph-conf --show-config-value crushtool`
ceph tell mon.\* injectargs --crushtool "true"
+
+
+ #import empty crushmap should failture.because the default pool rbd use the rule
+ ceph osd setcrushmap -i $empty_map.map 2>&1|grep "Error EINVAL: the crush rule no"|| return 1
+ #remove the default pool rbd
+ ceph osd pool delete rbd rbd --yes-i-really-really-mean-it || return 1
+
+ #now it can be successful to set the empty crush map
ceph osd setcrushmap -i $empty_map.map || return 1
+
# should be an empty crush map without any buckets
! test $(ceph osd crush dump --format=xml | \
$XMLSTARLET sel -t -m "//buckets/bucket" -v .) || return 1