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