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