Merge commit '00f1a4f432b3d8aad1aa270e91c44c57f03ef407'
[unleashed.git] / usr / src / cmd / stmsboot / stmsboot.sh
blob313dcaa6768cc0473e8a64a8f1c251a9371a4077
1 #!/sbin/sh -p
3 # CDDL HEADER START
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.
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.
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]
20 # CDDL HEADER END
23 # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 # Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 PATH=/usr/bin:/usr/sbin:$PATH; export PATH
28 STMSBOOTUTIL=/lib/mpxio/stmsboot_util
29 STMSMETHODSCRIPT=/lib/svc/method/mpxio-upgrade
30 KDRVCONF=
31 DRVCONF=
32 TMPDRVCONF=
33 TMPDRVCONF_MPXIO_ENTRY=
34 TMPDRVCONF_SATA_ENTRY=
35 DRVLIST=
36 GUID=
37 VFSTAB=/etc/vfstab
38 SAVEDIR=/etc/mpxio
39 BOOTDEVICES=$SAVEDIR/boot-devices
40 RECOVERFILE=$SAVEDIR/recover_instructions
41 SVCCFG_RECOVERY=$SAVEDIR/svccfg_recover
42 SUPPORTED_DRIVERS="fp|mpt|mpt_sas|pmcs"
43 USAGE=`gettext "Usage: stmsboot [-D $SUPPORTED_DRIVERS] -e | -d | -u | -L | -l controller_number"`
44 TEXTDOMAIN=SUNW_OST_OSCMD
45 export TEXTDOMAIN
46 STMSINSTANCE=svc:system/device/mpxio-upgrade:default
47 FASTBOOTINSTANCE=svc:system/boot-config:default
48 STMSBOOT=/usr/sbin/stmsboot
49 BOOTADM=/sbin/bootadm
50 MOUNT=/usr/sbin/mount
51 EEPROM=/usr/sbin/eeprom
52 EGREP=/usr/bin/egrep
53 GREP=/usr/bin/grep
54 AWK=/usr/bin/awk
55 CP=/usr/bin/cp
56 DF=/usr/bin/df
57 LS=/usr/bin/ls
58 MV=/usr/bin/mv
59 RM=/usr/bin/rm
60 SORT=/usr/bin/sort
61 UNIQ=/usr/bin/uniq
62 EXPR=/usr/bin/expr
63 MKDIR=/usr/bin/mkdir
64 REBOOT=/usr/sbin/reboot
65 SED=/usr/bin/sed
66 SVCPROP=/usr/bin/svcprop
67 SVCCFG=/usr/sbin/svccfg
68 SVCS=/usr/bin/svcs
69 SVCADM=/usr/sbin/svcadm
71 NOW=`/usr/bin/date +%G%m%d_%H%M`
72 MACH=`/usr/bin/uname -p`
73 BOOTENV_FILE=bootenv.rc
74 reboot_needed=0
75 new_bootpath=""
76 CLIENT_TYPE_PHCI=""
77 CLIENT_TYPE_VHCI="/scsi_vhci"
80 # Copy all entries (including comments) from source driver.conf
81 # to destination driver.conf except those entries which contain
82 # the mpxio-disable property.
83 # Take into consideration entries that spawn more than one line.
85 # $1 source driver.conf file
86 # $2 destination driver.conf file
88 # Returns 0 on success, non zero on failure.
90 delete_mpxio_disable_entries()
92 # be careful here, we've got embedded \t characters
93 # in sed's pattern space.
94 $SED '
95 /^[ ]*#/{ p
98 s/[ ]*$//
99 /^$/{ p
102 /mpxio-disable[ ]*=.*;$/{ w '$3'
105 /disable-sata-mpxio[ ]*=.*;$/{ w '$4'
108 /;$/{ p
111 :rdnext
113 s/[ ]*$//
114 /[^;]$/b rdnext
115 /mpxio-disable[ ]*=/{ s/\n/ /g
116 w '$3'
119 ' $1 > $2
121 return $?
125 # backup the last saved copy of the specified files.
126 # $* files to backup
128 backup_lastsaved()
130 for file in $*
132 newfile=`basename $file`
133 $CP $file $SAVEDIR/$newfile.$cmd.$NOW
134 done
138 # build recover instructions
140 # $1 1 to include boot script in the instructions
141 # 0 otherwise
143 build_recover()
145 gettext "Instructions to recover your previous STMS configuration (if in case the system does not boot):\n\n" > $RECOVERFILE
146 echo "\tboot net \c" >> $RECOVERFILE
147 gettext "(or from a cd/dvd/another disk)\n" >> $RECOVERFILE
148 echo "\tfsck <your-root-device>" >> $RECOVERFILE
149 echo "\tmount <your-root-device> /mnt" >> $RECOVERFILE
151 if [ "$cmd" = "update" ]; then
152 gettext "\tUndo the modifications you made to STMS configuration.\n\tFor example undo any changes you made to " >> $RECOVERFILE
153 echo "/mnt$KDRVCONF." >> $RECOVERFILE
154 else
155 echo "\tcp /mnt${SAVEDIR}/$DRVCONF.$cmd.$NOW /mnt$KDRVCONF" >> $RECOVERFILE
158 if [ $1 -eq 1 ]; then
159 echo "\tcp /mnt${SAVEDIR}/vfstab.$cmd.$NOW /mnt$VFSTAB" >> $RECOVERFILE
161 echo "repository /mnt/etc/svc/repository.db" > $SVCCFG_RECOVERY
162 echo "select $STMSINSTANCE" >> $SVCCFG_RECOVERY
163 echo "setprop general/enabled=false" >> $SVCCFG_RECOVERY
164 echo "exit" >> $SVCCFG_RECOVERY
166 echo "\t$SVCCFG -f /mnt$SVCCFG_RECOVERY" >> $RECOVERFILE
168 if [ -n "$new_bootpath" -a "$MACH" = "i386" ]; then
169 echo "\tcp /mnt${SAVEDIR}/bootenv.rc.$cmd.$NOW /mnt/boot/solaris/$BOOTENV_FILE" >> $RECOVERFILE
173 rootdisk=`$MOUNT | $GREP "/ on " | cut -f 3 -d " "`
174 echo "\tumount /mnt\n\treboot\n\n${rootdisk} \c" >> $RECOVERFILE
175 gettext "was your root device,\nbut it could be named differently after you boot net.\n" >> $RECOVERFILE
180 # Arrange for /etc/vfstab and dump configuration to be updated
181 # during the next reboot. If the cmd is "enable" or "disable", copy
182 # $TMPDRVCONF to $KDRVCONF.
184 # Returns 0 on success, 1 on failure.
186 update_sysfiles()
189 gettext "WARNING: This operation will require a reboot.\n"
190 gettext "Do you want to continue ? [y/n] (default: y) "
191 read response
193 if [ -n "$response" -a "$response" != "y" -a \
194 "$response" != "Y" ]; then
195 for d in $DRVLIST; do
196 TMPDRVCONF=/var/run/tmp.$d.conf.$$
197 $RM -f $TMPDRVCONF > /dev/null 2>&1
198 done;
199 return 0;
202 # set need_bootscript to the number of drivers that
203 # we support.
204 need_bootscript=`echo $SUPPORTED_DRIVERS|$AWK -F"|" '{print NF}'`
206 if [ "$cmd" = "enable" -o "$cmd" = "disable" ]; then
208 for d in $DRVLIST; do
209 DRVCONF=$d.conf
210 KDRVCONF=/kernel/drv/$d.conf
211 TMPDRVCONF=/var/run/tmp.$d.conf.$$
213 $CP $KDRVCONF $SAVEDIR/`basename $KDRVCONF`.$cmd.$NOW
214 if [ -f $TMPDRVCONF ]; then
215 $CP $TMPDRVCONF $KDRVCONF
216 $RM -f $TMPDRVCONF
217 else
218 # if $TMPDRVCONF doesn't exist, then we
219 # haven't made any changes to it
220 continue;
224 # there is no need to update the system files in the following
225 # cases:
226 # - we are enabling mpxio and the system has no configured
227 # disks accessible by phci paths.
228 # - we are disabling mpxio and the system has no configured
229 # disks accessible by vhci paths.
232 # Function to setup the CLIENT_TYPE_PHCI string based on
233 # the list of drivers that we're operating on. The variable
234 # depends upon the pathname of the parent node in the
235 # device tree, which can be different on x86/x64 and sparc.
237 CLIENT_TYPE_PHCI=`$STMSBOOTUTIL -D $d -N`;
239 if [ -z "$CLIENT_TYPE_PHCI" ]; then
240 continue;
243 if [ "$cmd" = "enable" ]; then
244 $LS -l /dev/dsk/*s2 2> /dev/null | \
245 $EGREP -s "$CLIENT_TYPE_PHCI"
246 else
247 $LS -l /dev/dsk/*s2 2> /dev/null | \
248 $EGREP -s "$CLIENT_TYPE_VHCI"
251 if [ $? -ne 0 ]; then
252 need_bootscript=`$EXPR $need_bootscript - 1`
254 done
257 if [ $need_bootscript -gt 0 ]; then
258 need_bootscript=1
259 if [ -n "$new_bootpath" -a "$MACH" = "i386" ]; then
260 #only update bootpath for x86.
261 $CP /boot/solaris/$BOOTENV_FILE $SAVEDIR/$BOOTENV_FILE.$cmd.$NOW
262 $EEPROM bootpath="$new_bootpath"
265 if [ "$MACH" = "i386" ]; then
266 # Disable Fast Reboot temporarily for the next reboot only.
267 HASZFSROOT=`$DF -g / |$GREP zfs`
268 if [ -n "$HASZFSROOT" ]; then
269 $SVCCFG -s $FASTBOOTINSTANCE addpg config_ovr application P > /dev/null 2>&1
270 $SVCCFG -s $FASTBOOTINSTANCE \
271 setprop config_ovr/fastreboot_default=boolean:\"false\"
272 $SVCCFG -s $FASTBOOTINSTANCE \
273 setprop config_ovr/fastreboot_onpanic=boolean:\"false\"
274 $SVCADM refresh $FASTBOOTINSTANCE
278 # Enable the mpxio-upgrade service for the reboot
279 $SVCADM disable -t $STMSINSTANCE
280 $SVCCFG -s $STMSINSTANCE "setprop general/enabled=true"
281 else
282 need_bootscript=0
285 build_recover $need_bootscript
287 if [ "$MACH" = "i386" ]; then
288 $BOOTADM update-archive
291 gettext "The changes will come into effect after rebooting the system.\nReboot the system now ? [y/n] (default: y) "
292 read response
294 if [ -z "$response" -o "$response" = "y" -o \
295 "$response" = "Y" ]; then
296 $REBOOT
299 return 0
304 # Enable or disable mpxio as specified by the cmd.
305 # Returns 0 on success, 1 on failure.
307 # Args: $cmd = {enable | disable}
308 # $d = {fp | mpt | mpt_sas | pmcs}
310 # the global variable $DRVLIST is used
312 configure_mpxio()
314 # be careful here, we've got embedded \t characters
315 # in sed's pattern space.
316 mpxiodisableno='mpxio-disable[ ]*=[ ]*"no"[ ]*;'
317 mpxiodisableyes='mpxio-disable[ ]*=[ ]*"yes"[ ]*;'
318 satadisableno='disable-sata-mpxio[ ]*=[ ]*"no"[ ]*;'
319 satadisableyes='disable-sata-mpxio[ ]*=[ ]*"yes"[ ]*;'
321 if [ "$cmd" = "enable" ]; then
322 mpxiodisable_cur_entry=$mpxiodisableyes
323 satadisable_cur_entry=$satadisableyes
324 propval=no
325 msg=`gettext "STMS already enabled"`
326 else
327 mpxiodisable_cur_entry=$mpxiodisableno
328 satadisable_cur_entry=$satadisableno
329 propval=yes
330 msg=`gettext "STMS already disabled"`
333 DRVCONF=$d.conf
334 KDRVCONF=/kernel/drv/$d.conf
335 TMPDRVCONF=/var/run/tmp.$d.conf.$$
336 TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$;
337 TMPDRVCONF_SATA_ENTRY=/var/run/tmp.$d.conf.sataentry.$$;
339 if delete_mpxio_disable_entries $KDRVCONF $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY $TMPDRVCONF_SATA_ENTRY; then
341 if [ -s $TMPDRVCONF_MPXIO_ENTRY ]; then
342 # $DRVCONF does have mpxiodisable entries
343 $EGREP -s "$mpxiodisable_cur_entry" $TMPDRVCONF_MPXIO_ENTRY
344 if [ $? -eq 0 ]; then
345 reboot_needed=`$EXPR $reboot_needed + 1`
346 else
347 # if all mpxiodisable entries are no/yes for
348 # enable/disable mpxio, notify the user
349 $EGREP -s "$satadisable_cur_entry" $TMPDRVCONF_SATA_ENTRY
350 if [ $? -eq 0 -a "$d" = "mpt" ]; then
351 reboot_needed=`$EXPR $reboot_needed + 1`
352 else
353 $RM -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY $TMPDRVCONF_SATA_ENTRY > /dev/null 2>&1
354 return 0;
358 # If mpxiodisable entries do not exist, always continue update
360 else
361 $RM -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY $TMPDRVCONF_SATA_ENTRY > /dev/null 2>&1
362 gettext "failed to update " 1>&2
363 echo "$KDRVCONF." 1>&2
364 gettext "No changes were made to your STMS configuration.\n" 1>&2
365 return 1
368 rm $TMPDRVCONF_MPXIO_ENTRY $TMPDRVCONF_SATA_ENTRY > /dev/null 2>&1
369 echo "mpxio-disable=\"${propval}\";" >> $TMPDRVCONF
370 if [ "$d" = "mpt" ]; then
371 echo "disable-sata-mpxio=\"${propval}\";" >> $TMPDRVCONF
376 setcmd()
378 if [ "$cmd" = "none" ]; then
379 cmd=$1
380 else
381 echo "$USAGE" 1>&2
382 exit 2
387 # Need to update bootpath on x86 if boot system from FC disk
388 # Only update bootpath here when mpxio is enabled
389 # If mpxio is currently disabled, then we'll update bootpath in the
390 # mpxio-upgrade service method on reboot.
393 get_newbootpath_for_stmsdev() {
394 if [ "$cmd" = "enable" ]; then
395 return 0
398 cur_bootpath=`$STMSBOOTUTIL -b`
399 if [ $? != 0 ]; then
400 return 1
403 # Since on x64 platforms the eeprom command doesn't update the
404 # kernel, the file /boot/solaris/bootenv.rc and the kernel's
405 # bootpath variable have a good chance of differing. We do some
406 # extra handwaving to get the correct bootpath variable setting.
408 ONDISKVER=`$AWK '/bootpath/ {print $3}' /boot/solaris/bootenv.rc|\
409 $SED -e"s,',,g"`
410 if [ "$ONDISKVER" != "$cur_bootpath" ]; then
411 cur_bootpath="$ONDISKVER"
414 NEWBOOTPATH=""
415 for path in $cur_bootpath; do
416 mapped=`$STMSBOOTUTIL -p $path`
417 if [ "$mapped" != "NOT_MAPPED" ]; then
418 if [ "$mapped" != "$path" ]; then
419 NEWBOOTPATH=`echo "$path " | \
420 $SED -e"s|$path|$mapped|"`" $NEWBOOTPATH"
421 else
422 NEWBOOTPATH="$NEWBOOTPATH $path"
425 done
426 # now strip off leading and trailing space chars
427 new_bootpath=`echo $NEWBOOTPATH`
428 return 0
432 # Emit a warning message to the user that by default we
433 # operate on all multipath-capable controllers that are
434 # attached to the system, and that if they want to operate
435 # on only a specific controller type (fp|mpt|mpt_sas|pmcs|....) then
436 # they need to re-invoke stmsboot with "-D $driver" in
437 # their argument list
440 emit_driver_warning_msg() {
442 # for each driver that we support, grab the list
443 # of controllers attached to the system.
445 echo ""
446 gettext "WARNING: stmsboot operates on each supported multipath-capable controller\n"
447 gettext " detected in a host. In your system, these controllers are\n\n"
449 for WARNDRV in `echo $SUPPORTED_DRIVERS| $SED -e"s,|, ,g"`; do
450 $STMSBOOTUTIL -D $WARNDRV -n
451 done;
453 echo ""
454 gettext "If you do NOT wish to operate on these controllers, please quit stmsboot\n"
455 gettext "and re-invoke with -D { fp | mpt | mpt_sas | pmcs} to specify which controllers you wish\n"
456 gettext "to modify your multipathing configuration for.\n"
458 echo ""
459 gettext "Do you wish to continue? [y/n] (default: y) "
460 read response
462 if [ -n "$response" -a "$response" != "Y" -a \
463 "$response" != "y" ]; then
464 exit
471 # main starts here
474 cmd=none
475 # process options
476 while getopts D:geduLl: c
478 case $c in
479 e) setcmd enable;;
480 d) setcmd disable;;
481 u) setcmd update;;
482 L) setcmd listall;;
483 l) setcmd list
484 controller=$OPTARG;;
485 D) DRV=$OPTARG;;
486 g) GUID="-g";;
487 \?) echo "$USAGE" 1>&2
488 exit 2;;
489 esac
490 done
492 if [ "$cmd" = "none" ]; then
493 echo "$USAGE" 1>&2
494 exit 2
497 if [ -z "$DRV" ]; then
498 DRVLIST="fp mpt mpt_sas pmcs"
499 else
500 DRVLIST=$DRV
503 USERID=`id | $EGREP "uid=0"`
504 if [ -z "$USERID" ]; then
505 gettext "You must be super-user to run this script.\n" 1>&2
506 exit 1
509 # just a sanity check
510 if [ ! -f $STMSBOOTUTIL -o ! -f $STMSMETHODSCRIPT ]; then
511 fmt=`gettext "Can't find %s and/or %s"`
512 printf "$fmt\n" "$STMSBOOTUTIL" "$STMSMETHODSCRIPT" 1>&2
513 exit 1
516 # If the old sun4u-specific SMF method is found, remove it
517 $SVCCFG -s "platform/sun4u/mpxio-upgrade:default" < /dev/null > /dev/null 2>&1
518 if [ $? -eq 0 ]; then
519 $SVCCFG delete "platform/sun4u/mpxio-upgrade:default" > /dev/null 2>&1
522 # now import the new service, if necessary
523 $SVCPROP -q $STMSINSTANCE < /dev/null > /dev/null 2>&1
524 if [ $? -ne 0 ]; then
525 if [ -f /lib/svc/manifest/system/device/mpxio-upgrade.xml ]; then
526 $SVCCFG import /lib/svc/manifest/system/device/mpxio-upgrade.xml
527 if [ $? -ne 0 ]; then
529 fmt=`gettext "Unable to import the %s service"`
530 printf "$fmt\n" "$STMSINSTANCE" 1>&2
531 exit 1
532 else
533 fmt=`gettext "Service %s imported successfully, continuing"`
534 printf "$fmt\n" "$STMSINSTANCE" 1>&2
536 else
537 fmt=`gettext "Service %s does not exist on this host"`
538 printf "$fmt\n" "$STMSINSTANCE" 1>&2
539 exit 1
544 # make sure we can stash our data somewhere private
545 if [ ! -d $SAVEDIR ]; then
546 $MKDIR -p $SAVEDIR
548 # prime the cache
549 $STMSBOOTUTIL -i
552 if [ "$cmd" = "enable" -o "$cmd" = "disable" -o "$cmd" = "update" ]; then
553 if $MOUNT -v | $EGREP -s " on / type nfs "; then
554 gettext "This command option is not supported on systems with an nfs mounted root filesystem.\n" 1>&2
555 exit 1
558 # if the user has left the system with the mpxio-upgrade service
559 # in a temporarily disabled state (ie, service is armed for the next
560 # reboot), then let them know. We need to ensure that the system is
561 # is in a sane state before allowing any further invocations, so
562 # try to get the system admin to do so
564 ISARMED=`$SVCS -l $STMSINSTANCE|$GREP "enabled.*false.*temporary"`
565 if [ ! $? ]; then
566 echo ""
567 gettext "You need to reboot the system in order to complete\n"
568 gettext "the previous invocation of stmsboot.\n"
569 echo ""
570 gettext "Do you wish to reboot the system now? (y/n, default y) "
571 read response
573 if [ -z "$response" -o "x$response" = "Y" -o \
574 "$response" = "y" ]; then
575 $REBOOT
576 else
577 echo ""
578 gettext "Please reboot this system before continuing\n"
579 echo ""
580 exit 1
585 # keep a copy of the last saved files, useful for manual
586 # recovery in case of a problem.
588 for d in $DRVLIST; do
589 DRVCONF=$d.conf
590 KDRVCONF=/kernel/drv/$d.conf
591 TMPDRVCONF=/var/run/tmp.$d.conf.$$
592 TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$;
593 if [ "$MACH" = "sparc" ]; then
594 backup_lastsaved $KDRVCONF $VFSTAB
595 else
596 backup_lastsaved $KDRVCONF $VFSTAB /boot/solaris/$BOOTENV_FILE
598 done
601 if [ "$cmd" = "enable" -o "$cmd" = "disable" ]; then
603 msgneeded=`echo "$DRVLIST" |$GREP " "`
604 if [ -n "$msgneeded" ]; then
605 emit_driver_warning_msg
607 for d in $DRVLIST; do
608 configure_mpxio $cmd $d
609 done
611 if [ $reboot_needed -ne 0 ]; then
612 # Need to update bootpath on x86 if our boot device is
613 # now accessed through mpxio.
614 # Only update bootpath before reboot when mpxio is enabled
615 # If mpxio is currently disabled, we will update bootpath
616 # on reboot in the mpxio-upgrade service
618 if [ "$cmd" = "disable" ]; then
619 if [ "$MACH" = "i386" ]; then
620 get_newbootpath_for_stmsdev
621 if [ $? -ne 0 ]; then
622 $RM -f $TMPDRVCONF > /dev/null 2>&1
623 gettext "failed to update bootpath.\n" 1>&2
624 gettext "No changes were made to your STMS configuration.\n" 1>&2
625 return 1
628 # If we're not using ZFS root then we need
629 # to keep track of what / maps to in case
630 # it's an active-active device and we boot from
631 # the other path
632 HASZFSROOT=`$DF -g / |$GREP zfs`
633 if [ -z "$HASZFSROOT" ]; then
634 ROOTSCSIVHCI=`$DF /|$AWK -F":" '{print $1}' | \
635 $AWK -F"(" '{print $2}'| $SED -e"s,),,"`
636 TMPROOTDEV=`$LS -l $ROOTSCSIVHCI |$AWK -F">" '{print $2}' | \
637 $SED -e"s, ../../devices,,"`
638 $STMSBOOTUTIL -q $TMPROOTDEV > $BOOTDEVICES
641 update_sysfiles
642 else
643 echo "STMS is already ${cmd}d. No changes or reboots needed"
647 elif [ "$cmd" = "update" ]; then
648 if [ "$MACH" = "i386" ]; then
649 # In this case we always change the bootpath to phci-based
650 # path first. bootpath will later be modified in mpxio-upgrade
651 # to the vhci-based path if mpxio is enabled on root.
652 get_newbootpath_for_stmsdev
653 if [ $? -ne 0 ]; then
654 gettext "failed to update bootpath.\n" 1>&2
655 return 1
658 update_sysfiles
660 elif [ "$cmd" = "list" ]; then
661 $STMSBOOTUTIL $GUID -l $controller
662 else
663 $STMSBOOTUTIL $GUID -L
666 exit $?