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