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