]> git.proxmox.com Git - ceph.git/blob - ceph/qa/standalone/scrub/osd-scrub-snaps.sh
update sources to v12.2.0
[ceph.git] / ceph / qa / standalone / scrub / osd-scrub-snaps.sh
1 #! /bin/bash
2 #
3 # Copyright (C) 2015 Red Hat <contact@redhat.com>
4 #
5 # Author: David Zafman <dzafman@redhat.com>
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU Library Public License as published by
9 # the Free Software Foundation; either version 2, or (at your option)
10 # any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Library Public License for more details.
16 #
17 source $CEPH_ROOT/qa/standalone/ceph-helpers.sh
18
19 function run() {
20 local dir=$1
21 shift
22
23 export CEPH_MON="127.0.0.1:7121" # git grep '\<7121\>' : there must be only one
24 export CEPH_ARGS
25 CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none "
26 CEPH_ARGS+="--mon-host=$CEPH_MON "
27
28 local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')}
29 for func in $funcs ; do
30 $func $dir || return 1
31 done
32 }
33
34 function TEST_scrub_snaps() {
35 local dir=$1
36 local poolname=test
37
38 TESTDATA="testdata.$$"
39
40 setup $dir || return 1
41 run_mon $dir a --osd_pool_default_size=1 || return 1
42 run_mgr $dir x || return 1
43 run_osd $dir 0 || return 1
44
45 create_rbd_pool || return 1
46 wait_for_clean || return 1
47
48 # Create a pool with a single pg
49 create_pool $poolname 1 1
50 wait_for_clean || return 1
51 poolid=$(ceph osd dump | grep "^pool.*[']test[']" | awk '{ print $2 }')
52
53 dd if=/dev/urandom of=$TESTDATA bs=1032 count=1
54 for i in `seq 1 15`
55 do
56 rados -p $poolname put obj${i} $TESTDATA
57 done
58
59 SNAP=1
60 rados -p $poolname mksnap snap${SNAP}
61 dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
62 rados -p $poolname put obj1 $TESTDATA
63 rados -p $poolname put obj5 $TESTDATA
64 rados -p $poolname put obj3 $TESTDATA
65 for i in `seq 6 14`
66 do rados -p $poolname put obj${i} $TESTDATA
67 done
68
69 SNAP=2
70 rados -p $poolname mksnap snap${SNAP}
71 dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
72 rados -p $poolname put obj5 $TESTDATA
73
74 SNAP=3
75 rados -p $poolname mksnap snap${SNAP}
76 dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
77 rados -p $poolname put obj3 $TESTDATA
78
79 SNAP=4
80 rados -p $poolname mksnap snap${SNAP}
81 dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
82 rados -p $poolname put obj5 $TESTDATA
83 rados -p $poolname put obj2 $TESTDATA
84
85 SNAP=5
86 rados -p $poolname mksnap snap${SNAP}
87 SNAP=6
88 rados -p $poolname mksnap snap${SNAP}
89 dd if=/dev/urandom of=$TESTDATA bs=256 count=${SNAP}
90 rados -p $poolname put obj5 $TESTDATA
91
92 SNAP=7
93 rados -p $poolname mksnap snap${SNAP}
94
95 rados -p $poolname rm obj4
96 rados -p $poolname rm obj2
97
98 kill_daemons $dir TERM osd || return 1
99
100 # Don't need to ceph_objectstore_tool function because osd stopped
101
102 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj1)"
103 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" --force remove
104
105 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj5 | grep \"snapid\":2)"
106 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" remove
107
108 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj5 | grep \"snapid\":1)"
109 OBJ5SAVE="$JSON"
110 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" remove
111
112 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj5 | grep \"snapid\":4)"
113 dd if=/dev/urandom of=$TESTDATA bs=256 count=18
114 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-bytes $TESTDATA
115
116 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj3)"
117 dd if=/dev/urandom of=$TESTDATA bs=256 count=15
118 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-bytes $TESTDATA
119
120 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --op list obj4 | grep \"snapid\":7)"
121 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" remove
122
123 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj2)"
124 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" rm-attr snapset
125
126 # Create a clone which isn't in snapset and doesn't have object info
127 JSON="$(echo "$OBJ5SAVE" | sed s/snapid\":1/snapid\":7/)"
128 dd if=/dev/urandom of=$TESTDATA bs=256 count=7
129 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-bytes $TESTDATA
130
131 rm -f $TESTDATA
132
133 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj6)"
134 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset
135 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj7)"
136 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset corrupt
137 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj8)"
138 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset seq
139 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj9)"
140 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset clone_size
141 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj10)"
142 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset clone_overlap
143 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj11)"
144 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset clones
145 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj12)"
146 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset head
147 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj13)"
148 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset snaps
149 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj14)"
150 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" clear-snapset size
151
152 echo "garbage" > $dir/bad
153 JSON="$(ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal --head --op list obj15)"
154 ceph-objectstore-tool --data-path $dir/0 --journal-path $dir/0/journal "$JSON" set-attr snapset $dir/bad
155 rm -f $dir/bad
156
157 run_osd $dir 0 || return 1
158 create_rbd_pool || return 1
159 wait_for_clean || return 1
160
161 local pgid="${poolid}.0"
162 if ! pg_scrub "$pgid" ; then
163 cat $dir/osd.0.log
164 return 1
165 fi
166 grep 'log_channel' $dir/osd.0.log
167
168 rados list-inconsistent-pg $poolname > $dir/json || return 1
169 # Check pg count
170 test $(jq '. | length' $dir/json) = "1" || return 1
171 # Check pgid
172 test $(jq -r '.[0]' $dir/json) = $pgid || return 1
173
174 rados list-inconsistent-snapset $pgid > $dir/json || return 1
175 test $(jq '.inconsistents | length' $dir/json) = "21" || return 1
176
177 local jqfilter='.inconsistents'
178 local sortkeys='import json; import sys ; JSON=sys.stdin.read() ; ud = json.loads(JSON) ; print json.dumps(ud, sort_keys=True, indent=2)'
179
180 jq "$jqfilter" << EOF | python -c "$sortkeys" > $dir/checkcsjson
181 {
182 "inconsistents": [
183 {
184 "errors": [
185 "headless"
186 ],
187 "snap": 1,
188 "locator": "",
189 "nspace": "",
190 "name": "obj1"
191 },
192 {
193 "errors": [
194 "size_mismatch"
195 ],
196 "snap": 1,
197 "locator": "",
198 "nspace": "",
199 "name": "obj10"
200 },
201 {
202 "errors": [
203 "headless"
204 ],
205 "snap": 1,
206 "locator": "",
207 "nspace": "",
208 "name": "obj11"
209 },
210 {
211 "errors": [
212 "size_mismatch"
213 ],
214 "snap": 1,
215 "locator": "",
216 "nspace": "",
217 "name": "obj14"
218 },
219 {
220 "errors": [
221 "headless"
222 ],
223 "snap": 1,
224 "locator": "",
225 "nspace": "",
226 "name": "obj6"
227 },
228 {
229 "errors": [
230 "headless"
231 ],
232 "snap": 1,
233 "locator": "",
234 "nspace": "",
235 "name": "obj7"
236 },
237 {
238 "errors": [
239 "size_mismatch"
240 ],
241 "snap": 1,
242 "locator": "",
243 "nspace": "",
244 "name": "obj9"
245 },
246 {
247 "errors": [
248 "headless"
249 ],
250 "snap": 4,
251 "locator": "",
252 "nspace": "",
253 "name": "obj2"
254 },
255 {
256 "errors": [
257 "size_mismatch"
258 ],
259 "snap": 4,
260 "locator": "",
261 "nspace": "",
262 "name": "obj5"
263 },
264 {
265 "errors": [
266 "headless"
267 ],
268 "snap": 7,
269 "locator": "",
270 "nspace": "",
271 "name": "obj2"
272 },
273 {
274 "errors": [
275 "oi_attr_missing",
276 "headless"
277 ],
278 "snap": 7,
279 "locator": "",
280 "nspace": "",
281 "name": "obj5"
282 },
283 {
284 "extra clones": [
285 1
286 ],
287 "errors": [
288 "extra_clones"
289 ],
290 "snap": "head",
291 "locator": "",
292 "nspace": "",
293 "name": "obj11"
294 },
295 {
296 "errors": [
297 "head_mismatch"
298 ],
299 "snap": "head",
300 "locator": "",
301 "nspace": "",
302 "name": "obj12"
303 },
304 {
305 "errors": [
306 "ss_attr_corrupted"
307 ],
308 "snap": "head",
309 "locator": "",
310 "nspace": "",
311 "name": "obj15"
312 },
313 {
314 "extra clones": [
315 7,
316 4
317 ],
318 "errors": [
319 "ss_attr_missing",
320 "extra_clones"
321 ],
322 "snap": "head",
323 "locator": "",
324 "nspace": "",
325 "name": "obj2"
326 },
327 {
328 "errors": [
329 "size_mismatch"
330 ],
331 "snap": "head",
332 "locator": "",
333 "nspace": "",
334 "name": "obj3"
335 },
336 {
337 "missing": [
338 7
339 ],
340 "errors": [
341 "clone_missing"
342 ],
343 "snap": "head",
344 "locator": "",
345 "nspace": "",
346 "name": "obj4"
347 },
348 {
349 "missing": [
350 2,
351 1
352 ],
353 "extra clones": [
354 7
355 ],
356 "errors": [
357 "extra_clones",
358 "clone_missing"
359 ],
360 "snap": "head",
361 "locator": "",
362 "nspace": "",
363 "name": "obj5"
364 },
365 {
366 "extra clones": [
367 1
368 ],
369 "errors": [
370 "extra_clones"
371 ],
372 "snap": "head",
373 "locator": "",
374 "nspace": "",
375 "name": "obj6"
376 },
377 {
378 "extra clones": [
379 1
380 ],
381 "errors": [
382 "head_mismatch",
383 "extra_clones"
384 ],
385 "snap": "head",
386 "locator": "",
387 "nspace": "",
388 "name": "obj7"
389 },
390 {
391 "errors": [
392 "snapset_mismatch"
393 ],
394 "snap": "head",
395 "locator": "",
396 "nspace": "",
397 "name": "obj8"
398 }
399 ],
400 "epoch": 20
401 }
402 EOF
403
404 jq "$jqfilter" $dir/json | python -c "$sortkeys" > $dir/csjson
405 diff ${DIFFCOLOPTS} $dir/checkcsjson $dir/csjson || return 1
406
407 if which jsonschema > /dev/null;
408 then
409 jsonschema -i $dir/json $CEPH_ROOT/doc/rados/command/list-inconsistent-snap.json || return 1
410 fi
411
412 for i in `seq 1 7`
413 do
414 rados -p $poolname rmsnap snap$i
415 done
416
417 ERRORS=0
418
419 pidfile=$(find $dir 2>/dev/null | grep $name_prefix'[^/]*\.pid')
420 pid=$(cat $pidfile)
421 if ! kill -0 $pid
422 then
423 echo "OSD crash occurred"
424 tail -100 $dir/osd.0.log
425 ERRORS=$(expr $ERRORS + 1)
426 fi
427
428 kill_daemons $dir || return 1
429
430 declare -a err_strings
431 err_strings[0]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj10:.* is missing in clone_overlap"
432 err_strings[1]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj5:7 no '_' attr"
433 err_strings[2]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj5:7 is an unexpected clone"
434 err_strings[3]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*::obj5:4 on disk size [(]4608[)] does not match object info size [(]512[)] adjusted for ondisk to [(]512[)]"
435 err_strings[4]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj5:head expected clone .*:::obj5:2"
436 err_strings[5]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj5:head expected clone .*:::obj5:1"
437 err_strings[6]="log_channel[(]cluster[)] log [[]INF[]] : scrub [0-9]*[.]0 .*:::obj5:head 2 missing clone[(]s[)]"
438 err_strings[7]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj12:head snapset.head_exists=false, but head exists"
439 err_strings[8]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj8:head snaps.seq not set"
440 err_strings[9]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj7:head snapset.head_exists=false, but head exists"
441 err_strings[10]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj7:1 is an unexpected clone"
442 err_strings[11]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj3:head on disk size [(]3840[)] does not match object info size [(]768[)] adjusted for ondisk to [(]768[)]"
443 err_strings[12]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj6:1 is an unexpected clone"
444 err_strings[13]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj2:head no 'snapset' attr"
445 err_strings[14]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj2:7 clone ignored due to missing snapset"
446 err_strings[15]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj2:4 clone ignored due to missing snapset"
447 err_strings[16]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj4:head expected clone .*:::obj4:7"
448 err_strings[17]="log_channel[(]cluster[)] log [[]INF[]] : scrub [0-9]*[.]0 .*:::obj4:head 1 missing clone[(]s[)]"
449 err_strings[18]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj1:1 is an unexpected clone"
450 err_strings[19]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj9:1 is missing in clone_size"
451 err_strings[20]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj11:1 is an unexpected clone"
452 err_strings[21]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj14:1 size 1032 != clone_size 1033"
453 err_strings[22]="log_channel[(]cluster[)] log [[]ERR[]] : [0-9]*[.]0 scrub 22 errors"
454 err_strings[23]="log_channel[(]cluster[)] log [[]ERR[]] : scrub [0-9]*[.]0 .*:::obj15:head can't decode 'snapset' attr buffer"
455
456 for err_string in "${err_strings[@]}"
457 do
458 if ! grep "$err_string" $dir/osd.0.log > /dev/null;
459 then
460 echo "Missing log message '$err_string'"
461 ERRORS=$(expr $ERRORS + 1)
462 fi
463 done
464
465 teardown $dir || return 1
466
467 if [ $ERRORS != "0" ];
468 then
469 echo "TEST FAILED WITH $ERRORS ERRORS"
470 return 1
471 fi
472
473 echo "TEST PASSED"
474 return 0
475 }
476
477 main osd-scrub-snaps "$@"
478
479 # Local Variables:
480 # compile-command: "cd ../.. ; make -j4 && \
481 # test/osd/osd-scrub-snaps.sh"