1 #! /usr/bin/ksh -p
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22
23 #
24 # Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
26 #
27
28 . $STF_TOOLS/include/stf.kshlib
29
30 # Include common STC utility functions
31 if [[ -s $STC_NFSUTILS/include/nfs-util.kshlib ]]; then
32 . $STC_NFSUTILS/include/nfs-util.kshlib
33 else
34 . $STF_TMPDIR/nfs-util.kshlib
35 fi
36
37 NAME=$(basename $0)
38 PATH=/usr/bin:/usr/sbin:$PATH; export PATH
39
40 # Function to cleanup and exit
41 # Usage: cleanup exit_code
42 #
43 function cleanup {
44 typeset Fname=cleanup
45 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
46 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
47
48 rm -f $STF_TMPDIR/*.out.$$
49 exit ${1}
50 }
51
52 # Function to generate option list with unique combination
53 # Usage: gen_opt_list the_option_array
54 # Return: the generated list
55 #
56 function gen_opt_list {
57 typeset Fname=gen_opt_list
58 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
59 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
60
61 typeset OPTLIST=${1}
62 typeset GENERATE_LIST=""
63 typeset -i length=$(echo $OPTLIST | wc -w)
64 if (( length <= 1 )); then
65 GENERATE_LIST=$OPTLIST
66 else
67 set - $OPTLIST
68 typeset item=$1 entry list
69 shift
70 list=$(gen_opt_list "$*")
71 for entry in $list; do
72 GENERATE_LIST="$GENERATE_LIST $item,$entry"
73 done
74 GENERATE_LIST="$GENERATE_LIST $item $list"
75 fi
76 echo $GENERATE_LIST
77 }
78
79 # Function to convert the form of options, currently including
80 # ro, rw, and root, combining them with :
81 # Usage: convert_form the_option_array
82 # Return: the converted list
83 #
84 function convert_form {
85 typeset Fname=convert_form
86 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
87 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
88
89 typeset rolist rwlist rootlist optlist
90 typeset opt
91 for opt in $(echo $1 | sed 's/,/ /g'); do
92 [[ $opt == ro=* ]] && rolist=$rolist:${opt##ro=}
93 [[ $opt == rw=* ]] && rwlist=$rwlist:${opt##rw=}
94 [[ $opt == root=* ]] && rootlist=$rootlist:${opt##root=}
95 done
96 [[ -n $rolist ]] && rolist="ro=${rolist#:}"
97 [[ -n $rwlist ]] && rwlist="rw=${rwlist#:}"
98 [[ -n $rootlist ]] && rootlist="root=${rootlist#:}"
99 for opt in $rolist $rwlist $rootlist; do
100 optlist=$optlist,$opt
101 done
102 echo ${optlist#,}
103 }
104
105 # Function to get all sec options from share/mount option string
106 # Usage: get_sec_str [option_str]
107 #
108 function get_sec_str {
109 typeset Fname=get_sec_str
110 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
111 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
112
113 typeset opts=$1
114 typeset secopts=""
115 opts=$(echo $opts | tr "," " ")
116 for o in $opts; do
117 if [[ $o == "sec="* ]]; then
118 o=${o#sec=}
119 o=$(echo $o | tr ":" " ")
120 secopts="$secopts $o"
121 fi
122 done
123 echo $secopts
124 }
125
126 # Function to get matched sec option used between client and server.
127 # Usage: get_sec_opt [mntopt] [shropt]
128 #
129 function get_sec_opt {
130 typeset Fname=get_sec_opt
131 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
132 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
133
134 mntopt=$1
135 shropt=$2
136
137 typeset sec_opt=""
138 sec_shr=$(get_sec_str $shropt)
139 # default sec flavour is "sys" when sharing
140 [[ -z $sec_shr ]] && sec_shr="sys"
141 sec_mnt=$(get_sec_str $mntopt)
142
143 if [[ -z $sec_mnt ]]; then
144 # if clients doesn't sepcify sec flavour when mounting,
145 # use the first one specified when sharing on server
146 sec_opt=$(echo $sec_shr | cut -d" " -f1)
147 else
148 if echo $sec_mnt | grep " " >/dev/null; then
149 # client can't specify multiple sec flavours when
150 # calling mount. Since domount_check() is called
151 # only in positive test cases, this shouldn't happen.
152 echo "\n$Fname: multiple sec options when mounting"
153 echo "*** mntopt=<$mntopt>, shropt=<$shropt>"
154 return 1
155 fi
156
157 # look for if $sec_shr contains the one specified by
158 # client
159 for o in $sec_shr; do
160 [[ $o == $sec_mnt ]] && sec_opt=$o && break
161 done
162 fi
163
164 if [[ -z $sec_opt ]]; then
165 # couldn't find matched sec option. This shouldn't happen
166 # because domount_check() is called only in positive test
167 echo "\n$Fname: didn't find matched sec flavor"
168 echo "*** mntopt=<$mntopt>, shropt=<$shropt>"
169 return 1
170 fi
171
172 echo "sec=$sec_opt"
173 }
174
175 # Function to do an NFS share with option provided at SERVER;
176 # then verify filesystem is shared correctly with the option
177 # SERVER, SHRDIR, MNTDIR and STF_TMPDIR are global variables
178 # Usage: share_check shropt [shared_filesystem]
179 #
180 function share_check {
181 typeset Fname=share_check
182 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
183 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
184
185 typeset shropt=${1} # options to use in share and check
186 [[ -n ${2} ]] && typeset SHRDIR=${2}
187
188 # provide the new share options to server
189 # and reshare SHRDIR with these options
190 echo "$shropt" > $STF_TMPDIR/shropt.out.$$
191
192 scp $STF_TMPDIR/shropt.out.$$ \
193 root@$SERVER:$SRV_TMPDIR/ShrOpts.sharemnt \
194 > $STF_TMPDIR/rcp.out.$$ 2>&1
195 if [[ $? != 0 ]]; then
196 echo "$Fname: failed to copy <shropt.out.$$> to <$SERVER>"
197 cat $STF_TMPDIR/rcp.out.$$
198 cleanup $STF_UNRESOLVED
199 fi
200
201 echo "Resharing $SHRDIR with <$shropt> options ... \c"
202 typeset SRVDEBUG=$STC_GENUTILS_DEBUG:$SHAREMNT_DEBUG
203 [[ :$SRVDEBUG: == *:RSH:* ]] && SRVDEBUG=all
204 RSH root $SERVER \
205 "export SHAREMNT_DEBUG=$SRVDEBUG; \
206 $SRV_TMPDIR/srv_setup -r $SHRDIR" \
207 > $STF_TMPDIR/rsh.out.$$ 2>&1
208 rc=$?
209 [[ :$SRVDEBUG: == *:all:* ]] && cat $STF_TMPDIR/rsh.out.$$ 1>&2
210 grep "Done" $STF_TMPDIR/rsh.out.$$ > /dev/null 2>&1
211 if [[ $? != 0 || $rc != 0 ]]; then
212 echo "$Fname: run $SRV_TMPDIR/srv_setup in $SERVER failed"
213 cat $STF_TMPDIR/rsh.out.$$
214 cleanup $STF_FAIL
215 fi
216
217 echo "OK"
218 rm -f $STF_TMPDIR/*.out.$$
219 }
220
221 # Function to do an NFS mount;
222 # then verify filesystem is mounted correctly with provided option
223 # SERVER, SHRDIR, MNTDIR and STF_TMPDIR are global variables
224 # Usage: domount_check [URL] mntopt [shropt] [shared_filesystem]
225 #
226 function domount_check {
227 typeset Fname=domount_check
228 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
229 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
230
231 typeset -i isURL=0
232 if [[ $1 == URL ]]; then
233 isURL=1
234 shift
235 fi
236 typeset mntopt=${1} # options to use in mount and check
237 typeset shropt=${2} # options to use in share and check
238 typeset opt_flg
239 [[ -n ${3} ]] && typeset SHRDIR=${3}
240 [[ -n $mntopt ]] && opt_flg="-o"
241
242 echo $mntopt | grep -i remount > /dev/null 2>&1
243 if (( $? != 0 )); then
244 # make sure MNTDIR is not mounted at this point
245 umount -f $MNTDIR > /dev/null 2>&1
246 fi
247
248 typeset resource="$SERVER:${SHRDIR}${SHRDIR_OFFSET}"
249 (( isURL == 1 )) && resource="nfs://$SERVER${SHRDIR}${SHRDIR_OFFSET}"
250 echo "Mounting $resource at $MNTDIR with MNTOPT=<$mntopt> ... \c"
251 mount -F nfs $opt_flg $mntopt $resource $MNTDIR \
252 > $STF_TMPDIR/mnt.out.$$ 2>&1
253 if (( $? != 0 )); then
254 echo "\n$Fname: mount failed"
255 cat $STF_TMPDIR/mnt.out.$$
256 cleanup $STF_FAIL
257 fi
258 echo "OK"
259
260 echo "Checking $MNTDIR with MNTOPT=$mntopt ... \c"
261 nfsstat -m $MNTDIR > $STF_TMPDIR/nstat.out.$$ 2>&1
262 if (( $? != 0 )); then
263 echo "\n$Fname: nfsstat failed"
264 cat $STF_TMPDIR/nstat.out.$$
265 cleanup $STF_UNRESOLVED
266 fi
267 mount | grep "^$MNTDIR on" > $STF_TMPDIR/opt.out.$$
268
269 typeset sec_opt=""
270 if [[ -n $shropt ]]; then
271 sec_opt=$(get_sec_opt "$mntopt" $shropt) || cleanup $STF_UNRESOLVED
272 fi
273
274 typeset OPTs=$(echo $mntopt | sed 's/,/ /g')
275 if ! echo $OPTs || grep "sec=" >/dev/null; then
276 OPTs="$OPTs $sec_opt"
277 fi
278 for opt in $OPTs; do
279 case $opt in
280 rw|remount) grep -w "read" $STF_TMPDIR/opt.out.$$ | \
281 grep -w "write" > /dev/null 2>&1
282 rc=$?
283 ;;
284 ro) grep "read only" $STF_TMPDIR/opt.out.$$ > /dev/null 2>&1
285 rc=$?
286 ;;
287 sec=krb5*) grep "Flags:" $STF_TMPDIR/nstat.out.$$ | \
288 grep "$opt," > /dev/null 2>&1
289 rc=$?
290 ;;
291 *) grep "Flags:" $STF_TMPDIR/nstat.out.$$ | \
292 grep -w "$opt" > /dev/null 2>&1
293 rc=$?
294 if (( $rc != 0 )); then
295 grep -w "$opt" $STF_TMPDIR/opt.out.$$ \
296 > /dev/null 2>&1
297 rc=$?
298 fi
299 ;;
300 esac
301 if (( $rc != 0 )); then
302 echo "\n$Fname: didn't get correct <$opt> \c"
303 echo "in mntopt<$mntopt>"
304 echo "*** opt=<$opt>, shropt=<$shropt>"
305 cat $STF_TMPDIR/opt.out.$$
306 cat $STF_TMPDIR/nstat.out.$$
307 cleanup $STF_FAIL
308 fi
309 done
310
311 echo "OK"
312 rm -f $STF_TMPDIR/*.out.$$
313 }
314
315 # Function to unmount an NFS mount point;
316 # then verify filesystem is unmounted successfully
317 # SERVER, SHRDIR, MNTDIR and STF_TMPDIR are global variables
318 # Usage: unmount_check
319 #
320 function unmount_check {
321 typeset Fname=unmount_check
322 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
323 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
324
325 echo "Unmounting current mount point $MNTDIR ... \c"
326
327 wait_now 10 "umount $MNTDIR > $STF_TMPDIR/umnt.out.$$ 2>&1"
328 if [[ $? != 0 ]]; then
329 echo "\n$Fname: umount failed"
330 cat $STF_TMPDIR/umnt.out.$$
331 cleanup $STF_FAIL
332 fi
333 nfsstat -m $MNTDIR | grep "$MNTDIR" > /dev/null 2>&1
334 if [[ $? == 0 ]]; then
335 echo "\n$Fname: umount didn't unmount $MNTDIR successfully"
336 echo "... $MNTDIR is still mounted"
337 nfsstat -m $MNTDIR
338 cleanup $STF_FAIL
339 fi
340
341 echo "OK"
342 rm -f $STF_TMPDIR/*.out.$$
343 }
344
345 # Function to do an NFS automount;
346 # then verify filesystem is mounted correctly with provided option
347 # SERVER, SHRDIR, MNTDIR and STF_TMPDIR are global variables
348 # Usage: automount_check [URL] mntopt [shropt] [tag] [shared_filesystem]
349 #
350 function automount_check {
351 typeset Fname=automount_check
352 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
353 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
354
355 typeset -i isURL=0
356 if [[ $1 == URL ]]; then
357 isURL=1
358 shift
359 fi
360 typeset mntopt=${1} # options to use in mount and check
361 typeset shropt=${2} # options to use in share and check
362 typeset tn="${3}_$$_" # short unique name for auto entry name
363 [[ -n ${4} ]] && typeset SHRDIR=${4}
364
365 # Insert the entry of these options to the map
366 typeset resource="$SERVER:${SHRDIR}${SHRDIR_OFFSET}"
367 (( isURL == 1 )) && resource="nfs://$SERVER${SHRDIR}${SHRDIR_OFFSET}"
368 an=$(echo "$mntopt" | sed -e 's/sec=//g' -e 's/://g')
369 an="$tn$an"
370 echo "SM_$an -${mntopt} $resource" \
371 > $STF_TMPDIR/auto_indirect.shmnt
372
373 echo "Auto-Mounting (indirectly) $AUTOIND/SM_$an ..."
374 echo "\t with MNTOPT=<$mntopt> ... \c"
375 # If resource is a file, use "ls" instead of "cd" to mount
376 ckFILE=$(basename $SHRDIR)
377 if [[ $ckFILE == *file ]]; then
378 # first time automount tries to check for ISDIR, ignore
379 ckCMD="ls -lv"
380 $ckCMD $AUTOIND/SM_$an > /dev/null 2>&1
381 else
382 ckCMD="cd"
383 fi
384 $ckCMD $AUTOIND/SM_$an > $STF_TMPDIR/amnt.out.$$ 2>&1
385 if (( $? != 0 )); then
386 echo "\n$Fname: automount ($ckCMD $AUTOIND/SM_$an) failed"
387 cat $STF_TMPDIR/amnt.out.$$
388 nfsstat -m $AUTOIND/SM_$an
389 cleanup $STF_FAIL
390 fi
391 echo "OK"
392
393 echo "Checking $AUTOIND/SM_$an with MNTOPT=$mntopt ... \c"
394 nfsstat -m $AUTOIND/SM_$an > $STF_TMPDIR/nstat.out.$$ 2>&1
395 if (( $? != 0 )); then
396 echo "\n$Fname: nfsstat failed"
397 cat $STF_TMPDIR/nstat.out.$$
398 cleanup $STF_UNRESOLVED
399 fi
400 mount | grep "$AUTOIND/SM_$an" > $STF_TMPDIR/opt.out.$$
401
402 typeset sec_opt=""
403 if [[ -n $shropt ]]; then
404 sec_opt=$(get_sec_opt "$mntopt" $shropt) || cleanup $STF_UNRESOLVED
405 fi
406
407 typeset OPTs=$(echo $mntopt | sed 's/,/ /g')
408 if ! echo $OPTs || grep "sec=" >/dev/null; then
409 OPTs="$OPTs $sec_opt"
410 fi
411 for opt in $OPTs; do
412 case $opt in
413 rw) grep -w "read" $STF_TMPDIR/opt.out.$$ | \
414 grep -w "write" > /dev/null 2>&1
415 rc=$?
416 ;;
417 ro) grep "read only" $STF_TMPDIR/opt.out.$$ > /dev/null 2>&1
418 rc=$?
419 ;;
420 sec=krb5*) grep "Flags:" $STF_TMPDIR/nstat.out.$$ | \
421 grep "$opt," > /dev/null 2>&1
422 rc=$?
423 ;;
424 *) grep "Flags:" $STF_TMPDIR/nstat.out.$$ | \
425 grep -w "$opt" > /dev/null 2>&1
426 rc=$?
427 if (( $rc != 0 )); then
428 grep -w "$opt" $STF_TMPDIR/opt.out.$$ \
429 > /dev/null 2>&1
430 rc=$?
431 fi
432 ;;
433 esac
434 if (( $rc != 0 )); then
435 echo "\n$Fname: didn't get correct <$opt> \c"
436 echo "in mntopt<$mntopt>"
437 echo "*** opt=<$opt>, shropt=<$shropt>"
438 cat $STF_TMPDIR/opt.out.$$
439 cat $STF_TMPDIR/nstat.out.$$
440 cleanup $STF_FAIL
441 fi
442 done
443
444 echo "OK"
445 rm -f $STF_TMPDIR/*.out.$$
446 }
447
448 # Function to check the unknown users map
449 # Usage: do_anon_check <anon_uid> <file>
450 #
451 function do_anon_check {
452 typeset Fname=do_anon_check
453 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
454 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
455
456 typeset anon_uid=$1
457 typeset real_uid=$(ls -ln $2 | awk '{print $3}')
458 if [[ $real_uid == $anon_uid ]]; then
459 return 0
460 else
461 echo "\tthe file owner is $real_uid instead of $anon_uid"
462 return 1
463 fi
464 }
465
466 # Function to do read/write testing in the NFS mount point
467 # SERVER, SHRDIR, MNTDIR and STF_TMPDIR are global variables
468 # Usage: do_rw_test [test_file_name]
469 # test_file_name - the name of log file. If this
470 # isn't specified, a default name will be used.
471 #
472 # do_rw_test <directive> <args>
473 # 1. directive = OWNER
474 # args - the expected owner of the file created
475 # in the test.
476 # 2. directive = ANON
477 # args - share options
478 # 3. directive = WRITER
479 # args - user name
480 #
481 function do_rw_test {
482 typeset Fname=do_rw_test
483 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
484 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
485
486 typeset Tfile=tfile.$$
487 typeset expected_owner=""
488 typeset anon_uid=""
489 typeset write_user=""
490 if (( $# == 1 )); then
491 Tfile=${1}
492 elif (( $# > 1 )); then
493 case $1 in
494 ANON)
495 if [[ -n $2 && $2 == *anon=* ]]; then
496 anon_uid=$(echo $2 | sed -e 's/.*anon=//;s/,.*//')
497 else
498 anon_uid=$(id nobody | \
499 sed 's/uid=\(.*\)(nobody) gid=.*/\1/')
500 fi
501 ;;
502 OWNER)
503 expected_owner=$2
504 ;;
505 WRITER)
506 write_user=$2
507 expected_owner=$2
508 ;;
509 *) echo "\n$Fname: Unknown keyword"
510 exit $STF_UNRESOLVED
511 ;;
512 esac
513 fi
514
515 echo "Doing READ/WRITE testing at $MNTDIR ... \c"
516 typeset TData="READ/WRITE tests at $MNTDIR"
517
518 if [[ -n $write_user ]]; then
519 su $write_user -c "echo $TData > $MNTDIR/$Tfile" \
520 2> $STF_TMPDIR/wr.out.$$
521 else
522 echo "$TData" 1> $MNTDIR/$Tfile 2> $STF_TMPDIR/wr.out.$$
523 fi
524 if (( $? != 0 )); then
525 echo "\n$Fname: WRITE to $MNTDIR failed"
526 cat $STF_TMPDIR/wr.out.$$
527 cleanup $STF_FAIL
528 fi
529 if [[ -n $anon_uid ]]; then
530 do_anon_check $anon_uid $MNTDIR/$Tfile \
531 > $STF_TMPDIR/anon.out.$$ 2>&1
532 if (( $? != 0 )); then
533 echo "\n$Fname: the file owner is not expected"
534 cat $STF_TMPDIR/anon.out.$$
535 cleanup $STF_FAIL
536 fi
537 fi
538 if [[ -n $write_user ]]; then
539 su $write_user -c "ls -lv $MNTDIR/$Tfile" \
540 2> $STF_TMPDIR/ls.out.$$ | grep "$Tfile" > /dev/null 2>&1
541 else
542 ls -lv $MNTDIR/$Tfile 2> $STF_TMPDIR/ls.out.$$ | \
543 grep "$Tfile" > /dev/null 2>&1
544 fi
545 if (( $? != 0 )); then
546 echo "\n$Fname: READDIR of <$Tfile> in $MNTDIR failed"
547 cat $STF_TMPDIR/ls.out.$$
548 cleanup $STF_FAIL
549 fi
550 if [[ -n $expected_owner ]]; then
551 if [[ -n $write_user ]]; then
552 typeset ck_line=$(su $write_user -c "ls -l $MNTDIR/$Tfile")
553 else
554 typeset ck_line=$(ls -l $MNTDIR/$Tfile)
555 fi
556 echo $ck_line | awk '{print $3}' | grep -w $expected_owner \
557 > /dev/null 2>&1
558 if (( $? != 0 )); then
559 echo "\n$Fname: <$Tfile> has incorrected owner"
560 echo $ck_line
561 cleanup $STF_FAIL
562 fi
563 fi
564 if [[ -n $write_user ]]; then
565 typeset fdata=$(su $write_user -c "cat $MNTDIR/$Tfile" \
566 2> $STF_TMPDIR/cat.out.$$)
567 else
568 typeset fdata=$(cat $MNTDIR/$Tfile 2> $STF_TMPDIR/cat.out.$$)
569 fi
570 if [[ "$fdata" != "$TData" ]]; then
571 echo "\n$Fname: READ file in $MNTDIR failed"
572 cat $STF_TMPDIR/cat.out.$$
573 cleanup $STF_FAIL
574 fi
575 if [[ -n $write_user ]]; then
576 su $write_user -c "rm $MNTDIR/$Tfile" 2> $STF_TMPDIR/rm.out.$$
577 else
578 rm $MNTDIR/$Tfile 2> $STF_TMPDIR/rm.out.$$
579 fi
580 if (( $? != 0 )); then
581 echo "\n$Fname: Remove $MNTDIR/$Tfile failed"
582 cat $STF_TMPDIR/rm.out.$$
583 cleanup $STF_FAIL
584 fi
585
586 echo "OK"
587 rm -f $STF_TMPDIR/*.out.$$
588 }
589
590 # Function to do read only testing in the NFS mount point
591 # SERVER, SHRDIR, MNTDIR and STF_TMPDIR are global variables
592 # Usage: do_ro_test
593 #
594 function do_ro_test {
595 typeset Fname=do_ro_test
596 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
597 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
598
599 echo "Doing READ ONLY testing at $MNTDIR ... \c"
600 typeset TData="This is a rofile for sharemnt Testing"
601 ls -lv $MNTDIR/rofile 2> $STF_TMPDIR/ls.out.$$ | \
602 grep "rofile" > /dev/null 2>&1
603 if [[ $? != 0 ]]; then
604 echo "\n$Fname: READDIR of <rofile> in $MNTDIR failed"
605 cat $STF_TMPDIR/ls.out.$$
606 cleanup $STF_FAIL
607 fi
608 typeset fdata=$(head -1 $MNTDIR/rofile 2> $STF_TMPDIR/head.out.$$)
609 if [[ "$fdata" != "$TData" ]]; then
610 echo "\n$Fname: READ rofile in $MNTDIR failed"
611 cat $STF_TMPDIR/head.out.$$
612 cleanup $STF_FAIL
613 fi
614 echo "New Line" >> $MNTDIR/rofile 2> /dev/null
615 if [[ $? == 0 ]]; then
616 echo "\n$Fname: Unexpected successful to write into rofile"
617 cat $MNTDIR/rofile
618 cleanup $STF_FAIL
619 fi
620
621 echo "OK"
622 rm -f $STF_TMPDIR/*.out.$$
623 }
624
625 # Function to do negative read testing in the NFS mount point
626 # SERVER, SHRDIR, MNTDIR and STF_TMPDIR are global variables
627 # Usage: do_neg_ro_test
628 #
629 function do_neg_ro_test {
630 typeset Fname=do_neg_ro_test
631 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
632 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
633
634 echo "Doing NEGATIVE READ testing at $MNTDIR ... \c"
635 ls -lv $MNTDIR >$STF_TMPDIR/*.out.$$ 2>&1
636 if [[ $? == 0 ]]; then
637 echo "\n$Fname: READDIR in $MNTDIR succeeded, but it shouldn't"
638 cat $STF_TMPDIR/*.out.$$
639 cleanup $STF_FAIL
640 fi
641
642 echo "OK"
643 rm -f $STF_TMPDIR/*.out.$$
644 }
645
646 # Function to do an NFS share;
647 # then verify filesystem can not be shared with provided options
648 # Usage: do_neg_share_check shropt [shared_filesystem]
649 #
650 function do_neg_share_check {
651 typeset Fname=do_neg_share_check
652 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
653 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
654 typeset shropt=${1} # options to use in share
655 [[ -n ${2} ]] && typeset SHRDIR=${2}
656
657 # provide the new share options to server
658 # and reshare SHRDIR with these options
659 echo "$shropt" > $STF_TMPDIR/shropt.out.$$
660
661 scp $stf_tmpdir/Shropt.out.$$ \
662 root@$SERVER:$SRV_TMPDIR/ShrOpts.sharemnt \
663 > $STF_TMPDIR/rcp.out.$$ 2>&1
664 if [[ $? != 0 ]]; then
665 echo "$Fname: failed to copy <shropt.out.$$> to <$SERVER>"
666 cat $STF_TMPDIR/rcp.out.$$
667 cleanup $STF_UNRESOLVED
668 fi
669
670 echo "Resharing $SHRDIR with <$shropt> options ... \c"
671 typeset SRVDEBUG=$STC_GENUTILS_DEBUG:$SHAREMNT_DEBUG
672 [[ :$SRVDEBUG: == *:RSH:* ]] && SRVDEBUG=all
673 RSH root $SERVER \
674 "export SHAREMNT_DEBUG=$SRVDEBUG; \
675 $SRV_TMPDIR/srv_setup -r $SHRDIR" \
676 > $STF_TMPDIR/rsh.out.$$ 2>&1
677 [[ :$SRVDEBUG: == *:all:* ]] && cat $STF_TMPDIR/rsh.out.$$ 1>&2
678 grep "Done" $STF_TMPDIR/rsh.out.$$ > /dev/null 2>&1
679 if [[ $? == 0 ]]; then
680 echo "\n$Fname: run $SRV_TMPDIR/srv_setup in $SERVER succeeded"
681 echo "$Fname: share succeeded, but it should fail for"
682 echo "\t the invalid SHROPT=<$shropt>"
683 cat $STF_TMPDIR/rsh.out.$$
684 cleanup $STF_FAIL
685 fi
686
687 echo "OK"
688 rm -f $STF_TMPDIR/*.out.$$
689 }
690
691 # Function to do an NFS mount;
692 # then verify filesystem can not be mounted with provided options
693 # Usage: do_neg_mount_check mntopt
694 #
695 function do_neg_mount_check {
696 typeset Fname=do_neg_mount_check
697 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
698 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
699 typeset mntopt=${1} # options to use in mount
700 typeset opts=""
701 [[ -n $mntopt ]] && opts="-o $mntopt"
702
703 echo $mntopt | grep -i remount > /dev/null 2>&1
704 if (( $? != 0 )); then
705 # make sure MNTDIR is not mounted at this point
706 umount -f $MNTDIR > /dev/null 2>&1
707 fi
708
709 echo "Mounting $SERVER:${SHRDIR}${SHRDIR_OFFSET} at $MNTDIR"
710 echo "\t with MNTOPT=<$mntopt> ... \c"
711 mount -F nfs $opts "$SERVER":${SHRDIR}${SHRDIR_OFFSET} $MNTDIR \
712 > $STF_TMPDIR/mnt.out.$$ 2>&1
713 if [[ $? == 0 && ,$mntopt, == @(*,vers=2,*|*,vers=3,*) ]]; then
714 echo "\n$Fname: mount succeeded, but it should fail"
715 cat $STF_TMPDIR/mnt.out.$$
716 umount -f $MNTDIR > /dev/null 2>&1
717 cleanup $STF_FAIL
718 fi
719 echo "OK"
720 echo $mntopt | grep -i remount > /dev/null 2>&1
721 if (( $? == 0 )); then
722 rm -f $STF_TMPDIR/*.out.$$
723 return
724 fi
725
726 echo "Checking $MNTDIR with MNTOPT=$mntopt ... \c"
727 nfsstat -m $MNTDIR > $STF_TMPDIR/nstat.out.$$ 2>&1
728 if (( $? != 0 )); then
729 echo "\n$Fname: nfsstat failed"
730 cat $STF_TMPDIR/nstat.out.$$
731 cleanup $STF_UNRESOLVED
732 elif [[ -s $STF_TMPDIR/nstat.out.$$ && \
733 ,$mntopt, == @(*,vers=2,*|*,vers=3,*) ]]; then
734 echo "\n$Fname: it is wrong for nfsstat to display some info."
735 cat $STF_TMPDIR/nstat.out.$$
736 umount -f $MNTDIR > /dev/null 2>&1
737 cleanup $STF_FAIL
738 fi
739
740 mount | grep "^$MNTDIR on" > $STF_TMPDIR/opt.out.$$
741 if [[ $? == 0 && ,$mntopt, == @(*,vers=2,*|*,vers=3,*) ]]; then
742 echo "\n$Fname: it is wrong to be found via mount."
743 cat $STF_TMPDIR/opt.out.$$
744 umount -f $MNTDIR > /dev/null 2>&1
745 cleanup $STF_FAIL
746 fi
747
748 ls -l $MNTDIR/rofile > $STF_TMPDIR/ls.out.$$ 2>/dev/null
749 if [[ $? == 0 && ,$mntopt, != @(*,vers=2,*|*,vers=3,*) ]]; then
750 echo "\n$Fname: it is wrong to find rofile:"
751 cat $STF_TMPDIR/ls.out.$$
752 umount -f $MNTDIR > /dev/null 2>&1
753 cleanup $STF_FAIL
754 fi
755
756 rm -f $STF_TMPDIR/*.out.$$
757 echo "OK"
758 }
759
760 # Function to do an NFS automount;
761 # then verify filesystem can not be mounted with provided options
762 # Usage: do_neg_automount_check mntopt [tag]
763 #
764 function do_neg_automount_check {
765 typeset Fname=do_neg_automount_check
766 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
767 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
768 typeset mntopt=${1} # options to use in mount
769 typeset tn="${2}_$$_" # short unique name for auto entry name
770
771 # Insert the entry of these options to the map
772 an=$(echo "$mntopt" | sed -e 's/sec=//g' -e 's/://g')
773 an="$tn$an"
774 echo "SM_$an -${mntopt} ${SERVER}:${SHRDIR}${SHRDIR_OFFSET}" \
775 > $STF_TMPDIR/auto_indirect.shmnt
776
777 echo "Auto-Mounting (indirectly) $AUTOIND/SM_$an ..."
778 echo "\t with MNTOPT=<$mntopt> ..."
779 cd "$AUTOIND/SM_$an" > $STF_TMPDIR/amnt.out.$$ 2>&1
780 if [[ $? == 0 && ,$mntopt, == @(*,vers=2,*|*,vers=3,*) ]]; then
781 echo "$Fname: automount (cd $AUTOIND/SM_$an) succeeded, \c"
782 echo "but it should fail"
783 cat $STF_TMPDIR/amnt.out.$$
784 umount -f $AUTOIND/SM_$an > /dev/null 2>&1
785 cleanup $STF_FAIL
786 fi
787
788 echo "Checking $AUTOIND/SM_$an with MNTOPT=$mntopt ..."
789 nfsstat -m "$AUTOIND/SM_$an" > $STF_TMPDIR/nstat.out.$$ 2>&1
790 if (( $? != 0 )); then
791 echo "\n$Fname: nfsstat failed"
792 cat $STF_TMPDIR/nstat.out.$$
793 cleanup $STF_UNRESOLVED
794 elif [[ -s $STF_TMPDIR/nstat.out.$$ && \
795 ,$mntopt, == @(*,vers=2,*|*,vers=3,*) ]]; then
796 echo "\n$Fname: it is wrong for nfsstat to display some info."
797 cat $STF_TMPDIR/nstat.out.$$
798 umount -f $AUTOIND/SM_$an > /dev/null 2>&1
799 cleanup $STF_FAIL
800 fi
801
802 mount | grep "^$AUTOIND/SM_$an on" > $STF_TMPDIR/opt.out.$$
803 if [[ $? == 0 && ,$mntopt, == @(*,vers=2,*|*,vers=3,*) ]]; then
804 echo "\n$Fname: it is wrong to be found via mount."
805 cat $STF_TMPDIR/opt.out.$$
806 umount -f $AUTOIND/SM_$an > /dev/null 2>&1
807 cleanup $STF_FAIL
808 fi
809
810 ls -l $AUTOIND/SM_$an/rofile > $STF_TMPDIR/ls.out.$$ 2>/dev/null
811 if [[ $? == 0 && ,$mntopt, != @(*,vers=2,*|*,vers=3,*) ]]; then
812 echo "\n$Fname: it is wrong to find rofile:"
813 cat $STF_TMPDIR/ls.out.$$
814 umount -f $AUTOIND/SM_$an > /dev/null 2>&1
815 cleanup $STF_FAIL
816 fi
817
818 rm -f $STF_TMPDIR/*.out.$$
819 echo "OK"
820 }
821
822 # Function to modify default_tgs_enctypes and default_tkt_enctypes
823 # in krb5.conf and create nfs principal with specified enctype.
824 # Usage: setup_enctype enctype_for_cfgfile enctype_for_nfs
825 #
826 function setup_enctype {
827 typeset Fname=setup_enctype
828 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
829 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
830 typeset logfile=$STF_TMPDIR/$Fname.$$
831
832 if (( $# < 2 )); then
833 echo "Usage: setup_enctype enctype_in_cfgfile enctype_of_nfssrv"
834 exit $STF_UNINITIATED
835 fi
836
837 typeset enctype_in_cfgfile=$1
838 typeset enctype_of_nfssrv=$2
839
840 # remove existing entries in krb5.conf if there are any
841 egrep -v "default_tgs_enctypes|default_tkt_enctypes" \
842 /etc/krb5/krb5.conf > /etc/krb5/krb5.tmp
843
844 # add user specified enctype values in krb5.conf
845 if [[ $enctype_in_cfgfile != "DEFAULT" ]]; then
846 awk '/^\[libdefaults\]$/ {
847 print $0;
848 printf "\tdefault_tgs_enctypes=%s\n",enc;
849 printf "\tdefault_tkt_enctypes=%s\n",enc;
850 continue } {print $0}' \
851 enc=$enctype_in_cfgfile /etc/krb5/krb5.tmp \
852 > /etc/krb5/krb5.conf
853 else
854 mv /etc/krb5/krb5.tmp /etc/krb5/krb5.conf
855 fi
856
857 # remove nfs principal on the server
858 princadm -c -p nfs/$SRV_FQDN $SRV_FQDN. 2>$logfile
859 ckresult $? "princadm failed" $logfile || exit $STF_UNINITIATED
860
861 # create nfs principal using user specified enctypes
862 typeset enctype_opt=""
863 [[ $enctype_of_nfssrv != DEFAULT ]] \
864 && enctype_opt=",enctype=$enctype_of_nfssrv"
865 princadm -s -p nfs/$SRV_FQDN"$enctype_opt" $SRV_FQDN. 2>$logfile
866 ckresult $? "princadm failed" $logfile || exit $STF_UNINITIATED
867 }
868
869 # Function to restore changes made by setup_enctype(). It removes
870 # default_tgs_enctypes and default_tkt_enctypes from krb5.conf and
871 # create nfs principals with default enctypes.
872 #
873 function cleanup_enctype {
874 setup_enctype DEFAULT DEFAULT
875 }
876
877 # Function to rcp the dfstab file to SERVER if provided and
878 # run shareall to share all entries in /etc/dfs/dfstab and
879 # verify all entries are shared with needed options
880 # Usage: do_shareall_check dfstab_file
881 #
882 function do_shareall_check {
883 typeset Fname=do_shareall_check
884 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
885 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
886
887 typeset shrfile=$1
888
889 # provide the new dfstab file to server
890 # and make those share entries effective by shareall
891 scp $shrfile root@$SERVER:/etc/dfs/dfstab \
892 > $STF_TMPDIR/rcp.out.$$ 2>&1
893 if (( $? != 0 )); then
894 echo "$Fname: failed to copy <$shrfile> to <$SERVER>"
895 cat $STF_TMPDIR/rcp.out.$$
896 cleanup $STF_UNRESOLVED
897 fi
898
899 echo "Sharing all entries in $SERVER:/etc/dfs/dfstab ... \c"
900 typeset SRVDEBUG=$STC_GENUTILS_DEBUG:$SHAREMNT_DEBUG
901 [[ :$SRVDEBUG: == *:RSH:* ]] && SRVDEBUG=all
902 RSH root $SERVER \
903 "export SHAREMNT_DEBUG=$SRVDEBUG; \
904 $SRV_TMPDIR/sharemnt.others -S" \
905 > $STF_TMPDIR/rsh.out.$$ 2>&1
906 rc=$?
907 [[ :$SRVDEBUG: == *:all:* ]] && cat $STF_TMPDIR/rsh.out.$$ 1>&2
908 grep "Done" $STF_TMPDIR/rsh.out.$$ > /dev/null 2>&1
909 if (( $? != 0 || $rc != 0 )); then
910 echo "$Fname: run <$SRV_TMPDIR/sharemnt.others -S> \
911 in <$SERVER> failed:"
912 cat $STF_TMPDIR/rsh.out.$$
913 cleanup $STF_FAIL
914 fi
915
916 echo "OK"
917 rm -f $STF_TMPDIR/*.out.$$
918 }
919
920 # Function to unshare all entries by unshareall in server
921 # and delete the dfstab test file in client if provided
922 # Usage: do_unshareall_check dfstab_file
923 #
924 function do_unshareall_check {
925 typeset Fname=do_unshareall_check
926 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
927 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
928
929 # delete the given test dfstab file
930 rm -f $1
931
932 # unshare all test filesystems in server
933 typeset SRVDEBUG=$STC_GENUTILS_DEBUG:$SHAREMNT_DEBUG
934 [[ :$SRVDEBUG: == *:RSH:* ]] && SRVDEBUG=all
935 RSH root $SERVER \
936 "export SHAREMNT_DEBUG=$SRVDEBUG; \
937 $SRV_TMPDIR/sharemnt.others -U" \
938 > $STF_TMPDIR/rsh.out.$$ 2>&1
939 rc=$?
940 [[ :$SRVDEBUG: == *:all:* ]] && cat $STF_TMPDIR/rsh.out.$$ 1>&2
941 grep "Done" $STF_TMPDIR/rsh.out.$$ > /dev/null 2>&1
942 if (( $? != 0 || $rc != 0 )); then
943 echo "$Fname: run <$SRV_TMPDIR/sharemnt.others \c"
944 echo "-C in <$SERVER> failed:"
945 cat $STF_TMPDIR/rsh.out.$$
946 cleanup $STF_FAIL
947 fi
948
949 echo "OK"
950 rm -f $STF_TMPDIR/*.out.$$
951 }
952
953 # Function to get the number of clients configured on server
954 # Notice:
955 # stress tests will call this function as it does not support mutilple clients
956 #
957 function get_clients_num {
958 typeset Fname=get_clients_num
959 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
960 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
961
962 RSH root $SERVER \
963 "/bin/ls -l $(dirname $SRV_TMPDIR)" \
964 > $STF_TMPDIR/rsh.out.$$ 2> $STF_TMPDIR/rsh.err.$$
965 typeset -i ret=$?
966
967 #
968 # Once a client is configured on server, we created a tmp dir named
969 # SRV_TMPDIR which looks like: /var/tmp/TMPDIR_shmnt_client01
970 # Notice: If SRV_TMPDIR changes, this function should be changed too.
971 #
972 typeset name_tag=$(basename $SRV_TMPDIR | awk -F_ '{print $1"_"$2"_"}')
973 typeset client_num=$(sed '1d' $STF_TMPDIR/rsh.out.$$ | \
974 awk '{print $NF}' | egrep "^$name_tag" | wc -l 2>&1)
975 if (( $ret != 0 )); then
976 print -u2 "$Fname: RSH to SERVER<SERVER> failed"
977 cat $STF_TMPDIR/rsh.*.$$
978 client_num=0
979 fi
980 rm -f $STF_TMPDIR/rsh.*.$$
981
982 echo $client_num
983 return $ret
984 }
985
986 # Function to delete users via its specific tag
987 # Usage: del_users <tag>
988 #
989 function del_users {
990 typeset Fname=del_users
991 [[ :$SHAREMNT_DEBUG: == *:$Fname:* \
992 || :$SHAREMNT_DEBUG: == *:all:* ]] && set -x
993
994 typeset ctag=$1
995 typeset -i ret=0
996
997 grep ":${ctag}:" /etc/passwd > $STF_TMPDIR/$NAME.users.$$ 2>/dev/null
998 while read line; do
999 user=$(echo $line | awk -F: '{print $1}')
1000 userdel $user
1001 (( $? != 0 )) && (( ret += 1 ))
1002 done < $STF_TMPDIR/$NAME.users.$$
1003
1004 rm -f $STF_TMPDIR/$NAME.users.$$
1005 return $ret
1006 }
1007
1008 # Function to print debug info from a file to stderr
1009 # Usage: print_debug <file>
1010 #
1011 function print_debug {
1012 [[ :$SHAREMNT_DEBUG: == *:$NAME:* \
1013 || :$SHAREMNT_DEBUG: == *:RSH:* \
1014 || :$SHAREMNT_DEBUG: == *:all:* ]] && cat $1 1>&2
1015 }