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