Whamcloud - gitweb
924fafc4288b03cb36c44529cc54325841d383dd
[fs/lustre-release.git] / lustre / tests / test-framework.sh
1 #!/bin/bash
2 # vim:expandtab:shiftwidth=4:softtabstop=4:tabstop=4:
3
4 trap 'print_summary && echo "test-framework exiting on error"' ERR
5 set -e
6 #set -x
7
8
9 export REFORMAT=${REFORMAT:-""}
10 export VERBOSE=false
11 export GMNALNID=${GMNALNID:-/usr/sbin/gmlndnid}
12 export CATASTROPHE=${CATASTROPHE:-/proc/sys/lnet/catastrophe}
13 export GSS=false
14 export GSS_KRB5=false
15 export GSS_PIPEFS=false
16 #export PDSH="pdsh -S -Rssh -w"
17
18 # eg, assert_env LUSTRE MDSNODES OSTNODES CLIENTS
19 assert_env() {
20     local failed=""
21     for name in $@; do
22         if [ -z "${!name}" ]; then
23             echo "$0: $name must be set"
24             failed=1
25         fi
26     done
27     [ $failed ] && exit 1 || true
28 }
29
30 usage() {
31     echo "usage: $0 [-r] [-f cfgfile]"
32     echo "       -r: reformat"
33
34     exit
35 }
36
37 print_summary () {
38     [ -n "$ONLY" ] && echo "WARNING: ONLY is set to ${ONLY}."
39     local form="%-13s %-17s %s\n"
40     echo "$(printf "$form" "status" "script" "skipped tests")"
41     echo "------------------------------------------------------------------------------------"
42     for O in $TESTSUITE_LIST; do
43         local skipped=""
44         local o=$(echo $O | tr "[:upper:]" "[:lower:]")
45         o=${o//_/-}
46         o=${o//tyn/tyN}
47         local log=${TMP}/${o}.log 
48         [ -f $log ] && skipped=$(cat $log | awk '{ printf " %s", $3 }' | sed 's/test_//g')
49         [ "${!O}" = "done" ] && \
50             echo "$(printf "$form" "Done" "$O" "$skipped")"
51     done
52
53     for O in $TESTSUITE_LIST; do
54         [ "${!O}" = "no" ] && \
55             echo "$(printf "$form" "Skipped" "$O" "")"
56     done
57
58     for O in $TESTSUITE_LIST; do
59         [ "${!O}" = "done" -o "${!O}" = "no" ] || \
60             echo "$(printf "$form" "UNFINISHED" "$O" "")"
61     done
62 }
63
64 init_test_env() {
65     export LUSTRE=`absolute_path $LUSTRE`
66     export TESTSUITE=`basename $0 .sh`
67     export LTESTDIR=${LTESTDIR:-$LUSTRE/../ltest}
68
69     [ -d /r ] && export ROOT=${ROOT:-/r}
70     export TMP=${TMP:-$ROOT/tmp}
71     export TESTSUITELOG=${TMP}/${TESTSUITE}.log
72
73     export PATH=:$PATH:$LUSTRE/utils:$LUSTRE/utils/gss:$LUSTRE/tests
74     export LCTL=${LCTL:-"$LUSTRE/utils/lctl"}
75     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
76     [ ! -f "$LCTL" ] && export LCTL=$(which lctl) 
77     export LFS=${LFS:-"$LUSTRE/utils/lfs"}
78     [ ! -f "$LFS" ] && export LFS=$(which lfs) 
79     export MKFS=${MKFS:-"$LUSTRE/utils/mkfs.lustre"}
80     [ ! -f "$MKFS" ] && export MKFS=$(which mkfs.lustre) 
81     export TUNEFS=${TUNEFS:-"$LUSTRE/utils/tunefs.lustre"}
82     [ ! -f "$TUNEFS" ] && export TUNEFS=$(which tunefs.lustre) 
83     export CHECKSTAT="${CHECKSTAT:-"checkstat -v"} "
84     export FSYTPE=${FSTYPE:-"ldiskfs"}
85     export NAME=${NAME:-local}
86     export LPROC=/proc/fs/lustre
87     export LGSSD=${LGSSD:-"$LUSTRE/utils/gss/lgssd"}
88     export LSVCGSSD=${LSVCGSSD:-"$LUSTRE/utils/gss/lsvcgssd"}
89     export KRB5DIR=${KRB5DIR:-"/usr/kerberos"}
90     export DIR2
91
92     if [ "$ACCEPTOR_PORT" ]; then
93         export PORT_OPT="--port $ACCEPTOR_PORT"
94     fi
95
96     case "x$SEC" in
97         xkrb5*)
98             echo "Using GSS/krb5 ptlrpc security flavor"
99             GSS=true
100             GSS_KRB5=true
101             ;;
102     esac
103
104     # Paths on remote nodes, if different 
105     export RLUSTRE=${RLUSTRE:-$LUSTRE}
106     export RPWD=${RPWD:-$PWD}
107     export I_MOUNTED=${I_MOUNTED:-"no"}
108
109     # command line
110     
111     while getopts "rvf:" opt $*; do 
112         case $opt in
113             f) CONFIG=$OPTARG;;
114             r) REFORMAT=--reformat;;
115             v) VERBOSE=true;;
116             \?) usage;;
117         esac
118     done
119
120     shift $((OPTIND - 1))
121     ONLY=${ONLY:-$*}
122
123     [ "$TESTSUITELOG" ] && rm -f $TESTSUITELOG || true
124
125 }
126
127 load_module() {
128     EXT=".ko"
129     module=$1
130     shift
131     BASE=`basename $module $EXT`
132     lsmod | grep -q ${BASE} || \
133       if [ -f ${LUSTRE}/${module}${EXT} ]; then
134         insmod ${LUSTRE}/${module}${EXT} $@
135     else
136         # must be testing a "make install" or "rpm" installation
137         # note failed to load ptlrpc_gss is considered not fatal
138         if [ "$BASE" == "ptlrpc_gss" ]; then
139             modprobe $BASE $@ 2>/dev/null || echo "gss/krb5 is not supported"
140         else
141             modprobe $BASE $@
142         fi
143     fi
144 }
145
146 load_modules() {
147     if [ -n "$MODPROBE" ]; then
148         # use modprobe
149     return 0
150     fi
151     if [ "$HAVE_MODULES" = true ]; then
152     # we already loaded
153         return 0
154     fi
155     HAVE_MODULES=true
156
157     echo Loading modules from $LUSTRE
158     load_module ../lnet/libcfs/libcfs
159     [ -z "$LNETOPTS" ] && \
160         LNETOPTS=$(awk '/^options lnet/ { print $0}' /etc/modprobe.conf | sed 's/^options lnet //g')
161     echo "lnet options: '$LNETOPTS'"
162     # note that insmod will ignore anything in modprobe.conf
163     load_module ../lnet/lnet/lnet $LNETOPTS
164     LNETLND=${LNETLND:-"socklnd/ksocklnd"}
165     load_module ../lnet/klnds/$LNETLND
166     [ "$FSTYPE" = "ldiskfs" ] && load_module ../ldiskfs/ldiskfs/ldiskfs
167     load_module lvfs/lvfs
168     load_module obdclass/obdclass
169     load_module lvfs/fsfilt_$FSTYPE
170     load_module ptlrpc/ptlrpc
171     load_module ptlrpc/gss/ptlrpc_gss
172     # Now, some modules depend on lquota without USE_QUOTA check,
173     # will fix later. Disable check "$USE_QUOTA" = "yes" temporary.
174     #[ "$USE_QUOTA" = "yes" ] && load_module quota/lquota
175     load_module quota/lquota
176     load_module fid/fid
177     load_module fld/fld
178     load_module lmv/lmv
179     load_module mdc/mdc
180     load_module osc/osc
181     load_module lov/lov
182     load_module mds/mds
183     load_module mdd/mdd
184     load_module mdt/mdt
185     load_module cmm/cmm
186     load_module osd/osd
187     load_module ost/ost
188     load_module obdfilter/obdfilter
189     load_module llite/lustre
190     load_module llite/llite_lloop
191     load_module mgc/mgc
192     load_module mgs/mgs
193     rm -f $TMP/ogdb-`hostname`
194     $LCTL modules > $TMP/ogdb-`hostname`
195     # 'mount' doesn't look in $PATH, just sbin
196     [ -f $LUSTRE/utils/mount.lustre ] && cp $LUSTRE/utils/mount.lustre /sbin/. || true
197 }
198
199 RMMOD=rmmod
200 if [ `uname -r | cut -c 3` -eq 4 ]; then
201     RMMOD="modprobe -r"
202 fi
203
204 wait_for_lnet() {
205     local UNLOADED=0
206     local WAIT=0
207     local MAX=60
208     MODULES=$($LCTL modules | awk '{ print $2 }')
209     while [ -n "$MODULES" ]; do
210     sleep 5
211     $RMMOD $MODULES > /dev/null 2>&1 || true
212     MODULES=$($LCTL modules | awk '{ print $2 }')
213         if [ -z "$MODULES" ]; then
214         return 0
215         else
216             WAIT=$((WAIT + 5))
217             echo "waiting, $((MAX - WAIT)) secs left"
218         fi
219         if [ $WAIT -eq $MAX ]; then
220             echo "LNET modules $MODULES will not unload"
221         lsmod
222             return 3
223         fi
224     done
225 }
226
227 unload_modules() {
228     wait_exit_ST client # bug 12845
229
230     lsmod | grep lnet > /dev/null && $LCTL dl && $LCTL dk $TMP/debug
231     local MODULES=$($LCTL modules | awk '{ print $2 }')
232     $RMMOD $MODULES > /dev/null 2>&1 || true
233      # do it again, in case we tried to unload ksocklnd too early
234     MODULES=$($LCTL modules | awk '{ print $2 }')
235     [ -n "$MODULES" ] && $RMMOD $MODULES > /dev/null 2>&1 || true
236     MODULES=$($LCTL modules | awk '{ print $2 }')
237     if [ -n "$MODULES" ]; then
238     echo "Modules still loaded: "
239     echo $MODULES 
240     if [ -e $LPROC ]; then
241         echo "Lustre still loaded"
242         cat $LPROC/devices || true
243         lsmod
244         return 2
245     else
246         echo "Lustre stopped but LNET is still loaded, waiting..."
247         wait_for_lnet || return 3
248     fi
249     fi
250     HAVE_MODULES=false
251
252     LEAK_LUSTRE=$(dmesg | tail -n 30 | grep "obd mem.*leaked" || true)
253     LEAK_PORTALS=$(dmesg | tail -n 20 | grep "Portals memory leaked" || true)
254     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
255         echo "$LEAK_LUSTRE" 1>&2
256         echo "$LEAK_PORTALS" 1>&2
257         mv $TMP/debug $TMP/debug-leak.`date +%s` || true
258         echo "Memory leaks detected"
259         [ -n "$IGNORE_LEAK" ] && echo "ignoring leaks" && return 0
260         return 254
261     fi
262     echo "modules unloaded."
263     return 0
264 }
265
266 check_gss_daemon_facet() {
267     facet=$1
268     dname=$2
269
270     num=`do_facet $facet ps -o cmd -C $dname | grep $dname | wc -l`
271     if [ $num -ne 1 ]; then
272         echo "$num instance of $dname on $facet"
273         return 1
274     fi
275     return 0
276 }
277
278 send_sigint() {
279     local facet=$1
280     shift
281     do_facet $facet "killall -2 $@ 2>/dev/null || true"
282 }
283
284 start_gss_daemons() {
285     # starting on MDT
286     for num in `seq $MDSCOUNT`; do
287         do_facet mds$num "$LSVCGSSD -v"
288         if $GSS_PIPEFS; then
289             do_facet mds$num "$LGSSD -v"
290         fi
291     done
292     # starting on OSTs
293     for num in `seq $OSTCOUNT`; do
294         do_facet ost$num "$LSVCGSSD -v"
295     done
296     # starting on client
297     # FIXME: is "client" the right facet name?
298     if $GSS_PIPEFS; then
299         do_facet client "$LGSSD -v"
300     fi
301
302     # wait daemons entering "stable" status
303     sleep 5
304
305     #
306     # check daemons are running
307     #
308     for num in `seq $MDSCOUNT`; do
309         check_gss_daemon_facet mds$num lsvcgssd
310         if $GSS_PIPEFS; then
311             check_gss_daemon_facet mds$num lgssd
312         fi
313     done
314     for num in `seq $OSTCOUNT`; do
315         check_gss_daemon_facet ost$num lsvcgssd
316     done
317     if $GSS_PIPEFS; then
318         check_gss_daemon_facet client lgssd
319     fi
320 }
321
322 stop_gss_daemons() {
323     for num in `seq $MDSCOUNT`; do
324         send_sigint mds$num lsvcgssd lgssd
325     done
326     for num in `seq $OSTCOUNT`; do
327         send_sigint ost$num lsvcgssd
328     done
329     send_sigint client lgssd
330 }
331
332 init_krb5_env() {
333     if [ ! -z $SEC ]; then
334         MDS_MOUNT_OPTS=$MDS_MOUNT_OPTS,sec=$SEC
335         OST_MOUNT_OPTS=$OST_MOUNT_OPTS,sec=$SEC
336     fi
337
338     if $GSS; then
339         start_gss_daemons
340     fi
341 }
342
343 cleanup_krb5_env() {
344     if $GSS; then
345         stop_gss_daemons
346         # maybe cleanup credential cache?
347     fi
348 }
349
350 mdsdevlabel() {
351     local num=$1
352     local device=`mdsdevname $num`
353     local label=`do_facet mds$num "e2label ${device}" | grep -v "CMD: "`
354     echo -n $label
355 }
356
357 ostdevlabel() {
358     local num=$1
359     local device=`ostdevname $num`
360     local label=`do_facet ost$num "e2label ${device}" | grep -v "CMD: "`
361     echo -n $label
362 }
363
364 # Facet functions
365 # start facet device options 
366 start() {
367     facet=$1
368     shift
369     device=$1
370     shift
371     echo "Starting ${facet}: $@ ${device} ${MOUNT%/*}/${facet}"
372     do_facet ${facet} mkdir -p ${MOUNT%/*}/${facet}
373     do_facet ${facet} mount -t lustre $@ ${device} ${MOUNT%/*}/${facet} 
374     RC=${PIPESTATUS[0]}
375     if [ $RC -ne 0 ]; then
376         echo mount -t lustre $@ ${device} ${MOUNT%/*}/${facet} 
377         echo Start of ${device} on ${facet} failed ${RC}
378     else 
379         do_facet ${facet} "sysctl -w lnet.debug=$PTLDEBUG; \
380         sysctl -w lnet.subsystem_debug=${SUBSYSTEM# }; \
381         sysctl -w lnet.debug_mb=${DEBUG_SIZE}"
382
383         do_facet ${facet} sync
384         label=$(do_facet ${facet} "e2label ${device}")
385         [ -z "$label" ] && echo no label for ${device} && exit 1
386         eval export ${facet}_svc=${label}
387         eval export ${facet}_dev=${device}
388         eval export ${facet}_opt=\"$@\"
389         echo Started ${label}
390     fi
391     return $RC
392 }
393
394 stop() {
395     local running
396     facet=$1
397     shift
398     HOST=`facet_active_host $facet`
399     [ -z $HOST ] && echo stop: no host for $facet && return 0
400
401     running=$(do_facet ${facet} "grep -c ${MOUNT%/*}/${facet}' ' /proc/mounts") || true
402     if [ ${running} -ne 0 ]; then
403         echo "Stopping ${MOUNT%/*}/${facet} (opts:$@)"
404         do_facet ${facet} umount -d $@ ${MOUNT%/*}/${facet}
405     fi
406
407     # umount should block, but we should wait for unrelated obd's
408     # like the MGS or MGC to also stop.
409     wait_exit_ST ${facet}
410 }
411
412 zconf_mount() {
413     local OPTIONS
414     local client=$1
415     local mnt=$2
416     # Only supply -o to mount if we have options
417     if [ -n "$MOUNTOPT" ]; then
418         OPTIONS="-o $MOUNTOPT"
419     fi
420     local device=$MGSNID:/$FSNAME
421     if [ -z "$mnt" -o -z "$FSNAME" ]; then
422         echo Bad zconf mount command: opt=$OPTIONS dev=$device mnt=$mnt
423         exit 1
424     fi
425
426     echo "Starting client: $OPTIONS $device $mnt" 
427     do_node $client mkdir -p $mnt
428     do_node $client mount -t lustre $OPTIONS $device $mnt || return 1
429
430     do_node $client "sysctl -w lnet.debug=$PTLDEBUG;
431         sysctl -w lnet.subsystem_debug=${SUBSYSTEM# };
432         sysctl -w lnet.debug_mb=${DEBUG_SIZE}"
433     [ -d /r ] && $LCTL modules > /r/tmp/ogdb-`hostname`
434     return 0
435 }
436
437 zconf_umount() {
438     client=$1
439     mnt=$2
440     [ "$3" ] && force=-f
441     local running=$(do_node $client "grep -c $mnt' ' /proc/mounts") || true
442     if [ $running -ne 0 ]; then
443         echo "Stopping client $mnt (opts:$force)"
444         do_node $client umount $force $mnt
445     fi
446 }
447
448 shutdown_facet() {
449     facet=$1
450     if [ "$FAILURE_MODE" = HARD ]; then
451         $POWER_DOWN `facet_active_host $facet`
452         sleep 2 
453     elif [ "$FAILURE_MODE" = SOFT ]; then
454         stop $facet
455     fi
456 }
457
458 reboot_facet() {
459     facet=$1
460     if [ "$FAILURE_MODE" = HARD ]; then
461         $POWER_UP `facet_active_host $facet`
462     else
463         sleep 10
464     fi
465 }
466
467 # verify that lustre actually cleaned up properly
468 cleanup_check() {
469     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
470         error "LBUG/LASSERT detected"
471     BUSY=`dmesg | grep -i destruct || true`
472     if [ "$BUSY" ]; then
473         echo "$BUSY" 1>&2
474         [ -e $TMP/debug ] && mv $TMP/debug $TMP/debug-busy.`date +%s`
475         exit 205
476     fi
477     LEAK_LUSTRE=`dmesg | tail -n 30 | grep "obd mem.*leaked" || true`
478     LEAK_PORTALS=`dmesg | tail -n 20 | grep "Portals memory leaked" || true`
479     if [ "$LEAK_LUSTRE" -o "$LEAK_PORTALS" ]; then
480         echo "$0: $LEAK_LUSTRE" 1>&2
481         echo "$0: $LEAK_PORTALS" 1>&2
482         echo "$0: Memory leak(s) detected..." 1>&2
483         mv $TMP/debug $TMP/debug-leak.`date +%s`
484         exit 204
485     fi
486
487     [ "`lctl dl 2> /dev/null | wc -l`" -gt 0 ] && lctl dl && \
488         echo "$0: lustre didn't clean up..." 1>&2 && return 202 || true
489
490     if [ "`/sbin/lsmod 2>&1 | egrep 'lnet|libcfs'`" ]; then
491         echo "$0: modules still loaded..." 1>&2
492         /sbin/lsmod 1>&2
493         return 203
494     fi
495     return 0
496 }
497
498 wait_delete_completed () {
499     local TOTALPREV=`awk 'BEGIN{total=0}; {total+=$1}; END{print total}' \
500             $LPROC/osc/*/kbytesavail`
501
502     local WAIT=0
503     local MAX_WAIT=20
504     while [ "$WAIT" -ne "$MAX_WAIT" ]; do
505         sleep 1
506         TOTAL=`awk 'BEGIN{total=0}; {total+=$1}; END{print total}' \
507             $LPROC/osc/*/kbytesavail`
508         [ "$TOTAL" -eq "$TOTALPREV" ] && break
509         echo "Waiting delete completed ... prev: $TOTALPREV current: $TOTAL "
510         TOTALPREV=$TOTAL
511         WAIT=$(( WAIT + 1))
512     done
513     echo "Delete completed."
514 }
515
516 wait_for_host() {
517     HOST=$1
518     check_network "$HOST" 900
519     while ! do_node $HOST "ls -d $LUSTRE " > /dev/null; do sleep 5; done
520 }
521
522 wait_for() {
523     facet=$1
524     HOST=`facet_active_host $facet`
525     wait_for_host $HOST
526 }
527
528 wait_mds_recovery_done () {
529     local timeout=`do_facet mds cat /proc/sys/lustre/timeout`
530 #define OBD_RECOVERY_TIMEOUT (obd_timeout * 5 / 2)
531 # as we are in process of changing obd_timeout in different ways
532 # let's set MAX longer than that
533     MAX=$(( timeout * 4 ))
534     WAIT=0
535     while [ $WAIT -lt $MAX ]; do
536         STATUS=`do_facet mds grep status /proc/fs/lustre/mdt/*-MDT*/recovery_status`
537         echo $STATUS | grep COMPLETE && return 0
538         sleep 5
539         WAIT=$((WAIT + 5))
540         echo "Waiting $(($MAX - $WAIT)) secs for MDS recovery done"
541     done
542     echo "MDS recovery not done in $MAX sec"
543     return 1            
544 }
545
546 wait_exit_ST () {
547     local facet=$1
548
549     local WAIT=0
550     local INTERVAL=1
551     # conf-sanity 31 takes a long time cleanup
552     while [ $WAIT -lt 300 ]; do
553         running=$(do_facet ${facet} "[ -e $LPROC ] && grep ST' ' $LPROC/devices") || true
554         [ -z "${running}" ] && return 0
555         echo "waited $WAIT for${running}"
556         [ $INTERVAL -lt 64 ] && INTERVAL=$((INTERVAL + INTERVAL))
557         sleep $INTERVAL
558         WAIT=$((WAIT + INTERVAL))
559     done
560     echo "service didn't stop after $WAIT seconds.  Still running:"
561     echo ${running}
562     return 1
563 }
564
565 client_df() {
566     # not every config has many clients
567     if [ ! -z "$CLIENTS" ]; then
568         $PDSH $CLIENTS "df $MOUNT" > /dev/null
569     fi
570 }
571
572 client_reconnect() {
573     uname -n >> $MOUNT/recon
574     if [ ! -z "$CLIENTS" ]; then
575         $PDSH $CLIENTS "df $MOUNT; uname -n >> $MOUNT/recon" > /dev/null
576     fi
577     echo Connected clients:
578     cat $MOUNT/recon
579     ls -l $MOUNT/recon > /dev/null
580     rm $MOUNT/recon
581 }
582
583 facet_failover() {
584     facet=$1
585     echo "Failing $facet on node `facet_active_host $facet`"
586     shutdown_facet $facet
587     reboot_facet $facet
588     client_df &
589     DFPID=$!
590     echo "df pid is $DFPID"
591     change_active $facet
592     TO=`facet_active_host $facet`
593     echo "Failover $facet to $TO"
594     wait_for $facet
595     local dev=${facet}_dev
596     local opt=${facet}_opt
597     start $facet ${!dev} ${!opt} || error "Restart of $facet failed"
598 }
599
600 obd_name() {
601     local facet=$1
602 }
603
604 replay_barrier() {
605     local facet=$1
606     do_facet $facet sync
607     df $MOUNT
608     local svc=${facet}_svc
609     do_facet $facet $LCTL --device %${!svc} readonly
610     do_facet $facet $LCTL --device %${!svc} notransno
611     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
612     $LCTL mark "local REPLAY BARRIER on ${!svc}"
613 }
614
615 replay_barrier_nodf() {
616     local facet=$1    echo running=${running}
617     do_facet $facet sync
618     local svc=${facet}_svc
619     echo Replay barrier on ${!svc}
620     do_facet $facet $LCTL --device %${!svc} readonly
621     do_facet $facet $LCTL --device %${!svc} notransno
622     do_facet $facet $LCTL mark "$facet REPLAY BARRIER on ${!svc}"
623     $LCTL mark "local REPLAY BARRIER on ${!svc}"
624 }
625
626 mds_evict_client() {
627     UUID=`cat /proc/fs/lustre/mdc/${mds1_svc}-mdc-*/uuid`
628     do_facet mds1 "echo $UUID > /proc/fs/lustre/mdt/${mds1_svc}/evict_client"
629 }
630
631 ost_evict_client() {
632     UUID=`grep ${ost1_svc}-osc- $LPROC/devices | egrep -v 'MDT' | awk '{print $5}'`
633     do_facet ost1 "echo $UUID > /proc/fs/lustre/obdfilter/${ost1_svc}/evict_client"
634 }
635
636 fail() {
637     facet_failover $* || error "failover: $?"
638     df $MOUNT || error "post-failover df: $?"
639 }
640
641 fail_abort() {
642     local facet=$1
643     stop $facet
644     change_active $facet
645     local svc=${facet}_svc
646     local dev=${facet}_dev
647     local opt=${facet}_opt
648     start $facet ${!dev} ${!opt}
649     do_facet $facet lctl --device %${!svc} abort_recovery
650     df $MOUNT || echo "first df failed: $?"
651     sleep 1
652     df $MOUNT || error "post-failover df: $?"
653 }
654
655 do_lmc() {
656     echo There is no lmc.  This is mountconf, baby.
657     exit 1
658 }
659
660 h2gm () {
661     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
662         ID=`$PDSH $1 $GMNALNID -l | cut -d\  -f2`
663         echo $ID"@gm"
664     fi
665 }
666
667 h2name_or_ip() {
668     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
669         echo $1"@$2" 
670     fi
671 }
672
673 h2ptl() {
674    if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
675        ID=`xtprocadmin -n $1 2>/dev/null | egrep -v 'NID' | awk '{print $1}'`
676        if [ -z "$ID" ]; then
677            echo "Could not get a ptl id for $1..."
678            exit 1
679        fi
680        echo $ID"@ptl"
681    fi
682 }
683 declare -fx h2ptl
684
685 h2tcp() {
686     h2name_or_ip "$1" "tcp"
687 }
688 declare -fx h2tcp
689
690 h2elan() {
691     if [ "$1" = "client" -o "$1" = "'*'" ]; then echo \'*\'; else
692         if type __h2elan >/dev/null 2>&1; then
693             ID=$(__h2elan $1)
694         else
695             ID=`echo $1 | sed 's/[^0-9]*//g'`
696         fi
697         echo $ID"@elan"
698     fi
699 }
700 declare -fx h2elan
701
702 h2openib() {
703     h2name_or_ip "$1" "openib"
704 }
705 declare -fx h2openib
706
707 h2o2ib() {
708     h2name_or_ip "$1" "o2ib"
709 }
710 declare -fx h2o2ib
711
712 facet_host() {
713     local facet=$1
714     varname=${facet}_HOST
715     if [ -z "${!varname}" ]; then
716         if [ "${facet:0:3}" == "ost" ]; then
717             eval ${facet}_HOST=${ost_HOST}
718         fi
719     fi
720     echo -n ${!varname}
721 }
722
723 facet_active() {
724     local facet=$1
725     local activevar=${facet}active
726
727     if [ -f ./${facet}active ] ; then
728         source ./${facet}active
729     fi
730
731     active=${!activevar}
732     if [ -z "$active" ] ; then 
733         echo -n ${facet}
734     else
735         echo -n ${active}
736     fi
737 }
738
739 facet_active_host() {
740     local facet=$1
741     local active=`facet_active $facet`
742     if [ "$facet" == client ]; then
743         hostname
744     else
745         echo `facet_host $active`
746     fi
747 }
748
749 change_active() {
750     local facet=$1
751     failover=${facet}failover 
752     host=`facet_host $failover`
753     [ -z "$host" ] && return
754     curactive=`facet_active $facet`
755     if [ -z "${curactive}" -o "$curactive" == "$failover" ] ; then
756         eval export ${facet}active=$facet
757     else
758         eval export ${facet}active=$failover
759     fi
760     # save the active host for this facet
761     activevar=${facet}active
762     echo "$activevar=${!activevar}" > ./$activevar
763 }
764
765 do_node() {
766     HOST=$1
767     shift
768     local myPDSH=$PDSH
769     if [ "$HOST" = "$(hostname)" ]; then
770         myPDSH="no_dsh"
771     fi
772     if $VERBOSE; then
773         echo "CMD: $HOST $@" >&2
774         $myPDSH $HOST $LCTL mark "$@" > /dev/null 2>&1 || :
775     fi
776     $myPDSH $HOST "(PATH=\$PATH:$RLUSTRE/utils:$RLUSTRE/tests:/sbin:/usr/sbin; cd $RPWD; sh -c \"$@\")" | sed "s/^${HOST}: //"
777     return ${PIPESTATUS[0]}
778 }
779
780 do_facet() {
781     facet=$1
782     shift
783     HOST=`facet_active_host $facet`
784     [ -z $HOST ] && echo No host defined for facet ${facet} && exit 1
785     do_node $HOST $@
786 }
787
788 add() {
789     local facet=$1
790     shift
791     # make sure its not already running
792     stop ${facet} -f
793     rm -f ${facet}active
794     do_facet ${facet} $MKFS $*
795 }
796
797 ostdevname() {
798     num=$1
799     DEVNAME=OSTDEV$num
800     #if $OSTDEVn isn't defined, default is $OSTDEVBASE + num
801     eval DEVPTR=${!DEVNAME:=${OSTDEVBASE}${num}}
802     echo -n $DEVPTR
803 }
804
805 mdsdevname() {
806     num=$1
807     DEVNAME=MDSDEV$num
808     #if $MDSDEVn isn't defined, default is $MDSDEVBASE + num
809     eval DEVPTR=${!DEVNAME:=${MDSDEVBASE}${num}}
810     echo -n $DEVPTR
811 }
812
813 ########
814 ## MountConf setup
815
816 stopall() {
817     # make sure we are using the primary server, so test-framework will
818     # be able to clean up properly.
819     activemds=`facet_active mds1`
820     if [ $activemds != "mds1" ]; then
821         fail mds1
822     fi
823     
824     # assume client mount is local 
825     grep " $MOUNT " /proc/mounts && zconf_umount `hostname` $MOUNT $*
826     grep " $MOUNT2 " /proc/mounts && zconf_umount `hostname` $MOUNT2 $*
827     for num in `seq $MDSCOUNT`; do
828         stop mds$num -f
829     done
830     for num in `seq $OSTCOUNT`; do
831         stop ost$num -f
832     done
833     return 0
834 }
835
836 cleanupall() {
837     stopall $*
838     unload_modules
839     cleanup_krb5_env
840 }
841
842 mdsmkfsopts()
843 {
844     local nr=$1
845     test $nr = 1 && echo -n $MDS_MKFS_OPTS || echo -n $MDSn_MKFS_OPTS
846 }
847
848 formatall() {
849     [ "$FSTYPE" ] && FSTYPE_OPT="--backfstype $FSTYPE"
850
851     stopall
852     # We need ldiskfs here, may as well load them all
853     load_modules
854     [ "$CLIENTONLY" ] && return
855     echo "Formatting mdts, osts"
856     for num in `seq $MDSCOUNT`; do
857         echo "Format mds$num: $(mdsdevname $num)"
858         if $VERBOSE; then
859             add mds$num `mdsmkfsopts $num` $FSTYPE_OPT --reformat `mdsdevname $num` || exit 9
860         else
861             add mds$num `mdsmkfsopts $num` $FSTYPE_OPT --reformat `mdsdevname $num` > /dev/null || exit 9
862         fi
863     done
864
865     for num in `seq $OSTCOUNT`; do
866         echo "Format ost$num: $(ostdevname $num)"
867         if $VERBOSE; then
868             add ost$num $OST_MKFS_OPTS --reformat `ostdevname $num` || exit 10
869         else
870             add ost$num $OST_MKFS_OPTS --reformat `ostdevname $num` > /dev/null || exit 10
871         fi
872     done
873 }
874
875 mount_client() {
876     grep " $1 " /proc/mounts || zconf_mount `hostname` $*
877 }
878
879 setupall() {
880     load_modules
881     init_krb5_env
882     if [ -z "$CLIENTONLY" ]; then
883         echo "Setup mdts, osts"
884         for num in `seq $MDSCOUNT`; do
885             DEVNAME=$(mdsdevname $num)
886             echo $REFORMAT | grep -q "reformat" \
887             || do_facet mds$num "$TUNEFS --writeconf $DEVNAME"
888             start mds$num $DEVNAME $MDS_MOUNT_OPTS
889         done
890         for num in `seq $OSTCOUNT`; do
891             DEVNAME=$(ostdevname $num)
892             start ost$num $DEVNAME $OST_MOUNT_OPTS
893         done
894     fi
895     [ "$DAEMONFILE" ] && $LCTL debug_daemon start $DAEMONFILE $DAEMONSIZE
896     mount_client $MOUNT
897     if [ "$MOUNT_2" ]; then
898         mount_client $MOUNT2
899     fi
900     sleep 5
901 }
902
903 mounted_lustre_filesystems() {
904         awk '($3 ~ "lustre" && $1 ~ ":") { print $2 }' /proc/mounts
905 }
906
907 check_and_setup_lustre() {
908     MOUNTED="`mounted_lustre_filesystems`"
909     if [ -z "$MOUNTED" ]; then
910         [ "$REFORMAT" ] && formatall
911         setupall
912         MOUNTED="`mounted_lustre_filesystems`"
913         [ -z "$MOUNTED" ] && error "NAME=$NAME not mounted"
914         export I_MOUNTED=yes
915     fi
916     if [ "$ONLY" == "setup" ]; then
917         exit 0
918     fi
919 }
920
921 cleanup_and_setup_lustre() {
922     if [ "$ONLY" == "cleanup" -o "`mount | grep $MOUNT`" ]; then
923         sysctl -w lnet.debug=0 || true
924         cleanupall
925         if [ "$ONLY" == "cleanup" ]; then 
926             exit 0
927         fi
928     fi
929     check_and_setup_lustre
930 }
931
932 check_and_cleanup_lustre() {
933     if [ "`mount | grep $MOUNT`" ]; then
934         rm -rf $DIR/[Rdfs][1-9]*
935         rm -f $DIR/${TESTSUITE}/[Rdfs][1-9]*
936     fi
937     if [ "$I_MOUNTED" = "yes" ]; then
938         cleanupall -f || error "cleanup failed"
939     fi
940     unset I_MOUNTED
941 }
942
943 ####### 
944 # General functions
945
946 check_network() {
947     local NETWORK=0
948     local WAIT=0
949     local MAX=$2
950     while [ $NETWORK -eq 0 ]; do
951         ping -c 1 -w 3 $1 > /dev/null
952         if [ $? -eq 0 ]; then
953             NETWORK=1
954         else
955             WAIT=$((WAIT + 5))
956             echo "waiting for $1, $((MAX - WAIT)) secs left"
957             sleep 5
958         fi
959         if [ $WAIT -gt $MAX ]; then
960             echo "Network not available"
961             exit 1
962         fi
963     done
964 }
965 check_port() {
966     while( !($DSH2 $1 "netstat -tna | grep -q $2") ) ; do
967         sleep 9
968     done
969 }
970
971 no_dsh() {
972     shift
973     eval $@
974 }
975
976 comma_list() {
977     # the sed converts spaces to commas, but leaves the last space
978     # alone, so the line doesn't end with a comma.
979     echo "$*" | tr -s " " "\n" | sort -b -u | tr "\n" " " | sed 's/ \([^$]\)/,\1/g'
980 }
981
982 absolute_path() {
983     (cd `dirname $1`; echo $PWD/`basename $1`)
984 }
985
986 ##################################
987 # OBD_FAIL funcs
988
989 drop_request() {
990 # OBD_FAIL_MDS_ALL_REQUEST_NET
991     RC=0
992     do_facet mds sysctl -w lustre.fail_loc=0x123
993     do_facet client "$1" || RC=$?
994     do_facet mds sysctl -w lustre.fail_loc=0
995     return $RC
996 }
997
998 drop_reply() {
999 # OBD_FAIL_MDS_ALL_REPLY_NET
1000     RC=0
1001     do_facet mds sysctl -w lustre.fail_loc=0x122
1002     do_facet client "$@" || RC=$?
1003     do_facet mds sysctl -w lustre.fail_loc=0
1004     return $RC
1005 }
1006
1007 drop_reint_reply() {
1008 # OBD_FAIL_MDS_REINT_NET_REP
1009     RC=0
1010     do_facet mds sysctl -w lustre.fail_loc=0x119
1011     do_facet client "$@" || RC=$?
1012     do_facet mds sysctl -w lustre.fail_loc=0
1013     return $RC
1014 }
1015
1016 pause_bulk() {
1017 #define OBD_FAIL_OST_BRW_PAUSE_BULK      0x214
1018     RC=0
1019     do_facet ost1 sysctl -w lustre.fail_loc=0x214
1020     do_facet client "$1" || RC=$?
1021     do_facet client "sync"
1022     do_facet ost1 sysctl -w lustre.fail_loc=0
1023     return $RC
1024 }
1025
1026 drop_ldlm_cancel() {
1027 #define OBD_FAIL_LDLM_CANCEL             0x304
1028     RC=0
1029     do_facet client sysctl -w lustre.fail_loc=0x304
1030     do_facet client "$@" || RC=$?
1031     do_facet client sysctl -w lustre.fail_loc=0
1032     return $RC
1033 }
1034
1035 drop_bl_callback() {
1036 #define OBD_FAIL_LDLM_BL_CALLBACK        0x305
1037     RC=0
1038     do_facet client sysctl -w lustre.fail_loc=0x305
1039     do_facet client "$@" || RC=$?
1040     do_facet client sysctl -w lustre.fail_loc=0
1041     return $RC
1042 }
1043
1044 drop_ldlm_reply() {
1045 #define OBD_FAIL_LDLM_REPLY              0x30c
1046     RC=0
1047     do_facet mds sysctl -w lustre.fail_loc=0x30c
1048     do_facet client "$@" || RC=$?
1049     do_facet mds sysctl -w lustre.fail_loc=0
1050     return $RC
1051 }
1052
1053 clear_failloc() {
1054     facet=$1
1055     pause=$2
1056     sleep $pause
1057     echo "clearing fail_loc on $facet"
1058     do_facet $facet "sysctl -w lustre.fail_loc=0"
1059 }
1060
1061 cancel_lru_locks() {
1062     $LCTL mark "cancel_lru_locks $1 start"
1063     for d in `find $LPROC/ldlm/namespaces | egrep -i $1`; do
1064         [ -f $d/lru_size ] && echo clear > $d/lru_size
1065         [ -f $d/lock_unused_count ] && grep [1-9] $d/lock_unused_count /dev/null
1066     done
1067     $LCTL mark "cancel_lru_locks $1 stop"
1068 }
1069
1070
1071 pgcache_empty() {
1072     for a in /proc/fs/lustre/llite/*/dump_page_cache; do
1073         if [ `wc -l $a | awk '{print $1}'` -gt 1 ]; then
1074             echo there is still data in page cache $a ?
1075             cat $a;
1076             return 1;
1077         fi
1078     done
1079     return 0
1080 }
1081
1082 debugsave() {
1083     DEBUGSAVE="$(sysctl -n lnet.debug)"
1084 }
1085
1086 debugrestore() {
1087     [ -n "$DEBUGSAVE" ] && sysctl -w lnet.debug="${DEBUGSAVE}"
1088     DEBUGSAVE=""
1089 }
1090
1091 ##################################
1092 # Test interface 
1093 ##################################
1094
1095 error() {
1096     local FAIL_ON_ERROR=${FAIL_ON_ERROR:-true}
1097     local TYPE=${TYPE:-"FAIL"}
1098     local ERRLOG
1099     sysctl -w lustre.fail_loc=0 2> /dev/null || true
1100     log " ${TESTSUITE} ${TESTNAME}: @@@@@@ ${TYPE}: $@ "
1101     ERRLOG=$TMP/lustre_${TESTSUITE}_${TESTNAME}.$(date +%s)
1102     echo "Dumping lctl log to $ERRLOG"
1103     # We need to dump the logs on all nodes
1104     local NODES=$(nodes_list)
1105     for NODE in $NODES; do
1106         do_node $NODE $LCTL dk $ERRLOG
1107     done
1108     debugrestore
1109     [ "$TESTSUITELOG" ] && echo "$0: ${TYPE}: $TESTNAME $@" >> $TESTSUITELOG
1110     if $FAIL_ON_ERROR; then
1111         exit 1
1112     fi
1113 }
1114
1115 # use only if we are ignoring failures for this test, bugno required.
1116 # (like ALWAYS_EXCEPT, but run the test and ignore the results.)
1117 # e.g. error_ignore 5494 "your message"
1118 error_ignore() {
1119     FAIL_ON_ERROR=false TYPE="IGNORE (bz$1)" error $2
1120 }
1121
1122 skip () {
1123         log " SKIP: ${TESTSUITE} ${TESTNAME} $@"
1124         [ "$TESTSUITELOG" ] && echo "${TESTSUITE}: SKIP: $TESTNAME $@" >> $TESTSUITELOG
1125 }
1126
1127 build_test_filter() {
1128     [ "$ONLY" ] && log "only running test `echo $ONLY`"
1129     for O in $ONLY; do
1130         eval ONLY_${O}=true
1131     done
1132     [ "$EXCEPT$ALWAYS_EXCEPT" ] && \
1133         log "skipping tests: `echo $EXCEPT $ALWAYS_EXCEPT`"
1134     for E in $EXCEPT $ALWAYS_EXCEPT; do
1135         eval EXCEPT_${E}=true
1136     done
1137     for G in $GRANT_CHECK_LIST; do
1138         eval GCHECK_ONLY_${G}=true
1139         done
1140 }
1141
1142 _basetest() {
1143     echo $*
1144 }
1145
1146 basetest() {
1147     IFS=abcdefghijklmnopqrstuvwxyz _basetest $1
1148 }
1149
1150 run_test() {
1151     export base=`basetest $1`
1152     if [ ! -z "$ONLY" ]; then
1153         testname=ONLY_$1
1154         if [ ${!testname}x != x ]; then
1155             run_one $1 "$2"
1156             return $?
1157         fi
1158         testname=ONLY_$base
1159         if [ ${!testname}x != x ]; then
1160             run_one $1 "$2"
1161             return $?
1162         fi
1163         echo -n "."
1164         return 0
1165     fi
1166     testname=EXCEPT_$1
1167     if [ ${!testname}x != x ]; then
1168         TESTNAME=test_$1 skip "skipping excluded test $1"
1169         return 0
1170     fi
1171     testname=EXCEPT_$base
1172     if [ ${!testname}x != x ]; then
1173         TESTNAME=test_$1 skip "skipping excluded test $1 (base $base)"
1174         return 0
1175     fi
1176     run_one $1 "$2"
1177     
1178     return $?
1179 }
1180
1181 EQUALS="======================================================================"
1182 equals_msg() {
1183     msg="$@"
1184
1185     local suffixlen=$((${#EQUALS} - ${#msg}))
1186     [ $suffixlen -lt 5 ] && suffixlen=5
1187     log `echo $(printf '===== %s %.*s\n' "$msg" $suffixlen $EQUALS)`
1188 }
1189
1190 log() {
1191     echo "$*"
1192     lsmod | grep lnet > /dev/null || load_modules
1193
1194     local MSG="$*"
1195     # Get rif of '
1196     MSG=${MSG//\'/\\\'}
1197     MSG=${MSG//\(/\\\(}
1198     MSG=${MSG//\)/\\\)}
1199     MSG=${MSG//\;/\\\;}
1200     local NODES=$(nodes_list)
1201     for NODE in $NODES; do
1202         do_node $NODE $LCTL mark "$MSG" 2> /dev/null || true
1203     done
1204 }
1205
1206 trace() {
1207         log "STARTING: $*"
1208         strace -o $TMP/$1.strace -ttt $*
1209         RC=$?
1210         log "FINISHED: $*: rc $RC"
1211         return 1
1212 }
1213
1214 pass() {
1215     echo PASS $@
1216 }
1217
1218 check_mds() {
1219     FFREE=`cat /proc/fs/lustre/mds/*/filesfree`
1220     FTOTAL=`cat /proc/fs/lustre/mds/*/filestotal`
1221     [ $FFREE -ge $FTOTAL ] && error "files free $FFREE > total $FTOTAL" || true
1222 }
1223
1224 run_one() {
1225     testnum=$1
1226     message=$2
1227     tfile=f${testnum}
1228     export tdir=d${TESTSUITE}/d${base}
1229     local SAVE_UMASK=`umask`
1230     umask 0022
1231     mkdir -p $DIR/$tdir
1232
1233     BEFORE=`date +%s`
1234     log "== test $testnum: $message ============ `date +%H:%M:%S` ($BEFORE)"
1235     #check_mds
1236     export TESTNAME=test_$testnum
1237     test_${testnum} || error "test_$testnum failed with $?"
1238     #check_mds
1239     check_grant ${testnum} || error "check_grant $testnum failed with $?"
1240     [ -f $CATASTROPHE ] && [ `cat $CATASTROPHE` -ne 0 ] && \
1241         error "LBUG/LASSERT detected"
1242     pass "($((`date +%s` - $BEFORE))s)"
1243     rmdir ${DIR}/$tdir >/dev/null 2>&1 || true
1244     unset TESTNAME
1245     unset tdir
1246     umask $SAVE_UMASK
1247     cd $SAVE_PWD
1248     $CLEANUP
1249 }
1250
1251 canonical_path() {
1252     (cd `dirname $1`; echo $PWD/`basename $1`)
1253 }
1254
1255 sync_clients() {
1256     [ -d $DIR1 ] && cd $DIR1 && sync; sleep 1; sync 
1257     [ -d $DIR2 ] && cd $DIR2 && sync; sleep 1; sync 
1258         cd $SAVE_PWD
1259 }
1260
1261 check_grant() {
1262     export base=`basetest $1`
1263     [ "$CHECK_GRANT" == "no" ] && return 0
1264
1265         testname=GCHECK_ONLY_${base}
1266         [ ${!testname}x == x ] && return 0
1267
1268         echo -n "checking grant......"
1269         cd $SAVE_PWD
1270         # write some data to sync client lost_grant
1271         rm -f $DIR1/${tfile}_check_grant_* 2>&1
1272         for i in `seq $OSTCOUNT`; do
1273                 $LFS setstripe $DIR1/${tfile}_check_grant_$i 0 $(($i -1)) 1
1274                 dd if=/dev/zero of=$DIR1/${tfile}_check_grant_$i bs=4k \
1275                                               count=1 > /dev/null 2>&1 
1276         done
1277         # sync all the data and make sure no pending data on server
1278         sync_clients
1279         
1280         #get client grant and server grant 
1281         client_grant=0
1282     for d in ${LPROC}/osc/*/cur_grant_bytes; do 
1283                 client_grant=$((client_grant + `cat $d`))
1284         done
1285         server_grant=0
1286         for d in ${LPROC}/obdfilter/*/tot_granted; do
1287                 server_grant=$((server_grant + `cat $d`))
1288         done
1289
1290         # cleanup the check_grant file
1291         for i in `seq $OSTCOUNT`; do
1292                 rm $DIR1/${tfile}_check_grant_$i
1293         done
1294
1295         #check whether client grant == server grant 
1296         if [ $client_grant != $server_grant ]; then
1297                 echo "failed: client:${client_grant} server: ${server_grant}"
1298                 return 1
1299         else
1300                 echo "pass"
1301         fi
1302 }
1303
1304 ########################
1305 # helper functions
1306
1307 osc_to_ost()
1308 {
1309     osc=$1
1310     ost=`echo $1 | awk -F_ '{print $3}'`
1311     if [ -z $ost ]; then
1312         ost=`echo $1 | sed 's/-osc.*//'`
1313     fi
1314     echo $ost
1315 }
1316
1317 remote_mds ()
1318 {
1319     [ ! -e /proc/fs/lustre/mdt/*MDT* ]
1320 }
1321
1322 remote_ost ()
1323 {
1324     [ $(grep -c obdfilter $LPROC/devices) -eq 0 ]
1325 }
1326
1327 mdts_nodes () {
1328     local MDSNODES=$(facet_host $SINGLEMDS)
1329
1330     # FIXME: Currenly we use only $SINGLEMDS,
1331     # should be fixed when we will start to test cmd.
1332     echo $MDSNODES
1333     return
1334
1335     for num in `seq $MDSCOUNT`; do
1336         local myMDS=$(facet_host mds$num)
1337         [[ ! '\ '"$MDSNODES"'\ ' = *'\ '"$myMDS"'\ '* ]] && MDSNODES="$MDSNODES $myMDS"
1338     done
1339
1340     echo $MDSNODES
1341 }
1342
1343 osts_nodes () {
1344     local OSTNODES=$(facet_host ost1)
1345
1346     for num in `seq $OSTCOUNT`; do
1347         local myOST=$(facet_host ost$num)
1348         [[ ! '\ '"$OSTNODES"'\ ' = *'\ '"$myOST"'\ '* ]] && OSTNODES="$OSTNODES $myOST"
1349     done
1350
1351     echo $OSTNODES
1352 }
1353
1354 nodes_list () {
1355     # FIXME. We need a list of clients
1356     local myNODES=`hostname`
1357
1358     local OSTNODES=$(osts_nodes)
1359     local myOSTNODES=`echo ' '"$OSTNODES"' ' | sed -e s/[\ ]$(hostname)[\ ]/\ /`
1360     [ -n "$myOSTNODES" ] && myNODES="$myNODES $myOSTNODES"
1361
1362     local myNODES=${myNODES% } 
1363     # Add to list only not listed mds nodes
1364     local MDSNODES=$(mdts_nodes)
1365     for myMDS in $MDSNODES; do
1366         [[ ! "'\ '$myNODES'\ '" = *'\ '"$myMDS"'\ '* ]] && myNODES="$myNODES $myMDS"
1367     done
1368
1369     echo $myNODES
1370 }
1371
1372 is_patchless ()
1373 {
1374     grep -q patchless $LPROC/version
1375 }