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