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