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