1# vim: filetype=sh 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 2007 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27# ident "@(#)history_common.kshlib 1.3 07/07/31 SMI" 28# 29 30. $STF_SUITE/include/libtest.kshlib 31 32# 33# Execute arguments and record them to the log file. 34# Notice: EXPECT_HISTORY need be defined. 35# 36# $1-n arguments for execution. 37# 38function exec_record 39{ 40 [[ -z $EXPECT_HISTORY ]] && log_fail "EXPECT_HISTORY is undefined." 41 42 typeset long_hist 43 typeset user='root' 44 typeset opt 45 while getopts ":lu:" opt; do 46 case $opt in 47 l) long_hist=1;; 48 u) user=$OPTARG ;; 49 esac 50 done 51 shift $(($OPTIND -1)) 52 53 if [[ $user == 'root' ]]; then 54 log_must "$@" 55 else 56 log_must $SU $user -c "$@" 57 fi 58 user_id=$(id -u $user) 59 60 typeset cmdline="$@" 61 # Remove "eval" ">*" & "<*" for 'zfs send' and 'zfs receive'. 62 cmdline=${cmdline#eval} 63 cmdline=${cmdline%%\>*} 64 cmdline=${cmdline%%\<*} 65 66 # Remove additional blank 67 cmdline=${cmdline## } 68 cmdline=${cmdline%% } 69 70 # Get the basename of command. i.e: /usr/sbin/zpool -> zpool 71 typeset cmd=$($ECHO $cmdline | $AWK '{print $1}') 72 eval cmdline=\${cmdline#$cmd} 73 cmd=${cmd##*/} 74 75 # Write basic history to file 76 print -n $cmd $cmdline >> $EXPECT_HISTORY 77 if [[ -n $long_hist ]]; then 78 # Write long history to file 79 hn=$($HOSTNAME) 80 zn=$($ZONENAME) 81 [ "$zn" = "global" ] && zn="" 82 [ -n "$zn" ] && zn=":$zn" 83 print -n " [user $user_id ($user) on $hn$zn]" >> $EXPECT_HISTORY 84 fi 85 # Plus enter in the end of line 86 print >> $EXPECT_HISTORY 87} 88 89# 90# Format 'zpool history' output to specified file. 91# 92# $1 pool name 93# $2 output file. 94# $3 option 95# 96function format_history 97{ 98 typeset pool=$1 99 typeset outfile=$2 100 typeset option=$3 101 102 [[ -z $pool || -z $outfile ]] && \ 103 log_fail "Usage: format_history <pool> <outfile> [option]" 104 105 typeset temp_history=$TMPDIR/temp_history.format_history.${TESTCASE_ID} 106 $ZPOOL history $option $pool > $temp_history 107 108 # Truncate output file 109 $CAT /dev/null > $outfile 110 111 typeset line 112 typeset -i n=0 113 while read line; do 114 # Ignore the first line and empty line 115 if [[ $n -eq 0 || -z $line ]]; then 116 n=1; continue 117 fi 118 $ECHO ${line#* } >> $outfile 119 done < $temp_history 120 121 $RM -f $temp_history 122} 123 124# 125# Get the additional pool history. 126# 127# $1 pool name 128# $2 additional history file 129# $3 option 130# 131function additional_history 132{ 133 typeset pool=$1 134 typeset add_his_file=$2 135 typeset option=$3 136 137 if [[ -z $pool || -z $add_his_file ]]; then 138 log_fail "Usage: additional_history <pool> " \ 139 "<additional_history_file> [option]" 140 fi 141 142 typeset temp_history=$TMPDIR/temp_history.additional_history.${TESTCASE_ID} 143 # Current current history 144 format_history $pool $temp_history $option 145 # Figure out new history 146 $DIFF $temp_history $REAL_HISTORY | $GREP "^<" | $SED 's/^<[ ]*//' > \ 147 $add_his_file 148 149 $CP $temp_history $REAL_HISTORY 150 $RM -f $temp_history 151} 152 153# 154# Get given dataset id 155# 156# $1 dataset name 157# 158function get_dataset_id 159{ 160 typeset ds=$1 161 162 # 163 # The zdb information looks like: 164 # 165 # Dataset pool/fs [ZPL], ID 21, cr_txg 6, 18.0K, 4 objects 166 # 167 typeset dst_id=$($ZDB $ds | $GREP "^Dataset $ds " | \ 168 $AWK -F\, '{print $2}' | $AWK '{print $2}') 169 170 $ECHO $dst_id 171} 172 173# 174# Special case of verify_history, but only for destroyed datasets. This is 175# needed because get_dataset_id depends on still having the original dataset 176# in order to obtain its dataset id. 177# 178function verify_destroyed #<his_file> <ds_id> 179{ 180 typeset his_file=$1 181 typeset ds_id=$2 182 183 $GREP -E "\[txg:[0-9]+\] destroy [^ ]+ \($ds_id\)" $his_file \ 184 > /dev/null 2>&1 185 (($? == 0)) && return 0 186 return 1 187} 188 189# 190# Verify directly executed commands in a history file. This differs from 191# verify_history in that it checks for explicit commands as opposed to 192# internally generated commands. 193# 194function verify_direct_history #<his_file> <subcmd> <ds> 195{ 196 typeset his_file=$1 197 typeset subcmd=$2 198 typeset ds=$3 199 200 $GREP "zfs ${subcmd} ${ds}" ${his_file} > /dev/null 2>&1 201 (($? == 0)) && return 0 202 return 1 203} 204 205# This function mostly just helps to collapse the case statement 206# in verify_history. It returns whether the line matches (1==true). 207function verify_history_line 208{ 209 typeset line=$1 210 typeset subcmd=$2 211 typeset ds=$3 212 typeset keyword=$4 213 214 typeset dst_id=$(get_dataset_id $ds) 215 log_note "Line: '$line'" 216 log_note "Checking cmd($subcmd) for $ds, keyword='$keyword'" 217 $ECHO $line | $GREP -E "\[txg:[0-9]+\] $subcmd $ds \($dst_id\)" | \ 218 $GREP $keyword >/dev/null 2>&1 219 [[ $? == 0 ]] && return 1 220 return 0 221} 222 223# 224# Scan history file and check if it include expected internal history 225# information 226# 227# $1 history file 228# $2 subcmd 229# $3 dataset 230# $4 keyword 231# 232function verify_history #<his_file> <subcmd> <ds> [keyword] 233{ 234 typeset his_file=$1 235 typeset subcmd=$2 236 typeset ds=$3 237 typeset keyword=$4 238 239 typeset line found=0 240 log_note "Test1" 241 while read line; do 242 case $subcmd in 243 snapshot|rollback|inherit) 244 # [txg:12] snapshot system/foo@0 (46) 245 keyword="$subcmd" 246 verify_history_line "$line" $subcmd $ds $keyword 247 [[ $? == 0 ]] && return 0 248 ;; 249 allow) 250 # [txg:10] permission update testpool.1477/testfs.1477 (40) s-$@basic snapshot 251 _subcmd="permission update" 252 verify_history_line "$line" "$_subcmd" $ds "$keyword" 253 [[ $? == 0 ]] && return 0 254 ;; 255 unallow) 256 # [txg:174] permission remove testpool.1477/testfs.1477 (40) El$ @set 257 _subcmd="permission remove" 258 verify_history_line "$line" "$_subcmd" $ds "$keyword" 259 [[ $? == 0 ]] && return 0 260 ;; 261 *) 262 ;; 263 esac 264 done < $his_file 265 return 1 266} 267