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