xref: /illumos-gate/usr/src/cmd/stmsboot/stmsboot.sh (revision 19397407)
1#!/sbin/sh -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 (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# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24# Use is subject to license terms.
25#
26#
27PATH=/usr/bin:/usr/sbin:$PATH; export PATH
28STMSBOOTUTIL=/lib/mpxio/stmsboot_util
29STMSMETHODSCRIPT=/lib/svc/method/mpxio-upgrade
30KDRVCONF=
31DRVCONF=
32TMPDRVCONF=
33TMPDRVCONF_MPXIO_ENTRY=
34DRVLIST=
35GUID=
36VFSTAB=/etc/vfstab
37SAVEDIR=/etc/mpxio
38RECOVERFILE=$SAVEDIR/recover_instructions
39SVCCFG_RECOVERY=$SAVEDIR/svccfg_recover
40SUPPORTED_DRIVERS="fp|mpt"
41USAGE=`gettext "Usage: stmsboot [-D $SUPPORTED_DRIVERS] -e | -d | -u | -L | -l controller_number"`
42TEXTDOMAIN=SUNW_OST_OSCMD
43export TEXTDOMAIN
44STMSINSTANCE=svc:system/device/mpxio-upgrade:default
45STMSBOOT=/usr/sbin/stmsboot
46BOOTADM=/sbin/bootadm
47MOUNT=/usr/sbin/mount
48EEPROM=/usr/sbin/eeprom
49EGREP=/usr/bin/egrep
50GREP=/usr/bin/grep
51AWK=/usr/bin/awk
52CP=/usr/bin/cp
53LS=/usr/bin/ls
54MV=/usr/bin/mv
55RM=/usr/bin/rm
56SORT=/usr/bin/sort
57UNIQ=/usr/bin/uniq
58EXPR=/usr/bin/expr
59MKDIR=/usr/bin/mkdir
60REBOOT=/usr/sbin/reboot
61SED=/usr/bin/sed
62SVCPROP=/usr/bin/svcprop
63SVCCFG=/usr/sbin/svccfg
64SVCS=/usr/bin/svcs
65SVCADM=/usr/sbin/svcadm
66
67NOW=`/usr/bin/date +%G%m%d_%H%M`
68MACH=`/usr/bin/uname -p`
69BOOTENV_FILE=bootenv.rc
70reboot_needed=0
71new_bootpath=""
72CLIENT_TYPE_PHCI=""
73CLIENT_TYPE_VHCI="/scsi_vhci"
74
75#
76# Copy all entries (including comments) from source driver.conf
77# to destination driver.conf except those entries which contain
78# the mpxio-disable property.
79# Take into consideration entries that spawn more than one line.
80#
81# $1	source driver.conf file
82# $2	destination driver.conf file
83#
84# Returns 0 on success, non zero on failure.
85#
86delete_mpxio_disable_entries()
87{
88	# be careful here, we've got embedded \t characters
89	# in sed's pattern space.
90	$SED '
91		/^[ 	]*#/{ p
92			      d
93			    }
94		s/[ 	]*$//
95		/^$/{ p
96		      d
97		    }
98		/mpxio-disable[ 	]*=.*;$/{ w '$3'
99						  d
100						}
101		/;$/{ p
102		      d
103		    }
104		:rdnext
105		N
106		s/[ 	]*$//
107		/[^;]$/b rdnext
108		/mpxio-disable[ 	]*=/{ s/\n/ /g
109					      w '$3'
110					      d
111					    }
112		' $1 > $2
113
114	return $?
115}
116
117#
118# backup the last saved copy of the specified files.
119# $*	files to backup
120#
121backup_lastsaved()
122{
123	for file in $*
124	do
125		newfile=`basename $file`
126		$CP $file $SAVEDIR/$newfile.$cmd.$NOW
127	done
128}
129
130#
131# build recover instructions
132#
133# $1	1 to include boot script in the instructions
134#	0 otherwise
135#
136build_recover()
137{
138	gettext "Instructions to recover your previous STMS configuration (if in case the system does not boot):\n\n" > $RECOVERFILE
139	echo "\tboot net \c"  >> $RECOVERFILE
140	gettext "(or from a cd/dvd/another disk)\n" >> $RECOVERFILE
141	echo "\tfsck <your-root-device>" >> $RECOVERFILE
142	echo "\tmount <your-root-device> /mnt" >> $RECOVERFILE
143
144	if [ "x$cmd" = xupdate ]; then
145		gettext "\tUndo the modifications you made to STMS configuration.\n\tFor example undo any changes you made to " >> $RECOVERFILE
146		echo "/mnt$KDRVCONF." >> $RECOVERFILE
147	else
148		echo "\tcp /mnt${SAVEDIR}/$DRVCONF.$cmd.$NOW /mnt$KDRVCONF" >> $RECOVERFILE
149	fi
150
151	if [ $1 -eq 1 ]; then
152		echo "\tcp /mnt${SAVEDIR}/vfstab.$cmd.$NOW /mnt$VFSTAB" >> $RECOVERFILE
153
154		echo "repository /mnt/etc/svc/repository.db" > $SVCCFG_RECOVERY
155		echo "select $STMSINSTANCE" >> $SVCCFG_RECOVERY
156		echo "setprop general/enabled=false" >> $SVCCFG_RECOVERY
157		echo "exit" >> $SVCCFG_RECOVERY
158
159		echo "\t$SVCCFG -f /mnt$SVCCFG_RECOVERY" >> $RECOVERFILE
160
161		if [ "x$MACH" = "xi386" -a "x$new_bootpath" != "x" ]; then
162			echo "\tcp /mnt${SAVEDIR}/bootenv.rc.$cmd.$NOW /mnt/boot/solaris/$BOOTENV_FILE" >> $RECOVERFILE
163		fi
164	fi
165
166	rootdisk=`$MOUNT | $GREP "/ on " | cut -f 3 -d " "`
167	echo "\tumount /mnt\n\treboot\n\n${rootdisk} \c" >> $RECOVERFILE
168	gettext "was your root device,\nbut it could be named differently after you boot net.\n" >> $RECOVERFILE
169}
170
171
172#
173# Arrange for /etc/vfstab and dump configuration to be updated
174# during the next reboot. If the cmd is "enable" or "disable", copy
175# $TMPDRVCONF to $KDRVCONF.
176#
177# Returns 0 on success, 1 on failure.
178#
179update_sysfiles()
180{
181
182	gettext "WARNING: This operation will require a reboot.\n"
183	gettext "Do you want to continue ? [y/n] (default: y) "
184	read response
185
186	if [ "x$response" != x -a "x$response" != xy -a \
187	    "x$response" != xY ]; then
188		for d in $DRVLIST; do
189			TMPDRVCONF=/var/run/tmp.$d.conf.$$
190			$RM -f $TMPDRVCONF > /dev/null 2>&1
191		done;
192		return 0;
193	fi
194
195	# set need_bootscript to the number of drivers that
196	# we support.
197	need_bootscript=`echo $SUPPORTED_DRIVERS|$AWK -F"|" '{print NF}'`
198
199	if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then
200
201		for d in $DRVLIST; do
202			DRVCONF=$d.conf
203			KDRVCONF=/kernel/drv/$d.conf
204			TMPDRVCONF=/var/run/tmp.$d.conf.$$
205
206			$CP $KDRVCONF $SAVEDIR/`basename $KDRVCONF`.$cmd.$NOW
207			if [ -f $TMPDRVCONF ]; then
208				$CP $TMPDRVCONF $KDRVCONF
209				$RM -f $TMPDRVCONF
210			else
211				# if $TMPDRVCONF doesn't exist, then we
212				# haven't made any changes to it
213				continue;
214			fi
215
216			#
217			# there is no need to update the system files in the following
218			# cases:
219			# - we are enabling mpxio and the system has no configured
220			#   disks accessible by phci paths.
221			# - we are disabling mpxio and the system has no configured
222			#   disks accessible by vhci paths.
223			#
224
225			# Function to setup the CLIENT_TYPE_PHCI string based on
226			# the list of drivers that we're operating on. The variable
227			# depends upon the pathname of the parent node in the
228			# device tree, which can be different on x86/x64 and sparc.
229
230			CLIENT_TYPE_PHCI=`$STMSBOOTUTIL -D $d -N`;
231
232			if [ "x$CLIENT_TYPE_PHCI" = "x" ]; then
233				continue;
234			fi
235
236			if [ "x$cmd" = "xenable" ]; then
237				$LS -l /dev/dsk/*s2 2> /dev/null | \
238				    $EGREP -s "$CLIENT_TYPE_PHCI"
239			else
240				$LS -l /dev/dsk/*s2 2> /dev/null | \
241				    $EGREP -s "$CLIENT_TYPE_VHCI"
242			fi
243
244			if [ $? -ne 0 ]; then
245				need_bootscript=`$EXPR $need_bootscript - 1`
246			fi
247		done
248	fi
249
250	if [ $need_bootscript -gt 0 ]; then
251		need_bootscript=1
252		if [ "x$MACH" = "xi386" -a "x$new_bootpath" != "x" ]; then
253			#only update bootpath for x86.
254			$CP /boot/solaris/$BOOTENV_FILE $SAVEDIR/$BOOTENV_FILE.$cmd.$NOW
255			$EEPROM bootpath="$new_bootpath"
256		fi
257		# Enable the mpxio-upgrade service for the reboot
258		$SVCADM disable -t $STMSINSTANCE
259		$SVCCFG -s $STMSINSTANCE "setprop general/enabled=true"
260	else
261		need_bootscript=0
262	fi
263
264	build_recover $need_bootscript
265
266	if [ "x$MACH" = "xi386" ]; then
267		$BOOTADM update-archive
268	fi
269
270	gettext "The changes will come into effect after rebooting the system.\nReboot the system now ? [y/n] (default: y) "
271	read response
272
273	if [ "x$response" = x -o "x$response" = xy -o \
274	    "x$response" = xY ]; then
275		$REBOOT
276	fi
277
278	return 0
279}
280
281
282#
283# Enable or disable mpxio as specified by the cmd.
284# Returns 0 on success, 1 on failure.
285#
286# Args: $cmd = {enable | disable}
287#	$d = {fp | mpt}
288#
289# the global variable $DRVLIST is used
290#
291configure_mpxio()
292{
293	# be careful here, we've got embedded \t characters
294	# in sed's pattern space.
295	mpxiodisableno='mpxio-disable[ 	]*=[ 	]*"no"[ 	]*;'
296	mpxiodisableyes='mpxio-disable[ 	]*=[ 	]*"yes"[ 	]*;'
297
298	if [ "x$cmd" = xenable ]; then
299		mpxiodisable_cur_entry=$mpxiodisableyes
300		propval=no
301		msg=`gettext "STMS already enabled"`
302	else
303		mpxiodisable_cur_entry=$mpxiodisableno
304		propval=yes
305		msg=`gettext "STMS already disabled"`
306	fi
307
308	DRVCONF=$d.conf
309	KDRVCONF=/kernel/drv/$d.conf
310	TMPDRVCONF=/var/run/tmp.$d.conf.$$
311	TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$;
312
313	if delete_mpxio_disable_entries $KDRVCONF $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY; then
314
315		if [ -s $TMPDRVCONF_MPXIO_ENTRY ]; then
316			# $DRVCONF does have mpxiodisable entries
317			$EGREP -s "$mpxiodisable_cur_entry" $TMPDRVCONF_MPXIO_ENTRY
318			if [ $? -ne 0 ]; then
319				# if all mpxiodisable entries are no/yes for
320				# enable/disable mpxio, notify the user
321				$RM -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1
322				continue;
323			else
324				reboot_needed=`$EXPR $reboot_needed + 1`
325			fi
326
327			# If mpxiodisable entries do not exist, always continue update
328		fi
329	else
330		$RM -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1
331		gettext "failed to update " 1>&2
332		echo "$KDRVCONF." 1>&2
333		gettext "No changes were made to your STMS configuration.\n" 1>&2
334		return 1
335	fi
336
337	rm $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1
338	echo "mpxio-disable=\"${propval}\";" >> $TMPDRVCONF
339
340}
341
342setcmd()
343{
344	if [ "x$cmd" = xnone ]; then
345		cmd=$1
346	else
347		echo "$USAGE" 1>&2
348		exit 2
349	fi
350}
351
352#
353# Need to update bootpath on x86 if boot system from FC disk
354# Only update bootpath here when mpxio is enabled
355# If mpxio is currently disabled, then we'll update bootpath in the
356# mpxio-upgrade service method on reboot.
357#
358
359get_newbootpath_for_stmsdev() {
360	if [ "x$cmd" = "xenable" ]; then
361		return 0
362	fi
363
364	cur_bootpath=`$STMSBOOTUTIL -b`
365	if [ $? != 0 ]; then
366		return 1
367	fi
368
369	# Since on x64 platforms the eeprom command doesn't update the
370	# kernel, the file /boot/solaris/bootenv.rc and the kernel's
371	# bootpath variable have a good chance of differing. We do some
372	# extra handwaving to get the correct bootpath variable setting.
373
374	ONDISKVER=`$AWK '/bootpath/ {print $3}' /boot/solaris/bootenv.rc|\
375		$SED -e"s,',,g"`
376	if [ "x$ONDISKVER" != "x$cur_bootpath" ]; then
377		cur_bootpath="$ONDISKVER"
378	fi
379
380	NEWBOOTPATH=""
381	for path in $cur_bootpath; do
382		mapped=`$STMSBOOTUTIL -p $path`
383		if [ "$mapped" != "NOT_MAPPED" ]; then
384			if [ "$mapped" != "$path" ]; then
385				NEWBOOTPATH=`echo "$path " | \
386				   $SED -e"s|$path|$mapped|"`" $NEWBOOTPATH"
387			else
388				NEWBOOTPATH="$NEWBOOTPATH $path"
389			fi
390		fi
391	done
392	# now strip off leading and trailing space chars
393	new_bootpath=`echo $NEWBOOTPATH`
394	return 0
395}
396
397#
398# Emit a warning message to the user that by default we
399# operate on all multipath-capable controllers that are
400# attached to the system, and that if they want to operate
401# on only a specific controller type (fp|mpt|....) then
402# they need to re-invoke stmsboot with "-D $driver" in
403# their argument list
404#
405
406emit_driver_warning_msg() {
407
408	# for each driver that we support, grab the list
409	# of controllers attached to the system.
410
411	echo ""
412	gettext "WARNING: stmsboot operates on each supported multipath-capable controller\n"
413	gettext "         detected in a host. In your system, these controllers are\n\n"
414
415	for WARNDRV in `echo $SUPPORTED_DRIVERS| $SED -e"s,|, ,g"`; do
416		$STMSBOOTUTIL -D $WARNDRV -n
417	done;
418
419	echo ""
420	gettext "If you do NOT wish to operate on these controllers, please quit stmsboot\n"
421	gettext "and re-invoke with -D { fp | mpt } to specify which controllers you wish\n"
422	gettext "to modify your multipathing configuration for.\n"
423
424	echo ""
425	gettext "Do you wish to continue? [y/n] (default: y) "
426	read response
427
428	if [ "x$response" != "x" -a "x$response" != "xY" -a \
429	    "x$response" != "xy" ]; then
430		exit
431	fi
432}
433
434
435#
436#
437# main starts here
438#
439
440cmd=none
441# process options
442while getopts D:geduLl: c
443do
444	case $c in
445	e)	setcmd enable;;
446	d)	setcmd disable;;
447	u)	setcmd update;;
448	L)	setcmd listall;;
449	l)	setcmd list
450		controller=$OPTARG;;
451	D)	DRV=$OPTARG;;
452	g)	GUID="-g";;
453	\?)	echo "$USAGE" 1>&2
454		exit 2;;
455	esac
456done
457
458if [ "x$cmd" = xnone ]; then
459	echo "$USAGE" 1>&2
460	exit 2
461fi
462
463if [ "x$DRV" = "x" ]; then
464	DRVLIST="fp mpt"
465else
466	DRVLIST=$DRV
467fi
468
469USERID=`id | $EGREP "uid=0"`
470if [ -z "$USERID" ]; then
471	gettext "You must be super-user to run this script.\n" 1>&2
472	exit 1
473fi
474
475# just a sanity check
476if [ ! -f $STMSBOOTUTIL -o ! -f $STMSMETHODSCRIPT ]; then
477	fmt=`gettext "Can't find %s and/or %s"`
478	printf "$fmt\n" "$STMSBOOTUTIL" "$STMSMETHODSCRIPT" 1>&2
479	exit 1
480fi
481
482# If the old sun4u-specific SMF method is found, remove it
483$SVCCFG -s "platform/sun4u/mpxio-upgrade:default" < /dev/null > /dev/null 2>&1
484if [ $? -eq 0 ]; then
485	$SVCCFG delete "platform/sun4u/mpxio-upgrade:default" > /dev/null 2>&1
486fi
487
488# now import the new service, if necessary
489$SVCPROP -q $STMSINSTANCE < /dev/null > /dev/null 2>&1
490if [ $? -ne 0 ]; then
491	if [ -f /var/svc/manifest/system/device/mpxio-upgrade.xml ]; then
492		$SVCCFG import /var/svc/manifest/system/device/mpxio-upgrade.xml
493		if [ $? -ne 0 ]; then
494			fmt=`gettext "Unable to import the %s service"`
495			printf "$fmt\n" "$STMSINSTANCE" 1>&2
496			exit 1
497		else
498			fmt=`gettext "Service %s imported successfully, continuing"`
499			printf "$fmt\n" "$STMSINSTANCE" 1>&2
500		fi
501	else
502		fmt=`gettext "Service %s does not exist on this host"`
503 		printf "$fmt\n" "$STMSINSTANCE" 1>&2
504		exit 1
505	fi
506fi
507
508
509# make sure we can stash our data somewhere private
510if [ ! -d $SAVEDIR ]; then
511	$MKDIR -p $SAVEDIR
512fi
513# prime the cache
514$STMSBOOTUTIL -i
515
516
517if [ "x$cmd" = xenable -o "x$cmd" = xdisable -o "x$cmd" = xupdate ]; then
518	#
519	# The bootup script doesn't work on cache-only-clients as the script
520	# is executed before the plumbing for cachefs mounting of root is done.
521	#
522	if $MOUNT -v | $EGREP -s " on / type (nfs|cachefs) "; then
523		gettext "This command option is not supported on systems with an nfs or cachefs mounted root filesystem.\n" 1>&2
524		exit 1
525	fi
526
527	# if the user has left the system with the mpxio-upgrade service
528	# in a temporarily disabled state (ie, service is armed for the next
529	# reboot), then let them know. We need to ensure that the system is
530	# is in a sane state before allowing any further invocations, so
531	# try to get the system admin to do so
532
533	ISARMED=`$SVCS -l $STMSINSTANCE|$GREP "enabled.*false.*temporary"`
534	if [ ! $? ]; then
535		echo ""
536		gettext "You need to reboot the system in order to complete\n"
537		gettext "the previous invocation of stmsboot.\n"
538		echo ""
539		gettext "Do you wish to reboot the system now? (y/n, default y) "
540		read response
541
542		if [ "x$response" = "x" -o "x$response" = "xY" -o \
543		    "x$response" = "xy" ]; then
544			$REBOOT
545		else
546			echo ""
547			gettext "Please reboot this system before continuing\n"
548			echo ""
549			exit 1
550		fi
551	fi
552
553	#
554	# keep a copy of the last saved files, useful for manual
555	# recovery in case of a problem.
556	#
557	for d in $DRVLIST; do
558		DRVCONF=$d.conf
559		KDRVCONF=/kernel/drv/$d.conf
560		TMPDRVCONF=/var/run/tmp.$d.conf.$$
561		TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$;
562		if [ "x$MACH" = "xsparc" ]; then
563			backup_lastsaved $KDRVCONF $VFSTAB
564		else
565			backup_lastsaved $KDRVCONF $VFSTAB /boot/solaris/$BOOTENV_FILE
566		fi
567	done
568fi
569
570if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then
571
572	msgneeded=`echo "$DRVLIST" |grep " "`
573	if [ -n "$msgneeded" ]; then
574		emit_driver_warning_msg
575	fi
576	for d in $DRVLIST; do
577		configure_mpxio $cmd $d
578	done
579
580	if [ $reboot_needed -ne 0 ]; then
581		# Need to update bootpath on x86 if our boot device is
582		# now accessed through mpxio.
583		# Only update bootpath before reboot when mpxio is enabled
584		# If mpxio is currently disabled, we will update bootpath
585		# on reboot in the mpxio-upgrade service
586
587		if [ "x$MACH" = "xi386" -a "x$cmd" = "xdisable" ]; then
588			get_newbootpath_for_stmsdev
589			if [ $? -ne 0 ]; then
590				$RM -f $TMPDRVCONF > /dev/null 2>&1
591				gettext "failed to update bootpath.\n" 1>&2
592				gettext "No changes were made to your STMS configuration.\n" 1>&2
593				return 1
594			fi
595		fi
596		update_sysfiles
597	else
598		echo "STMS is already ${cmd}d. No changes or reboots needed"
599	fi
600
601
602elif [ "x$cmd" = xupdate ]; then
603	if [ "x$MACH" = "xi386" ]; then
604	# In this case we always change the bootpath to phci-based
605	# path first. bootpath will later be modified in mpxio-upgrade
606	# to the vhci-based path if mpxio is enabled on root.
607		get_newbootpath_for_stmsdev
608		if [ $? -ne 0 ]; then
609			gettext "failed to update bootpath.\n" 1>&2
610			return 1
611		fi
612	fi
613	update_sysfiles
614
615elif [ "x$cmd" = xlist ]; then
616		$STMSBOOTUTIL $GUID -l $controller
617else
618		$STMSBOOTUTIL $GUID -L
619fi
620
621exit $?
622