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