Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[fs/lustre-release.git] / lustre / tests / test-framework.sh
1 #!/bin/sh
2
3 set -e
4 export REFORMAT=""
5 export VERBOSE=false
6
7 # eg, assert_env LUSTRE MDSNODES OSTNODES CLIENTS
8 assert_env() {
9     local failed=""
10     for name in $@; do
11       if [ -z "${!name}" ]; then
12           echo "$0: $name must be set"
13           failed=1
14       fi
15     done
16     [ $failed ] && exit 1 || true
17 }
18
19 usage() {
20     echo "usage: $0 [-r] [-f cfgfile]"
21     echo "       -r: reformat"
22
23     exit
24 }
25
26 init_test_env() {
27     export LUSTRE=`absolute_path $LUSTRE`
28     export TESTSUITE=`basename $0 .sh`
29     export XMLCONFIG=${XMLCONFIG:-${TESTSUITE}.xml}
30     export LTESTDIR=${LTESTDIR:-$LUSTRE/../ltest}
31
32     [ -d /r ] && export ROOT=/r
33     export TMP=${TMP:-$ROOT/tmp}
34
35     export PATH=:$PATH:$LUSTRE/utils:$LUSTRE/tests
36     export LLMOUNT=${LLMOUNT:-"llmount"}
37     export LCONF=${LCONF:-"lconf"}
38     export LMC=${LMC:-"lmc"}
39     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
40     export CHECKSTAT="${CHECKSTAT:-checkstat} "
41     export FSYTPE=${FSTYPE:-"ext3"}
42
43     # Paths on remote nodes, if different 
44     export RLUSTRE=${RLUSTRE:-$LUSTRE}
45     export RPWD=${RPWD:-$PWD}
46
47     # command line
48     
49     while getopts "rvf:" opt $*; do 
50         case $opt in
51             f) CONFIG=$OPTARG;;
52             r) REFORMAT=--reformat;;
53             v) VERBOSE=true;;
54             \?) usage;;
55         esac
56     done
57     
58     shift $((OPTIND - 1))
59     ONLY=${ONLY:-$*}
60     
61     # save the name of the config file for the upcall
62     echo "XMLCONFIG=$LUSTRE/tests/$XMLCONFIG"  > $LUSTRE/tests/XMLCONFIG
63 #    echo "CONFIG=`canonical_path $CONFIG`"  > $LUSTRE/tests/CONFIG
64 }
65
66 # Facet functions
67 start() {
68     facet=$1
69     shift
70     active=`facet_active $facet`
71     do_facet $facet $LCONF --select ${facet}_svc=${active}_facet \
72         --node ${active}_facet  --ptldebug $PTLDEBUG --subsystem $SUBSYSTEM \
73         $@ $XMLCONFIG
74 }
75
76 stop() {
77     facet=$1
78     active=`facet_active $facet`
79     shift
80     do_facet $facet $LCONF --select ${facet}_svc=${active}_facet \
81         --node ${active}_facet  --ptldebug $PTLDEBUG --subsystem $SUBSYSTEM \
82         $@ --cleanup $XMLCONFIG
83 }
84
85 zconf_mount() {
86     client=$1
87     mnt=$2
88
89     do_node $client mkdir $mnt 2> /dev/null || :
90
91     if [ -x /sbin/mount.lustre ] ; then
92         do_node $client mount -t lustre -o nettype=$NETTYPE `facet_active_host mds1`:/mds1_svc/client_facet $mnt || return 1
93     else
94        # this is so cheating
95        do_node $client $LCONF --nosetup --node client_facet $XMLCONFIG  > /dev/null || return 2
96        do_node $client $LLMOUNT `facet_active_host mds1`:/mds1_svc/client_facet $mnt -o nettype=$NETTYPE|| return 4
97     fi
98
99     [ -d /r ] && $LCTL modules > /r/tmp/ogdb-`hostname`
100     return 0
101 }
102
103 zconf_umount() {
104     client=$1
105     mnt=$2
106     [ "$3" ] && force=-f
107     do_node $client umount $force  $mnt || :
108     do_node $client $LCONF --cleanup --nosetup --node client_facet $XMLCONFIG > /dev/null || :
109 }
110
111 shutdown_facet() {
112     facet=$1
113     if [ "$FAILURE_MODE" = HARD ]; then
114        $POWER_DOWN `facet_active_host $facet`
115        sleep 2 
116     elif [ "$FAILURE_MODE" = SOFT ]; then
117        stop $facet --force --failover --nomod
118     fi
119 }
120
121 reboot_facet() {
122     facet=$1
123     if [ "$FAILURE_MODE" = HARD ]; then
124        $POWER_UP `facet_active_host $facet`
125     fi
126 }
127
128 wait_for_host() {
129    HOST=$1
130    check_network  $HOST 900
131    while ! do_node $HOST "ls -d $LUSTRE " > /dev/null; do sleep 5; done
132 }
133
134 wait_for() {
135    facet=$1
136    HOST=`facet_active_host $facet`
137    wait_for_host $HOST
138 }
139
140 client_df() {
141     # not every config has many clients
142     if [ ! -z "$CLIENTS" ]; then
143         $PDSH $CLIENTS "df $MOUNT" > /dev/null
144     fi
145 }
146
147 facet_failover() {
148     facet=$1
149     echo "Failing $facet node `facet_active_host $facet`"
150     shutdown_facet $facet
151     reboot_facet $facet
152     client_df &
153     DFPID=$!
154     echo "df pid is $DFPID"
155     change_active $facet
156     TO=`facet_active_host $facet`
157     echo "Failover $facet to $TO"
158     wait_for $facet
159     start $facet
160 }
161
162 replay_barrier() {
163     local facet=$1
164     do_facet $facet sync
165     df $MOUNT
166     do_facet $facet $LCTL --device %${facet}_svc readonly
167     do_facet $facet $LCTL --device %${facet}_svc notransno
168     do_facet $facet $LCTL mark "REPLAY BARRIER"
169     $LCTL mark "REPLAY BARRIER"
170 }
171
172 mds_evict_client() {
173     UUID=`cat /proc/fs/lustre/mdc/*_MNT_*/uuid`
174     do_facet mds "echo $UUID > /proc/fs/lustre/mds/mds1_svc/evict_client"
175 }
176
177 fail() {
178     local facet=$1
179     facet_failover $facet
180     df $MOUNT || error "post-failover df: $?"
181 }
182
183 fail_abort() {
184     local facet=$1
185     stop $facet --force --failover --nomod
186     change_active $facet
187     start $facet
188     do_facet $facet lctl --device %${facet}_svc abort_recovery
189     df $MOUNT || echo "first df failed: $?"
190     sleep 1
191     df $MOUNT || error "post-failover df: $?"
192 }
193
194 do_lmc() {
195     $LMC -m ${XMLCONFIG} $@
196 }
197
198 h2gm () {
199    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
200        $PDSH $1 $GMNALNID -l | cut -d\  -f2
201    fi
202 }
203
204 h2tcp() {
205    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
206    echo $1 
207    fi
208 }
209 declare -fx h2tcp
210
211 h2elan() {
212    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
213    echo $1 | sed 's/[^0-9]*//g'
214    fi
215 }
216 declare -fx h2elan
217
218 h2openib() {
219    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
220    echo $1 | sed 's/[^0-9]*//g'
221    fi
222 }
223 declare -fx h2openib
224
225
226 facet_host() {
227    local facet=$1
228    varname=${facet}_HOST
229    echo -n ${!varname}
230 }
231
232 facet_nid() {
233    facet=$1
234    HOST=`facet_host $facet`
235    if [ -z "$HOST" ]; then
236         echo "The env variable ${facet}_HOST must be set."
237         exit 1
238    fi
239    echo `h2$NETTYPE $HOST`
240 }
241
242 facet_active() {
243     local facet=$1
244     local activevar=${facet}active
245
246     if [ -f ./${facet}active ] ; then
247         source ./${facet}active
248     fi
249
250     active=${!activevar}
251     if [ -z "$active" ] ; then 
252         echo -n ${facet}
253     else
254         echo -n ${active}
255     fi
256 }
257
258 facet_active_host() {
259     local facet=$1
260     local active=`facet_active $facet`
261     if [ "$facet" == client ]; then
262         hostname
263     else
264         echo `facet_host $active`
265     fi
266 }
267
268 change_active() {
269     local facet=$1
270     failover=${facet}failover 
271     host=`facet_host $failover`
272     [ -z "$host" ] && return
273     curactive=`facet_active $facet`
274     if [ -z "${curactive}" -o "$curactive" == "$failover" ] ; then
275         eval export ${facet}active=$facet
276     else
277         eval export ${facet}active=$failover
278     fi
279     # save the active host for this facet
280     activevar=${facet}active
281     echo "$activevar=${!activevar}" > ./$activevar
282 }
283
284 do_node() {
285     HOST=$1
286     shift
287
288     if $VERBOSE; then
289         echo "CMD: $HOST $@"
290         $PDSH $HOST $LCTL mark "$@" > /dev/null 2>&1 || :
291     fi
292     $PDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests; cd $RPWD; sh -c \"$@\")"
293 }
294
295 mds_list() {
296     seq -f mds%g $MDSCOUNT
297 }
298
299 do_facet() {
300     facet=$1
301     shift
302
303     if [ "$facet" == "mds" ]; then
304         for mds in `mds_list`; do
305            HOST=`facet_active_host $mds`
306            do_node $HOST $@
307         done
308     else
309         HOST=`facet_active_host $facet`
310         do_node $HOST $@
311     fi
312 }
313
314 add_facet() {
315     local facet=$1
316     shift
317     echo "add facet $facet: `facet_host $facet`"
318     do_lmc --add node --node ${facet}_facet $@ --timeout $TIMEOUT \
319         --lustre_upcall $UPCALL --ptldebug $PTLDEBUG --subsystem $SUBSYSTEM
320     do_lmc --add net --node ${facet}_facet --nid `facet_nid $facet` \
321         --nettype $NETTYPE
322 }
323
324 add_mds() {
325     facet=$1
326     shift
327     rm -f ${facet}active
328     add_facet $facet
329     do_lmc --add mds --node ${facet}_facet --mds ${facet}_svc --fstype $FSTYPE $*
330 }
331
332 add_mdsfailover() {
333     facet=$1
334     shift
335     add_facet ${facet}failover  --lustre_upcall $UPCALL
336     do_lmc --add mds  --node ${facet}failover_facet --mds ${facet}_svc --fstype $FSTYPE $*
337 }
338
339 add_ost() {
340     facet=$1
341     shift
342     rm -f ${facet}active
343     add_facet $facet
344     do_lmc --add ost --node ${facet}_facet --ost ${facet}_svc --fstype $FSTYPE $*
345 }
346
347 del_ost() {
348     facet=$1
349     shift
350     do_lmc --delete ost --node ${facet}_facet --ost ${facet}_svc $*
351 }
352
353 deactivate_ost() {
354     facet=$1
355     shift
356     do_lmc --deactivate ost --node ${facet}_facet --ost ${facet}_svc $*
357 }
358
359 add_ostfailover() {
360     facet=$1
361     shift
362     add_facet ${facet}failover
363     do_lmc --add ost --failover --node ${facet}failover_facet --ost ${facet}_svc --fstype $FSTYPE $*
364 }
365
366 add_lov() {
367     lov=$1
368     mds_facet=$2
369     shift; shift
370     do_lmc --add lov --mds ${mds_facet}_svc --lov $lov $*
371 }
372
373 add_lov_to_lmv() {
374     lov=$1
375     lmv=$2
376     shift; shift
377     do_lmc --add lov --lmv $lmv --lov $lov $*
378 }
379
380 add_lmv() {
381     lmv=$1
382     shift;
383     do_lmc --add lmv --lmv $lmv $*
384 }
385
386 add_client() {
387     facet=$1
388     mds=$2
389     shift; shift
390     add_facet $facet --lustre_upcall $UPCALL
391     do_lmc --add mtpt --node ${facet}_facet --mds ${mds}_svc $*
392 }
393
394 config_commit() {
395     do_lmc --commit
396 }
397
398 ####### 
399 # General functions
400
401 check_network() {
402    local NETWORK=0
403    local WAIT=0
404    local MAX=$2
405    while [ $NETWORK -eq 0 ]; do
406       ping -c 1 -w 3 $1 > /dev/null
407       if [ $? -eq 0 ]; then
408          NETWORK=1
409       else
410          WAIT=$((WAIT + 5))
411          echo "waiting for $1, $((MAX - WAIT)) secs left"
412          sleep 5
413       fi
414       if [ $WAIT -gt $MAX ]; then
415          echo "Network not available"
416          exit 1
417       fi
418    done
419 }
420 check_port() {
421    while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
422       sleep 9
423    done
424 }
425
426 no_dsh() {
427    shift
428    eval $@
429 }
430
431 comma_list() {
432     # the sed converts spaces to commas, but leaves the last space
433     # alone, so the line doesn't end with a comma.
434     echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
435 }
436
437 absolute_path() {
438    (cd `dirname $1`; echo $PWD/`basename $1`)
439 }
440
441 ##################################
442 # OBD_FAIL funcs
443
444 drop_request() {
445 # OBD_FAIL_MDS_ALL_REQUEST_NET
446     RC=0
447     do_facet mds "echo 0x123 > /proc/sys/lustre/fail_loc"
448     do_facet client "$1" || RC=$?
449     do_facet mds "echo 0 > /proc/sys/lustre/fail_loc"
450     return $RC
451 }
452
453 drop_reply() {
454 # OBD_FAIL_MDS_ALL_REPLY_NET
455     RC=0
456     do_facet mds "echo 0x122 > /proc/sys/lustre/fail_loc"
457     do_facet client "$@" || RC=$?
458     do_facet mds "echo 0 > /proc/sys/lustre/fail_loc"
459     return $RC
460 }
461
462 drop_reint_reply() {
463 # OBD_FAIL_MDS_REINT_NET_REP
464     RC=0
465     do_facet mds "echo 0x119 > /proc/sys/lustre/fail_loc"
466     do_facet client "$@" || RC=$?
467     do_facet mds "echo 0 > /proc/sys/lustre/fail_loc"
468     return $RC
469 }
470
471 pause_bulk() {
472 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
473     RC=0
474     do_facet ost "echo 0x214 > /proc/sys/lustre/fail_loc"
475     do_facet client "$1" || RC=$?
476     do_facet client "sync"
477     do_facet ost "echo 0 > /proc/sys/lustre/fail_loc"
478     return $RC
479 }
480
481 drop_ldlm_cancel() {
482 #define OBD_FAIL_LDLM_CANCEL             0x304
483     RC=0
484     do_facet client "echo 0x304 > /proc/sys/lustre/fail_loc"
485     do_facet client "$@" || RC=$?
486     do_facet client "echo 0 > /proc/sys/lustre/fail_loc"
487     return $RC
488 }
489
490 drop_bl_callback() {
491 #define OBD_FAIL_LDLM_BL_CALLBACK        0x305
492     RC=0
493     do_facet client "echo 0x305 > /proc/sys/lustre/fail_loc"
494     do_facet client "$@" || RC=$?
495     do_facet client "echo 0 > /proc/sys/lustre/fail_loc"
496     return $RC
497 }
498
499 clear_failloc() {
500     facet=$1
501     pause=$2
502     sleep $pause
503     echo "clearing fail_loc on $facet"
504     do_facet $facet "sysctl -w lustre.fail_loc=0"
505 }
506
507 cancel_lru_locks() {
508     $LCTL mark cancel_lru_locks
509     for d in /proc/fs/lustre/ldlm/namespaces/$1*; do
510         if [ -f $d/lru_size ]; then
511             echo clear > $d/lru_size
512             grep [0-9] $d/lock_unused_count
513         fi
514     done
515 }
516
517
518 pgcache_empty() {
519     for a in /proc/fs/lustre/llite/*/dump_page_cache; do
520         if [ `wc -l $a | awk '{print $1}'` -gt 1 ]; then
521                 echo there is still data in page cache $a ?
522                 cat $a;
523                 return 1;
524         fi
525     done
526     return 0
527 }
528
529 ##################################
530 # Test interface 
531 error() {
532     echo "${TESTSUITE}: **** FAIL:" $@
533     log "FAIL: $@"
534     exit 1
535 }
536
537 build_test_filter() {
538         for O in $ONLY; do
539             eval ONLY_${O}=true
540         done
541         for E in $EXCEPT $ALWAYS_EXCEPT; do
542             eval EXCEPT_${E}=true
543         done
544 }
545
546 _basetest() {
547     echo $*
548 }
549
550 basetest() {
551     IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
552 }
553
554 run_test() {
555         export base=`basetest $1`
556         if [ ! -z "$ONLY" ]; then
557                  testname=ONLY_$1
558                  if [ ${!testname}x != x ]; then
559                      run_one $1 "$2"
560                      return $?
561                  fi
562                  testname=ONLY_$base
563                  if [ ${!testname}x != x ]; then
564                      run_one $1 "$2"
565                      return $?
566                  fi
567                  echo -n "."
568                  return 0
569         fi
570         testname=EXCEPT_$1
571         if [ ${!testname}x != x ]; then
572                  echo "skipping excluded test $1"
573                  return 0
574         fi
575         testname=EXCEPT_$base
576         if [ ${!testname}x != x ]; then
577                  echo "skipping excluded test $1 (base $base)"
578                  return 0
579         fi
580         run_one $1 "$2"
581
582         return $?
583 }
584
585 EQUALS="======================================================================"
586 equals_msg() {
587    msg="$@"
588
589    local suffixlen=$((${#EQUALS} - ${#msg}))
590    [ $suffixlen -lt 5 ] && suffixlen=5
591    printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS
592 }
593
594 log() {
595         echo "$*"
596         lctl mark "$*" 2> /dev/null || true
597 }
598
599 run_one() {
600     testnum=$1
601     message=$2
602     tfile=f${testnum}
603     tdir=d${base}
604
605     # Pretty tests run faster.
606     equals_msg $testnum: $message
607
608     log "== test $1: $2"
609     test_${testnum} || error "test_$testnum failed with $?"
610 }
611
612 canonical_path() {
613    (cd `dirname $1`; echo $PWD/`basename $1`)
614 }
615