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