Merge pull request #18598 from dillaman/wip-21958
[ceph.git] / qa / workunits / cephtool / test.sh
1 #!/bin/bash -x
2
3 set -e
4 set -o functrace
5 PS4=' ${FUNCNAME[0]}: $LINENO: '
6 SUDO=${SUDO:-sudo}
7
8 function check_no_osd_down()
9 {
10     ! ceph osd dump | grep ' down '
11 }
12
13 function wait_no_osd_down()
14 {
15   for i in $(seq 1 300) ; do
16     if ! check_no_osd_down ; then
17       echo "waiting for osd(s) to come back up"
18       sleep 1
19     else
20       break
21     fi
22   done
23   check_no_osd_down
24 }
25
26 function get_pg()
27 {
28         local pool obj map_output pg
29         pool=$1
30         obj=$2
31         declare -a map_output
32         map_output=($(ceph osd map $1 $2))
33         for (( i=0; i<${#map_output[*]}; i++ )) ; do
34                 if [ "${map_output[$i]}" == "pg" ] ; then
35                         pg=${map_output[((i+2))]}
36                         break
37                 fi
38         done
39         pg=$(echo $pg | sed 's/[()]//g')
40         echo $pg
41 }
42
43 function expect_false()
44 {
45         set -x
46         if "$@"; then return 1; else return 0; fi
47 }
48
49 TMPDIR=/tmp/cephtool$$
50 mkdir $TMPDIR
51 trap "rm -fr $TMPDIR" 0
52
53 TMPFILE=$TMPDIR/test_invalid.$$
54
55 #
56 # retry_eagain max cmd args ...
57 #
58 # retry cmd args ... if it exits on error and its output contains the
59 # string EAGAIN, at most $max times
60 #
61 function retry_eagain()
62 {
63     local max=$1
64     shift
65     local status
66     local tmpfile=$TMPDIR/retry_eagain.$$
67     local count
68     for count in $(seq 1 $max) ; do
69         status=0
70         "$@" > $tmpfile 2>&1 || status=$?
71         if test $status = 0 || 
72             ! grep --quiet EAGAIN $tmpfile ; then
73             break
74         fi
75         sleep 1
76     done
77     if test $count = $max ; then
78         echo retried with non zero exit status, $max times: "$@" >&2
79     fi
80     cat $tmpfile
81     rm $tmpfile
82     return $status
83 }
84
85 #
86 # map_enxio_to_eagain cmd arg ...
87 #
88 # add EAGAIN to the output of cmd arg ... if the output contains
89 # ENXIO.
90 #
91 function map_enxio_to_eagain()
92 {
93     local status=0
94     local tmpfile=$TMPDIR/map_enxio_to_eagain.$$
95
96     "$@" > $tmpfile 2>&1 || status=$?
97     if test $status != 0 &&
98         grep --quiet ENXIO $tmpfile ; then
99         echo "EAGAIN added by $0::map_enxio_to_eagain" >> $tmpfile
100     fi
101     cat $tmpfile
102     rm $tmpfile
103     return $status
104 }
105
106 function check_response()
107 {
108         expected_string=$1
109         retcode=$2
110         expected_retcode=$3
111         if [ "$expected_retcode" -a $retcode != $expected_retcode ] ; then
112                 echo "return code invalid: got $retcode, expected $expected_retcode" >&2
113                 exit 1
114         fi
115
116         if ! grep --quiet -- "$expected_string" $TMPFILE ; then 
117                 echo "Didn't find $expected_string in output" >&2
118                 cat $TMPFILE >&2
119                 exit 1
120         fi
121 }
122
123 function get_config_value_or_die()
124 {
125   local target config_opt raw val
126
127   target=$1
128   config_opt=$2
129
130   raw="`$SUDO ceph daemon $target config get $config_opt 2>/dev/null`"
131   if [[ $? -ne 0 ]]; then
132     echo "error obtaining config opt '$config_opt' from '$target': $raw"
133     exit 1
134   fi
135
136   raw=`echo $raw | sed -e 's/[{} "]//g'`
137   val=`echo $raw | cut -f2 -d:`
138
139   echo "$val"
140   return 0
141 }
142
143 function expect_config_value()
144 {
145   local target config_opt expected_val val
146   target=$1
147   config_opt=$2
148   expected_val=$3
149
150   val=$(get_config_value_or_die $target $config_opt)
151
152   if [[ "$val" != "$expected_val" ]]; then
153     echo "expected '$expected_val', got '$val'"
154     exit 1
155   fi
156 }
157
158 function ceph_watch_start()
159 {
160     local whatch_opt=--watch
161
162     if [ -n "$1" ]; then
163         whatch_opt=--watch-$1
164     fi
165
166     CEPH_WATCH_FILE=${TMPDIR}/CEPH_WATCH_$$
167     ceph $whatch_opt > $CEPH_WATCH_FILE &
168     CEPH_WATCH_PID=$!
169 }
170
171 function ceph_watch_wait()
172 {
173     local regexp=$1
174     local timeout=30
175
176     if [ -n "$2" ]; then
177         timeout=$2
178     fi
179
180     for i in `seq ${timeout}`; do
181         sleep 1
182         grep -q "$regexp" $CEPH_WATCH_FILE && break
183     done
184
185     kill $CEPH_WATCH_PID
186
187     if ! grep "$regexp" $CEPH_WATCH_FILE; then
188         echo "pattern ${regexp} not found in watch file. Full watch file content:" >&2
189         cat $CEPH_WATCH_FILE >&2
190         return 1
191     fi
192 }
193
194 function test_mon_injectargs()
195 {
196   CEPH_ARGS='--mon_debug_dump_location the.dump' ceph tell osd.0 injectargs --no-osd_debug_op_order >& $TMPFILE || return 1
197   check_response "osd_debug_op_order = 'false'"
198   ! grep "the.dump" $TMPFILE || return 1
199   ceph tell osd.0 injectargs '--osd_debug_op_order --osd_failsafe_full_ratio .99' >& $TMPFILE || return 1
200   check_response "osd_debug_op_order = 'true' osd_failsafe_full_ratio = '0.99'"
201   ceph tell osd.0 injectargs --no-osd_debug_op_order >& $TMPFILE || return 1
202   check_response "osd_debug_op_order = 'false'"
203   ceph tell osd.0 injectargs -- --osd_debug_op_order >& $TMPFILE || return 1
204   check_response "osd_debug_op_order = 'true'"
205   ceph tell osd.0 injectargs -- '--osd_debug_op_order --osd_failsafe_full_ratio .98' >& $TMPFILE || return 1
206   check_response "osd_debug_op_order = 'true' osd_failsafe_full_ratio = '0.98'" 
207 }
208
209 function test_mon_injectargs_SI()
210 {
211   # Test SI units during injectargs and 'config set'
212   # We only aim at testing the units are parsed accordingly
213   # and don't intend to test whether the options being set
214   # actually expect SI units to be passed.
215   # Keep in mind that all integer based options (i.e., INT,
216   # LONG, U32, U64) will accept SI unit modifiers.
217   initial_value=$(get_config_value_or_die "mon.a" "mon_pg_warn_min_objects")
218   $SUDO ceph daemon mon.a config set mon_pg_warn_min_objects 10
219   expect_config_value "mon.a" "mon_pg_warn_min_objects" 10
220   $SUDO ceph daemon mon.a config set mon_pg_warn_min_objects 10K
221   expect_config_value "mon.a" "mon_pg_warn_min_objects" 10240
222   $SUDO ceph daemon mon.a config set mon_pg_warn_min_objects 1G
223   expect_config_value "mon.a" "mon_pg_warn_min_objects" 1073741824
224   $SUDO ceph daemon mon.a config set mon_pg_warn_min_objects 10F > $TMPFILE || true
225   check_response "'10F': (22) Invalid argument"
226   # now test with injectargs
227   ceph tell mon.a injectargs '--mon_pg_warn_min_objects 10'
228   expect_config_value "mon.a" "mon_pg_warn_min_objects" 10
229   ceph tell mon.a injectargs '--mon_pg_warn_min_objects 10K'
230   expect_config_value "mon.a" "mon_pg_warn_min_objects" 10240
231   ceph tell mon.a injectargs '--mon_pg_warn_min_objects 1G'
232   expect_config_value "mon.a" "mon_pg_warn_min_objects" 1073741824
233   expect_false ceph tell mon.a injectargs '--mon_pg_warn_min_objects 10F'
234   $SUDO ceph daemon mon.a config set mon_pg_warn_min_objects $initial_value
235 }
236
237 function test_tiering_agent()
238 {
239   local slow=slow_eviction
240   local fast=fast_eviction
241   ceph osd pool create $slow  1 1
242   ceph osd pool create $fast  1 1
243   ceph osd tier add $slow $fast
244   ceph osd tier cache-mode $fast writeback
245   ceph osd tier set-overlay $slow $fast
246   ceph osd pool set $fast hit_set_type bloom
247   rados -p $slow put obj1 /etc/group
248   ceph osd pool set $fast target_max_objects  1
249   ceph osd pool set $fast hit_set_count 1
250   ceph osd pool set $fast hit_set_period 5
251   # wait for the object to be evicted from the cache
252   local evicted
253   evicted=false
254   for i in 1 2 4 8 16 32 64 128 256 ; do
255       if ! rados -p $fast ls | grep obj1 ; then
256           evicted=true
257           break
258       fi
259       sleep $i
260   done
261   $evicted # assert
262   # the object is proxy read and promoted to the cache
263   rados -p $slow get obj1 /tmp/obj1
264   # wait for the promoted object to be evicted again
265   evicted=false
266   for i in 1 2 4 8 16 32 64 128 256 ; do
267       if ! rados -p $fast ls | grep obj1 ; then
268           evicted=true
269           break
270       fi
271       sleep $i
272   done
273   $evicted # assert
274   ceph osd tier remove-overlay $slow
275   ceph osd tier remove $slow $fast
276   ceph osd pool delete $fast $fast --yes-i-really-really-mean-it
277   ceph osd pool delete $slow $slow --yes-i-really-really-mean-it
278 }
279
280 function test_tiering()
281 {
282   # tiering
283   ceph osd pool create slow 2
284   ceph osd pool create slow2 2
285   ceph osd pool create cache 2
286   ceph osd pool create cache2 2
287   ceph osd tier add slow cache
288   ceph osd tier add slow cache2
289   expect_false ceph osd tier add slow2 cache
290   # test some state transitions
291   ceph osd tier cache-mode cache writeback
292   ceph osd tier cache-mode cache forward
293   ceph osd tier cache-mode cache readonly
294   ceph osd tier cache-mode cache forward
295   ceph osd tier cache-mode cache none
296   ceph osd tier cache-mode cache writeback
297   expect_false ceph osd tier cache-mode cache none
298   expect_false ceph osd tier cache-mode cache readonly
299   # test with dirty objects in the tier pool
300   # tier pool currently set to 'writeback'
301   rados -p cache put /etc/passwd /etc/passwd
302   ceph tell osd.* flush_pg_stats || true
303   # 1 dirty object in pool 'cache'
304   ceph osd tier cache-mode cache forward
305   expect_false ceph osd tier cache-mode cache none
306   expect_false ceph osd tier cache-mode cache readonly
307   ceph osd tier cache-mode cache writeback
308   # remove object from tier pool
309   rados -p cache rm /etc/passwd
310   rados -p cache cache-flush-evict-all
311   ceph tell osd.* flush_pg_stats || true
312   # no dirty objects in pool 'cache'
313   ceph osd tier cache-mode cache forward
314   ceph osd tier cache-mode cache none
315   ceph osd tier cache-mode cache readonly
316   TRIES=0
317   while ! ceph osd pool set cache pg_num 3 --yes-i-really-mean-it 2>$TMPFILE
318   do
319     grep 'currently creating pgs' $TMPFILE
320     TRIES=$(( $TRIES + 1 ))
321     test $TRIES -ne 60
322     sleep 3
323   done
324   expect_false ceph osd pool set cache pg_num 4
325   ceph osd tier cache-mode cache none
326   ceph osd tier set-overlay slow cache
327   expect_false ceph osd tier set-overlay slow cache2
328   expect_false ceph osd tier remove slow cache
329   ceph osd tier remove-overlay slow
330   ceph osd tier set-overlay slow cache2
331   ceph osd tier remove-overlay slow
332   ceph osd tier remove slow cache
333   ceph osd tier add slow2 cache
334   expect_false ceph osd tier set-overlay slow cache
335   ceph osd tier set-overlay slow2 cache
336   ceph osd tier remove-overlay slow2
337   ceph osd tier remove slow2 cache
338   ceph osd tier remove slow cache2
339
340   # make sure a non-empty pool fails
341   rados -p cache2 put /etc/passwd /etc/passwd
342   while ! ceph df | grep cache2 | grep ' 1 ' ; do
343     echo waiting for pg stats to flush
344     sleep 2
345   done
346   expect_false ceph osd tier add slow cache2
347   ceph osd tier add slow cache2 --force-nonempty
348   ceph osd tier remove slow cache2
349
350   ceph osd pool ls | grep cache2
351   ceph osd pool ls -f json-pretty | grep cache2
352   ceph osd pool ls detail | grep cache2
353   ceph osd pool ls detail -f json-pretty | grep cache2
354
355   ceph osd pool delete cache cache --yes-i-really-really-mean-it
356   ceph osd pool delete cache2 cache2 --yes-i-really-really-mean-it
357
358   # make sure we can't clobber snapshot state
359   ceph osd pool create snap_base 2
360   ceph osd pool create snap_cache 2
361   ceph osd pool mksnap snap_cache snapname
362   expect_false ceph osd tier add snap_base snap_cache
363   ceph osd pool delete snap_base snap_base --yes-i-really-really-mean-it
364   ceph osd pool delete snap_cache snap_cache --yes-i-really-really-mean-it
365
366   # make sure we can't create an ec pool tier
367   ceph osd pool create eccache 2 2 erasure
368   ceph osd pool create repbase 2
369   expect_false ceph osd tier add repbase eccache
370   ceph osd pool delete repbase repbase --yes-i-really-really-mean-it
371   ceph osd pool delete eccache eccache --yes-i-really-really-mean-it
372
373   # convenient add-cache command
374   ceph osd pool create cache3 2
375   ceph osd tier add-cache slow cache3 1024000
376   ceph osd dump | grep cache3 | grep bloom | grep 'false_positive_probability: 0.05' | grep 'target_bytes 1024000' | grep '1200s x4'
377   ceph osd tier remove slow cache3 2> $TMPFILE || true
378   check_response "EBUSY: tier pool 'cache3' is the overlay for 'slow'; please remove-overlay first"
379   ceph osd tier remove-overlay slow
380   ceph osd tier remove slow cache3
381   ceph osd pool ls | grep cache3
382   ceph osd pool delete cache3 cache3 --yes-i-really-really-mean-it
383   ! ceph osd pool ls | grep cache3 || exit 1
384
385   ceph osd pool delete slow2 slow2 --yes-i-really-really-mean-it
386   ceph osd pool delete slow slow --yes-i-really-really-mean-it
387
388   # check add-cache whether work
389   ceph osd pool create datapool 2
390   ceph osd pool create cachepool 2
391   ceph osd tier add-cache datapool cachepool 1024000
392   ceph osd tier cache-mode cachepool writeback
393   dd if=/dev/zero of=/tmp/add-cache bs=4K count=1
394   rados -p datapool put object /tmp/add-cache
395   rados -p cachepool stat object
396   rados -p cachepool cache-flush object
397   rados -p datapool stat object
398   ceph osd tier remove-overlay datapool
399   ceph osd tier remove datapool cachepool
400   ceph osd pool delete cachepool cachepool --yes-i-really-really-mean-it
401   ceph osd pool delete datapool datapool --yes-i-really-really-mean-it
402   rm -rf /tmp/add-cache
403
404   # protection against pool removal when used as tiers
405   ceph osd pool create datapool 2
406   ceph osd pool create cachepool 2
407   ceph osd tier add-cache datapool cachepool 1024000
408   ceph osd pool delete cachepool cachepool --yes-i-really-really-mean-it 2> $TMPFILE || true
409   check_response "EBUSY: pool 'cachepool' is a tier of 'datapool'"
410   ceph osd pool delete datapool datapool --yes-i-really-really-mean-it 2> $TMPFILE || true
411   check_response "EBUSY: pool 'datapool' has tiers cachepool"
412   ceph osd tier remove-overlay datapool
413   ceph osd tier remove datapool cachepool
414   ceph osd pool delete cachepool cachepool --yes-i-really-really-mean-it
415   ceph osd pool delete datapool datapool --yes-i-really-really-mean-it
416
417   # check health check
418   ceph osd pool create datapool 2
419   ceph osd pool create cache4 2
420   ceph osd tier add datapool cache4
421   ceph osd pool set cache4 target_max_objects 5
422   ceph osd pool set cache4 target_max_bytes 1000
423   for f in `seq 1 5` ; do
424     rados -p cache4 put foo$f /etc/passwd
425   done
426   while ! ceph df | grep cache4 | grep ' 5 ' ; do
427     echo waiting for pg stats to flush
428     sleep 2
429   done
430   ceph health | grep WARN | grep cache4
431   ceph health detail | grep cache4 | grep 'target max' | grep objects
432   ceph health detail | grep cache4 | grep 'target max' | grep 'B'
433   ceph osd tier remove datapool cache4
434   ceph osd pool delete cache4 cache4 --yes-i-really-really-mean-it
435   ceph osd pool delete datapool datapool --yes-i-really-really-mean-it
436
437   # make sure 'tier remove' behaves as we expect
438   # i.e., removing a tier from a pool that's not its base pool only
439   # results in a 'pool foo is now (or already was) not a tier of bar'
440   #
441   ceph osd pool create basepoolA 2
442   ceph osd pool create basepoolB 2
443   poolA_id=$(ceph osd dump | grep 'pool.*basepoolA' | awk '{print $2;}')
444   poolB_id=$(ceph osd dump | grep 'pool.*basepoolB' | awk '{print $2;}')
445
446   ceph osd pool create cache5 2
447   ceph osd pool create cache6 2
448   ceph osd tier add basepoolA cache5
449   ceph osd tier add basepoolB cache6
450   ceph osd tier remove basepoolB cache5 2>&1 | grep 'not a tier of'
451   ceph osd dump | grep "pool.*'cache5'" 2>&1 | grep "tier_of[ \t]\+$poolA_id"
452   ceph osd tier remove basepoolA cache6 2>&1 | grep 'not a tier of'
453   ceph osd dump | grep "pool.*'cache6'" 2>&1 | grep "tier_of[ \t]\+$poolB_id"
454
455   ceph osd tier remove basepoolA cache5 2>&1 | grep 'not a tier of'
456   ! ceph osd dump | grep "pool.*'cache5'" 2>&1 | grep "tier_of" || exit 1
457   ceph osd tier remove basepoolB cache6 2>&1 | grep 'not a tier of'
458   ! ceph osd dump | grep "pool.*'cache6'" 2>&1 | grep "tier_of" || exit 1
459
460   ! ceph osd dump | grep "pool.*'basepoolA'" 2>&1 | grep "tiers" || exit 1
461   ! ceph osd dump | grep "pool.*'basepoolB'" 2>&1 | grep "tiers" || exit 1
462
463   ceph osd pool delete cache6 cache6 --yes-i-really-really-mean-it
464   ceph osd pool delete cache5 cache5 --yes-i-really-really-mean-it
465   ceph osd pool delete basepoolB basepoolB --yes-i-really-really-mean-it
466   ceph osd pool delete basepoolA basepoolA --yes-i-really-really-mean-it
467 }
468
469 function test_auth()
470 {
471   ceph auth add client.xx mon allow osd "allow *"
472   ceph auth export client.xx >client.xx.keyring
473   ceph auth add client.xx -i client.xx.keyring
474   rm -f client.xx.keyring
475   ceph auth list | grep client.xx
476   ceph auth get client.xx | grep caps | grep mon
477   ceph auth get client.xx | grep caps | grep osd
478   ceph auth get-key client.xx
479   ceph auth print-key client.xx
480   ceph auth print_key client.xx
481   ceph auth caps client.xx osd "allow rw"
482   expect_false "ceph auth get client.xx | grep caps | grep mon"
483   ceph auth get client.xx | grep osd | grep "allow rw"
484   ceph auth export | grep client.xx
485   ceph auth export -o authfile
486   ceph auth import -i authfile
487   ceph auth export -o authfile2
488   diff authfile authfile2
489   rm authfile authfile2
490   ceph auth del client.xx
491   expect_false ceph auth get client.xx
492
493   # (almost) interactive mode
494   echo -e 'auth add client.xx mon allow osd "allow *"\n' | ceph
495   ceph auth get client.xx
496   # script mode
497   echo 'auth del client.xx' | ceph
498   expect_false ceph auth get client.xx
499
500   #
501   # get / set auid
502   #
503   local auid=444
504   ceph-authtool --create-keyring --name client.TEST --gen-key --set-uid $auid TEST-keyring
505   ceph auth import --in-file TEST-keyring
506   rm TEST-keyring
507   ceph auth get client.TEST > $TMPFILE
508   check_response "auid = $auid"
509   ceph --format json-pretty auth get client.TEST > $TMPFILE
510   check_response '"auid": '$auid
511   ceph auth list > $TMPFILE
512   check_response "auid: $auid"
513   ceph --format json-pretty auth list > $TMPFILE
514   check_response '"auid": '$auid
515   ceph auth del client.TEST
516 }
517
518 function test_auth_profiles()
519 {
520   ceph auth add client.xx-profile-ro mon 'allow profile read-only'
521   ceph auth add client.xx-profile-rw mon 'allow profile read-write'
522   ceph auth add client.xx-profile-rd mon 'allow profile role-definer'
523
524   ceph auth export > client.xx.keyring
525
526   # read-only is allowed all read-only commands (auth excluded)
527   ceph -n client.xx-profile-ro -k client.xx.keyring status
528   ceph -n client.xx-profile-ro -k client.xx.keyring osd dump
529   ceph -n client.xx-profile-ro -k client.xx.keyring pg dump
530   ceph -n client.xx-profile-ro -k client.xx.keyring mon dump
531   ceph -n client.xx-profile-ro -k client.xx.keyring mds dump
532   # read-only gets access denied for rw commands or auth commands
533   ceph -n client.xx-profile-ro -k client.xx.keyring log foo >& $TMPFILE || true
534   check_response "EACCES: access denied"
535   ceph -n client.xx-profile-ro -k client.xx.keyring osd set noout >& $TMPFILE || true
536   check_response "EACCES: access denied"
537   ceph -n client.xx-profile-ro -k client.xx.keyring auth list >& $TMPFILE || true
538   check_response "EACCES: access denied"
539
540   # read-write is allowed for all read-write commands (except auth)
541   ceph -n client.xx-profile-rw -k client.xx.keyring status
542   ceph -n client.xx-profile-rw -k client.xx.keyring osd dump
543   ceph -n client.xx-profile-rw -k client.xx.keyring pg dump
544   ceph -n client.xx-profile-rw -k client.xx.keyring mon dump
545   ceph -n client.xx-profile-rw -k client.xx.keyring mds dump
546   ceph -n client.xx-profile-rw -k client.xx.keyring log foo
547   ceph -n client.xx-profile-rw -k client.xx.keyring osd set noout
548   ceph -n client.xx-profile-rw -k client.xx.keyring osd unset noout
549   # read-write gets access denied for auth commands
550   ceph -n client.xx-profile-rw -k client.xx.keyring auth list >& $TMPFILE || true
551   check_response "EACCES: access denied"
552
553   # role-definer is allowed RWX 'auth' commands and read-only 'mon' commands
554   ceph -n client.xx-profile-rd -k client.xx.keyring auth list
555   ceph -n client.xx-profile-rd -k client.xx.keyring auth export
556   ceph -n client.xx-profile-rd -k client.xx.keyring auth add client.xx-profile-foo
557   ceph -n client.xx-profile-rd -k client.xx.keyring status
558   ceph -n client.xx-profile-rd -k client.xx.keyring osd dump >& $TMPFILE || true
559   check_response "EACCES: access denied"
560   ceph -n client.xx-profile-rd -k client.xx.keyring pg dump >& $TMPFILE || true
561   check_response "EACCES: access denied"
562   # read-only 'mon' subsystem commands are allowed
563   ceph -n client.xx-profile-rd -k client.xx.keyring mon dump
564   # but read-write 'mon' commands are not
565   ceph -n client.xx-profile-rd -k client.xx.keyring mon add foo 1.1.1.1 >& $TMPFILE || true
566   check_response "EACCES: access denied"
567   ceph -n client.xx-profile-rd -k client.xx.keyring mds dump >& $TMPFILE || true
568   check_response "EACCES: access denied"
569   ceph -n client.xx-profile-rd -k client.xx.keyring log foo >& $TMPFILE || true
570   check_response "EACCES: access denied"
571   ceph -n client.xx-profile-rd -k client.xx.keyring osd set noout >& $TMPFILE || true
572   check_response "EACCES: access denied"
573
574   ceph -n client.xx-profile-rd -k client.xx.keyring auth del client.xx-profile-ro
575   ceph -n client.xx-profile-rd -k client.xx.keyring auth del client.xx-profile-rw
576   
577   # add a new role-definer with the existing role-definer
578   ceph -n client.xx-profile-rd -k client.xx.keyring \
579     auth add client.xx-profile-rd2 mon 'allow profile role-definer'
580   ceph -n client.xx-profile-rd -k client.xx.keyring \
581     auth export > client.xx.keyring.2
582   # remove old role-definer using the new role-definer
583   ceph -n client.xx-profile-rd2 -k client.xx.keyring.2 \
584     auth del client.xx-profile-rd
585   # remove the remaining role-definer with admin
586   ceph auth del client.xx-profile-rd2
587   rm -f client.xx.keyring client.xx.keyring.2
588 }
589
590 function test_mon_misc()
591 {
592   # with and without verbosity
593   ceph osd dump | grep '^epoch'
594   ceph --concise osd dump | grep '^epoch'
595
596   # df
597   ceph df > $TMPFILE
598   grep GLOBAL $TMPFILE
599   grep -v DIRTY $TMPFILE
600   ceph df detail > $TMPFILE
601   grep CATEGORY $TMPFILE
602   grep DIRTY $TMPFILE
603   ceph df --format json > $TMPFILE
604   grep 'total_bytes' $TMPFILE
605   grep -v 'dirty' $TMPFILE
606   ceph df detail --format json > $TMPFILE
607   grep 'rd_bytes' $TMPFILE
608   grep 'dirty' $TMPFILE
609   ceph df --format xml | grep '<total_bytes>'
610   ceph df detail --format xml | grep '<rd_bytes>'
611
612   ceph fsid
613   ceph health
614   ceph health detail
615   ceph health --format json-pretty
616   ceph health detail --format xml-pretty
617
618   ceph_watch_start
619   mymsg="this is a test log message $$.$(date)"
620   ceph log "$mymsg"
621   ceph_watch_wait "$mymsg"
622 }
623
624 function check_mds_active()
625 {
626     ceph mds dump | grep active
627 }
628
629 function wait_mds_active()
630 {
631   for i in $(seq 1 300) ; do
632       if ! check_mds_active ; then
633           echo "waiting for an active MDS daemon"
634           sleep 5
635       else
636           break
637       fi
638   done
639   check_mds_active
640 }
641
642 function get_mds_gids()
643 {
644     ceph mds dump --format=json | python -c "import json; import sys; print ' '.join([m['gid'].__str__() for m in json.load(sys.stdin)['info'].values()])"
645 }
646
647 function fail_all_mds()
648 {
649   ceph mds cluster_down
650   mds_gids=$(get_mds_gids)
651   for mds_gid in $mds_gids ; do
652       ceph mds fail $mds_gid
653   done
654   if check_mds_active ; then
655       echo "An active MDS remains, something went wrong"
656       ceph mds dump
657       exit -1
658   fi
659
660 }
661
662 function remove_all_fs()
663 {
664   existing_fs=$(ceph fs ls --format=json | python -c "import json; import sys; print ' '.join([fs['name'] for fs in json.load(sys.stdin)])")
665   if [ -n "$existing_fs" ] ; then
666       fail_all_mds
667       echo "Removing existing filesystem '${existing_fs}'..."
668       ceph fs rm $existing_fs --yes-i-really-mean-it
669       echo "Removed '${existing_fs}'."
670   fi
671 }
672
673 # So that tests requiring MDS can skip if one is not configured
674 # in the cluster at all
675 function mds_exists()
676 {
677     ceph auth list | grep "^mds"
678 }
679
680 function test_mds_tell()
681 {
682   if ! mds_exists ; then
683       echo "Skipping test, no MDS found"
684       return
685   fi
686
687   remove_all_fs
688   ceph osd pool create fs_data 10
689   ceph osd pool create fs_metadata 10
690   ceph fs new cephfs fs_metadata fs_data
691   wait_mds_active
692
693   # Test injectargs by GID
694   old_mds_gids=$(get_mds_gids)
695   echo Old GIDs: $old_mds_gids
696
697   for mds_gid in $old_mds_gids ; do
698       ceph tell mds.$mds_gid injectargs "--debug-mds 20"
699   done
700
701   # Test respawn by rank
702   ceph tell mds.0 respawn
703   new_mds_gids=$old_mds_gids
704   while [ $new_mds_gids -eq $old_mds_gids ] ; do
705       sleep 5
706       new_mds_gids=$(get_mds_gids)
707   done
708   echo New GIDs: $new_mds_gids
709
710   # Test respawn by ID
711   ceph tell mds.a respawn
712   new_mds_gids=$old_mds_gids
713   while [ $new_mds_gids -eq $old_mds_gids ] ; do
714       sleep 5
715       new_mds_gids=$(get_mds_gids)
716   done
717   echo New GIDs: $new_mds_gids
718
719   remove_all_fs
720   ceph osd pool delete fs_data fs_data --yes-i-really-really-mean-it
721   ceph osd pool delete fs_metadata fs_metadata --yes-i-really-really-mean-it
722 }
723
724 function test_mon_mds()
725 {
726   remove_all_fs
727
728   ceph osd pool create fs_data 10
729   ceph osd pool create fs_metadata 10
730   ceph fs new cephfs fs_metadata fs_data
731
732   ceph mds cluster_down
733   ceph mds cluster_up
734
735   ceph mds compat rm_incompat 4
736   ceph mds compat rm_incompat 4
737
738   # We don't want any MDSs to be up, their activity can interfere with
739   # the "current_epoch + 1" checking below if they're generating updates
740   fail_all_mds
741
742   # Check for default crash_replay_interval set automatically in 'fs new'
743   #This may vary based on ceph.conf (e.g., it's 5 in teuthology runs)
744   #ceph osd dump | grep fs_data > $TMPFILE
745   #check_response "crash_replay_interval 45 "
746
747   ceph mds compat show
748   expect_false ceph mds deactivate 2
749   ceph mds dump
750   # XXX mds fail, but how do you undo it?
751   mdsmapfile=$TMPDIR/mdsmap.$$
752   current_epoch=$(ceph mds getmap -o $mdsmapfile --no-log-to-stderr 2>&1 | grep epoch | sed 's/.*epoch //')
753   [ -s $mdsmapfile ]
754   rm $mdsmapfile
755
756   ceph osd pool create data2 10
757   ceph osd pool create data3 10
758   data2_pool=$(ceph osd dump | grep 'pool.*data2' | awk '{print $2;}')
759   data3_pool=$(ceph osd dump | grep 'pool.*data3' | awk '{print $2;}')
760   ceph mds add_data_pool $data2_pool
761   ceph mds add_data_pool $data3_pool
762   ceph mds add_data_pool 100 >& $TMPFILE || true
763   check_response "Error ENOENT"
764   ceph mds add_data_pool foobarbaz >& $TMPFILE || true
765   check_response "Error ENOENT"
766   ceph mds remove_data_pool $data2_pool
767   ceph mds remove_data_pool $data3_pool
768   ceph osd pool delete data2 data2 --yes-i-really-really-mean-it
769   ceph osd pool delete data3 data3 --yes-i-really-really-mean-it
770   ceph mds set_max_mds 4
771   ceph mds set_max_mds 3
772   ceph mds set max_mds 4
773   expect_false ceph mds set max_mds asdf
774   expect_false ceph mds set inline_data true
775   ceph mds set inline_data true --yes-i-really-mean-it
776   ceph mds set inline_data yes --yes-i-really-mean-it
777   ceph mds set inline_data 1 --yes-i-really-mean-it
778   expect_false ceph mds set inline_data --yes-i-really-mean-it
779   ceph mds set inline_data false
780   ceph mds set inline_data no
781   ceph mds set inline_data 0
782   expect_false ceph mds set inline_data asdf
783   ceph mds set max_file_size 1048576
784   expect_false ceph mds set max_file_size 123asdf
785
786   expect_false ceph mds set allow_new_snaps
787   expect_false ceph mds set allow_new_snaps true
788   ceph mds set allow_new_snaps true --yes-i-really-mean-it
789   ceph mds set allow_new_snaps 0
790   ceph mds set allow_new_snaps false
791   ceph mds set allow_new_snaps no
792   expect_false ceph mds set allow_new_snaps taco
793
794   # we should never be able to add EC pools as data or metadata pools
795   # create an ec-pool...
796   ceph osd pool create mds-ec-pool 10 10 erasure
797   set +e
798   ceph mds add_data_pool mds-ec-pool 2>$TMPFILE
799   check_response 'erasure-code' $? 22
800   set -e
801   ec_poolnum=$(ceph osd dump | grep "pool.* 'mds-ec-pool" | awk '{print $2;}')
802   data_poolnum=$(ceph osd dump | grep "pool.* 'fs_data" | awk '{print $2;}')
803   metadata_poolnum=$(ceph osd dump | grep "pool.* 'fs_metadata" | awk '{print $2;}')
804
805   fail_all_mds
806
807   # Check that 'fs reset' runs
808   ceph fs reset cephfs --yes-i-really-mean-it
809
810   fail_all_mds
811
812   # Clean up to enable subsequent newfs tests
813   ceph fs rm cephfs --yes-i-really-mean-it
814
815   set +e
816   ceph mds newfs $metadata_poolnum $ec_poolnum --yes-i-really-mean-it 2>$TMPFILE
817   check_response 'erasure-code' $? 22
818   ceph mds newfs $ec_poolnum $data_poolnum --yes-i-really-mean-it 2>$TMPFILE
819   check_response 'erasure-code' $? 22
820   ceph mds newfs $ec_poolnum $ec_poolnum --yes-i-really-mean-it 2>$TMPFILE
821   check_response 'erasure-code' $? 22
822   ceph fs new cephfs fs_metadata mds-ec-pool 2>$TMPFILE
823   check_response 'erasure-code' $? 22
824   ceph fs new cephfs mds-ec-pool fs_data 2>$TMPFILE
825   check_response 'erasure-code' $? 22
826   ceph fs new cephfs mds-ec-pool mds-ec-pool 2>$TMPFILE
827   check_response 'erasure-code' $? 22
828   set -e
829
830   # ... new create a cache tier in front of the EC pool...
831   ceph osd pool create mds-tier 2
832   ceph osd tier add mds-ec-pool mds-tier
833   ceph osd tier set-overlay mds-ec-pool mds-tier
834   tier_poolnum=$(ceph osd dump | grep "pool.* 'mds-tier" | awk '{print $2;}')
835
836   # Use of a readonly tier should be forbidden
837   ceph osd tier cache-mode mds-tier readonly
838   set +e
839   ceph fs new cephfs fs_metadata mds-ec-pool 2>$TMPFILE
840   check_response 'has a write tier (mds-tier) that is configured to forward' $? 22
841   set -e
842
843   # Use of a writeback tier should enable FS creation
844   ceph osd tier cache-mode mds-tier writeback
845   ceph fs new cephfs fs_metadata mds-ec-pool
846
847   # While a FS exists using the tiered pools, I should not be allowed
848   # to remove the tier
849   set +e
850   ceph osd tier remove-overlay mds-ec-pool 2>$TMPFILE
851   check_response 'in use by CephFS' $? 16
852   ceph osd tier remove mds-ec-pool mds-tier 2>$TMPFILE
853   check_response 'in use by CephFS' $? 16
854   set -e
855
856   fail_all_mds
857   ceph fs rm cephfs --yes-i-really-mean-it
858
859   # ... but we should be forbidden from using the cache pool in the FS directly.
860   set +e
861   ceph mds newfs $metadata_poolnum $tier_poolnum --yes-i-really-mean-it 2>$TMPFILE
862   check_response 'in use as a cache tier' $? 22
863   ceph mds newfs $tier_poolnum $data_poolnum --yes-i-really-mean-it 2>$TMPFILE
864   check_response 'in use as a cache tier' $? 22
865   ceph mds newfs $tier_poolnum $tier_poolnum --yes-i-really-mean-it 2>$TMPFILE
866   check_response 'in use as a cache tier' $? 22
867   ceph fs new cephfs fs_metadata mds-tier 2>$TMPFILE
868   check_response 'in use as a cache tier' $? 22
869   ceph fs new cephfs mds-tier fs_data 2>$TMPFILE
870   check_response 'in use as a cache tier' $? 22
871   ceph fs new cephfs mds-tier mds-tier 2>$TMPFILE
872   check_response 'in use as a cache tier' $? 22
873   set -e
874
875   # Clean up tier + EC pools
876   ceph osd tier remove-overlay mds-ec-pool
877   ceph osd tier remove mds-ec-pool mds-tier
878
879   # Create a FS using the 'cache' pool now that it's no longer a tier
880   ceph fs new cephfs fs_metadata mds-tier
881
882   # We should be forbidden from using this pool as a tier now that
883   # it's in use for CephFS
884   set +e
885   ceph osd tier add mds-ec-pool mds-tier 2>$TMPFILE
886   check_response 'in use by CephFS' $? 16
887   set -e
888
889   fail_all_mds
890   ceph fs rm cephfs --yes-i-really-mean-it
891   ceph osd pool delete mds-ec-pool mds-ec-pool --yes-i-really-really-mean-it
892
893   # Create a FS and check that we can subsequently add a cache tier to it
894   ceph fs new cephfs fs_metadata fs_data
895
896   # Adding overlay to FS pool should be permitted, RADOS clients handle this.
897   ceph osd tier add fs_metadata mds-tier
898   ceph osd tier cache-mode mds-tier writeback
899   ceph osd tier set-overlay fs_metadata mds-tier
900
901   # Removing tier should be permitted because the underlying pool is
902   # replicated (#11504 case)
903   ceph osd tier cache-mode mds-tier forward
904   ceph osd tier remove-overlay fs_metadata
905   ceph osd tier remove fs_metadata mds-tier
906   ceph osd pool delete mds-tier mds-tier --yes-i-really-really-mean-it
907
908   # Clean up FS
909   fail_all_mds
910   ceph fs rm cephfs --yes-i-really-mean-it
911
912   ceph mds stat
913   # ceph mds tell mds.a getmap
914   # ceph mds rm
915   # ceph mds rmfailed
916   # ceph mds set_state
917   # ceph mds stop
918
919   ceph osd pool delete fs_data fs_data --yes-i-really-really-mean-it
920   ceph osd pool delete fs_metadata fs_metadata --yes-i-really-really-mean-it
921 }
922
923 function test_mon_mon()
924 {
925   # no mon add/remove
926   ceph mon dump
927   ceph mon getmap -o $TMPDIR/monmap.$$
928   [ -s $TMPDIR/monmap.$$ ]
929   # ceph mon tell
930   ceph mon_status
931 }
932
933 function test_mon_osd()
934 {
935   #
936   # osd blacklist
937   #
938   bl=192.168.0.1:0/1000
939   ceph osd blacklist add $bl
940   ceph osd blacklist ls | grep $bl
941   ceph osd blacklist rm $bl
942   expect_false "ceph osd blacklist ls | grep $bl"
943
944   bl=192.168.0.1
945   # test without nonce, invalid nonce
946   ceph osd blacklist add $bl
947   ceph osd blacklist ls | grep $bl
948   ceph osd blacklist rm $bl
949   expect_false "ceph osd blacklist ls | grep $bl"
950   expect_false "ceph osd blacklist $bl/-1"
951   expect_false "ceph osd blacklist $bl/foo"
952
953   #
954   # osd crush
955   #
956   ceph osd crush reweight-all
957   ceph osd crush tunables legacy
958   ceph osd crush show-tunables | grep argonaut
959   ceph osd crush tunables bobtail
960   ceph osd crush show-tunables | grep bobtail
961   ceph osd crush tunables firefly
962   ceph osd crush show-tunables | grep firefly
963
964   ceph osd crush set-tunable straw_calc_version 0
965   ceph osd crush get-tunable straw_calc_version | grep 0
966   ceph osd crush set-tunable straw_calc_version 1
967   ceph osd crush get-tunable straw_calc_version | grep 1
968
969   #
970   # osd scrub
971   #
972   # how do I tell when these are done?
973   ceph osd scrub 0
974   ceph osd deep-scrub 0
975   ceph osd repair 0
976
977   for f in noup nodown noin noout noscrub nodeep-scrub nobackfill norebalance norecover notieragent full
978   do
979     ceph osd set $f
980     ceph osd unset $f
981   done
982   expect_false ceph osd set bogus
983   expect_false ceph osd unset bogus
984
985   ceph osd set noup
986   ceph osd down 0
987   ceph osd dump | grep 'osd.0 down'
988   ceph osd unset noup
989   for ((i=0; i < 100; i++)); do
990     if ! ceph osd dump | grep 'osd.0 up'; then
991       echo "waiting for osd.0 to come back up"
992       sleep 10
993     else
994       break
995     fi
996   done
997   ceph osd dump | grep 'osd.0 up'
998
999   ceph osd thrash 0
1000
1001   ceph osd dump | grep 'osd.0 up'
1002   ceph osd find 1
1003   ceph --format plain osd find 1 # falls back to json-pretty
1004   ceph osd metadata 1 | grep 'distro'
1005   ceph --format plain osd metadata 1 | grep 'distro' # falls back to json-pretty
1006   ceph osd out 0
1007   ceph osd dump | grep 'osd.0.*out'
1008   ceph osd in 0
1009   ceph osd dump | grep 'osd.0.*in'
1010   ceph osd find 0
1011
1012   f=$TMPDIR/map.$$
1013   ceph osd getcrushmap -o $f
1014   [ -s $f ]
1015   ceph osd setcrushmap -i $f
1016   rm $f
1017   ceph osd getmap -o $f
1018   [ -s $f ]
1019   rm $f
1020   save=$(ceph osd getmaxosd | sed -e 's/max_osd = //' -e 's/ in epoch.*//')
1021   ceph osd setmaxosd 10
1022   ceph osd getmaxosd | grep 'max_osd = 10'
1023   ceph osd setmaxosd $save
1024   ceph osd getmaxosd | grep "max_osd = $save"
1025
1026   for id in `ceph osd ls` ; do
1027     retry_eagain 5 map_enxio_to_eagain ceph tell osd.$id version
1028   done
1029
1030   ceph osd rm 0 2>&1 | grep 'EBUSY'
1031
1032   local old_osds=$(echo $(ceph osd ls))
1033   id=`ceph osd create`
1034   ceph osd lost $id --yes-i-really-mean-it
1035   expect_false ceph osd setmaxosd $id
1036   local new_osds=$(echo $(ceph osd ls))
1037   for id in $(echo $new_osds | sed -e "s/$old_osds//") ; do
1038       ceph osd rm $id
1039   done
1040
1041   uuid=`uuidgen`
1042   id=`ceph osd create $uuid`
1043   id2=`ceph osd create $uuid`
1044   [ "$id" = "$id2" ]
1045   ceph osd rm $id
1046
1047   ceph osd ls
1048   ceph osd pool create data 10
1049   ceph osd lspools | grep data
1050   ceph osd map data foo | grep 'pool.*data.*object.*foo.*pg.*up.*acting'
1051   ceph osd pool delete data data --yes-i-really-really-mean-it
1052
1053   ceph osd pause
1054   ceph osd dump | grep 'flags pauserd,pausewr'
1055   ceph osd unpause
1056
1057   ceph osd tree
1058   ceph osd perf
1059   ceph osd blocked-by
1060
1061   ceph osd stat | grep up,
1062 }
1063
1064 function test_mon_osd_pool()
1065 {
1066   #
1067   # osd pool
1068   #
1069   ceph osd pool create data 10
1070   ceph osd pool mksnap data datasnap
1071   rados -p data lssnap | grep datasnap
1072   ceph osd pool rmsnap data datasnap
1073   ceph osd pool delete data data --yes-i-really-really-mean-it
1074
1075   ceph osd pool create data2 10
1076   ceph osd pool rename data2 data3
1077   ceph osd lspools | grep data3
1078   ceph osd pool delete data3 data3 --yes-i-really-really-mean-it
1079
1080   ceph osd pool create replicated 12 12 replicated
1081   ceph osd pool create replicated 12 12 replicated
1082   ceph osd pool create replicated 12 12 # default is replicated
1083   ceph osd pool create replicated 12    # default is replicated, pgp_num = pg_num
1084   # should fail because the type is not the same
1085   expect_false ceph osd pool create replicated 12 12 erasure
1086   ceph osd lspools | grep replicated
1087   ceph osd pool delete replicated replicated --yes-i-really-really-mean-it
1088 }
1089
1090 function test_mon_osd_pool_quota()
1091 {
1092   #
1093   # test osd pool set/get quota
1094   #
1095
1096   # create tmp pool
1097   ceph osd pool create tmp-quota-pool 36
1098   #
1099   # set erroneous quotas
1100   #
1101   expect_false ceph osd pool set-quota tmp-quota-pool max_fooness 10
1102   expect_false ceph osd pool set-quota tmp-quota-pool max_bytes -1
1103   expect_false ceph osd pool set-quota tmp-quota-pool max_objects aaa
1104   #
1105   # set valid quotas
1106   #
1107   ceph osd pool set-quota tmp-quota-pool max_bytes 10
1108   ceph osd pool set-quota tmp-quota-pool max_objects 10M
1109   #
1110   # get quotas
1111   #
1112   ceph osd pool get-quota tmp-quota-pool | grep 'max bytes.*10B'
1113   ceph osd pool get-quota tmp-quota-pool | grep 'max objects.*10240k objects'
1114   #
1115   # get quotas in json-pretty format
1116   #
1117   ceph osd pool get-quota tmp-quota-pool --format=json-pretty | \
1118     grep '"quota_max_objects":.*10485760'
1119   ceph osd pool get-quota tmp-quota-pool --format=json-pretty | \
1120     grep '"quota_max_bytes":.*10'
1121   #
1122   # reset pool quotas
1123   #
1124   ceph osd pool set-quota tmp-quota-pool max_bytes 0
1125   ceph osd pool set-quota tmp-quota-pool max_objects 0
1126   #
1127   # test N/A quotas
1128   #
1129   ceph osd pool get-quota tmp-quota-pool | grep 'max bytes.*N/A'
1130   ceph osd pool get-quota tmp-quota-pool | grep 'max objects.*N/A'
1131   #
1132   # cleanup tmp pool
1133   ceph osd pool delete tmp-quota-pool tmp-quota-pool --yes-i-really-really-mean-it
1134 }
1135
1136 function test_mon_pg()
1137 {
1138   ceph pg debug unfound_objects_exist
1139   ceph pg debug degraded_pgs_exist
1140   ceph pg deep-scrub 0.0
1141   ceph pg dump
1142   ceph pg dump pgs_brief --format=json
1143   ceph pg dump pgs --format=json
1144   ceph pg dump pools --format=json
1145   ceph pg dump osds --format=json
1146   ceph pg dump sum --format=json
1147   ceph pg dump all --format=json
1148   ceph pg dump pgs_brief osds --format=json
1149   ceph pg dump pools osds pgs_brief --format=json
1150   ceph pg dump_json
1151   ceph pg dump_pools_json
1152   ceph pg dump_stuck inactive
1153   ceph pg dump_stuck unclean
1154   ceph pg dump_stuck stale
1155   ceph pg dump_stuck undersized
1156   ceph pg dump_stuck degraded
1157   ceph pg ls
1158   ceph pg ls 0
1159   ceph pg ls stale
1160   ceph pg ls active stale repair recovering
1161   ceph pg ls 0 active
1162   ceph pg ls 0 active stale
1163   ceph pg ls-by-primary osd.0
1164   ceph pg ls-by-primary osd.0 0
1165   ceph pg ls-by-primary osd.0 active
1166   ceph pg ls-by-primary osd.0 active stale
1167   ceph pg ls-by-primary osd.0 0 active stale
1168   ceph pg ls-by-osd osd.0
1169   ceph pg ls-by-osd osd.0 0
1170   ceph pg ls-by-osd osd.0 active
1171   ceph pg ls-by-osd osd.0 active stale
1172   ceph pg ls-by-osd osd.0 0 active stale
1173   ceph pg ls-by-pool rbd
1174   ceph pg ls-by-pool rbd active stale
1175   # can't test this...
1176   # ceph pg force_create_pg
1177   ceph pg getmap -o $TMPDIR/map.$$
1178   [ -s $TMPDIR/map.$$ ]
1179   ceph pg map 0.0 | grep acting
1180   ceph pg repair 0.0
1181   ceph pg scrub 0.0
1182
1183   ceph pg send_pg_creates
1184   ceph pg set_full_ratio 0.90
1185   ceph pg dump --format=plain | grep '^full_ratio 0.9'
1186   ceph pg set_full_ratio 0.95
1187   ceph pg set_nearfull_ratio 0.90
1188   ceph pg dump --format=plain | grep '^nearfull_ratio 0.9'
1189   ceph pg set_nearfull_ratio 0.85
1190   ceph pg stat | grep 'pgs:'
1191   ceph pg 0.0 query
1192   ceph tell 0.0 query
1193   ceph quorum enter
1194   ceph quorum_status
1195   ceph report | grep osd_stats
1196   ceph status
1197   ceph -s
1198
1199   #
1200   # tell osd version
1201   #
1202   ceph tell osd.0 version
1203   expect_false ceph tell osd.9999 version 
1204   expect_false ceph tell osd.foo version
1205
1206   # back to pg stuff
1207
1208   ceph tell osd.0 dump_pg_recovery_stats | grep Started
1209
1210   ceph osd reweight 0 0.9
1211   expect_false ceph osd reweight 0 -1
1212   ceph osd reweight 0 1
1213
1214   ceph osd primary-affinity osd.0 .9
1215   expect_false ceph osd primary-affinity osd.0 -2
1216   ceph osd primary-affinity osd.0 1
1217
1218   ceph osd pg-temp 0.0 0 1 2
1219   ceph osd pg-temp 0.0 1 0 2
1220   expect_false ceph osd pg-temp asdf qwer
1221   expect_false ceph osd pg-temp 0.0 asdf
1222   expect_false ceph osd pg-temp 0.0
1223
1224   # don't test ceph osd primary-temp for now
1225 }
1226
1227 function test_mon_osd_pool_set()
1228 {
1229   TEST_POOL_GETSET=pool_getset
1230   ceph osd pool create $TEST_POOL_GETSET 10
1231
1232   for s in pg_num pgp_num size min_size crash_replay_interval crush_ruleset; do
1233     ceph osd pool get $TEST_POOL_GETSET $s
1234   done
1235
1236   old_size=$(ceph osd pool get $TEST_POOL_GETSET size | sed -e 's/size: //')
1237   (( new_size = old_size + 1 ))
1238   ceph osd pool set $TEST_POOL_GETSET size $new_size
1239   ceph osd pool get $TEST_POOL_GETSET size | grep "size: $new_size"
1240   ceph osd pool set $TEST_POOL_GETSET size $old_size
1241
1242   ceph osd pool create pool_erasure 12 12 erasure
1243   set +e
1244   ceph osd pool set pool_erasure size 4444 2>$TMPFILE
1245   check_response 'not change the size'
1246   set -e
1247   ceph osd pool get pool_erasure erasure_code_profile
1248
1249   auid=5555
1250   ceph osd pool set $TEST_POOL_GETSET auid $auid
1251   ceph osd pool get $TEST_POOL_GETSET auid | grep $auid
1252   ceph --format=xml osd pool get $TEST_POOL_GETSET auid | grep $auid
1253   ceph osd pool set $TEST_POOL_GETSET auid 0
1254
1255   for flag in hashpspool nodelete nopgchange nosizechange; do
1256       ceph osd pool set $TEST_POOL_GETSET $flag false
1257       ceph osd pool set $TEST_POOL_GETSET $flag true
1258       ceph osd pool set $TEST_POOL_GETSET $flag 1
1259       ceph osd pool set $TEST_POOL_GETSET $flag 0
1260       expect_false ceph osd pool set $TEST_POOL_GETSET $flag asdf
1261       expect_false ceph osd pool set $TEST_POOL_GETSET $flag 2
1262   done
1263
1264   ceph osd pool set $TEST_POOL_GETSET nopgchange 1
1265   expect_false ceph osd pool set $TEST_POOL_GETSET pg_num 10
1266   expect_false ceph osd pool set $TEST_POOL_GETSET pgp_num 10
1267   ceph osd pool set $TEST_POOL_GETSET nopgchange 0
1268   ceph osd pool set $TEST_POOL_GETSET pg_num 10
1269   ceph osd pool set $TEST_POOL_GETSET pgp_num 10
1270
1271   ceph osd pool set $TEST_POOL_GETSET nosizechange 1
1272   expect_false ceph osd pool set $TEST_POOL_GETSET size 2
1273   expect_false ceph osd pool set $TEST_POOL_GETSET min_size 2
1274   ceph osd pool set $TEST_POOL_GETSET nosizechange 0
1275   ceph osd pool set $TEST_POOL_GETSET size 2
1276   ceph osd pool set $TEST_POOL_GETSET min_size 2
1277
1278   ceph osd pool set $TEST_POOL_GETSET nodelete 1
1279   expect_false ceph osd pool delete $TEST_POOL_GETSET $TEST_POOL_GETSET --yes-i-really-really-mean-it
1280   ceph osd pool set $TEST_POOL_GETSET nodelete 0
1281   ceph osd pool delete $TEST_POOL_GETSET $TEST_POOL_GETSET --yes-i-really-really-mean-it
1282
1283   ceph osd pool get rbd crush_ruleset | grep 'crush_ruleset: 0'
1284 }
1285
1286 function test_mon_osd_tiered_pool_set()
1287 {
1288   # this is really a tier pool
1289   ceph osd pool create real-tier 2
1290   ceph osd tier add rbd real-tier
1291
1292   ceph osd pool set real-tier hit_set_type explicit_hash
1293   ceph osd pool get real-tier hit_set_type | grep "hit_set_type: explicit_hash"
1294   ceph osd pool set real-tier hit_set_type explicit_object
1295   ceph osd pool get real-tier hit_set_type | grep "hit_set_type: explicit_object"
1296   ceph osd pool set real-tier hit_set_type bloom
1297   ceph osd pool get real-tier hit_set_type | grep "hit_set_type: bloom"
1298   expect_false ceph osd pool set real-tier hit_set_type i_dont_exist
1299   ceph osd pool set real-tier hit_set_period 123
1300   ceph osd pool get real-tier hit_set_period | grep "hit_set_period: 123"
1301   ceph osd pool set real-tier hit_set_count 12
1302   ceph osd pool get real-tier hit_set_count | grep "hit_set_count: 12"
1303   ceph osd pool set real-tier hit_set_fpp .01
1304   ceph osd pool get real-tier hit_set_fpp | grep "hit_set_fpp: 0.01"
1305
1306   ceph osd pool set real-tier target_max_objects 123
1307   ceph osd pool get real-tier target_max_objects | \
1308     grep 'target_max_objects:[ \t]\+123'
1309   ceph osd pool set real-tier target_max_bytes 123456
1310   ceph osd pool get real-tier target_max_bytes | \
1311     grep 'target_max_bytes:[ \t]\+123456'
1312   ceph osd pool set real-tier cache_target_dirty_ratio .123
1313   ceph osd pool get real-tier cache_target_dirty_ratio | \
1314     grep 'cache_target_dirty_ratio:[ \t]\+0.123'
1315   expect_false ceph osd pool set real-tier cache_target_dirty_ratio -.2
1316   expect_false ceph osd pool set real-tier cache_target_dirty_ratio 1.1
1317   ceph osd pool set real-tier cache_target_full_ratio .123
1318   ceph osd pool get real-tier cache_target_full_ratio | \
1319     grep 'cache_target_full_ratio:[ \t]\+0.123'
1320   ceph osd dump -f json-pretty | grep '"cache_target_full_ratio_micro": 123000'
1321   ceph osd pool set real-tier cache_target_full_ratio 1.0
1322   ceph osd pool set real-tier cache_target_full_ratio 0
1323   expect_false ceph osd pool set real-tier cache_target_full_ratio 1.1
1324   ceph osd pool set real-tier cache_min_flush_age 123
1325   ceph osd pool get real-tier cache_min_flush_age | \
1326     grep 'cache_min_flush_age:[ \t]\+123'
1327   ceph osd pool set real-tier cache_min_evict_age 234
1328   ceph osd pool get real-tier cache_min_evict_age | \
1329     grep 'cache_min_evict_age:[ \t]\+234'
1330
1331   # this is not a tier pool
1332   ceph osd pool create fake-tier 2
1333
1334   expect_false ceph osd pool set fake-tier hit_set_type explicit_hash
1335   expect_false ceph osd pool get fake-tier hit_set_type
1336   expect_false ceph osd pool set fake-tier hit_set_type explicit_object
1337   expect_false ceph osd pool get fake-tier hit_set_type
1338   expect_false ceph osd pool set fake-tier hit_set_type bloom
1339   expect_false ceph osd pool get fake-tier hit_set_type
1340   expect_false ceph osd pool set fake-tier hit_set_type i_dont_exist
1341   expect_false ceph osd pool set fake-tier hit_set_period 123
1342   expect_false ceph osd pool get fake-tier hit_set_period
1343   expect_false ceph osd pool set fake-tier hit_set_count 12
1344   expect_false ceph osd pool get fake-tier hit_set_count
1345   expect_false ceph osd pool set fake-tier hit_set_fpp .01
1346   expect_false ceph osd pool get fake-tier hit_set_fpp
1347
1348   expect_false ceph osd pool set fake-tier target_max_objects 123
1349   expect_false ceph osd pool get fake-tier target_max_objects
1350   expect_false ceph osd pool set fake-tier target_max_bytes 123456
1351   expect_false ceph osd pool get fake-tier target_max_bytes
1352   expect_false ceph osd pool set fake-tier cache_target_dirty_ratio .123
1353   expect_false ceph osd pool get fake-tier cache_target_dirty_ratio
1354   expect_false ceph osd pool set fake-tier cache_target_dirty_ratio -.2
1355   expect_false ceph osd pool set fake-tier cache_target_dirty_ratio 1.1
1356   expect_false ceph osd pool set fake-tier cache_target_full_ratio .123
1357   expect_false ceph osd pool get fake-tier cache_target_full_ratio
1358   expect_false ceph osd pool set fake-tier cache_target_full_ratio 1.0
1359   expect_false ceph osd pool set fake-tier cache_target_full_ratio 0
1360   expect_false ceph osd pool set fake-tier cache_target_full_ratio 1.1
1361   expect_false ceph osd pool set fake-tier cache_min_flush_age 123
1362   expect_false ceph osd pool get fake-tier cache_min_flush_age
1363   expect_false ceph osd pool set fake-tier cache_min_evict_age 234
1364   expect_false ceph osd pool get fake-tier cache_min_evict_age
1365
1366   ceph osd tier remove rbd real-tier
1367   ceph osd pool delete real-tier real-tier --yes-i-really-really-mean-it
1368   ceph osd pool delete fake-tier fake-tier --yes-i-really-really-mean-it
1369 }
1370
1371 function test_mon_osd_erasure_code()
1372 {
1373
1374   ceph osd erasure-code-profile set fooprofile a=b c=d
1375   ceph osd erasure-code-profile set fooprofile a=b c=d
1376   expect_false ceph osd erasure-code-profile set fooprofile a=b c=d e=f
1377   ceph osd erasure-code-profile set fooprofile a=b c=d e=f --force
1378   ceph osd erasure-code-profile set fooprofile a=b c=d e=f
1379   expect_false ceph osd erasure-code-profile set fooprofile a=b c=d e=f g=h
1380   #
1381   # cleanup by removing profile 'fooprofile'
1382   ceph osd erasure-code-profile rm fooprofile
1383 }
1384
1385 function test_mon_osd_misc()
1386 {
1387   set +e
1388
1389   # expect error about missing 'pool' argument
1390   ceph osd map 2>$TMPFILE; check_response 'pool' $? 22
1391
1392   # expect error about unused argument foo
1393   ceph osd ls foo 2>$TMPFILE; check_response 'unused' $? 22 
1394
1395   # expect "not in range" for invalid full ratio
1396   ceph pg set_full_ratio 95 2>$TMPFILE; check_response 'not in range' $? 22
1397
1398   # expect "not in range" for invalid overload percentage
1399   ceph osd reweight-by-utilization 80 2>$TMPFILE; check_response 'higher than 100' $? 22
1400
1401   set -e
1402
1403   ceph osd reweight-by-utilization 110
1404   ceph osd reweight-by-utilization 110 .5
1405   ceph osd test-reweight-by-utilization 110 .5 --no-increasing
1406   ceph osd reweight-by-pg 110
1407   ceph osd test-reweight-by-pg 110 .5
1408   ceph osd reweight-by-pg 110 rbd
1409   ceph osd reweight-by-pg 110 .5 rbd
1410   expect_false ceph osd reweight-by-pg 110 boguspoolasdfasdfasdf
1411 }
1412
1413 function test_mon_heap_profiler()
1414 {
1415   do_test=1
1416   set +e
1417   # expect 'heap' commands to be correctly parsed
1418   ceph heap stats 2>$TMPFILE
1419   if [[ $? -eq 22 && `grep 'tcmalloc not enabled' $TMPFILE` ]]; then
1420     echo "tcmalloc not enabled; skip heap profiler test"
1421     do_test=0
1422   fi
1423   set -e
1424
1425   [[ $do_test -eq 0 ]] && return 0
1426
1427   ceph heap start_profiler
1428   ceph heap dump
1429   ceph heap stop_profiler
1430   ceph heap release
1431 }
1432
1433 function test_osd_bench()
1434 {
1435   # test osd bench limits
1436   # As we should not rely on defaults (as they may change over time),
1437   # lets inject some values and perform some simple tests
1438   # max iops: 10              # 100 IOPS
1439   # max throughput: 10485760  # 10MB/s
1440   # max block size: 2097152   # 2MB
1441   # duration: 10              # 10 seconds
1442
1443   ceph tell osd.0 injectargs "\
1444     --osd-bench-duration 10 \
1445     --osd-bench-max-block-size 2097152 \
1446     --osd-bench-large-size-max-throughput 10485760 \
1447     --osd-bench-small-size-max-iops 10"
1448
1449   # anything with a bs larger than 2097152  must fail
1450   expect_false ceph tell osd.0 bench 1 2097153
1451   # but using 'osd_bench_max_bs' must succeed
1452   ceph tell osd.0 bench 1 2097152
1453
1454   # we assume 1MB as a large bs; anything lower is a small bs
1455   # for a 4096 bytes bs, for 10 seconds, we are limited by IOPS
1456   # max count: 409600 (bytes)
1457
1458   # more than max count must not be allowed
1459   expect_false ceph tell osd.0 bench 409601 4096
1460   # but 409600 must be succeed
1461   ceph tell osd.0 bench 409600 4096
1462
1463   # for a large bs, we are limited by throughput.
1464   # for a 2MB block size for 10 seconds, assuming 10MB/s throughput,
1465   # the max count will be (10MB * 10s) = 100MB
1466   # max count: 104857600 (bytes)
1467
1468   # more than max count must not be allowed
1469   expect_false ceph tell osd.0 bench 104857601 2097152
1470   # up to max count must be allowed
1471   ceph tell osd.0 bench 104857600 2097152
1472 }
1473
1474 function test_osd_negative_filestore_merge_threshold()
1475 {
1476   $SUDO ceph daemon osd.0 config set filestore_merge_threshold -1
1477   expect_config_value "osd.0" "filestore_merge_threshold" -1
1478 }
1479
1480 function test_mon_tell()
1481 {
1482   ceph tell mon.a version
1483   ceph tell mon.b version
1484   expect_false ceph tell mon.foo version
1485
1486   sleep 1
1487
1488   ceph_watch_start debug
1489   ceph tell mon.a version
1490   ceph_watch_wait 'mon.0 \[DBG\] from.*cmd=\[{"prefix": "version"}\]: dispatch'
1491
1492   ceph_watch_start debug
1493   ceph tell mon.b version
1494   ceph_watch_wait 'mon.1 \[DBG\] from.*cmd=\[{"prefix": "version"}\]: dispatch'
1495 }
1496
1497 function test_mon_crushmap_validation()
1498 {
1499   local map=$TMPDIR/map
1500   ceph osd getcrushmap -o $map
1501
1502   # crushtool validation timesout and is ignored
1503   cat > $TMPDIR/crushtool <<EOF
1504 #!/bin/sh
1505 sleep 1000
1506 exit 0 # success
1507 EOF
1508   chmod +x $TMPDIR/crushtool
1509   ceph tell mon.* injectargs --crushtool $TMPDIR/crushtool
1510   ceph osd setcrushmap -i $map 2>&1 | grep 'took too long'
1511
1512   # crushtool validation fails and is ignored
1513   cat > $TMPDIR/crushtool <<EOF
1514 #!/bin/sh
1515 echo 'TEST FAIL' >&2
1516 exit 1 # failure
1517 EOF
1518   chmod +x $TMPDIR/crushtool
1519   ceph tell mon.* injectargs --crushtool $TMPDIR/crushtool
1520   ceph osd setcrushmap -i $map 2>&1 | grep 'Failed crushmap test'
1521
1522   ceph tell mon.* injectargs --crushtool crushtool
1523
1524   # crushtool validation succeeds
1525   ceph osd setcrushmap -i $map
1526 }
1527
1528 function test_mon_cephdf_commands()
1529 {
1530   # ceph df detail:
1531   # pool section:
1532   # RAW USED The near raw used per pool in raw total
1533
1534   ceph osd pool create cephdf_for_test 32 32 replicated
1535   ceph osd pool set cephdf_for_test size 2
1536
1537   dd if=/dev/zero of=./cephdf_for_test bs=4k count=1
1538   rados put cephdf_for_test cephdf_for_test -p cephdf_for_test
1539
1540   #wait for update
1541   sleep 10
1542
1543   cal_raw_used_size=`ceph df detail | grep cephdf_for_test | awk -F ' ' '{printf "%d\n", 2 * $4}'`
1544   raw_used_size=`ceph df detail | grep cephdf_for_test | awk -F ' '  '{print $11}'`
1545
1546   ceph osd pool delete cephdf_for_test cephdf_for_test --yes-i-really-really-mean-it
1547   rm ./cephdf_for_test
1548
1549   expect_false test $cal_raw_used_size != $raw_used_size
1550 }
1551
1552 #
1553 # New tests should be added to the TESTS array below
1554 #
1555 # Individual tests may be run using the '-t <testname>' argument
1556 # The user can specify '-t <testname>' as many times as she wants
1557 #
1558 # Tests will be run in order presented in the TESTS array, or in
1559 # the order specified by the '-t <testname>' options.
1560 #
1561 # '-l' will list all the available test names
1562 # '-h' will show usage
1563 #
1564 # The test maintains backward compatibility: not specifying arguments
1565 # will run all tests following the order they appear in the TESTS array.
1566 #
1567
1568 set +x
1569 MON_TESTS+=" mon_injectargs"
1570 MON_TESTS+=" mon_injectargs_SI"
1571 MON_TESTS+=" tiering"
1572 MON_TESTS+=" auth"
1573 MON_TESTS+=" auth_profiles"
1574 MON_TESTS+=" mon_misc"
1575 MON_TESTS+=" mon_mon"
1576 MON_TESTS+=" mon_osd"
1577 MON_TESTS+=" mon_osd_pool"
1578 MON_TESTS+=" mon_osd_pool_quota"
1579 MON_TESTS+=" mon_pg"
1580 MON_TESTS+=" mon_osd_pool_set"
1581 MON_TESTS+=" mon_osd_tiered_pool_set"
1582 MON_TESTS+=" mon_osd_erasure_code"
1583 MON_TESTS+=" mon_osd_misc"
1584 MON_TESTS+=" mon_heap_profiler"
1585 MON_TESTS+=" mon_tell"
1586 MON_TESTS+=" mon_crushmap_validation"
1587 MON_TESTS+=" mon_cephdf_commands"
1588
1589 OSD_TESTS+=" osd_bench"
1590 OSD_TESTS+=" osd_negative_filestore_merge_threshold"
1591 OSD_TESTS+=" tiering_agent"
1592
1593 MDS_TESTS+=" mds_tell"
1594 MDS_TESTS+=" mon_mds"
1595
1596 TESTS+=$MON_TESTS
1597 TESTS+=$OSD_TESTS
1598 TESTS+=$MDS_TESTS
1599
1600 #
1601 # "main" follows
1602 #
1603
1604 function list_tests()
1605 {
1606   echo "AVAILABLE TESTS"
1607   for i in $TESTS; do
1608     echo "  $i"
1609   done
1610 }
1611
1612 function usage()
1613 {
1614   echo "usage: $0 [-h|-l|-t <testname> [-t <testname>...]]"
1615 }
1616
1617 tests_to_run=()
1618
1619 sanity_check=true
1620
1621 while [[ $# -gt 0 ]]; do
1622   opt=$1
1623
1624   case "$opt" in
1625     "-l" )
1626       do_list=1
1627       ;;
1628     "--asok-does-not-need-root" )
1629       SUDO=""
1630       ;;
1631     "--no-sanity-check" )
1632       sanity_check=false
1633       ;;
1634     "--test-mon" )
1635       tests_to_run+="$MON_TESTS"
1636       ;;
1637     "--test-osd" )
1638       tests_to_run+="$OSD_TESTS"
1639       ;;
1640     "--test-mds" )
1641       tests_to_run+="$MDS_TESTS"
1642       ;;
1643     "-t" )
1644       shift
1645       if [[ -z "$1" ]]; then
1646         echo "missing argument to '-t'"
1647         usage ;
1648         exit 1
1649       fi
1650       tests_to_run+=" $1"
1651       ;;
1652     "-h" )
1653       usage ;
1654       exit 0
1655       ;;
1656   esac
1657   shift
1658 done
1659
1660 if [[ $do_list -eq 1 ]]; then
1661   list_tests ;
1662   exit 0
1663 fi
1664
1665 if test -z "$tests_to_run" ; then
1666   tests_to_run="$TESTS"
1667 fi
1668
1669 if $sanity_check ; then
1670     wait_no_osd_down
1671 fi
1672 for i in $tests_to_run; do
1673   if $sanity_check ; then
1674       check_no_osd_down
1675   fi
1676   set -x
1677   test_${i}
1678   set +x
1679 done
1680 if $sanity_check ; then
1681     check_no_osd_down
1682 fi
1683
1684 set -x
1685
1686 echo OK