xref: /illumos-gate/usr/src/cmd/fm/scripts/fmsim.ksh (revision 88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98)
1#!/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, Version 1.0 only
7# (the "License").  You may not use this file except in compliance
8# with the License.
9#
10# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
11# or http://www.opensolaris.org/os/licensing.
12# See the License for the specific language governing permissions
13# and limitations under the License.
14#
15# When distributing Covered Code, include this CDDL HEADER in each
16# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
17# If applicable, add the following below this CDDL HEADER, with the
18# fields enclosed by brackets "[]" replaced with your own identifying
19# information: Portions Copyright [yyyy] [name of copyright owner]
20#
21# CDDL HEADER END
22#
23#
24# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
25# Use is subject to license terms.
26#
27#ident	"%Z%%M%	%I%	%E% SMI"
28
29export PATH=/usr/bin:/usr/sbin:/usr/ccs/bin
30unset ENV TMPDIR
31umask 022
32cwd=$PWD
33
34if [[ -n "$CODEMGR_WS" ]]; then
35	sysroot=$CODEMGR_WS/proto/root_`uname -p`
36elif [[ -n "$ROOT" ]]; then
37	sysroot=$ROOT
38else
39	sysroot=/
40fi
41
42quote=
43eol='\'
44files=
45
46simchan=com.sun:fm:fmd$$
47simroot=/tmp/fmd.$$
48simscript=run
49simpid=
50
51truss_cmd=
52truss_args=
53dump_args=
54inj_args=
55fmd_args=
56
57opt_h=false
58opt_i=false
59opt_s=false
60opt_x=false
61
62function cp_so
63{
64	nm -ghp $1 2>/dev/null | while read addr type name; do
65		[[ $type != T ]] && continue
66		case $name in
67		_fmd_init)        cp $1 $2/usr/lib/fm/fmd/plugins; return ;;
68		fmd_fmri_nvl2str) cp $1 $2/usr/lib/fm/fmd/schemes; return ;;
69		topo_load)        cp $1 $2/usr/lib/fm/topo; return ;;
70		esac
71	done
72	die "\nunknown .so type -- $1"
73}
74
75function list_cmds
76{
77	for cmd in fmadm fmdump fmstat; do
78		echo usr/sbin/$cmd
79	done
80}
81
82function wait_status
83{
84	if [[ $1 -gt 128 ]]; then
85		sig=$(kill -l $(($1 - 128)))
86		die "fmd terminated from signal $sig (see $simroot)"
87	elif [[ $1 -ne 0 ]]; then
88		die "fmd terminated with status $1 (see $simroot)"
89	fi
90}
91
92function die
93{
94	echo "fmsim: $*" >& 2
95	[[ -n "$simpid" ]] && exit 1 || exit 2
96}
97
98while [[ $# -gt 0 ]]; do
99	OPTIND=1; while getopts ':d:D:ehio:st:vVx' c; do
100		case "$c" in
101		d)
102			simroot=$OPTARG
103			;;
104		D)
105			truss_cmd=dtrace
106			truss_args="-s $OPTARG -c"
107			quote="'"; eol=""
108			;;
109		e|v|V)
110			dump_args="$dump_args -$c"
111			;;
112		h|i|s|x)
113			eval opt_$c'='true
114			;;
115		o)
116			fmd_args="$fmd_args -o $OPTARG"
117			;;
118		t)
119			truss_cmd=truss
120			truss_args="$OPTARG"
121			;;
122		:)
123			die "option requires an argument -- $OPTARG"
124			;;
125		*)
126			die "illegal option -- $OPTARG"
127			;;
128		esac
129	done
130	let OPTIND="$OPTIND - 1"; shift $OPTIND
131
132	if [[ $# -gt 0 ]]; then
133		if [[ -d $1 ]]; then
134			files="$files $1/*"
135		else
136			files="$files $1"
137		fi
138		shift
139	fi
140done
141
142for file in $files; do
143	[[ -r $file ]] || die "input file is missing or not readable -- $file"
144done
145
146if $opt_h || [[ -z "$files" && $opt_i = false ]]; then
147	echo "Usage: fmsim [-ehiksvV] [-d dir] [-D a.d] [-o opt=val]" \
148	    "[-t args] [file ...]"
149
150	echo "\t-D  start fmd(1M) using dtrace(1M) and specified D script"
151	echo "\t-e  display error log content instead of fault log content"
152	echo "\t-h  display usage information for fmsim and exit"
153	echo "\t-i  set interactive mode: do not stop after sending events"
154	echo "\t-o  set fmd(1M) option to specified value during simulation"
155	echo "\t-s  set up simulation world but do not actually run simulation"
156	echo "\t-t  start fmd(1M) using truss(1) and specified arguments"
157	echo "\t-v  set verbose mode: display additional event detail"
158	echo "\t-V  set very verbose mode: display complete event contents"
159	echo "\t-x  delete simulation world if simulation is successful"
160
161	exit 0
162fi
163
164echo "fmsim: creating simulation world $simroot ... \c"
165[[ -d $simroot ]] || mkdir -p $simroot || exit 1
166cd $simroot || exit 1
167echo "done."
168
169echo "fmsim: populating /var ... \c"
170mkdir -p -m 0755 var/fm/fmd
171mkdir -p -m 0700 var/fm/fmd/ckpt
172mkdir -p -m 0700 var/fm/fmd/rsrc
173echo "done."
174
175echo "fmsim: populating /usr/lib/fm from $sysroot ... \c"
176(cd $sysroot && find usr/lib/fm -depth -print | cpio -pdmu $simroot)
177
178for platdir in $sysroot/usr/platform/*/lib/fm; do
179	[[ -d $platdir ]] && platdir=${platdir#$sysroot} || continue
180	echo "fmsim: populating $platdir from $sysroot ... \c"
181	(cd $sysroot && find ${platdir#/} -depth -print | cpio -pdmu $simroot)
182done
183
184echo "fmsim: populating /usr/lib/locale/$LANG from $sysroot ... \c"
185(cd $sysroot && find usr/lib/locale/$LANG -depth -print | cpio -pdmu $simroot)
186
187echo "fmsim: populating /usr/sbin from $sysroot ... \c"
188(cd $sysroot && list_cmds | cpio -pdmu $simroot)
189
190echo "fmsim: adding customizations:\c"
191cd $cwd || exit $1
192
193for file in $files; do
194	base=$(basename $file)
195	case $base in
196	*.cmd)	die "\neversholt command file not yet supported -- $file" ;;
197	fmd.conf) cp $file $simroot/etc/fm/fmd ;;
198	*.conf)	cp $file $simroot/usr/lib/fm/fmd/plugins ;;
199	*.dict)	cp $file $simroot/usr/lib/fm/dict ;;
200	*.eft)	die "\neversholt fault tree file not yet supported -- $file" ;;
201	*.esc)	die "\neversholt source file not yet supported -- $file" ;;
202	*.inj)	inj_args="$inj_args $file" ;;
203	*.log)	inj_args="$inj_args $file" ;;
204	*log)	inj_args="$inj_args $file" ;;
205	*.mo)	cp $file $simroot/usr/lib/locale/$LANG/LC_MESSAGES ;;
206	*.so)	cp_so $file $simroot ;;
207	*.topo) cp $file $simroot/usr/lib/fm/topo ;;
208	*)	die "\nunknown file type or suffix -- $file" ;;
209	esac
210	echo " $base\c"
211done
212
213cd $simroot || exit 1
214echo " done."
215
216echo "fmsim: generating script ... \c"
217cat >$simscript <<EOS
218#!/bin/ksh -p
219#
220# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
221# Use is subject to license terms.
222#
223#ident	"%Z%%M%	%I%	%E% SMI"
224
225#
226# fmsim(1M) script generated for $simroot $(date)
227#
228
229export LD_LIBRARY_PATH=$simroot/usr/lib
230export LD_LIBRARY_PATH_64=$simroot/usr/lib/64
231
232exec $truss_cmd $truss_args $quote./usr/lib/fm/fmd/fmd -R $simroot $eol
233    -o fg=true -o rpc.adm.path=$simroot/rpc -o xprt.device=/dev/null $eol
234    -o errchan=$simchan -o clock=simulated $fmd_args$quote
235
236EOS
237
238chmod 0555 $simscript
239echo "done."
240
241if $opt_s; then
242	echo "fmsim: simulation is saved in $simroot"
243	exit 0
244fi
245
246export LD_LIBRARY_PATH=$simroot/usr/lib
247export LD_LIBRARY_PATH_64=$simroot/usr/lib/64
248
249echo "fmsim: simulation $$ running fmd(1M)\c"
250./usr/lib/fm/fmd/fmd -V | cut -d: -f2
251
252./$simscript &
253simpid=$!
254trap '' INT HUP
255cd $cwd
256i=0
257
258while [[ ! -s $simroot/rpc ]]; do
259	[[ $i -ge 30 ]] && kill -9 $simpid >/dev/null 2>&1
260	kill -0 $simpid >/dev/null 2>&1 || break
261	let i="$i + 1"
262	sleep 1
263done
264
265kill -0 $simpid >/dev/null 2>&1 || {
266	wait $simpid
267	wait_status $?
268}
269
270echo "fmsim: rpc adm requests can rendezvous at" $(<$simroot/rpc)
271echo "fmsim: injectors should use channel $simchan"
272echo "fmsim: debuggers should attach to PID $simpid"
273
274for arg in $inj_args; do
275	echo "fmsim: injecting events from $arg ... \c"
276	$simroot/usr/lib/fm/fmd/fminject -q -c $simchan $arg || {
277		echo "fmsim: fminject failed for $arg: aborting simulation" >& 2
278		kill $simpid >/dev/null 2>&1
279	}
280	echo "done."
281done
282
283if [[ $opt_i = false ]]; then
284	echo "fmsim: injecting event to advance to end-of-time ... \c"
285	echo 'endhrtime;' | $simroot/usr/lib/fm/fmd/fminject -q -c $simchan -
286	echo "done."
287fi
288
289wait $simpid
290status=$?
291
292if [[ -f $simroot/var/fm/fmd/errlog ]]; then
293	echo; $simroot/usr/sbin/fmdump -R $simroot $dump_args; echo
294fi
295
296wait_status $status
297$opt_x && rm -rf $simroot
298exit 0
299