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