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