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