xref: /illumos-gate/usr/src/cmd/th_tools/th_script.sh (revision fc910014e8a32a65612105835a10995f2c13d942)
1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21#
22# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23# Use is subject to license terms.
24#
25
26#
27# usage: force_state_change <path> <target state>
28#
29force_state_change()
30{
31	[[ $2 != "online" && $2 != "offline" ]] && exit 1
32	th_manage $1 getstate | read path state busy
33	[[ $? != 0 ]] && exit 1
34	[[ "$state" = "$2" ]] && return 0
35	th_manage $1 $2
36	[[ $? != 0 ]] && exit 1
37	th_manage $1 getstate | read path state busy
38	[[ $? != 0 ]] && exit 1
39	[[ "$state" != "$2" ]] && exit 1
40	return 0
41}
42
43
44script_pid=0
45trap ' terminate $script_pid ' 1 2 3 15
46terminate()
47{
48	[[ $1 -gt 0 ]] && kill $1 > /dev/null 2>&1
49	exit 1
50}
51
52#
53# usage: control_workload <path> <pid>
54# The following function is called (as a background task) prior to taking a
55# driver instance offline and immediately after it is brought online. If the
56# th_define process which created this script did not specify a script with the
57# -e option then the default action is to run in the background this script
58# which will continuously offline and online the instance until the injected
59# error is detected by the driver or until the errdef is aborted.
60#
61control_workload()
62{
63	fixup_script 1
64	if [ $? == 0 ]; then
65		return
66	fi
67
68	#
69	# Default workload - continuously offline and online the driver instance
70	# while injecting errors
71	#
72
73	if [[ $2 -gt 0 ]]; then
74		kill $2 > /dev/null 2>&1
75	fi
76	if [ $# -lt 2 ]; then
77		echo syntax: $0 path pid
78	elif [ $DRIVER_UNCONFIGURE = 1 ]; then
79		: no unconfigure action required ;
80	elif [ $DRIVER_CONFIGURE = 1 ]; then
81		while [ 1 ]; do
82			sleep 2
83			force_state_change $1 offline
84			force_state_change $1 online
85		done &
86		script_pid=$!
87	fi
88}
89
90#
91# usage: prepare_for_errdef <path> <driver> <instance> <do_unconfigure>
92#
93prepare_for_errdef()
94{
95	export DRIVER_PATH=$1
96	export DRIVER_NAME=$2
97	export DRIVER_INSTANCE=$3
98	export DRIVER_UNCONFIGURE=1
99	export DRIVER_CONFIGURE=0
100	control_workload $1 $script_pid
101	script_pid=0
102
103	th_manage $2 $3 get_handles >/dev/null 2>&1
104	[[ $? != 0 ]] && exit 1
105	force_state_change $1 offline
106	force_state_change $1 online
107
108	export DRIVER_UNCONFIGURE=0
109	export DRIVER_CONFIGURE=1
110	[[ $4 == 1 ]] &&
111		control_workload $1 $script_pid
112}
113
114# usage: monitor_edef <driver> <instance> <nsteps>
115monitor_edef()
116{
117	let aborted=0
118	trap ' (( aborted += 1 )) ' 16
119	sleep 2	# Wait for the errdef to be added
120	th_manage $1 $2 start
121	[[ $? != 0 ]] && exit 1
122
123	let s=0
124	let x=$3
125	set -A stats 0 0 1 0 0 0 0 ""
126
127	#
128	# Loop for x reports unless the error is reported or the access fail
129	# count goes to zero.
130	#
131	while (( (x -= 1) >= 0 ))
132	do
133		(( aborted > 0 )) && break
134		read line
135		[ -z "$line" ] && break
136		set -A stats $(echo "$line" |
137		    /usr/bin/awk -F: '{for (i = 1; i <= NF; i++) print $i}')
138		[ "${stats[6]}" -ne "0" ] && break	# Fault was reported
139		#
140		# If fail count is zero - increment a loop counter 3 times
141		# before aborting this errdef.
142		#
143		[ "${stats[3]}" = "0" ] && (( (s += 1) > 3 )) && break
144	done
145	th_manage $1 $2 clear_errdefs			# Clear errors.
146	[[ $? != 0 ]] && exit 1
147	echo "${stats[@]}"
148}
149
150#
151# Install, activate and monitor some error definitions
152# usage: run_subtest <driver> <instance> < errdefs
153#
154run_subtest()
155{
156	let edefid=0
157	drv=$1
158	inst=$2
159	if [ $devpath = "NULL" ]
160	then
161		path=$(th_manage $1 $2 getpath)
162	else
163		path=$devpath
164	fi
165	while read line
166	do
167		set -- $(echo "$line" | \
168		    /usr/bin/awk '{for (i = 1; i <= NF; i++) print $i}')
169		w=${line##*"-w "}
170		let a=${w%%" "*}
171		let b=${w##*" "}
172		let x='a / b'
173		(( a % b > 0 )) && (( x += 1 ))
174		prepare_for_errdef $path $drv $inst 1
175		set -A status $(th_define $* 2>./elog | \
176		    monitor_edef $drv $inst $x)
177		if [ "${status[2]}" -gt 0 ]; then
178			res="test not triggered"
179		elif [ "${status[1]}" -eq 0 ]; then
180			res="success (error undetected)"
181		elif [ "${status[1]}" -gt 0 ]; then
182			if [ "${status[6]}" -eq 16 ]; then
183				res="failure (no service impact reported)"
184			else
185				res="success (error reported)"
186			fi
187		else
188			res=
189		fi
190		echo "Subtest $edefid: Result: \"$res\""
191		echo $line
192		if [ -n "${status[7]}" ]; then
193			let i=6
194			let l=${#status[@]}
195			echo "	Fail Msg  :\t\c"
196			while (( (i += 1) <= l ))
197			do
198				echo "${status[$i]} \c"
199			done
200			echo ""
201		fi
202		echo "\tFail Time :\t${status[0]}\tMsg Time  :\t${status[1]}"
203		echo "\tAcc count :\t${status[2]}\tFail count:\t${status[3]}"
204		echo "\tAccess Chk:\t${status[4]}\tEmsg count:\t${status[5]}"
205		if [ "${status[6]}" -eq 0 ]; then
206			echo "\tSeverity:\tSERVICE UNAFFECTED"
207		elif [ "${status[6]}" -eq -16 ]; then
208			echo "\tSeverity:\tSERVICE DEGRADED"
209		elif [ "${status[6]}" -eq -32 ]; then
210			echo "\tSeverity:\tSERVICE LOST"
211		fi
212		((edefid += 1))
213	done
214
215	fixup_script 0
216	prepare_for_errdef $path $drv $inst 0
217}
218