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