12fae26bdSAlan Somers# vim: filetype=sh
22fae26bdSAlan Somers#
32fae26bdSAlan Somers# CDDL HEADER START
42fae26bdSAlan Somers#
52fae26bdSAlan Somers# The contents of this file are subject to the terms of the
62fae26bdSAlan Somers# Common Development and Distribution License (the "License").
72fae26bdSAlan Somers# You may not use this file except in compliance with the License.
82fae26bdSAlan Somers#
92fae26bdSAlan Somers# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
102fae26bdSAlan Somers# or http://www.opensolaris.org/os/licensing.
112fae26bdSAlan Somers# See the License for the specific language governing permissions
122fae26bdSAlan Somers# and limitations under the License.
132fae26bdSAlan Somers#
142fae26bdSAlan Somers# When distributing Covered Code, include this CDDL HEADER in each
152fae26bdSAlan Somers# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
162fae26bdSAlan Somers# If applicable, add the following below this CDDL HEADER, with the
172fae26bdSAlan Somers# fields enclosed by brackets "[]" replaced with your own identifying
182fae26bdSAlan Somers# information: Portions Copyright [yyyy] [name of copyright owner]
192fae26bdSAlan Somers#
202fae26bdSAlan Somers# CDDL HEADER END
212fae26bdSAlan Somers#
222fae26bdSAlan Somers
232fae26bdSAlan Somers#
242fae26bdSAlan Somers# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
252fae26bdSAlan Somers# Use is subject to license terms.
262fae26bdSAlan Somers
272fae26bdSAlan Somers. $STF_SUITE/include/libtest.kshlib
282fae26bdSAlan Somers
292fae26bdSAlan Somers#
302fae26bdSAlan Somers# Execute arguments and record them to the log file.
312fae26bdSAlan Somers# Notice: EXPECT_HISTORY need be defined.
322fae26bdSAlan Somers#
332fae26bdSAlan Somers# $1-n arguments for execution.
342fae26bdSAlan Somers#
352fae26bdSAlan Somersfunction exec_record
362fae26bdSAlan Somers{
372fae26bdSAlan Somers	[[ -z $EXPECT_HISTORY ]] && log_fail "EXPECT_HISTORY is undefined."
382fae26bdSAlan Somers
392fae26bdSAlan Somers	typeset long_hist
402fae26bdSAlan Somers	typeset user='root'
412fae26bdSAlan Somers	typeset opt
422fae26bdSAlan Somers	while getopts ":lu:" opt; do
432fae26bdSAlan Somers		case $opt in
442fae26bdSAlan Somers			l)	long_hist=1;;
452fae26bdSAlan Somers			u)	user=$OPTARG ;;
462fae26bdSAlan Somers		esac
472fae26bdSAlan Somers	done
482fae26bdSAlan Somers	shift $(($OPTIND -1))
492fae26bdSAlan Somers
502fae26bdSAlan Somers	if [[ $user == 'root' ]]; then
512fae26bdSAlan Somers		log_must "$@"
522fae26bdSAlan Somers	else
532fae26bdSAlan Somers		log_must $SU $user -c "$@"
542fae26bdSAlan Somers	fi
552fae26bdSAlan Somers	user_id=$(id -u $user)
562fae26bdSAlan Somers
572fae26bdSAlan Somers	typeset cmdline="$@"
582fae26bdSAlan Somers	# Remove "eval" ">*" & "<*" for 'zfs send' and 'zfs receive'.
592fae26bdSAlan Somers	cmdline=${cmdline#eval}
602fae26bdSAlan Somers	cmdline=${cmdline%%\>*}
612fae26bdSAlan Somers	cmdline=${cmdline%%\<*}
622fae26bdSAlan Somers
632fae26bdSAlan Somers	# Remove additional blank
642fae26bdSAlan Somers	cmdline=${cmdline## }
652fae26bdSAlan Somers	cmdline=${cmdline%% }
662fae26bdSAlan Somers
672fae26bdSAlan Somers	# Get the basename of command. i.e: /usr/sbin/zpool -> zpool
682fae26bdSAlan Somers	typeset cmd=$($ECHO $cmdline | $AWK '{print $1}')
692fae26bdSAlan Somers	eval cmdline=\${cmdline#$cmd}
702fae26bdSAlan Somers	cmd=${cmd##*/}
712fae26bdSAlan Somers
722fae26bdSAlan Somers	# Write basic history to file
732fae26bdSAlan Somers	print -n $cmd $cmdline >> $EXPECT_HISTORY
742fae26bdSAlan Somers	if [[ -n $long_hist ]]; then
752fae26bdSAlan Somers		# Write long history to file
762fae26bdSAlan Somers		hn=$($HOSTNAME)
772fae26bdSAlan Somers		zn=$($ZONENAME)
782fae26bdSAlan Somers		[ "$zn" = "global" ] && zn=""
792fae26bdSAlan Somers		[ -n "$zn" ] && zn=":$zn"
802fae26bdSAlan Somers		print -n " [user $user_id ($user) on $hn$zn]" >> $EXPECT_HISTORY
812fae26bdSAlan Somers	fi
822fae26bdSAlan Somers	# Plus enter in the end of line
832fae26bdSAlan Somers	print >> $EXPECT_HISTORY
842fae26bdSAlan Somers}
852fae26bdSAlan Somers
862fae26bdSAlan Somers#
872fae26bdSAlan Somers# Format 'zpool history' output to specified file.
882fae26bdSAlan Somers#
892fae26bdSAlan Somers# $1 pool name
902fae26bdSAlan Somers# $2 output file.
912fae26bdSAlan Somers# $3 option
922fae26bdSAlan Somers#
932fae26bdSAlan Somersfunction format_history
942fae26bdSAlan Somers{
952fae26bdSAlan Somers	typeset pool=$1
962fae26bdSAlan Somers	typeset outfile=$2
972fae26bdSAlan Somers	typeset option=$3
982fae26bdSAlan Somers
992fae26bdSAlan Somers	[[ -z $pool || -z $outfile ]] && \
1002fae26bdSAlan Somers		log_fail "Usage: format_history <pool> <outfile> [option]"
1012fae26bdSAlan Somers
1022fae26bdSAlan Somers	typeset temp_history=$TMPDIR/temp_history.format_history.${TESTCASE_ID}
1032fae26bdSAlan Somers	$ZPOOL history $option $pool > $temp_history
1042fae26bdSAlan Somers
1052fae26bdSAlan Somers	# Truncate output file
1062fae26bdSAlan Somers	$CAT /dev/null > $outfile
1072fae26bdSAlan Somers
1082fae26bdSAlan Somers	typeset line
1092fae26bdSAlan Somers	typeset -i n=0
1102fae26bdSAlan Somers	while read line; do
1112fae26bdSAlan Somers		# Ignore the first line and empty line
1122fae26bdSAlan Somers		if [[ $n -eq 0 || -z $line ]]; then
1132fae26bdSAlan Somers			n=1; continue
1142fae26bdSAlan Somers		fi
1152fae26bdSAlan Somers		$ECHO ${line#* } >> $outfile
1162fae26bdSAlan Somers	done < $temp_history
1172fae26bdSAlan Somers
1182fae26bdSAlan Somers	$RM -f $temp_history
1192fae26bdSAlan Somers}
1202fae26bdSAlan Somers
1212fae26bdSAlan Somers#
1222fae26bdSAlan Somers# Get the additional pool history.
1232fae26bdSAlan Somers#
1242fae26bdSAlan Somers# $1 pool name
1252fae26bdSAlan Somers# $2 additional history file
1262fae26bdSAlan Somers# $3 option
1272fae26bdSAlan Somers#
1282fae26bdSAlan Somersfunction additional_history
1292fae26bdSAlan Somers{
1302fae26bdSAlan Somers	typeset pool=$1
1312fae26bdSAlan Somers	typeset add_his_file=$2
1322fae26bdSAlan Somers	typeset option=$3
1332fae26bdSAlan Somers
1342fae26bdSAlan Somers	if [[ -z $pool || -z $add_his_file ]]; then
1352fae26bdSAlan Somers		log_fail "Usage: additional_history <pool> " \
1362fae26bdSAlan Somers			"<additional_history_file> [option]"
1372fae26bdSAlan Somers	fi
1382fae26bdSAlan Somers
1392fae26bdSAlan Somers	typeset temp_history=$TMPDIR/temp_history.additional_history.${TESTCASE_ID}
1402fae26bdSAlan Somers	# Current current history
1412fae26bdSAlan Somers	format_history $pool $temp_history $option
1422fae26bdSAlan Somers	# Figure out new history
1432fae26bdSAlan Somers	$DIFF $temp_history $REAL_HISTORY | $GREP "^<" | $SED 's/^<[ ]*//' > \
1442fae26bdSAlan Somers		$add_his_file
1452fae26bdSAlan Somers
1462fae26bdSAlan Somers	$CP $temp_history $REAL_HISTORY
1472fae26bdSAlan Somers	$RM -f $temp_history
1482fae26bdSAlan Somers}
1492fae26bdSAlan Somers
1502fae26bdSAlan Somers#
1512fae26bdSAlan Somers# Get given dataset id
1522fae26bdSAlan Somers#
1532fae26bdSAlan Somers# $1 dataset name
1542fae26bdSAlan Somers#
1552fae26bdSAlan Somersfunction get_dataset_id
1562fae26bdSAlan Somers{
1572fae26bdSAlan Somers	typeset ds=$1
1582fae26bdSAlan Somers
1592fae26bdSAlan Somers	#
1602fae26bdSAlan Somers	# The zdb information looks like:
1612fae26bdSAlan Somers	#
1622fae26bdSAlan Somers	# Dataset pool/fs [ZPL], ID 21, cr_txg 6, 18.0K, 4 objects
1632fae26bdSAlan Somers	#
1642fae26bdSAlan Somers	typeset dst_id=$($ZDB $ds | $GREP "^Dataset $ds " | \
1652fae26bdSAlan Somers			$AWK -F\, '{print $2}' | $AWK '{print $2}')
1662fae26bdSAlan Somers
1672fae26bdSAlan Somers	$ECHO $dst_id
1682fae26bdSAlan Somers}
1692fae26bdSAlan Somers
1702fae26bdSAlan Somers#
1712fae26bdSAlan Somers# Special case of verify_history, but only for destroyed datasets.  This is
1722fae26bdSAlan Somers# needed because get_dataset_id depends on still having the original dataset
1732fae26bdSAlan Somers# in order to obtain its dataset id.
1742fae26bdSAlan Somers#
1752fae26bdSAlan Somersfunction verify_destroyed #<his_file> <ds_id>
1762fae26bdSAlan Somers{
1772fae26bdSAlan Somers	typeset his_file=$1
1782fae26bdSAlan Somers	typeset ds_id=$2
1792fae26bdSAlan Somers
1802fae26bdSAlan Somers	$GREP -E "\[txg:[0-9]+\] destroy [^ ]+ \($ds_id\)" $his_file \
1812fae26bdSAlan Somers		> /dev/null 2>&1
1822fae26bdSAlan Somers	(($? == 0)) && return 0
1832fae26bdSAlan Somers	return 1
1842fae26bdSAlan Somers}
1852fae26bdSAlan Somers
1862fae26bdSAlan Somers#
1872fae26bdSAlan Somers# Verify directly executed commands in a history file.  This differs from
1882fae26bdSAlan Somers# verify_history in that it checks for explicit commands as opposed to
1892fae26bdSAlan Somers# internally generated commands.
1902fae26bdSAlan Somers#
1912fae26bdSAlan Somersfunction verify_direct_history #<his_file> <subcmd> <ds>
1922fae26bdSAlan Somers{
1932fae26bdSAlan Somers	typeset his_file=$1
1942fae26bdSAlan Somers	typeset subcmd=$2
1952fae26bdSAlan Somers	typeset ds=$3
1962fae26bdSAlan Somers
1972fae26bdSAlan Somers	$GREP "zfs ${subcmd} ${ds}" ${his_file} > /dev/null 2>&1
1982fae26bdSAlan Somers	(($? == 0)) && return 0
1992fae26bdSAlan Somers	return 1
2002fae26bdSAlan Somers}
2012fae26bdSAlan Somers
2022fae26bdSAlan Somers# This function mostly just helps to collapse the case statement
2032fae26bdSAlan Somers# in verify_history.  It returns whether the line matches (1==true).
2042fae26bdSAlan Somersfunction verify_history_line
2052fae26bdSAlan Somers{
2062fae26bdSAlan Somers	typeset line=$1
2072fae26bdSAlan Somers	typeset subcmd=$2
2082fae26bdSAlan Somers	typeset ds=$3
2092fae26bdSAlan Somers	typeset keyword=$4
2102fae26bdSAlan Somers
2112fae26bdSAlan Somers	typeset dst_id=$(get_dataset_id $ds)
2122fae26bdSAlan Somers	log_note "Line: '$line'"
2132fae26bdSAlan Somers	log_note "Checking cmd($subcmd) for $ds, keyword='$keyword'"
2142fae26bdSAlan Somers	$ECHO $line | $GREP -E "\[txg:[0-9]+\] $subcmd $ds \($dst_id\)" | \
2152fae26bdSAlan Somers		$GREP $keyword >/dev/null 2>&1
2162fae26bdSAlan Somers	[[ $? == 0 ]] && return 1
2172fae26bdSAlan Somers	return 0
2182fae26bdSAlan Somers}
2192fae26bdSAlan Somers
2202fae26bdSAlan Somers#
2212fae26bdSAlan Somers# Scan history file and check if it include expected internal history
2222fae26bdSAlan Somers# information
2232fae26bdSAlan Somers#
2242fae26bdSAlan Somers# $1 history file
2252fae26bdSAlan Somers# $2 subcmd
2262fae26bdSAlan Somers# $3 dataset
2272fae26bdSAlan Somers# $4 keyword
2282fae26bdSAlan Somers#
2292fae26bdSAlan Somersfunction verify_history #<his_file> <subcmd> <ds> [keyword]
2302fae26bdSAlan Somers{
2312fae26bdSAlan Somers	typeset his_file=$1
2322fae26bdSAlan Somers	typeset subcmd=$2
2332fae26bdSAlan Somers	typeset ds=$3
2342fae26bdSAlan Somers	typeset keyword=$4
2352fae26bdSAlan Somers
2362fae26bdSAlan Somers	typeset line found=0
2372fae26bdSAlan Somers	log_note "Test1"
2382fae26bdSAlan Somers	while read line; do
2392fae26bdSAlan Somers		case $subcmd in
2402fae26bdSAlan Somers		snapshot|rollback|inherit)
2412fae26bdSAlan Somers			# [txg:12] snapshot system/foo@0 (46)
2422fae26bdSAlan Somers			keyword="$subcmd"
2432fae26bdSAlan Somers			verify_history_line "$line" $subcmd $ds $keyword
2442fae26bdSAlan Somers			[[ $? == 0 ]] && return 0
2452fae26bdSAlan Somers			;;
2462fae26bdSAlan Somers		allow)
2472fae26bdSAlan Somers			# [txg:10] permission update testpool.1477/testfs.1477 (40) s-$@basic snapshot
2482fae26bdSAlan Somers			_subcmd="permission update"
2492fae26bdSAlan Somers			verify_history_line "$line" "$_subcmd" $ds "$keyword"
2502fae26bdSAlan Somers			[[ $? == 0 ]] && return 0
2512fae26bdSAlan Somers			;;
2522fae26bdSAlan Somers		unallow)
2532fae26bdSAlan Somers			# [txg:174] permission remove testpool.1477/testfs.1477 (40) El$ @set
2542fae26bdSAlan Somers			_subcmd="permission remove"
2552fae26bdSAlan Somers			verify_history_line "$line" "$_subcmd" $ds "$keyword"
2562fae26bdSAlan Somers			[[ $? == 0 ]] && return 0
2572fae26bdSAlan Somers			;;
2582fae26bdSAlan Somers		*)
2592fae26bdSAlan Somers			;;
2602fae26bdSAlan Somers		esac
2612fae26bdSAlan Somers	done < $his_file
2622fae26bdSAlan Somers	return 1
2632fae26bdSAlan Somers}
264