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 2009 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 continue; 340 fi 341 fi 342 343 # If mpxiodisable entries do not exist, always continue update 344 fi 345 else 346 $RM -f $TMPDRVCONF $TMPDRVCONF_MPXIO_ENTRY $TMPDRVCONF_SATA_ENTRY > /dev/null 2>&1 347 gettext "failed to update " 1>&2 348 echo "$KDRVCONF." 1>&2 349 gettext "No changes were made to your STMS configuration.\n" 1>&2 350 return 1 351 fi 352 353 rm $TMPDRVCONF_MPXIO_ENTRY > /dev/null 2>&1 354 echo "mpxio-disable=\"${propval}\";" >> $TMPDRVCONF 355 echo "disable-sata-mpxio=\"${propval}\";" >> $TMPDRVCONF 356 357} 358 359setcmd() 360{ 361 if [ "x$cmd" = xnone ]; then 362 cmd=$1 363 else 364 echo "$USAGE" 1>&2 365 exit 2 366 fi 367} 368 369# 370# Need to update bootpath on x86 if boot system from FC disk 371# Only update bootpath here when mpxio is enabled 372# If mpxio is currently disabled, then we'll update bootpath in the 373# mpxio-upgrade service method on reboot. 374# 375 376get_newbootpath_for_stmsdev() { 377 if [ "x$cmd" = "xenable" ]; then 378 return 0 379 fi 380 381 cur_bootpath=`$STMSBOOTUTIL -b` 382 if [ $? != 0 ]; then 383 return 1 384 fi 385 386 # Since on x64 platforms the eeprom command doesn't update the 387 # kernel, the file /boot/solaris/bootenv.rc and the kernel's 388 # bootpath variable have a good chance of differing. We do some 389 # extra handwaving to get the correct bootpath variable setting. 390 391 ONDISKVER=`$AWK '/bootpath/ {print $3}' /boot/solaris/bootenv.rc|\ 392 $SED -e"s,',,g"` 393 if [ "x$ONDISKVER" != "x$cur_bootpath" ]; then 394 cur_bootpath="$ONDISKVER" 395 fi 396 397 NEWBOOTPATH="" 398 for path in $cur_bootpath; do 399 mapped=`$STMSBOOTUTIL -p $path` 400 if [ "$mapped" != "NOT_MAPPED" ]; then 401 if [ "$mapped" != "$path" ]; then 402 NEWBOOTPATH=`echo "$path " | \ 403 $SED -e"s|$path|$mapped|"`" $NEWBOOTPATH" 404 else 405 NEWBOOTPATH="$NEWBOOTPATH $path" 406 fi 407 fi 408 done 409 # now strip off leading and trailing space chars 410 new_bootpath=`echo $NEWBOOTPATH` 411 return 0 412} 413 414# 415# Emit a warning message to the user that by default we 416# operate on all multipath-capable controllers that are 417# attached to the system, and that if they want to operate 418# on only a specific controller type (fp|mpt|....) then 419# they need to re-invoke stmsboot with "-D $driver" in 420# their argument list 421# 422 423emit_driver_warning_msg() { 424 425 # for each driver that we support, grab the list 426 # of controllers attached to the system. 427 428 echo "" 429 gettext "WARNING: stmsboot operates on each supported multipath-capable controller\n" 430 gettext " detected in a host. In your system, these controllers are\n\n" 431 432 for WARNDRV in `echo $SUPPORTED_DRIVERS| $SED -e"s,|, ,g"`; do 433 $STMSBOOTUTIL -D $WARNDRV -n 434 done; 435 436 echo "" 437 gettext "If you do NOT wish to operate on these controllers, please quit stmsboot\n" 438 gettext "and re-invoke with -D { fp | mpt } to specify which controllers you wish\n" 439 gettext "to modify your multipathing configuration for.\n" 440 441 echo "" 442 gettext "Do you wish to continue? [y/n] (default: y) " 443 read response 444 445 if [ "x$response" != "x" -a "x$response" != "xY" -a \ 446 "x$response" != "xy" ]; then 447 exit 448 fi 449} 450 451 452# 453# 454# main starts here 455# 456 457cmd=none 458# process options 459while getopts D:geduLl: c 460do 461 case $c in 462 e) setcmd enable;; 463 d) setcmd disable;; 464 u) setcmd update;; 465 L) setcmd listall;; 466 l) setcmd list 467 controller=$OPTARG;; 468 D) DRV=$OPTARG;; 469 g) GUID="-g";; 470 \?) echo "$USAGE" 1>&2 471 exit 2;; 472 esac 473done 474 475if [ "x$cmd" = xnone ]; then 476 echo "$USAGE" 1>&2 477 exit 2 478fi 479 480if [ "x$DRV" = "x" ]; then 481 DRVLIST="fp mpt" 482else 483 DRVLIST=$DRV 484fi 485 486USERID=`id | $EGREP "uid=0"` 487if [ -z "$USERID" ]; then 488 gettext "You must be super-user to run this script.\n" 1>&2 489 exit 1 490fi 491 492# just a sanity check 493if [ ! -f $STMSBOOTUTIL -o ! -f $STMSMETHODSCRIPT ]; then 494 fmt=`gettext "Can't find %s and/or %s"` 495 printf "$fmt\n" "$STMSBOOTUTIL" "$STMSMETHODSCRIPT" 1>&2 496 exit 1 497fi 498 499# If the old sun4u-specific SMF method is found, remove it 500$SVCCFG -s "platform/sun4u/mpxio-upgrade:default" < /dev/null > /dev/null 2>&1 501if [ $? -eq 0 ]; then 502 $SVCCFG delete "platform/sun4u/mpxio-upgrade:default" > /dev/null 2>&1 503fi 504 505# now import the new service, if necessary 506$SVCPROP -q $STMSINSTANCE < /dev/null > /dev/null 2>&1 507if [ $? -ne 0 ]; then 508 if [ -f /var/svc/manifest/system/device/mpxio-upgrade.xml ]; then 509 $SVCCFG import /var/svc/manifest/system/device/mpxio-upgrade.xml 510 if [ $? -ne 0 ]; then 511 fmt=`gettext "Unable to import the %s service"` 512 printf "$fmt\n" "$STMSINSTANCE" 1>&2 513 exit 1 514 else 515 fmt=`gettext "Service %s imported successfully, continuing"` 516 printf "$fmt\n" "$STMSINSTANCE" 1>&2 517 fi 518 else 519 fmt=`gettext "Service %s does not exist on this host"` 520 printf "$fmt\n" "$STMSINSTANCE" 1>&2 521 exit 1 522 fi 523fi 524 525 526# make sure we can stash our data somewhere private 527if [ ! -d $SAVEDIR ]; then 528 $MKDIR -p $SAVEDIR 529fi 530# prime the cache 531$STMSBOOTUTIL -i 532 533 534if [ "x$cmd" = xenable -o "x$cmd" = xdisable -o "x$cmd" = xupdate ]; then 535 # 536 # The bootup script doesn't work on cache-only-clients as the script 537 # is executed before the plumbing for cachefs mounting of root is done. 538 # 539 if $MOUNT -v | $EGREP -s " on / type (nfs|cachefs) "; then 540 gettext "This command option is not supported on systems with an nfs or cachefs mounted root filesystem.\n" 1>&2 541 exit 1 542 fi 543 544 # if the user has left the system with the mpxio-upgrade service 545 # in a temporarily disabled state (ie, service is armed for the next 546 # reboot), then let them know. We need to ensure that the system is 547 # is in a sane state before allowing any further invocations, so 548 # try to get the system admin to do so 549 550 ISARMED=`$SVCS -l $STMSINSTANCE|$GREP "enabled.*false.*temporary"` 551 if [ ! $? ]; then 552 echo "" 553 gettext "You need to reboot the system in order to complete\n" 554 gettext "the previous invocation of stmsboot.\n" 555 echo "" 556 gettext "Do you wish to reboot the system now? (y/n, default y) " 557 read response 558 559 if [ "x$response" = "x" -o "x$response" = "xY" -o \ 560 "x$response" = "xy" ]; then 561 $REBOOT 562 else 563 echo "" 564 gettext "Please reboot this system before continuing\n" 565 echo "" 566 exit 1 567 fi 568 fi 569 570 # 571 # keep a copy of the last saved files, useful for manual 572 # recovery in case of a problem. 573 # 574 for d in $DRVLIST; do 575 DRVCONF=$d.conf 576 KDRVCONF=/kernel/drv/$d.conf 577 TMPDRVCONF=/var/run/tmp.$d.conf.$$ 578 TMPDRVCONF_MPXIO_ENTRY=/var/run/tmp.$d.conf.mpxioentry.$$; 579 if [ "x$MACH" = "xsparc" ]; then 580 backup_lastsaved $KDRVCONF $VFSTAB 581 else 582 backup_lastsaved $KDRVCONF $VFSTAB /boot/solaris/$BOOTENV_FILE 583 fi 584 done 585fi 586 587if [ "x$cmd" = xenable -o "x$cmd" = xdisable ]; then 588 589 msgneeded=`echo "$DRVLIST" |grep " "` 590 if [ -n "$msgneeded" ]; then 591 emit_driver_warning_msg 592 fi 593 for d in $DRVLIST; do 594 configure_mpxio $cmd $d 595 done 596 597 if [ $reboot_needed -ne 0 ]; then 598 # Need to update bootpath on x86 if our boot device is 599 # now accessed through mpxio. 600 # Only update bootpath before reboot when mpxio is enabled 601 # If mpxio is currently disabled, we will update bootpath 602 # on reboot in the mpxio-upgrade service 603 604 if [ "x$cmd" = "xdisable" ]; then 605 if [ "x$MACH" = "xi386" ]; then 606 get_newbootpath_for_stmsdev 607 if [ $? -ne 0 ]; then 608 $RM -f $TMPDRVCONF > /dev/null 2>&1 609 gettext "failed to update bootpath.\n" 1>&2 610 gettext "No changes were made to your STMS configuration.\n" 1>&2 611 return 1 612 fi 613 fi 614 # If we're not using ZFS root then we need 615 # to keep track of what / maps to in case 616 # it's an active-active device and we boot from 617 # the other path 618 ROOTSCSIVHCI=`$DF /|$AWK -F":" '{print $1}' | \ 619 $AWK -F"(" '{print $2}'| \ 620 $SED -e"s,dsk,rdsk," -e"s,s.),,"` 621 $STMSBOOTUTIL -L | $GREP $ROOTSCSIVHCI | \ 622 $AWK '{print $1}' | $SED -e"s,rdsk,dsk,g" \ 623 >$BOOTDEVICES 624 fi 625 update_sysfiles 626 else 627 echo "STMS is already ${cmd}d. No changes or reboots needed" 628 fi 629 630 631elif [ "x$cmd" = xupdate ]; then 632 if [ "x$MACH" = "xi386" ]; then 633 # In this case we always change the bootpath to phci-based 634 # path first. bootpath will later be modified in mpxio-upgrade 635 # to the vhci-based path if mpxio is enabled on root. 636 get_newbootpath_for_stmsdev 637 if [ $? -ne 0 ]; then 638 gettext "failed to update bootpath.\n" 1>&2 639 return 1 640 fi 641 fi 642 update_sysfiles 643 644elif [ "x$cmd" = xlist ]; then 645 $STMSBOOTUTIL $GUID -l $controller 646else 647 $STMSBOOTUTIL $GUID -L 648fi 649 650exit $? 651