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