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