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