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 # Test to verify SERVER log the correct data in nfslog given the specified
29 # tag. This test is part of the sharemnt/stc2 harness to test various
30 # combinations of valid nfslog.conf tag entries.
31 #
32 # Usage:
33 # test_nfslogd <test_case_name> <test_file> <tag_name>
34 # <LOG_OK> <BUF_OK> <FHT_OK> <DEBUG_switch>
35 #
36 # - LOG_OK indicates if the logging tag contains a valid log file
37 # This is either 1 for a valid file or 0 for an invalid file.
38 # (This should always be 1)
39 # - BUF_OK indicates if the logging tag contains a valid buffer file.
40 # This is either 1 for a valid file or 0 for an invalid file.
41 # (This should always be 1 for nfsv2/3)
42 # - FHT_OK indicates if the logging tag contains a valid file handle table.
43 # This is either 1 for a valid file or 0 for an invalid file.
44 # (This should always be 1 for nfsv2/3)
45 #
46 # This test verifies that nfslogd successfully logged the expected
47 # information specified by the specified <tag>. We use the <tag> to
48 # search /etc/nfs/nfslog.conf on the $SERVER to find the corresponding
49 # buffer, logfile, fh2path_table and verify that they were created, or
50 # not created as expected. The logfile is then searched to verify
51 # that the appropriate log record has been created. This log record of
52 # of the form "$NFSLOGDDIR/$TESTFILE write" or "$NFSLOGDDIR/$TESTFILE i" for
53 # the log format.
54 #
55 # This test will copy itself to the $STF_TMPDIR directory in the host defined
56 # by $SERVER. It will then execute the copy in the $SERVER
57 #
58 # Note that the tag in nfslog.conf has to be unique. We grep for this
59 # tag in the nfslog.conf file, and rely on the fact that we will only
60 # find one match.
61
62 #
63 # Returns 0 if the requested pattern ($2) is defined in the input line ($1).
64 # The value of the pattern is stored in $NEWVALUE.
65 # Returns non-zero if the pattern is not found.
66 #
67 function get_pattern_value {
68 [[ -n $DEBUG ]] && set -x
69
70 NEWVALUE=$(echo $1 | /usr/bin/nawk -v pattern=$2 \
71 '{for (i = 1; i <= NF; i++) if ($i ~ pattern) print $i; }')
72 # Not defined; we're done
73 [[ -z $NEWVALUE ]] && return 1
74 NEWVALUE=$(echo $NEWVALUE | /usr/bin/nawk -F= '{print $2}')
75 return 0
76 }
77
78 #
79 # Returns the absolute path of the requested pattern.
80 # Prepends $THE_DEFAULTDIR to the requested pattern if it is a relative
81 # path.
82 # The absolute value is stored in $NEWVALUE
83 #
84 function get_absolute_path {
85 [[ -n $DEBUG ]] && set -x
86
87 FIRSTCHAR=$(echo $1 | /usr/bin/cut -c1)
88 [[ $FIRSTCHAR == "/" ]] && NEWVALUE=$1 || NEWVALUE=$THE_DEFAULTDIR/$1
89 return 0
90 }
91
92 #
93 # Sets the value of the current entry of the /etc/nfs/nfslog.conf file.
94 # The values are stored in:
95 # defaultdir= $THE_DEFAULTDIR
96 # buffer= $THE_BUFFER
97 # fhtable= $THE_FHPATH
98 # log= $THE_LOGPATH
99 # logformat= $THE_LOGFORMAT
100 #
101 # The values are all absolute directory values (except for THE_LOGFORMAT).
102 #
103 function get_nfslogconf {
104 [[ -n $DEBUG ]] && set -x
105
106 GLOBAL_LINE=$(grep "^global" /etc/nfs/nfslog.conf)
107
108 if [[ -n $GLOBAL_LINE ]]; then
109 # Global tag defined, get the new values
110 get_pattern_value "$GLOBAL_LINE" "defaultdir="
111 (( $? == 0 )) && THE_DEFAULTDIR=$NEWVALUE
112
113 get_pattern_value "$GLOBAL_LINE" "buffer="
114 (( $? == 0 )) && THE_BUFFER=$NEWVALUE
115
116 get_pattern_value "$GLOBAL_LINE" "fhtable="
117 (( $? == 0 )) && THE_FHPATH=$NEWVALUE
118
119 get_pattern_value "$GLOBAL_LINE" "log="
120 (( $? == 0 )) && THE_LOGPATH=$NEWVALUE
121
122 get_pattern_value "$GLOBAL_LINE" "logformat="
123 (( $? == 0 )) && THE_LOGFORMAT=$NEWVALUE
124 fi
125
126 TAG_LINE=$(grep "^$LOGTAG" /etc/nfs/nfslog.conf)
127 if [[ -n $TAG_LINE ]]; then
128 # Specified tag defined, get the new values
129 get_pattern_value "$TAG_LINE" "defaultdir="
130 (( $? == 0 )) && THE_DEFAULTDIR=$NEWVALUE
131
132 get_pattern_value "$TAG_LINE" "buffer="
133 (( $? == 0 )) && THE_BUFFER=$NEWVALUE
134
135 get_pattern_value "$TAG_LINE" "fhtable="
136 (( $? == 0 )) && THE_FHPATH=$NEWVALUE
137
138 get_pattern_value "$TAG_LINE" "log="
139 (( $? == 0 )) && THE_LOGPATH=$NEWVALUE
140
141 get_pattern_value "$TAG_LINE" "logformat="
142 (( $? == 0 )) && THE_LOGFORMAT=$NEWVALUE
143 fi
144
145 #
146 # Obtain the absolute path of the interesting files
147 #
148 get_absolute_path $THE_BUFFER
149 THE_BUFFER=$NEWVALUE
150 get_absolute_path $THE_FHPATH
151 THE_FHPATH=$NEWVALUE
152 get_absolute_path $THE_LOGPATH
153 THE_LOGPATH=$NEWVALUE
154 }
155
156 #
157 # Print the contents of the nfslog.conf file entry we're interested in.
158 #
159 function print_nfslogconf {
160 echo "defaultdir= " $THE_DEFAULTDIR
161 echo "buffer= " $THE_BUFFER
162 echo "fhtable= " $THE_FHPATH
163 echo "log= " $THE_LOGPATH
164 echo "logformat= " $THE_LOGFORMAT
165 }
166
167 #
168 # Verifies that the buffer, fhtable and logfile all exist if the entires
169 # in BUF_OK, FHT_OK and LOG_OK are all set to 1. Verifies if FHT_OK or
170 # LOG_OK are set to 0 that the fhtable or logfile do not exist. Verifies
171 # that the expected log record was recorded in the logfile. Returns 0 on
172 # success, non-zero otherwise.
173 #
174 function check_nfslog_files {
175 [[ -n $DEBUG ]] && set -x
176
177 LOG_OK=$1
178 BUF_OK=$2
179 FHT_OK=$3
180 get_nfslogconf
181
182 #
183 # Check for the existence of the logging files.
184 # This area checks for the existence of the log file, buffer file
185 # and the fh2path_table files. The contents of the log file is
186 # checked in the next section.
187 #
188
189 if (( $BUF_OK == 1 )); then
190 if [[ ! -f ${THE_BUFFER}_log_in_process ]]; then
191 echo "$TNAME: Could not locate buffer. Tag=$LOGTAG"
192 return 1
193 fi
194 else
195 if [[ -f ${THE_BUFFER}_log_in_process ]]; then
196 echo "$TNAME: Buffer file exists but should not. Tag=$LOGTAG"
197 return 1
198 fi
199 fi
200
201 if (( $FHT_OK == 1 )); then
202 if [ ! -f $THE_FHPATH.* ]; then
203 echo "$TNAME: Could not locate fhtable. Tag=$LOGTAG"
204 return 1
205 fi
206 else
207 if [[ ! -f $THE_FHPATH.* ]]; then
208 echo "$TNAME: File Handle table exists but should not. "
209 echo "\cTag=$LOGTAG"
210 return 1
211 fi
212 fi
213
214 if (( $LOG_OK == 1 )); then
215 if [[ ! -f $THE_LOGPATH ]]; then
216 echo "$TNAME: Could not locate logfile. Tag=$LOGTAG"
217 return 1
218 else
219 awk '{printf("%s %s\n", $9, $12)}' $THE_LOGPATH \
220 2>&1 > $STF_TMPDIR/$NAME.awk.$$
221 fi
222 else
223 if [[ ! -f $THE_LOGPATH ]]; then
224 return 0
225 else
226 echo "$TNAME: Log file exists but should not. Tag=$LOGTAG"
227 return 1
228 fi
229 fi
230
231 #
232 # Check Log file.
233 # This section parses the log file and checks this for the write
234 # line from the write to a file in the test.
235 #
236
237 if (( $FHT_OK == 1 )); then
238 if [[ $THE_LOGFORMAT == extended ]]; then
239 grep "$NFSLOGDDIR/$TESTFILE write" $STF_TMPDIR/$NAME.awk.$$ \
240 > /dev/null 2>&1
241 RET_VAL=$?
242 else
243 grep "$NFSLOGDDIR/$TESTFILE i" $STF_TMPDIR/$NAME.awk.$$ \
244 > /dev/null 2>&1
245 RET_VAL=$?
246 fi
247 else
248 if [[ $THE_LOGFORMAT == extended ]]; then
249 grep "$TESTFILE write" $STF_TMPDIR/$NAME.awk.$$ \
250 > /dev/null 2>&1
251 RET_VAL=$?
252 else
253 grep "$TESTFILE i" $STF_TMPDIR/$NAME.awk.$$ \
254 > /dev/null 2>&1
255 RET_VAL=$?
256 fi
257 fi
258
259 if (( $RET_VAL != 0 )); then
260 echo "$TNAME: Write operation not logged in logfile."
261 echo "\ctag=$LOGTAG. testfile=$TESTFILE"
262 cat $THE_LOGPATH
263 return 1
264 fi
265
266 return 0
267 }
268
269 #
270 # Return 0 if nfslogd is running, return non-zero otherwise.
271 # Shutdowns nfslogd to make sure that the nfslog has been flushed.
272 # the daemon will be started in cleanup{}
273 #
274 function kill_nfslogd {
275 [[ -n $DEBUG ]] && set -x
276
277 /usr/bin/pgrep -z $ZONENAME -x -u 0 nfslogd > /dev/null 2>&1
278 if (( $? != 0 )); then
279 echo "$TNAME: nfslogd not running on server. Tag=$LOGTAG"
280 return 1
281 fi
282
283 #
284 # Wait up to 10 seconds for nfslogd to gracefully handle SIGHUP
285 #
286 /usr/bin/pkill -HUP -z $ZONENAME -x -u 0 nfslogd
287 condition="! /usr/bin/pgrep -z $ZONENAME -x -u 0 nfslogd > /dev/null"
288 wait_now 10 "$condition"
289 #
290 # Kill nfslogd more forcefully if it did not shutdown during
291 # the grace period
292 #
293 if (( $? != 0 )); then
294 /usr/bin/pkill -TERM -z $ZONENAME -x -u 0 nfslogd
295 (( $? != 0 )) && /usr/bin/pkill -9 -z $ZONENAME -x -u 0 nfslogd
296 fi
297
298 return 0
299 }
300
301 # cleanup function on all exit
302 function cleanup {
303 [[ -n $DEBUG ]] && set -x
304
305 ret=$1
306 (( $ret != 0 )) && print_nfslogconf
307
308 rm -rf /etc/nfs/nfslogtab
309 cd $Test_Log_Dir/; rm -rf defaults/* absolute/* results/*
310
311 # restart nfslogd for next test.
312 touch /etc/nfs/nfslogtab
313 /usr/lib/nfs/nfslogd > $STF_TMPDIR/$TNAME.nfslogd.$$ 2>&1
314 if (( $? != 0 )); then
315 echo "$TNAME: ERROR - failed to restart nfslogd"
316 echo "The failure will also cause next test failed."
317 cat $STF_TMPDIR/$TNAME.nfslogd.$$
318 ret=1
319 fi
320 # wait a while and check nfslogd is running
321 condition="/usr/bin/pgrep -z $ZONENAME -x -u 0 nfslogd > /dev/null 2>&1"
322 wait_now 20 "$condition"
323 if (( $? != 0 )); then
324 echo "$TNAME: ERROR - nfslogd is still not running after 20 seconds"
325 echo "The failure will also cause next test failed."
326 ret=1
327 fi
328
329 rm -fr $STF_TMPDIR/*.$$
330 exit $ret
331 }
332
333 # start test ...
334
335 NAME=$(basename $0)
336
337 THE_DEFAULTDIR="/var/nfs"
338 THE_BUFFER="nfslog_workbuffer"
339 THE_FHPATH="fhtable"
340 THE_LOGPATH="nfslog"
341 THE_LOGFORMAT="basic"
342
343 # variables gotten from client system:
344 STF_TMPDIR=STF_TMPDIR_from_client
345 DEBUG=$7
346 TNAME=$1
347 TESTFILE=$2
348 LOGTAG=$3
349 ZONENAME=$(zonename)
350 Test_Log_Dir="/var/nfs/smtest"
351
352 . $STF_TMPDIR/srv_config.vars
353
354 # Include common STC utility functions
355 if [[ -s $STC_GENUTILS/include/nfs-util.kshlib ]]; then
356 . $STC_GENUTILS/include/nfs-util.kshlib
357 else
358 . $STF_TMPDIR/nfs-util.kshlib
359 fi
360
361 # Turn on debug info, if requested
362 [[ -n $DEBUG ]] && set -x
363
364 # kill nfslogd to flush nfslog
365 kill_nfslogd
366 (( $? != 0 )) && cleanup 1
367
368 # verify log, sleep 5 mins to refresh log.
369 wtime=300
370 while (( $wtime > 0 )); do
371 sleep 5
372 echo "sleep 5 ... "
373 sync
374 check_nfslog_files $4 $5 $6 > $STF_TMPDIR/$NAME.chk.$$ 2>&1
375 ret=$?
376 (( $ret != 0 )) && wtime=$((wtime - 5)) || break
377 done
378
379 if (( $ret != 0 )); then
380 echo "$TNAME: check_nfslog_files failed after sleeping 5 minutes."
381 cat $STF_TMPDIR/$NAME.chk.$$
382 fi
383
384 cleanup $ret