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