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