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