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 2008 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
26 #
27
28 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
29
30 NAME=$(basename $0)
31 CDIR=$(pwd)
32
33 . $TESTROOT/libsmf.shlib
34
35 # proc to check if running as root
36 # Usage: is_root [testname] [tmessage]
37 # testname optional; if provided, add to the output
38 # tmessage optional; if provided, must be followed by testname
39 # The main purpose of testname and message is to provide a line that emulates
40 # an assertion, so that the failure is captured in the summary and reported.
41 # On success, it just returns 0, on failure, a message is printed, and
42 # exit UNINITIATED is issued.
43 function is_root
44 {
45 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
46 TName=$1
47 [[ -n $TName ]] && TName="$TName: "
48 Msg=$2
49 Stat=""
50 [[ -n $Msg ]] && Stat="\tTest UNINITIATED: " || Msg="\c"
51 id | grep "0(root)" > /dev/null 2>&1
52 if (( $? != 0 )); then
53 echo "$TName$Msg"
54 echo "${Stat}Must run the tests as root."
55 exit $UNINITIATED
56 fi
57 return 0
58 }
59
60 # proc to get a field from ls -l (owner or group) and print it to stdout
61 # Usage: get_val position filepath
62 # gets ${position}th parameter from "ls -l ${filepath}
63 function get_val
64 {
65 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
66
67 if (( $# != 2 )); then
68 echo "error_bad_#_parameters"
69 return 1
70 fi
71 pos=$1
72 path=$2
73
74 ls -l $path > $TMPDIR/getval.out 2> $TMPDIR/getval.err
75 res=$?
76 if [[ $DEBUG != 0 ]]; then
77 cat $TMPDIR/getval.out >&2
78 cat $TMPDIR/getval.err >&2
79 fi
80 if (( res != 0 )); then
81 if [[ $DEBUG == 0 ]]; then
82 echo "stdout was:" >&2
83 cat $TMPDIR/getval.out >&2
84 echo "stderr was:" >&2
85 cat $TMPDIR/getval.err >&2
86 fi
87 rm -f $TMPDIR/getval.out $TMPDIR/getval.err 2> /dev/null
88 return $res
89 fi
90 out=$(awk "{print \$$pos}" $TMPDIR/getval.out 2> $TMPDIR/getval.err)
91 res=$?
92 [[ $DEBUG != 0 ]] && echo $out >&2
93 (( res != 0 )) && cat $TMPDIR/getval.err >&2
94 rm -f $TMPDIR/getval.out $TMPDIR/getval.err 2> /dev/null
95 echo $out
96
97 return $res
98 }
99
100
101 # proc to get a field from getfacl and print it to stdout
102 # Usage: get_val field_key filepath
103 # looks for the field_key, and prints its value
104 #example get_acl_val user:root /aPath/myfile
105 function get_acl_val
106 {
107 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
108
109 if (( $# != 2 )); then
110 echo "error_bad_#_parameters"
111 return 1
112 fi
113 key=$1
114 path=$2
115
116 getfacl $path > $TMPDIR/getval.out 2> $TMPDIR/getval.err
117 res=$?
118 if [[ $DEBUG != 0 ]]; then
119 cat $TMPDIR/getval.out >&2
120 cat $TMPDIR/getval.err >&2
121 fi
122 if (( res != 0 )); then
123 if [[ $DEBUG == 0 ]]; then
124 echo "stdout was:" >&2
125 cat $TMPDIR/getval.out >&2
126 echo "stderr was:" >&2
127 cat $TMPDIR/getval.err >&2
128 fi
129 rm -f $TMPDIR/getval.out $TMPDIR/getval.err 2> /dev/null
130 return $res
131 fi
132 out=$(grep "$key" $TMPDIR/getval.out | awk '{print $1}' \
133 2> $TMPDIR/getval.err)
134 res=$?
135 [[ $DEBUG != 0 ]] && echo "stdout was: <$out>" >&2
136 (( res != 0 )) && cat $TMPDIR/getval.err >&2
137 rm -f $TMPDIR/getval.out $TMPDIR/getval.err 2> /dev/null
138 temp=$(echo $out | awk -F: '{print $2}')
139 [[ -n $temp ]] && echo $temp
140
141 return $res
142 }
143
144 # proc to check result and print out failure messages
145 # Usage: ckres test_operation status expected_st op_result_msg
146 # test_operation string describing operation tested
147 # status result (status) from operation
148 # expected_st expected result (status)
149 # op_result_msg file or string diagnostic to print if failure
150 # test_code can be used to substitute FAIL. Also, expected_st
151 # can take several values separated by '|' and behave as true if any of the
152 # values matches $status.
153
154 function ckres
155 {
156 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
157
158 op=$1
159 st=$2
160 expt=$3
161 if [[ -n $4 ]]; then
162 res=$4
163 # if $res is an operation output file, get its content
164 if [[ -f $res ]]; then
165 res=$(cat $res)
166 else
167 # is a string, get all components from $4 to last
168 shift; shift; shift
169 res="$@"
170 fi
171 fi
172 tmp=$(echo $expt | sed 's/|/ /g')
173 expt=$tmp
174 code="FAIL"
175 # if exported var for code different from FAIL
176 [[ -n $ckres_code ]] && code=$ckres_code
177 ret=$(echo $expt | grep "$st")
178 if (( $? != 0 )); then
179 echo "\tTest $code: $op returned ($st), expected ($expt)"
180 [[ -n $res ]] && echo "\t\tres = $res\n"
181 else
182 echo "\tTest PASS"
183 fi
184 return $st
185 }
186
187 # proc to check result and print out failure messages. It is a improved version
188 # of the original ckres().
189 # Usage: ckres2 <-s> test_operation status expected_st op_result_msg logfile
190 # result_str
191 # -s output nothing if the check passes
192 # test_operation string describing operation tested
193 # status result (status) from operation
194 # expected_st expected result (status)
195 # op_result_msg user-specified error message to print if it fails
196 # logfile the file which contains diagnostic information
197 # result_str Alternative result string to use instead of FAIL
198 # expected_st can take several values separated by '|' and behave as true
199 # if any of them is matched against.
200 #
201 # Compared with the original ckres(), it has the following new features:
202 #
203 # 1) User-specified error message and logfile are represented by two different
204 # arguments now. The format of the failure message is:
205 #
206 # <content of logfile>
207 # \tTest FAIL
208 # \t\terr=$msg
209 #
210 # 2) User can specify alternative result string on failure with the $result_str
211 # argument. This is useful in testcase-specific setup code, where the result
212 # string should be "UNRESOLVED", instead of "FAIL".
213 # 3) If alternative result string is "ERROR" or "WARNING", the failure message
214 # has a different format:
215 #
216 # <content of logfile>
217 # ERROR: $msg
218 #
219 # This is useful in setup code unrelated to specific testcase.
220 # 4) If -s option is specified, ckres output nothing if the check passes.
221 # This is useful in that one can call ckres2() multiple times to in
222 # different checking steps in a single testcase.
223 # 5) More helpful return value. ckres2() returns 0 if result string matches
224 # the expected one; and 1 if not.
225 # 6) More strict checking. ckres2() checks if result string matches EXACTLY
226 # with the expected string.
227
228 function ckres2
229 {
230 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
231
232 subcheck=0
233 if [[ $1 == -s ]]; then
234 subcheck=1
235 shift
236 fi
237
238 op=$1
239 res=$2
240 exp=$3
241 msg=$4
242 [[ -n $5 ]] && errlog=$5
243 [[ -n $6 ]] && alt_str=$6
244
245 # set error string. Use $alt_str if user specified it.
246 code=FAIL
247 [[ -n $alt_str ]] && code=$alt_str
248
249 matched=0
250 echo "$exp" | grep "|" > /dev/null
251 if (( $? == 1 )); then
252 [[ $exp == $res ]] && matched=1
253 else
254 i=1
255 while true; do
256 var=$(echo "$exp" | cut -d\| -f$i)
257 # if we have run through all the values
258 [[ -z $var ]] && break
259 # if we find a matched value
260 [[ $var == $res ]] && matched=1 && break
261 # continue the loop
262 i=$((i + 1))
263 done
264 fi
265
266 if (( matched == 0 )); then
267 # error log
268 [[ -f $errlog ]] && cat $errlog && rm -f $errlog
269
270 # summary of operation result
271 if [[ $code == ERROR || $code == WARNING ]]; then
272 echo "$code: $msg\n"
273 else
274 echo "\tTest $code: $op returned ($res), expected ($exp)"
275 # user-specified error message
276 [[ -n $msg ]] && echo "\t\terr = $msg\n"
277 fi
278
279 return 1
280 else
281 [[ -f $errlog ]] && rm -f $errlog
282 (( subcheck != 1 )) && echo "\tTest PASS"
283 return 0
284 fi
285 }
286
287 # proc to check return code and print out failure messages
288 # if return-code is 0, this function simply return back 0.
289 # Usage: ckreturn [-r] return_code error_message [err_detail_file]
290 # [result_string]
291 # -r Invert the test logic (failure becomes return_code = 0)
292 # return_code Return code to check
293 # error_message The fail message to print at FAIL
294 # err_detail_file The file to cat out if exists, on failure
295 # result_string Alternative result string to use instead of FAIL
296 #
297 # A result string of "WARNING" or "ERROR" will prevent
298 # the use of the assertion result format (\tTest XXX: msg)
299
300 function ckreturn
301 {
302 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
303 USAGE=\
304 "Usage: ckreturn [-r] return_code error_message [err_detail_file] \
305 \t\t\t[result_string]\n\
306 \tif -r is specified, error condition becomes return_code = 0,\n\
307 \tif result_string is not specified, \"FAIL\" is assumed."
308 typeset n=$#
309 typeset inv_flg=0
310 # requested negative logic (rc == 0)?
311 if [[ $1 == -r ]]; then
312 n=$((n - 1))
313 inv_flg=1
314 shift
315 fi
316 # verify needed args are provided and get them
317 (( n < 2 || n > 4 )) && echo $USAGE && exit $OTHER
318 typeset rc=$1
319 typeset msg=$2
320 typeset cf=""
321 (( n >= 3 )) && cf=$3
322 typeset res="FAIL"
323 (( n >= 4 )) && res=$4
324
325 #check if appropriate error condition is present
326 typeset tst=0
327 if (( inv_flg == 0 )); then
328 (( rc != 0 )) && tst=1
329 else # -r was specified
330 (( rc == 0 )) && tst=1
331 fi
332
333 # on error, cat info file and print Test result message
334 if (( tst == 1 )); then
335 [[ -n $cf && -f $cf ]] && cat $cf && rm -f $cf
336 typeset TEST="\tTest "
337 [[ $res == @(WARNING|ERROR) ]] && TEST=""
338 echo "$TEST$res: $msg"
339 fi
340 #propagate original return code
341 return $rc
342 }
343
344
345 # Proc to poll until a condition is met or the specified timeout expires.
346 # If condition's returned value met the criteria supplied, is considered
347 # successful and the polling finishes, otherwise keep polling after a second
348 # delay until timeout expires.
349 # The returned value is that of the condition passed (as a string).
350 # Usage: poll timeout test condition
351 # timeout timeout in seconds
352 # criteria success criteria for returned code of condition
353 # condition condition to be polling on
354
355 function poll
356 {
357 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
358
359 timeout=$1
360 criteria=$2
361 shift
362 shift
363 condition=$@
364 # change return code ($?) in criteria to $st
365 criteria=$(echo $criteria | sed 's/\$\?/\$st/g')
366
367 # loop until condition is met or timeout is reached
368 i=0
369 while (( i < timeout ))
370 do
371 sleep 1
372 i=$((i + 1))
373 eval $condition > /dev/null 2>&1
374 st=$?
375 eval [[ $criteria ]] && break
376 done
377 return $st
378 }
379
380
381 # proc to print string describing assertion.
382 # Usage: assertion assertion_name description_msg expected value
383 # also global variable NAME must contain the name of the current test file
384 function assertion
385 {
386 Aname=$1
387 ASSERTION=$2
388 shift
389 shift
390 Expected=$@
391 echo "$NAME{$Aname}: $ASSERTION, expect $Expected"
392 }
393
394 # proc to get domain by hostname, using korn shell
395 # Usage: get_domain hostname FQDN(optional)
396 # hostname hostname of the machine
397 # FQDN a flag, if set, return full fully qualified domain name
398 # DEBUG global to enable debugging mode
399 #
400 function get_domain
401 {
402 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
403 mach=$1
404 FQDN=$2
405 ns="dig"
406
407 [[ -z $mach ]] && return 1
408 res=$(getent hosts $mach)
409 (( $? != 0 )) && return 1
410 ipaddr=$(echo $res | nawk '{print $1}')
411 $ns @$DNS_SERVER +noqu -x $ipaddr > $TMPDIR/$ns.out.$$ 2>&1
412 res=$(cat $TMPDIR/$ns.out.$$ | grep 'PTR')
413 ret=$?
414 [[ $ret != 0 && -n $DEBUG && $DEBUG != 0 ]] \
415 && cat $TMPDIR/$ns.out.$$ >&2
416 rm -f $TMPDIR/$ns.out.$$
417 (( ret != 0 )) && return 1
418
419 res=$(echo $res | nawk '{print $5}' | tr "[:upper:]" "[:lower:]")
420 res=${res%.}
421 if [[ $FQDN != FQDN ]]; then
422 mn1=$(echo $res | cut -d. -f1)
423 res=$(echo $res | sed "s/$mn1.//")
424 fi
425
426 echo $res
427 return $ret
428 }
429
430
431 # proc to remotely execute one or more commands, using korn shell.
432 # Usage: execute machine user command_string(rest of line)
433 # machine remote machine to execute command
434 # user target user on remote system
435 # command_string any desired command(s) (korn shell)
436 # DEBUG global to enable debugging mode
437 # UNIX_RES global to detect failures, if unix standard is followed
438 # for return codes (0=OK, !0=failure).
439 # This proc in addition to execute remote command, adds code for
440 # getting the return code from last operation, and to trace
441 # the remote execution asenabled by set -x (depending on $DEBUG).
442 #
443 # note: Take care of not redirection stderr to stdout as that will cause
444 # a very messy output in debug mode, and possible test failures.
445
446 function execute
447 {
448 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
449
450 rmach=$1
451 ruser=$2
452 shift; shift
453 SETD=""
454 [[ -n $DEBUG && $DEBUG != 0 ]] \
455 && SETD="DEBUG=$DEBUG; export DEBUG; set -x; "
456 rcmd="$SETD$@"
457 # by default, expect UNIX standard result codes
458 UNIX_RES=${UNIX_RES:=1}
459
460 file=$TMPDIR/$rmach.$$.out
461 file2=$TMPDIR/exec.result
462 ssh -o "StrictHostKeyChecking no" $rmach -l $ruser "$rcmd; print -u 2 \"returned=(\$?)\"" > $file 2> $file2
463 ret=$?
464 if (( ret != 0 )); then
465 cat $file2
466 return $ret
467 fi
468 cat $file
469 tag=0
470 # if debug info, ignore error message length criteria
471 if [[ -n $DEBUG && $DEBUG != 0 ]]; then
472 errl=0
473 else
474 errl=$(grep -v 'print -u 2' $file2| grep -v 'returned=('| wc -l)
475 fi
476 ret=$(grep -v 'print -u 2' $file2 | grep 'returned=(' | \
477 sed 's/^.*returned=(//' | sed 's/).*$//')
478 # if DEBUG on, mark reason for printing file2
479 [[ -n $DEBUG && $DEBUG != 0 ]] && tag=2
480 # if error, overwrite reason for printing file2
481 [[ $errl != 0 && $DEBUG == 0 ]] || \
482 (( UNIX_RES != 0 && ret != 0 )) || \
483 [[ $ret == 0 && $errl != 0 && -n $DEBUG && $DEBUG != 0 ]] && tag=1
484 [[ -n $DEBUG && $DEBUG != 0 ]] || (( errl != 0 )) || \
485 (( ret != 0 && UNIX_RES != 0 )) && cat $file2 >&2
486
487 rm -f $file $file2 > /dev/null 2>&1
488 return $ret
489 }
490
491
492 # proc to remotely execute one or more commands in the background,
493 # using korn shell.
494 # Usage: executebg machine user command_string(rest of line)
495 # machine remote machine to execute command
496 # user target user on remote system
497 # command_string any desired command(s) (korn shell)
498 # DEBUG global to enable debugging mode
499 # This proc execute remote command in the background
500 # getting the return code from rsh. stdout and stderr are directed
501 # to files for getting results or diagnostics. But execution
502 # tracing (debug) is not enabled on remote system.
503 #
504 # note: Take care of not redirection stderr to stdout as that will cause
505 # a very messy output in debug mode, and possible test failures.
506
507 function executebg
508 {
509 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
510
511 rmach=$1
512 ruser=$2
513 shift; shift
514 rcmd=$@
515 file=$TMPDIR/$rmach.$$.out
516 file2=$TMPDIR/exec.result
517 ssh -o "StrictHostKeyChecking no" $rmach -l $ruser "/usr/bin/ksh -c $rcmd" >$file 2>$file2 &
518 ret=$?
519 sleep 1
520 [[ -s $file ]] && cat $file 2> /dev/null
521 [[ -s $file2 ]] && cat $file2 >&2
522 rm -f $file $file2 > /dev/null 2>&1
523
524 return $ret
525 }
526
527
528 # wrapper proc to mount an NFS file system
529 # Usage: mountit server remote_path local_path NFS_version
530 #we have a local environment variable "MNT_OPT" to the function
531 #if you need some extra mount options at the delegation test,
532 #you may need to export it before the test,for example
533 #in an RDMA enable system,export MNT_OPT="proto=rdma"
534
535 function mountit
536 {
537 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
538 server=$1
539 rpath=$2
540 lpath=$3
541 version=$4
542 options="rw,vers=$version"
543 export MNT_OPT
544 [[ -z $MNT_OPT ]] || options="rw,$MNT_OPT,vers=$version"
545
546 is_cipso "vers=$version" $server
547 if (( $? == CIPSO_NFSV2 )); then
548 echo "CIPSO NFSv2 not supported under Trusted Extensions"
549 return 1
550 fi
551
552 mount -F nfs -o $options $server:$rpath $lpath
553 res=$?
554 (( res != 0 )) && \
555 echo "mount -F nfs -o $options $server:$rpath $lpath FAILED"
556 return $res
557 }
558
559 # wrapper proc to mount an NFS file system
560 # Usage: umountit local_path [kill_flag]
561 # tries to umount path, if unsuccessful, gets and prints PIDs of
562 # procs using that NFS file system, and if the kill flag is set
563 # and there is any process, tries to kill them and retry the umount
564
565 function umountit
566 {
567 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
568
569 lpath=$1
570 kflag=0
571 (( $# > 1 )) && kflag=1
572 umount $lpath
573 res=$?
574 if [ $res != "0" ]; then
575 echo "initial umount unsuccessful ..."
576 echo "fuser -cu $lpath output:"
577 out=$(fuser -cu $lpath 2> /dev/null)
578 fuser -cu $lpath
579 echo "info for processes involved:"
580 pids=$(echo $out|sed 's/^[^0-9]*//')
581 pids=$(echo $pids|sed 's/[^0-9]*)//g')
582 echo $pids | grep "^[0-9].*" > /dev/null 2>&1
583 (( $? != 0 )) && return $res
584 ps -fp "$pids"
585 if (( kflag != 0 )); then
586 echo "killing processes"
587 for i in $pids
588 do
589 echo "kill -9 $i"
590 kill -9 $i
591 done
592 # small delay for kills to finish
593 sleep 5
594 umount $lpath
595 res=$?
596 (( res != 0 )) && echo "umount $lpath FAILED ($res)"
597 fi
598 fi
599 return $res
600 }
601
602
603 # proc to convert user names to user ids
604 # Usage: get_uid user_name_string
605 function get_uid
606 {
607 uid=$1
608 uid=$(id $uid | sed 's/^.*uid=//' | sed 's/(.*$//' 2>/dev/null)
609 res=$?
610 (( res != 0 )) && return $res
611 echo $uid
612 return $res
613 }
614
615
616 # proc to convert group names to group ids
617 # Usage: get_gid group_name_string
618 function get_gid
619 {
620 uid=$1
621 gid=$(id $uid | sed 's/^.*gid=//' | sed 's/(.*$//' 2>/dev/null)
622 res=$?
623 (( res != 0 )) && return $res
624 echo $gid
625 return $res
626 }
627
628
629 # proc to conditionally print a message and the content of an error file,
630 # and erase that temporal error file.
631 #
632 # Usage: dprint "message" [temp_error_file]
633 # message Any string surrounded by double (or single)
634 # quote marks.
635 # temp_error_file Optional temporal file with debug information.
636 function dprint
637 {
638 [[ -z $DEBUG || $DEBUG == 0 ]] && return
639 (( $# < 1 )) && return
640 msg=$1
641 echo $msg
642 if (( $# >= 2 )); then
643 efile=$2
644 if [[ -f $efile ]]; then
645 echo "\tstderr has:\n$(cat $efile)"
646 rm -f $efile > /dev/null 2>&1
647 fi
648 fi
649 }
650
651 function get_del
652 {
653 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
654 (( $# != 1 )) && echo "USAGE: get_del <SERVER>" >&2 && return $FAIL
655 SERVER=$1
656 GET_DEL="sharectl get -p SERVER_DELEGATION nfs"
657 res=$(execute $SERVER root "$GET_DEL")
658 if (( $? != 0 )); then
659 assertion setup \
660 "ERROR: Cannot get delegation policy for $SERVER." \
661 "Get to succeed" >&2
662 echo "stdout=<$res>" >&2
663 return $UNINITIATED
664 else
665 [[ $DEBUG != 0 ]] && echo "stdout=<$res>" >&2
666 res=$(echo $res | awk -F= '{print $2}')
667 if [[ $res == @(off|OFF) ]]; then
668 echo off
669 else
670 echo on
671 fi
672 fi
673 return 0
674 }
675
676 function set_del
677 {
678 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
679 if (( $# != 2 )); then
680 echo "USAGE: set_del <SERVER> <on/off>" >&2
681 assertion setup \
682 "ERROR: Could not set delegation policy for $SERVER" \
683 "Set to succeed" >&2
684 echo "\tTest UNINITIATED: Terminating" >&2
685 return $UNINITIATED
686 fi
687 SERVER=$1
688 value=$2
689 echo $value | egrep "on|off" > /dev/null 2>&1
690 if (( $? != 0 )); then
691 assertion setup \
692 "ERROR: bad delegation policy value ($value)" \
693 "'on' or 'off'" >&2
694 echo "\tTest UNINITIATED: Terminating" >&2
695 return $UNINITIATED
696 fi
697 SET_DEL="sharectl set -p SERVER_DELEGATION=$value nfs"
698 res=$(execute $SERVER root "$SET_DEL" 2> $TMPDIR/result)
699 if (( $? != 0 )); then
700 assertion setup \
701 "ERROR: Cannot set delegation policy for $SERVER." \
702 "Set to succeed" >&2
703 echo "stdout=<$res>" >&2
704 echo "stderr=<$(cat $TMPDIR/result)>" >&2
705 echo "\tTest UNINITIATED: Terminating" >&2
706 rm -f $TMPDIR/result > /dev/null 2>&1
707 return $UNINITIATED
708 else
709 [[ $DEBUG != 0 ]] && cat $TMPDIR/result >&2
710 rm -f $TMPDIR/result > /dev/null 2>&1
711 wait_now 10 "[[ \$(execute $SERVER root sharectl get -p \
712 SERVER_DELEGATION nfs | awk -F= '{print \$2}') == $value ]]"
713 if (( $? != 0 )); then
714 assertion setup \
715 "ERROR: the delegation policy for $SERVER has not been \
716 updated to $value even after 10 seconds." \
717 "Set to succeed" >&2
718 return $UNINITIATED
719 fi
720 fi
721
722 # Make sure the server is out of the grace period before moving on.
723 # Take advantage of nfs client behavior to do it
724 touch $MNTPTR/wait_for_grace_period
725 rm -f $MNTPTR/wait_for_grace_period >/dev/null 2>&1
726 return 0
727 }
728
729 # proc to convert a return code integer to its equivalent string
730 #
731 # Usage: rc2str return_code
732 # return_code return code to convert to its equivalent string
733
734 function rc2str
735 {
736 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
737
738 (( $# != 1 )) && echo "USAGE: rc2str return_code" && exit 1
739
740 typeset rc=$1
741 case $rc in
742 0 ) echo "PASS" ;;
743 1 ) echo "FAIL" ;;
744 2 ) echo "UNRESOLVED" ;;
745 3 ) echo "NOTINUSE" ;;
746 4 ) echo "UNSUPPORTED" ;;
747 5 ) echo "UNTESTED" ;;
748 6 ) echo "UNINITIATED" ;;
749 7 ) echo "NORESULT" ;;
750 8 ) echo "WARNING" ;;
751 9 ) echo "TIMED_OUT" ;;
752 10 ) echo "OTHER" ;;
753 * ) echo "OTHER: (rc=$rc)" ;;
754 esac
755
756 return 0
757 }
758
759 # Clean up function
760 function deleg_cleanit
761 {
762 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
763
764 if [[ $NAMEATTR == ON ]]; then
765 runat $OPF "rm -f deleg.* endless*"
766 rm -f $OPF
767 rm -f $TMPDIR/as_*
768 fi
769
770 rm -f $TMPDIR/tstres > /dev/null 2>&1
771 rm -f $TMPDIR/result > /dev/null 2>&1
772 rm -f $TMPDIR/stat.tmp > /dev/null 2>&1
773
774 rm -f $TESTDIR/deleg.* $TESTDIR/endless_*.*
775 ls $TESTDIR/deleg.* $TESTDIR/endless_*.* > /dev/null 2>&1
776 (( $? == 0 )) && echo "WARNING: (Tests CLEANUP) could not remove \
777 $TESTDIR/deleg.* $TESTDIR/endless_*.*"
778
779 cd /
780 umountit $TESTDIR clean
781 if (( $? != 0 )); then
782 umount -f $TESTDIR
783 (( $? != 0 )) && echo "WARNING: (Test CLEANUP) could not \
784 umount -f $TESTDIR"
785 fi
786 rmdir $TESTDIR
787 (( $? != 0 )) && echo "WARNING: (Test CLEANUP) Cannot rmdir $TESTDIR"
788
789 res=$(execute $CLIENT2 root "umount $TESTDIR")
790 if (( $? != 0 )); then
791 echo "WARNING: Cannot umount $TESTDIR on $CLIENT2.\nres = $res"
792 res=$(execute $CLIENT2 root "umount -f $TESTDIR")
793 if (( $? != 0 )); then
794 echo "\t(Test CLEANUP) Cannot umount -f \
795 $TESTDIR on $CLIENT2."
796 echo "res = $res"
797 fi
798 fi
799 res=$(execute $CLIENT2 root "rmdir $TESTDIR")
800 (( $? != 0 )) && echo "(Test CLEANUP) WARNING: Cannot rmdir $TESTDIR \
801 on $CLIENT2.\nres = $res"
802 }
803
804 # Usage: ck_zone [return_flg] [err_msg]
805 # return_flg (optional); if provided and not 0, it will returned
806 # to the caller when in non-global zone; otherwise
807 # it will exit
808 # err_msg (optional); if provided, it will be added to the output
809 # when in non-global zone
810 #
811 # This proc is to verify if the current zone is a non-global zone
812 # Yes, it just returns 0 without any messages printed;
813 # No, it prints an error message and return/exit 4 (UNSUPPORTED).
814 #
815 # The original vesion locates under usr/ontest/util/stc/nfs/nfs-util.ksh
816
817 function ck_zone
818 {
819 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
820 Return=$1
821 ErrMsg=$2
822 [[ -z $ErrMsg ]] && \
823 ErrMsg="This test is not supported in non-global zone."
824 zn=$(/usr/bin/zonename)
825 if [[ $zn != global ]]; then
826 echo "ck_zone: current zonename is <$zn>"
827 echo " $ErrMsg"
828 if (( Return == 0 )); then
829 echo "\tTest UNSUPPORTED: Terminating"
830 exit 4
831 else
832 return 4
833 fi
834 fi
835 return 0
836 }
837
838 # ------------------------------------------------------------------------
839 # is_cipso
840 # --------
841 # Determine whether the connection to be NFS mounted is
842 # a CIPSO connection and if it is return a value corresponding
843 # to NFSv2 | NFSv3 | NFSv4.
844 #
845 # usage: is_cipso <mount options> <server name>
846 #
847 # Example usage:
848 #
849 # if [[ -n $MNTOPTS ]]; then
850 # is_cipso $MNTOPTS $SERVER
851 # if (( $? == CIPSO_NFSV4 )); then
852 # <setup server exported dir to include >
853 # <non-global path in its exported dir >
854 # <setup client mount point dir to include>
855 # <non-global path >
856 # fi
857 # fi
858 #
859 # return: 0: NOT cipso
860 # 1: IS cipso NFSv2
861 # 2: IS cipso NFSv3
862 # 3: IS cipso and NOT NFSv2 or NFSv3
863 #
864 # Original version is located in: usr/ontest/util/stc/nfs/common_funcs.shlib
865 # ------------------------------------------------------------------------
866 CIPSO_NOT=0
867 CIPSO_NFSV2=1
868 CIPSO_NFSV3=2
869 CIPSO_NFSV4=3
870
871 function is_cipso
872 {
873 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
874
875 if (( $# < 2 )); then
876 /bin/echo "is_cipso() wrong number of args!"
877 return $CIPSO_NOT
878 fi
879
880 M_OPTS=$1
881 ASERVER=$2
882
883 if [[ -x /usr/sbin/tninfo ]]; then
884 /usr/sbin/tninfo -h $ASERVER | grep cipso >/dev/null 2>&1
885 (( $? != 0 )) && return $CIPSO_NOT
886
887 echo "$M_OPTS" | grep "vers=2" >/dev/null 2>&1
888 (( $? == 0 )) && return $CIPSO_NFSV2
889
890 echo "$M_OPTS" | grep "vers=3" >/dev/null 2>&1
891 (( $? == 0 )) && return $CIPSO_NFSV3
892 return $CIPSO_NFSV4
893 fi
894 return $CIPSO_NOT
895 }
896
897 # ------------------------------------------------------------------------
898 # cipso_check_mntpaths()
899 # ----------------------
900 # 1. Check that any zones exist.
901 # 2. Check that at least one non-global zone exists.
902 # 3. Check that the server's exported directory contains
903 # a path to a non-global zone's directory.
904 # 4. Check that the client's mount point dir contains a path
905 # to the same non-global zone that's in the server's
906 # exported directory path.
907 #
908 # An example of valid paths are:
909 # ------------------------------
910 # server's exported directory: /zone/public/root/var/tmp/junk
911 # client's mount point directory: /zone/public/mnt
912 #
913 # Then the client can mount it via:
914 # ---------------------------------
915 # mount -F nfs <server>:/zone/public/root/var/tmp/junk /zone/public/mnt
916 #
917 # usage: cipso_check_mntpaths <server's export dir> <client's mnt pnt>
918 #
919 # return: 0: Everything is OK
920 # 1: No non global zones exist
921 # 2: No non global zone path in server's exported dir
922 # 3: No non global zone path in client's mount point dir
923 #
924 # Original version is located in: usr/ontest/util/stc/nfs/common_funcs.shlib
925 # ------------------------------------------------------------------------
926 CIPSO_NO_NG_ZONE=1
927 CIPSO_NO_EXPORT_ZONEPATH=2
928 CIPSO_NO_MNTPT_ZONEPATH=3
929
930 function cipso_check_mntpaths
931 {
932 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
933
934 if (( $# < 2 )); then
935 /bin/echo "cipso_check_mntpaths() wrong number of args!"
936 return $CIPSO_NO_NG_ZONE
937 fi
938
939 [[ -z $ZONE_PATH ]] && return $CIPSO_NO_NG_ZONE
940
941 srvdir=$1
942 clntdir=$2
943
944 zlist=$(/usr/sbin/zoneadm list)
945 [[ -z $zlist ]] && return $CIPSO_NO_NG_ZONE
946
947 [[ $zlist == global ]] && return $CIPSO_NO_NG_ZONE
948
949 fnd=0
950 for azone in $zlist
951 do
952 [[ $azone == global ]] && continue
953 X=$(zoneadm -z $azone list -p | cut -d ":" -f 4)
954 [[ -z $X ]] && continue
955 X1=$(echo $X | sed -e 's/\// /g' | awk '{print $1}')
956 X2=$(echo $X | sed -e 's/\// /g' | awk '{print $2}')
957 Y1=$(echo $ZONE_PATH | sed -e 's/\// /g' | awk '{print $1}')
958 Y2=$(echo $ZONE_PATH | sed -e 's/\// /g' | awk '{print $2}')
959 if [[ $X1 == $Y1 && $X2 == $Y2 ]]; then
960 fnd=1
961 break
962 fi
963 done
964
965 (( fnd == 0 )) && return $CIPSO_NO_NG_ZONE
966
967 echo $srvdir | /bin/grep "^$ZONE_PATH" >/dev/null 2>&1
968 (( $? != 0 )) && return $CIPSO_NO_EXPORT_ZONEPATH
969
970 echo $clntdir | /bin/grep "^$ZONE_PATH" >/dev/null 2>&1
971 (( $? != 0 )) && return $CIPSO_NO_MNTPT_ZONEPATH
972 return 0
973 }
974
975 # A wait function to verify a specified condition
976 # Usage: wait_now max_TIMER the_condition
977 # max_TIMER the maximum timer to wait
978 # condition the condition to break the wait:
979 # "true" wait_now{} returns 0
980 # "false" wait_now{} continues until the TIMER
981 #
982
983 function wait_now
984 {
985 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
986 (( $# < 2 )) && \
987 echo "Usage: wait_now max_TIMER the_condition" && \
988 return -1
989
990 Timer=$1
991 shift
992 Wcond=$@
993
994 i=0
995 while (( i < Timer ))
996 do
997 eval $Wcond
998 (( $? == 0 )) && return 0
999 sleep 1
1000 i=$((i + 1))
1001 done
1002 echo "wait_now function failed"
1003 return $i
1004 }
1005
1006 function start_fmri
1007 {
1008 [[ -n $DEBUG ]] && [[ $DEBUG != 0 ]] && set -x
1009 (( $# == 0 )) && \
1010 echo "Usage: start_fmri fmri [host]" &&
1011 return -1
1012 typeset fmri=$1 host=$2
1013 typeset msg cmd ret=0 res
1014 if [[ -z $host ]]; then
1015 msg="Warning: Failed to start $fmri on $CLIENT"
1016 smf_fmri_transition_state do $fmri online 10 \
1017 > $TMPDIR/fmri.out.$$ 2>&1
1018 ret=$?
1019 ckreturn $ret "$msg" $TMPDIR/fmri.out.$$
1020 return $ret
1021 else
1022 msg="Warning: Failed to start $fmri on $host"
1023 cmd=". $TMPDIR/libsmf.shlib; \
1024 smf_fmri_transition_state do $fmri online 10; \
1025 t=\$?; echo \"ret=\$t\""
1026 res=$(execute $host root "$cmd")
1027 ret=$(echo $res | grep "ret=" | sed 's/.*ret=/ret=/' | \
1028 awk -F= '{print $NF}' | awk '{print $1}')
1029 ckreturn $ret "$msg"
1030 return $ret
1031 fi
1032 }