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