summaryrefslogtreecommitdiffstats
path: root/src/ceph/qa/standalone/mon/osd-crush.sh
blob: 747e30db5ae0cff59795d293b1dca31c8a304c67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
#!/bin/bash
#
# Copyright (C) 2014 Cloudwatt <libre.licensing@cloudwatt.com>
# Copyright (C) 2014, 2015 Red Hat <contact@redhat.com>
#
# Author: Loic Dachary <loic@dachary.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Library Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library Public License for more details.
#
source $CEPH_ROOT/qa/standalone/ceph-helpers.sh

function run() {
    local dir=$1
    shift

    export CEPH_MON="127.0.0.1:7104" # git grep '\<7104\>' : there must be only one
    export CEPH_ARGS
    CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
    CEPH_ARGS+="--mon-host=$CEPH_MON "

    local funcs=${@:-$(set | ${SED} -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
    for func in $funcs ; do
        setup $dir || return 1
        $func $dir || return 1
        teardown $dir || return 1
    done
}

function TEST_crush_rule_create_simple() {
    local dir=$1

    run_mon $dir a || return 1

    ceph --format xml osd crush rule dump replicated_rule | \
        egrep '<op>take</op><item>[^<]+</item><item_name>default</item_name>' | \
        grep '<op>choose_firstn</op><num>0</num><type>osd</type>' || return 1
    local ruleset=ruleset0
    local root=host1
    ceph osd crush add-bucket $root host
    local failure_domain=osd
    ceph osd crush rule create-simple $ruleset $root $failure_domain || return 1
    ceph osd crush rule create-simple $ruleset $root $failure_domain 2>&1 | \
        grep "$ruleset already exists" || return 1
    ceph --format xml osd crush rule dump $ruleset | \
        egrep '<op>take</op><item>[^<]+</item><item_name>'$root'</item_name>' | \
        grep '<op>choose_firstn</op><num>0</num><type>'$failure_domain'</type>' || return 1
    ceph osd crush rule rm $ruleset || return 1
}

function TEST_crush_rule_dump() {
    local dir=$1

    run_mon $dir a || return 1

    local ruleset=ruleset1
    ceph osd crush rule create-erasure $ruleset || return 1
    test $(ceph --format json osd crush rule dump $ruleset | \
           jq ".rule_name == \"$ruleset\"") == true || return 1
    test $(ceph --format json osd crush rule dump | \
           jq "map(select(.rule_name == \"$ruleset\")) | length == 1") == true || return 1
    ! ceph osd crush rule dump non_existent_ruleset || return 1
    ceph osd crush rule rm $ruleset || return 1
}

function TEST_crush_rule_rm() {
    local ruleset=erasure2

    run_mon $dir a || return 1

    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
}

function TEST_crush_rule_create_erasure() {
    local dir=$1

    run_mon $dir a || return 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
    #
    ceph osd crush rule create-erasure $ruleset || return 1
    ceph osd crush rule create-erasure $ruleset 2>&1 | \
        grep "$ruleset already exists" || return 1
    ceph --format xml osd crush rule dump $ruleset | \
        egrep '<op>take</op><item>[^<]+</item><item_name>default</item_name>' | \
        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 $(get_asok_path mon.a) log flush || return 1
    grep 'profile set default' $dir/mon.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 check_ruleset_id_match_rule_id() {
    local rule_name=$1
    rule_id=`ceph osd crush rule dump $rule_name | grep "\"rule_id\":" | awk -F ":|," '{print int($2)}'`
    ruleset_id=`ceph osd crush rule dump $rule_name | grep "\"ruleset\":"| awk -F ":|," '{print int($2)}'`
    test $ruleset_id = $rule_id || return 1
}

function generate_manipulated_rules() {
    local dir=$1
    ceph osd crush add-bucket $root host
    ceph osd crush rule create-simple test_rule1 $root osd firstn || return 1
    ceph osd crush rule create-simple test_rule2 $root osd firstn || return 1
    ceph osd getcrushmap -o $dir/original_map
    crushtool -d $dir/original_map -o $dir/decoded_original_map
    #manipulate the rulesets , to make the rule_id != ruleset_id
    ${SED} -i 's/ruleset 0/ruleset 3/' $dir/decoded_original_map
    ${SED} -i 's/ruleset 2/ruleset 0/' $dir/decoded_original_map
    ${SED} -i 's/ruleset 1/ruleset 2/' $dir/decoded_original_map

    crushtool -c $dir/decoded_original_map -o $dir/new_map
    ceph osd setcrushmap -i $dir/new_map

    ceph osd crush rule dump
}

function TEST_crush_ruleset_match_rule_when_creating() {
    local dir=$1

    run_mon $dir a || return 1

    local root=host1

    generate_manipulated_rules $dir

    ceph osd crush rule create-simple special_rule_simple $root osd firstn || return 1

    ceph osd crush rule dump
    #show special_rule_simple has same rule_id and ruleset_id
    check_ruleset_id_match_rule_id special_rule_simple || return 1
}

function TEST_add_ruleset_failed() {
    local dir=$1

    run_mon $dir a || return 1

    local root=host1

    ceph osd crush add-bucket $root host
    ceph osd crush rule create-simple test_rule1 $root osd firstn || return 1
    ceph osd crush rule create-simple test_rule2 $root osd firstn || return 1
    ceph osd getcrushmap > $dir/crushmap || return 1
    crushtool --decompile $dir/crushmap > $dir/crushmap.txt || return 1
    for i in $(seq 3 255)
        do
            cat <<EOF
rule test_rule$i {
	ruleset $i
	type replicated
	min_size 1
	max_size 10
	step take $root
	step choose firstn 0 type osd
	step emit
}
EOF
    done >> $dir/crushmap.txt
    crushtool --compile $dir/crushmap.txt -o $dir/crushmap || return 1
    ceph osd setcrushmap -i $dir/crushmap  || return 1
    ceph osd crush rule create-simple test_rule_nospace $root osd firstn 2>&1 | grep "Error ENOSPC" || return 1

}

function TEST_crush_rename_bucket() {
    local dir=$1

    run_mon $dir a || return 1

    ceph osd crush add-bucket host1 host
    ceph osd tree
    ! ceph osd tree | grep host2 || return 1
    ceph osd crush rename-bucket host1 host2 || return 1
    ceph osd tree
    ceph osd tree | grep host2 || return 1
    ceph osd crush rename-bucket host1 host2 || return 1 # idempotency
    ceph osd crush rename-bucket nonexistent something 2>&1 | grep "Error ENOENT" || return 1
}

function TEST_crush_reject_empty() {
    local dir=$1
    run_mon $dir a || return 1
    # should have at least one OSD
    run_osd $dir 0 || return 1
    create_rbd_pool || return 1

    local empty_map=$dir/empty_map
    :> $empty_map.txt
    crushtool -c $empty_map.txt -o $empty_map.map || return 1
    expect_failure $dir "Error EINVAL" \
        ceph osd setcrushmap -i $empty_map.map || return 1
}

main osd-crush "$@"

# Local Variables:
# compile-command: "cd ../.. ; make -j4 && test/mon/osd-crush.sh"
# End: