1 #!/usr/bin/ksh
   2 # CDDL HEADER START
   3 #
   4 # The contents of this file are subject to the terms of the
   5 # Common Development and Distribution License (the "License").
   6 # You may not use this file except in compliance with the License.
   7 #
   8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9 # or http://www.opensolaris.org/os/licensing.
  10 # See the License for the specific language governing permissions
  11 # and limitations under the License.
  12 #
  13 # When distributing Covered Code, include this CDDL HEADER in each
  14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15 # If applicable, add the following below this CDDL HEADER, with the
  16 # fields enclosed by brackets "[]" replaced with your own identifying
  17 # information: Portions Copyright [yyyy] [name of copyright owner]
  18 #
  19 # CDDL HEADER END
  20 #
  21 #
  22 # Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23 # Use is subject to license terms.
  24 #
  25 
  26 typeset -r PROG=$(basename $0)
  27 typeset -r CTAG_NULL="-"
  28 
  29 #
  30 # help message
  31 #
  32 help()
  33 {
  34         $xopt
  35 
  36         cluster_configured
  37         CLUSTER_CONFIGURED=$?
  38 
  39         echo "\
  40 usage:
  41         $PROG
  42         $PROG -i
  43         $PROG -e [-r][-p]
  44         $PROG -d [-r]" >&2
  45         if [ $CLUSTER_CONFIGURED -eq 1 ]; then
  46                 echo "\
  47         $PROG -s" >&2
  48         fi
  49 
  50         echo "\
  51         -i      : display information on the Availability Suite services
  52         -e      : enable Availability Suite services (all, by default)
  53         -d      : disable Availability Suite services (all, by default)
  54         -r      : enable/disable Remote Mirror
  55         -p      : enable Point in Time Copy" >&2
  56         if [ $CLUSTER_CONFIGURED -eq 1 ]; then
  57                 echo "\
  58         -s      : set the location of the cluster configuration database" >&2
  59         fi
  60         echo "\
  61         -x      : turn on script debugging (may be used with any valid option)
  62 
  63          When executed with no options or with nothing but -x, $PROG runs in
  64          interactive fashion, allowing the user to initialize the local (and
  65          if applicable, the cluster) configuration database, and to start the
  66          Availability Suite services." >&2
  67 
  68         exit 2
  69 }
  70 
  71 ########################## SET GLOBAL VARIABLES ######################
  72 
  73 # root directory
  74 PKG_INSTALL_ROOT=""
  75 export PKG_INSTALL_ROOT
  76 
  77 # set lib path
  78 LD_LIBRARY_PATH=/usr/lib:/usr/lib
  79 export LD_LIBRARY_PATH
  80 
  81 # set dscfg
  82 DSCFG="/usr/sbin/dscfg"
  83 export DSCFG
  84 
  85 # set parser config location
  86 PCONFIG="/etc/dscfg_format"
  87 export PCONFIG
  88 
  89 # set local dscfg location
  90 export LOCAL_DSCFG="/etc/dscfg_local"
  91 
  92 # set cluster dscfg reference file
  93 export CLUSTER_REF="/etc/dscfg_cluster"
  94 
  95 # a service that has a dependency on us
  96 FS_LOCAL_SVC="svc:/system/filesystem/local"
  97 
  98 NODELIST="/tmp/nodelist"
  99 DSCFGLOCKDCF="/etc/dscfg_lockdb"
 100 DSCFG_DEPEND_NOCHK="/tmp/.dscfgadm_pid"
 101 
 102 # SMF defines
 103 MANIFEST_PATH=/lib/svc/manifest/system
 104 
 105 # SMF services (enable and disable)
 106 SMF_ENABLE="nws_scm nws_sv nws_ii nws_rdc nws_rdcsyncd"
 107 SMF_DISABLE="nws_rdcsyncd nws_rdc nws_ii nws_sv nws_scm"
 108 
 109 # state of each service
 110 nws_scm_enabled=0
 111 nws_sv_enabled=0
 112 nws_ii_enabled=0
 113 nws_rdc_enabled=0
 114 nws_rdcsyncd_enabled=0
 115 
 116 # set path
 117 PATH=/usr/bin:/usr/sbin:/sbin/sh
 118 export PATH
 119 
 120 # set architecture
 121 ARCH=`uname -p`
 122 export ARCH
 123 OS_MINOR=`uname -r | cut -d '.' -f2`
 124 
 125 # number of sectors required for database
 126 # 1024*1024*5.5/512
 127 REQUIRED=11264
 128 
 129 # must set here, else seen as null in MAIN
 130 VALID_DB_ENTERED=0
 131 
 132 NO_ARGS=0
 133 
 134 # for debugging
 135 xopt=
 136 
 137 # set lengthy message here
 138 CLUST_LOC_MESS="The current location is invalid for a Sun StorageTek \
 139 Data Services configuration database.  Once a valid location is \
 140 entered (raw slice on \"did\" device), you may upgrade the existing \
 141 database to this new location - following the procedure outlined \
 142 in the Installation and Configuration Guide."
 143 
 144 ########################## SET GLOBAL VARIABLES ######################
 145 
 146 
 147 ########################## ERROR  ####################################
 148 
 149 # called with optional error msg $1
 150 # prints basic guidelines for configuration of the database location
 151 error()
 152 {
 153     $xopt
 154 
 155     echo >&2
 156     echo "INSTALLATION ERROR" >&2
 157     echo "Error: $1" >&2
 158     echo >&2
 159     in_cluster
 160 
 161     if [ $? -eq 1 ]; then
 162         echo "GENERAL INSTALLATION RULES:" >&2
 163         echo "\tBecause you are installing on a cluster," >&2
 164         echo "\tthe database must be located on a raw slice of a did device.">&2
 165         echo "\t  e.g. /dev/did/rdsk/d17s1" >&2
 166     fi
 167     # let?
 168     MB=`expr $REQUIRED / 2 / 1024`
 169     echo "\t$REQUIRED sectors ($MB MBs) are required for the database." >&2
 170 }
 171 
 172 ########################## ERROR  ####################################
 173 
 174 ########################## ALL LOCATION TESTS ########################
 175 
 176 # sets numerous environment variables describing the state of the system
 177 get_system_state()
 178 {
 179         $xopt
 180 
 181         valid_local_dscfg_exists
 182         VALID_LOCAL_DB=$?
 183         OLD_VALID_LOCAL_DB=$VALID_LOCAL_DB
 184 
 185         in_cluster
 186         IN_CLUSTER=$?
 187 
 188         cluster_configured
 189         CLUSTER_CONFIGURED=$?
 190 
 191         if [ $IN_CLUSTER = 1 ]; then
 192                 valid_cluster_dscfg_exists
 193                 VALID_CLUSTER_DB=$?
 194                 OLD_VALID_CLUSTER_DB=$VALID_CLUSTER_DB
 195         else
 196                 VALID_CLUSTER_DB=0
 197         fi
 198 }
 199 
 200 # Checks if in cluster
 201 # returns 1 if in cluster, else 0
 202 #
 203 in_cluster()
 204 {
 205     $xopt
 206 
 207     if [ -x /usr/sbin/clinfo ]; then
 208             clinfo
 209         if [ $? -eq 0 ]; then
 210             return 1
 211         else
 212             return 0
 213         fi
 214     else
 215         return 0
 216     fi
 217 }
 218 
 219 # checks if a system is configured as a cluster
 220 # returns 1 if configured as a cluster, 0 if not
 221 #
 222 cluster_configured()
 223 {
 224     $xopt
 225 
 226     if [ -f /etc/cluster/nodeid ]; then
 227         return 1
 228     else
 229         return 0
 230     fi
 231 }
 232 
 233 # Check the list of Sun Cluster device groups known in the dscfg, determing
 234 # if they are currently enabled on this Sun Cluster node. If so, fail allowing
 235 # the system administator to scswitch them elsewhere.
 236 #
 237 check_device_groups()
 238 {
 239         $xopt
 240 
 241         if [ $VALID_CLUSTER_DB == 1 ]; then
 242                 DEVICE_GROUPS=`$DSCFG -s $FILE_LOC -l 2>/dev/null | \
 243                 grep "^dsvol:" | cut -d' ' -f3 | sort | uniq | xargs`
 244                 for x in $DEVICE_GROUPS
 245                 do
 246                         $DSCFG -D $x 2>/dev/null
 247                         if [ $? -eq 1 ]
 248                         then
 249                                 IN_USE="$IN_USE $x"
 250                         fi
 251                 done
 252 
 253                 if [ -n "$IN_USE" ]
 254                 then
 255                     print "The following Sun Cluster device groups are in use "
 256                     print "by Availability Suite on this node."
 257                     print ""
 258                     print "$IN_USE"
 259                     print ""
 260                     print "'scswitch' them to another Sun Cluster node before "
 261                     print "attempting to disable any data services."
 262                     return 1
 263                 else
 264                     return 0
 265                 fi
 266         fi
 267         
 268         return 0
 269 }
 270 
 271 # checks to see if this is a char device in the
 272 # /dev/did/rdsk directory returns 1 if so.
 273 #
 274 is_did_device()
 275 {
 276         $xopt
 277 
 278         DID=`echo $1 | awk -F/ '{print $3}'`
 279         RDSK=`echo $1 | awk -F/ '{print $4}'`
 280 
 281         if [ "did" = $DID -a "rdsk" = $RDSK -a -c $1 ]; then
 282                 return 1
 283         else    
 284                 return 0
 285         fi
 286 }
 287 
 288 #
 289 # checks size of area for db location
 290 #
 291 check_size()
 292 {
 293         $xopt
 294 
 295         # if in cluster look for d*s*
 296         SLICE=`echo $1 | sed -n 's/.*d.*s\(.*\)/\1/p'`
 297 
 298         SECTORS=`prtvtoc $1 | tr -s ' '| grep "^ $SLICE " | awk '{print $5}'`
 299 
 300         if [ -z "$SECTORS" ]; then
 301             echo "SLICE at $1 not found on this device"
 302             return 0
 303         fi
 304 
 305         # if required size is greater than space available, then fail
 306         if [ $REQUIRED -gt $SECTORS ]; then
 307                 return 0
 308         else
 309                 return 1
 310         fi
 311 }
 312 
 313 # looks in dscfg_cluster reference file.  if a location is configured,
 314 # tests to see if it is a valid database.  if so, returns 1
 315 #
 316 valid_cluster_dscfg_exists()
 317 {
 318     $xopt
 319 
 320     if [ -s $CLUSTER_REF ]; then
 321         FILE_LOC=`head -1 $CLUSTER_REF`
 322         contains_data $FILE_LOC
 323         return $?
 324     else
 325         return 0
 326     fi
 327 }
 328 
 329 
 330 # checks for the existence of dscfg_local database, and if it exists,
 331 # tests to see if it is a valid database.  if so, returns 1
 332 #
 333 valid_local_dscfg_exists()
 334 {
 335     $xopt
 336 
 337     if [ -s $LOCAL_DSCFG ]; then
 338         contains_data $LOCAL_DSCFG
 339         return $?
 340     else
 341        return 0
 342     fi
 343 }
 344 
 345 # used to test if a valid DS config database exists on machine already
 346 # MAGIC_STRING is the top line in the config used in v3.1 & v3.2
 347 #
 348 contains_data()
 349 {
 350     $xopt
 351 
 352     # dscfg distinct strings, varies on the architecture
 353     if [ $ARCH = "sparc" ]
 354     then
 355         MAGIC_STRING="MAGI"
 356     elif [ $ARCH = "i386" ]
 357     then
 358         MAGIC_STRING="IGAM"
 359     fi
 360 
 361     # Create a PID unique temporary file
 362     TMP_FILE=/tmp/$$
 363 
 364     # Write the first or 16th block (skipping over VTOC) to
 365     # the TMP_FILE, then scan for the presence of the "MAGI"
 366     #
 367     for offset in 0 16
 368     do
 369         if [ ! -z "$1" ]; then
 370             dd if=$1 of=$TMP_FILE count=1 iseek=$offset 2>/dev/null
 371             FILECONTENTS=`strings $TMP_FILE | head -1 2>/dev/null`
 372             if [ `echo $FILECONTENTS | grep -c "$MAGIC_STRING"` -gt 0 ]; then
 373                 rm $TMP_FILE
 374                 return 1
 375             fi
 376         fi
 377     done
 378 
 379     rm $TMP_FILE
 380     return 0
 381 }
 382 
 383 ########################## ALL LOCATION TESTS ########################
 384 
 385 
 386 ########################## MAIN FUNCTIONS ############################
 387 
 388 # since location already has been set, asks what to do now?  keeping
 389 # it still checks the size (since an upgrade from 3.0 may still be
 390 # occuring) and also checks if was an old cluster config on disallowed
 391 # /dev/did/dsk directory
 392 #
 393 # returns:
 394 #       0 if cluster location is invalid or the user does not want to keep it
 395 #       1 if the location is valid and the user wants to keep it.
 396 #
 397 keep_it()
 398 {
 399     $xopt
 400 
 401     NOTE="\nThe Sun StorageTek Data Services database configuration"
 402     NOTE="$NOTE location has already been set."
 403     echo $NOTE
 404 
 405     echo "\nCurrent location: $PKG_INSTALL_ROOT$FILE_LOC"
 406 
 407     QUEST="Would you like to preserve the existing configuration"
 408     QUEST="$QUEST information at its current location? "
 409 
 410     ANS=`ckyorn -Qd n -p "$QUEST"`
 411 
 412     case $ANS in
 413         y|Y|yes|YES|Yes)
 414             #Since the user has said "yes I want to keep this current one"
 415             #it may actually be a 3.x database, which only required 4.5mb
 416             #space, so now will check that there is room to grow another 1mb"
 417             check_location $FILE_LOC
 418             if [ $? = 0 ]; then
 419                 error "$CLUST_LOC_MESS"
 420                 return 0
 421             else
 422                 OLD_FILE_LOC=$FILE_LOC
 423                 FILE_LOC=$NULL
 424                 return 1
 425             fi
 426             ;;
 427         *)
 428             return 0
 429             ;;
 430     esac
 431 }
 432 
 433 #
 434 # asks if user wants to keep existing db information, overwrite with
 435 # a new db, or view the contents, and be asked again...
 436 # returns:
 437 #       0 if old location is bad
 438 #       1 if old location is good
 439 #
 440 preserve_overwrite_maybe()
 441 {
 442     $xopt
 443 
 444     echo "\nIt appears a valid database configuration exists here already."
 445 
 446     while true
 447     do
 448       SAFE_LOC=$FILE_LOC
 449 
 450         echo "\nWould you like to preserve this information and continue?"
 451         echo "\ty - preserve current configuration"
 452         echo "\tn - overwrite with new configuration"
 453         echo "\tmaybe - view contents of current configuration"
 454 
 455         ANS=`ckkeywd -Q y n maybe`
 456         case $ANS in
 457           y)
 458                 check_location $FILE_LOC
 459                 if [ $? = 0 ]; then
 460                         error "$CLUST_LOC_MESS"
 461                         return 0
 462                 else
 463                         $DSCFG -s "$FILE_LOC" -C $CTAG_NULL >/dev/null 2>&1
 464                         OLD_FILE_LOC=$FILE_LOC
 465                         FILE_LOC=$NULL
 466                         return 1
 467                 fi
 468                 ;;
 469           n)
 470                 check_location $FILE_LOC
 471                 if [ $? = 0 ]; then
 472                         error "$CLUST_LOC_MESS"
 473                         return 0
 474                 else
 475                         return 1
 476                 fi
 477                 ;;
 478 
 479           maybe)
 480                 # print contents of this db config.
 481                 echo "\nContents of database configuration found at $SAFE_LOC are:"
 482                 $DSCFG -l -s "$FILE_LOC" | more
 483                 FILE_LOC=$SAFE_LOC
 484                 continue
 485               ;;
 486         esac
 487     done
 488 }
 489 
 490 # gets location from user
 491 #
 492 get_location()
 493 {
 494     $xopt
 495 
 496     #Checks for absolute path name, and if file name and file doesn't
 497     #exist, creates it.
 498     echo "\n\n----------ENTER DATABASE CONFIGURATION LOCATION-----------------"
 499     echo "Note:  Please ensure this location meets all requirements specified"
 500     echo "in the Availability Suite Installation Guide."
 501 
 502     FILE_LOC=`ckpath -artwQ -p "Enter location:"`
 503     if [ $? = 1 ]
 504         then
 505             exit 1
 506         fi
 507 
 508     # allow non-root user to access for least privileges
 509     chmod 666 $FILE_LOC
 510 }
 511 
 512 
 513 #
 514 # tests for proper config
 515 #
 516 # returns:
 517 #       0 if bad location
 518 #       1 if good location
 519 #
 520 check_location()
 521 {
 522         $xopt
 523 
 524         # set to FILE_LOC
 525         LOCATION=$1
 526 
 527         did_clust_msg="You are in cluster and $LOCATION is not valid DID device"
 528 
 529         # Set "actual file location" variable here to equal file location
 530         # entered by user because getting here means contains_data was already
 531         # successfully called before and now the two can equal each other for
 532         # future testing.
 533 
 534         SAFE_LOC=$FILE_LOC
 535 
 536         if [ $IN_CLUSTER = 1 -o $CLUSTER_CONFIGURED = 1 ]; then
 537                 if [ -b "$LOCATION" ] || [ -c "$LOCATION" ]; then
 538                         is_did_device $LOCATION
 539                         if [ $? = 0 ]; then
 540                                 error "$did_clust_msg"
 541                                 return 0
 542                         fi
 543                 else
 544                         error "$did_clust_msg"
 545                         return 0
 546                 fi
 547         else
 548                 echo "Location may not be changed in a non Sun Cluster OE." 2>&1
 549                 return 0
 550         fi
 551 
 552         check_size $LOCATION
 553 
 554         if [ $? != 1 ]; then
 555                 error "$LOCATION does not meet minimum space requirement."
 556                 return 0
 557         else
 558                 return 1
 559         fi
 560 }
 561 
 562 #
 563 # Notifies the user that the SMF services are online,
 564 # and gives him the option to disable the services before proceeding.  If
 565 # the services are not disabled, the program cannot proceed with setting
 566 # a new dscfg location.
 567 #
 568 ask_to_disable()
 569 {
 570     $xopt
 571 
 572     echo "\
 573 \nYour services must be disabled before a new configuration location is set.\n"
 574 
 575     QUEST="Would you like to disable the services now and continue with the"
 576     QUEST="$QUEST Availability Suite setup? " 
 577 
 578     ANS=`ckyorn -Qd n -p "$QUEST"`
 579 
 580     case $ANS
 581         in y|Y|yes|YES|Yes)
 582             return 1
 583             ;;
 584         *)
 585             return 0
 586             ;;
 587     esac
 588 }
 589 
 590 #
 591 # Asks the user if he would like to enable the services now.  If so,
 592 # import them (if necessary) and enable them.
 593 #
 594 ask_to_enable()
 595 {
 596     $xopt
 597 
 598     echo "\
 599 \nIf you would like to start using the Availability Suite immediately, you may
 600 start the SMF services now.  You may also choose to start the services later
 601 using the $PROG -e command."
 602 
 603     QUEST="Would you like to start the services now? "
 604 
 605     ANS=`ckyorn -Qd n -p "$QUEST"`
 606 
 607     case $ANS
 608         in y|Y|yes|YES|Yes)
 609             return 1
 610             ;;
 611         *)
 612             return 0
 613             ;;
 614     esac
 615 }
 616 
 617 #
 618 # display information about the system
 619 #
 620 display_info()
 621 {
 622         $xopt
 623 
 624         typeset grp_error_flg=0
 625         typeset -L15 svc state en SVC="SERVICE" STATE="STATE" EN="ENABLED"
 626         echo "$SVC\t$STATE\t$EN"
 627 
 628         for i in $SMF_ENABLE
 629         do
 630                 is_imported $i
 631                 if [ $? = 1 ]
 632                 then
 633                         state=`svcprop -c -p restarter/state \
 634                             svc:/system/${i}:default`
 635                         en=`svcprop -c -p general/enabled \
 636                             svc:/system/${i}:default`
 637                         check_fs_local_grouping $i
 638                         if [ $? -ne 0 ]
 639                         then
 640                                 svc="${i}***"
 641                                 grp_error_flg=$((grp_error_flg + 1))
 642                         else
 643                                 svc=$i
 644                         fi
 645 
 646                         echo "$svc\t$state\t$en"
 647                 fi
 648         done
 649 
 650         print "\nAvailability Suite Configuration:"
 651         printf "Local configuration database: "
 652         if [ $VALID_LOCAL_DB = 1 ]
 653         then
 654                 print "valid"   
 655         else
 656                 print "invalid" 
 657         fi
 658 
 659         if [ $CLUSTER_CONFIGURED = 1 ]
 660         then
 661                 printf "cluster configuration database: "
 662                 if [ $VALID_CLUSTER_DB = 1 ]
 663                 then
 664                         print "valid"   
 665                         print "cluster configuration location: ${FILE_LOC}"
 666                 else
 667                         print "invalid" 
 668                 fi
 669         fi
 670 
 671         if [ $grp_error_flg -gt 0 ]
 672         then
 673                 typeset p
 674                 typeset p_has
 675                 if [ $grp_error_flg -gt 1 ]
 676                 then
 677                         p="s"
 678                         p_has="have"
 679                 else
 680                         p=""
 681                         p_has="has"
 682                 fi
 683 
 684                 printf "\n*** Warning: The service$p above $p_has an incorrect "
 685                 printf "dependency.  To repair the\n"
 686                 printf "problem, run \"dscfgadm\".\n"
 687         fi
 688 }
 689 
 690 #
 691 # initialize the local configuration database (only called if none exists)
 692 # returns 0 if successful, 1 if failed
 693 #
 694 initialize_local_db()
 695 {
 696         $xopt
 697 
 698         echo "Could not find a valid local configuration database."
 699         echo "Initializing local configuration database..."
 700         echo y | ${DSCFG} -i > /dev/null 2>&1
 701         ${DSCFG} -i -p ${PCONFIG} > /dev/null 2>&1
 702 
 703         # Make sure the new location is initialized properly
 704         valid_local_dscfg_exists
 705         VALID_LOCAL_DB=$?
 706         if [ $VALID_LOCAL_DB != 1 ]
 707         then
 708                 echo "Unable to initialize local configuration database" >&2
 709                 return 1
 710         else    
 711                 echo "Successfully initialized local configuration database"
 712         fi
 713 
 714         return 0
 715 }
 716 
 717 #
 718 # initialize the cluster configuration database, if necessary
 719 # returns 0 if successful, 1 if failed
 720 #
 721 initialize_cluster_db()
 722 {
 723         $xopt
 724 
 725         if [ ! -n "$FILE_LOC" ]
 726         then
 727                 return 0
 728         fi
 729 
 730         echo "Initializing cluster configuration database..."
 731         ${DSCFG} -s ${FILE_LOC} -C $CTAG_NULL > /dev/null 2>&1
 732         echo y | ${DSCFG} -i -C $CTAG_NULL > /dev/null 2>&1
 733         ${DSCFG} -i -p ${PCONFIG} -C $CTAG_NULL > /dev/null 2>&1
 734 
 735         # make sure the cluster db is valid now
 736         valid_cluster_dscfg_exists
 737         VALID_CLUSTER_DB=$?
 738         if [ $VALID_CLUSTER_DB != 1 ]
 739         then
 740                 echo "Unable to initialize cluster configuration database" >&2
 741                         return 1
 742         else
 743                 echo "Successfully initialized cluster configuration database"
 744         fi
 745 
 746         return 0
 747 
 748 }
 749 
 750 #
 751 # prompt the user for a config location and set AVS to use that location
 752 #
 753 set_cluster_config()
 754 {
 755 
 756 $xopt
 757 
 758 REPEAT=0
 759 while [ $REPEAT -eq 0 ]; do
 760   # See if user has entered location already, and it was an existing
 761   # db.  Retruns FILE_LOC value
 762   if [ $VALID_DB_ENTERED = 1 ]; then
 763 
 764         # reset
 765       VALID_DB_ENTERED=0
 766         preserve_overwrite_maybe
 767 
 768         # if 1, location passes, and FILE_LOC being passed to end, else
 769       # set VALID_CLUSTER_DB to 0 since the "valid one" isn't valid anymore
 770       # (bad size, etc) thereby when looping go straight to get_location
 771       if [ $? = 1 ]; then
 772           REPEAT=1
 773           continue
 774       else
 775           VALID_CLUSTER_DB=0
 776           continue
 777       fi
 778   fi
 779 
 780   # if 1, then valid db exists, now see what user wants to do
 781   if [ $VALID_CLUSTER_DB = 1 ]; then
 782       SAFE_LOC=$FILE_LOC
 783       keep_it
 784 
 785       # if 0, then user can't or won't keep location.  set PROMPT
 786       # so we will get new location from user.
 787       if [ $? = 0 ]; then
 788           PROMPT=0
 789       else
 790           PROMPT=1
 791         fi
 792   fi
 793 
 794   # if either are 0, then user wants or needs new db as outlined in
 795   # earlier comments
 796   if [ $VALID_CLUSTER_DB = 0 ] || [ $PROMPT = 0 ]; then
 797         #
 798         # We cannot proceed if the services are running.  Give the user
 799         # a chance to stop the services.  If he chooses not to, bail.
 800         #
 801         check_enabled
 802         if [ $? = 1 ]
 803         then
 804                 show_enabled
 805                 ask_to_disable
 806                 if [ $? = 0 ]
 807                 then
 808                         echo "A new configuration location was not set."
 809                         exit 1
 810                 else
 811                         disable_services
 812                         if [ $? != 0 ]
 813                         then
 814                                 exit 1
 815                         fi      
 816                 fi
 817                         
 818         fi
 819                         
 820         get_location
 821         contains_data $FILE_LOC
 822 
 823         # if 1, then user entered an existsing db location, loop
 824         # back to ask what to do with it
 825         if [ $? = 1 ]; then
 826           VALID_DB_ENTERED=1
 827           continue
 828         else
 829           check_location $FILE_LOC
 830 
 831           # if 0, that means location has failed, loop and
 832           # get_location again
 833           if [ $? = 0 ]; then
 834                 VALID_CLUSTER_DB=0
 835                 continue
 836           fi
 837           # entered location passes tests
 838           REPEAT=1
 839           continue
 840         fi
 841   else
 842       # user wants to leave location where and how it is
 843         # FILE_LOC being passed all the way to end
 844         REPEAT=1
 845         continue
 846   fi
 847 done
 848 
 849 }
 850 
 851 ########################## MAIN FUNCTIONS ############################
 852 
 853 ######################## SMF HELPER FUNCTIONS ########################
 854 #
 855 # check if any SMF service is online (enabled)
 856 #
 857 check_enabled()
 858 {
 859         $xopt
 860         typeset ret=0
 861         typeset svc
 862 
 863         for svc in $SMF_ENABLE
 864         do
 865                 is_enabled $svc
 866                 eval ${svc}_enabled=$?
 867                 ret=$((ret | ${svc}_enabled))
 868         done
 869 
 870         return $ret
 871 }
 872 
 873 #
 874 # Display which services are enabled.  (Must be called after check_enabled)
 875 #
 876 show_enabled()
 877 {
 878         $xopt
 879         typeset svc
 880 
 881         echo "\nThe following Availability Suite services are enabled:"
 882 
 883         for svc in $SMF_ENABLE
 884         do
 885         if (( ${svc}_enabled == 1 ))
 886         then
 887             printf "$svc "
 888         fi
 889         done
 890 
 891         echo ""
 892 }
 893 
 894 
 895 #
 896 # check if the given SMF service is online (enabled)
 897 # 
 898 # $1: service name to check for
 899 #
 900 is_enabled()
 901 {
 902         $xopt
 903         typeset en
 904 
 905         is_imported $1
 906         if [ $? = 1 ]
 907         then
 908                 en=`svcprop -c -p general/enabled svc:/system/${1}:default`
 909                 if [ $en = "true" ]
 910                 then
 911                         return 1
 912                 fi
 913         fi
 914         
 915         return 0
 916         
 917 }
 918 
 919 #
 920 # If necessary, flag no dependency check
 921 #
 922 no_depend_check()
 923 {
 924         $xopt
 925         typeset pid
 926         typeset msg=0
 927 
 928         if [ $OS_MINOR -lt 11 ]
 929         then
 930                 if [ -f $DSCFG_DEPEND_NOCHK ]
 931                 then
 932                         pid=`cat $DSCFG_DEPEND_NOCHK`
 933                         echo "Another dscfgadm disable is in progress."
 934                         echo "Waiting for pid: $pid to terminate..."
 935 
 936                         while [ -f $DSCFG_DEPEND_NOCHK ]
 937                         do
 938                                 if (( msg && (msg % 6 == 0)))
 939                                 then
 940                                         printf "\nAnother dscfgadm disable "
 941                                         printf "(pid: $pid) still appears to "
 942                                         printf " be in progress.\n"
 943                                         printf "If this is not the case, you "
 944                                         printf "may remove "
 945                                         printf "$DSCFG_DEPEND_NOCHK.\n"
 946                                 fi
 947                                 sleep 5
 948                                 msg=$((msg + 1))
 949                         done
 950                 fi
 951 
 952                 touch $DSCFG_DEPEND_NOCHK
 953                 echo $$ >> $DSCFG_DEPEND_NOCHK
 954         fi
 955 }
 956 
 957 #
 958 # If necessary, remove the no dependency check flag
 959 #
 960 rm_no_depend_check()
 961 {
 962         $xopt
 963         if [ $OS_MINOR -lt 11 ]
 964         then
 965                 rm -f $DSCFG_DEPEND_NOCHK
 966         fi
 967 }
 968 
 969 # 
 970 # set the filesystem/local dependency type and refresh
 971 #
 972 # $1: service name
 973 # $2: either "require_all" or "optional_all"
 974 #
 975 set_fs_local_grouping()
 976 {
 977         $xopt
 978         typeset svc=$1
 979         typeset dep_group=$2
 980 
 981         # set proper dependency type for fs-local
 982         if [ $svc != nws_rdcsyncd ]; then
 983                 svccfg -s $FS_LOCAL_SVC setprop \
 984                    ${svc}-local-fs/grouping=$dep_group
 985                 if [ $? -ne 0 ]
 986                 then
 987                         printf "command failed: svccfg -s $FS_LOCAL_SVC "
 988                         printf "setprop ${svc}-local-fs/grouping=$dep_group "
 989                         printf ">&2\n"
 990                         return 1
 991                 fi
 992 
 993                 # we need local-fs to know about the new grouping attributes
 994                 svcadm refresh ${FS_LOCAL_SVC}:default
 995                 if [ $? -ne 0 ]
 996                 then
 997                         print "Failed to refresh ${FS_LOCAL_SVC} >&2"
 998                         return 1
 999                 fi
1000         fi
1001 
1002         return 0
1003 }
1004 
1005 #
1006 # check if the grouping dependency type for filesystem/local is correct
1007 #
1008 # input:
1009 # $1: service name
1010 #
1011 # returns:
1012 #       0 if the setting is correct
1013 #       1 if the setting is incorrect
1014 # outputs: sets CORRECT_GROUPING with the value of what the grouping should be.
1015 #
1016 check_fs_local_grouping()
1017 {
1018         $xopt
1019         typeset svc=$1
1020         typeset cur_grouping
1021 
1022         if [ $svc = nws_rdcsyncd ]
1023         then
1024                 return 0
1025         fi
1026 
1027         # If it's not imported, we just return success, since we don't want
1028         # further processing
1029         is_imported $svc
1030         if [ $? = 0 ]
1031         then
1032                 return 0
1033         fi
1034 
1035         # get the current grouping value from the repository
1036         cur_grouping=`svcprop -c -p ${svc}-local-fs/grouping $FS_LOCAL_SVC`
1037 
1038         # Figure out what the grouping should be (based on enabled status)
1039         is_enabled $svc
1040         if [ $? = 1 ]
1041         then
1042                 CORRECT_GROUPING="require_all"
1043         else
1044                 CORRECT_GROUPING="optional_all"
1045         fi
1046 
1047         if [ "$cur_grouping" != "$CORRECT_GROUPING" ]
1048         then
1049                 # grouping is incorrect
1050                 return 1
1051         else 
1052                 # grouping is just fine
1053                 return 0
1054         fi
1055 }
1056 
1057 #
1058 # enable/disable the given SMF service.  Also, update the filesystem-local
1059 # dependency, if appropriate.
1060 #
1061 # $1: service name to check for
1062 # $2: "enable" or "disable"
1063 #
1064 svc_operation()
1065 {
1066         $xopt
1067         typeset svc=$1
1068         typeset command=$2
1069         typeset enable_state
1070         typeset dep_group
1071 
1072         # If disabling, then enable_state better be true, and we are
1073         # transitioning to "option_all" grouping
1074         if [ $command = "disable" ]
1075         then
1076                 enable_state=1
1077                 dep_group="optional_all"
1078 
1079         # If enabling, then enable_state better be false, and we are
1080         # transitioning to "require_all" grouping
1081         elif [ $command = "enable" ]
1082         then    
1083                 enable_state=0
1084                 dep_group="require_all"
1085         else
1086                 echo "invalid command: $command" >&2
1087         fi
1088 
1089         is_imported $svc
1090         if [ $? = 1 ]
1091         then
1092                 is_enabled $svc
1093                 if [ $? = $enable_state ]
1094                 then
1095                         if [ $enable_state -eq 1 ]
1096                         then
1097                                 # we're doing a disable--remove hard dependency
1098                                 set_fs_local_grouping $svc $dep_group
1099                                 if [ $? -ne 0 ]
1100                                 then
1101                                         return 1
1102                                 fi
1103                         fi
1104 
1105                         svcadm $command -s svc:/system/$svc
1106                         if [ $? != 0 ]
1107                         then
1108                                 echo "$svc failed to $command" >&2
1109                                 return 1
1110                         fi
1111 
1112                         if [ $enable_state -eq 0 ]
1113                         then
1114                                 # we just did an enable--create hard dependency 
1115                                 set_fs_local_grouping $svc $dep_group
1116                                 if [ $? -ne 0 ]
1117                                 then
1118                                         return 1
1119                                 fi
1120                         fi
1121 
1122                 else
1123                         echo "$svc service already ${command}d... skipping"
1124                 fi
1125         fi
1126 
1127         return 0
1128 }
1129 
1130 #
1131 # This chart summarizes the behavior of the -r and -p sub-options for the 
1132 # -e and -d options.
1133 # There are 5 possible states, and 5 transitions out of each state.
1134 #
1135 # states: (vertical axis)
1136 # -------
1137 # 0: no services enabled
1138 # C: one or both core services enabled (illegal state)
1139 # R: both core services and RM services enabled
1140 # P: both core services and PITC service enabled
1141 # A: all services enabled
1142 #
1143 # transitions: (horizontal axis)
1144 # ------------
1145 # +/-a: enable/disable, respectively, with neither -r nor -p
1146 # +/-r: enable/disable, respectively, with -r flag
1147 # +p: enable with -p flag
1148 #
1149 # The result of the function is the next state after the action has been 
1150 # successfully performed.
1151 #
1152 #      +a | -a | +r | -r | +p | 
1153 #   ++----+----+----+----+----+ 
1154 #   ++----+----+----+----+----+
1155 # 0 || A  | 0* | R  | 0* | P  |
1156 # --++----+----+----+----+----+
1157 # C || A* | 0* | R  | 0  | P  | 
1158 # --++----+----+----+----+----+
1159 # R || A* | 0* | R* | 0  | A  |
1160 # --++----+----+----+----+----+
1161 # P || A* | 0* | A* | P* | P* |
1162 # --++----+----+----+----+----+
1163 # A || A* | 0  | A* | P  | A* |
1164 # --++----+----+----+----+----+
1165 #
1166 # *: warning message is displayed, stating that a service is already
1167 #    enabled/disabled.
1168 #
1169 
1170 # enable the SMF services needed for the Availability Suite
1171 #
1172 enable_services()
1173 {
1174         $xopt
1175         typeset svc
1176 
1177         # first, import them if they have not yet been imported
1178         import_services
1179 
1180         # if neither r_flag nor p_flag is set, enable all services
1181         if (( (r_flag | p_flag) == 0 ))
1182         then
1183                 for svc in $SMF_ENABLE
1184                 do
1185                         if ! svc_operation $svc enable
1186                         then
1187                                 return 1
1188                         fi
1189                 done
1190         else
1191                 # figure out which services are enabled
1192                 check_enabled
1193 
1194                 # First, make sure both core services are enabled
1195                 for svc in nws_scm nws_sv
1196                 do
1197                         if (( ${svc}_enabled == 0 )) && \
1198                                 ! svc_operation $svc enable
1199                         then
1200                                 return 1        
1201                         fi
1202                 done
1203 
1204                 if ((p_flag))
1205                 then
1206                         if ! svc_operation nws_ii enable
1207                         then
1208                                 return 1
1209                         fi
1210                 fi
1211                 
1212                 if ((r_flag))
1213                 then
1214                         for svc in nws_rdc nws_rdcsyncd
1215                         do
1216                                 if ! svc_operation $svc enable
1217                                 then
1218                                         return 1
1219                                 fi
1220                         done
1221                 fi
1222 
1223         fi      
1224 
1225         return 0
1226 }
1227 
1228 #
1229 # disable the SMF services needed for the Availability Suite
1230 #
1231 disable_services()
1232 {
1233         $xopt
1234         typeset svc
1235 
1236         check_device_groups
1237         if [ $? == 1 ]
1238         then
1239                 return 1
1240         fi
1241 
1242         # This flags the shutdown scripts to not check to make sure the
1243         # services' dependents have been disabled.  The flag must be removed
1244         # before returning from this function.
1245         no_depend_check
1246 
1247         # NB: p_flag is not allowed for disables.  II should not be
1248         # disabled if sndr is enabled.  If rdc is not enabled, disabling just
1249         # II is equivalent to disabling all the remaining services.
1250 
1251         # If no flags passed in, just disable everything
1252         if (( r_flag == 0 ))
1253         then
1254                 for svc in $SMF_DISABLE
1255                 do
1256                         if ! svc_operation $svc disable
1257                         then
1258                                 rm_no_depend_check
1259                                 return 1
1260                         fi
1261                 done
1262 
1263                 # Now that we've disable the services, lets unload them
1264                 # from the Solaris kernel
1265                 #
1266                 modinfo | grep '(nws:' | grep -v "kRPC Stub" | sort -r | cut -d' ' -f1 | xargs -l modunload -i 2>/dev/null
1267                 modinfo | grep '(nws:' | grep -v "kRPC Stub" | sort -r | cut -d' ' -f1 | xargs -l modunload -i 2>/dev/null
1268         else
1269                 # we're disabling just rdc.  If II is not already enabled,
1270                 # we disable core services, as well.
1271                 
1272                 # figure out which services are enabled
1273                 check_enabled
1274 
1275                 for svc in nws_rdcsyncd nws_rdc
1276                 do
1277                         if ! svc_operation $svc disable
1278                         then
1279                                 rm_no_depend_check
1280                                 return 1
1281                         fi
1282                 done
1283 
1284                 if (( nws_ii_enabled == 0 ))
1285                 then
1286                         for svc in nws_sv nws_scm
1287                         do
1288                                 if ((${svc}_enabled)) && \
1289                                         ! svc_operation $svc disable
1290                                 then
1291                                         rm_no_depend_check
1292                                         return 1        
1293                                 fi
1294                         done
1295                 fi
1296         fi
1297 
1298 
1299         rm_no_depend_check
1300         return 0
1301 }
1302 
1303 #
1304 # check if a service has been imported into the repository
1305 # $1: service to check 
1306 # returns 1 if it is imported, 0 if it is not
1307 #
1308 is_imported()
1309 {
1310         $xopt
1311 
1312         typeset svc=$1
1313 
1314         svcprop -q -p general/entity_stability svc:/system/${svc}
1315         if [ $? = 1 ]
1316         then
1317                 return 0
1318         else
1319                 return 1
1320         fi
1321 }
1322 
1323 #
1324 # import the SMF services into the repository, if necessary
1325 #
1326 import_services()
1327 {
1328         $xopt
1329         typeset svc
1330 
1331         for svc in $SMF_ENABLE
1332         do
1333                 import_service $svc
1334         done
1335 }
1336 
1337 #
1338 # check to see if an SMF service is in the repository.  If it is not,
1339 # import it in.
1340 # $1: name of service to import
1341 #
1342 import_service()
1343 {
1344         $xopt
1345         typeset svc=$1
1346 
1347         is_imported $svc
1348         if [ $? = 0 ]
1349         then
1350                 if [ -f $PKG_INSTALL_ROOT/$MANIFEST_PATH/$svc.xml ]
1351                 then
1352                         svccfg import $PKG_INSTALL_ROOT/$MANIFEST_PATH/$svc.xml
1353 
1354                         if [ $OS_MINOR -lt 11 ]
1355                         then
1356                                 # workaround for 6221374--let local-fs know
1357                                 # that it depends on us.
1358                                 svcadm refresh ${FS_LOCAL_SVC}:default
1359                         fi
1360                 fi
1361         fi
1362 }
1363 
1364 
1365 ########################## MAIN ######################################
1366 
1367 # getopt processing
1368 enable=0
1369 disable=0
1370 set_location=0
1371 get_info=0
1372 r_flag=0
1373 p_flag=0
1374 while getopts "xedsirp" opt 2>/dev/null
1375 do
1376         case $opt in
1377         \?)
1378                 help
1379                 ;;
1380         e)
1381                 enable=1
1382                 ;;
1383         d)
1384                 disable=1
1385                 ;;
1386         x)
1387                 xopt="set -x"
1388                 set -x
1389                 ;;
1390         s)
1391                 set_location=1
1392                 ;;
1393         i)
1394                 get_info=1
1395                 ;;
1396         r)
1397                 r_flag=1
1398                 ;;
1399         p)
1400                 p_flag=1
1401                 ;;
1402         esac
1403 done
1404 
1405 # at most one option (besides -x) may be specified at a time
1406 options_count=$((enable + disable + set_location + get_info))
1407 if [ $options_count -gt 1 ]
1408 then
1409         help
1410 elif [ $options_count = 0 ]
1411 then
1412         NO_ARGS=1
1413 fi
1414 
1415 if (( ((r_flag + p_flag) > 0) && ((enable | disable) == 0) ))
1416 then
1417         echo "-r and -p options may only be used with -d or -e options" >&2
1418         return 1
1419 elif (( p_flag && disable ))
1420 then
1421         echo "The -p option may not be used with the -d option" >&2
1422         return 1
1423 fi
1424 
1425 
1426 
1427 # set all the system information variables
1428 get_system_state
1429 
1430 # if we're enabling, we need to make sure we have a valid dscfg out there.
1431 if [ $enable = 1 -a $VALID_LOCAL_DB != 1 ]
1432 then
1433         echo "Cannot find a valid configuration database" >&2
1434         return 1
1435 fi
1436 
1437 if [ $NO_ARGS = 1 ]
1438 then
1439 
1440         # only initialize the database if necessary
1441         if [ $VALID_LOCAL_DB = 1 ]; then
1442                 echo "Local configuration database is already initialized."
1443         else
1444                 initialize_local_db
1445                 if [ $? != 0 ]; then
1446                         return 1
1447                 fi
1448         fi
1449 
1450         if [ $CLUSTER_CONFIGURED = 1 ]
1451         then
1452                 if [ $VALID_CLUSTER_DB = 1 ]; then
1453                         printf "Cluster configuration database is already "
1454                         printf "initialized.\n"
1455                 else    
1456                         # ask the user for a cluster database location
1457                         set_cluster_config
1458 
1459                         # initialize the new db
1460                         initialize_cluster_db
1461                         if [ $? != 0 ]; then
1462                                 return 1
1463                         fi
1464                 fi
1465 
1466         fi
1467 
1468         # make sure that the local filesystem dependency type is correct
1469         for svc in $SMF_ENABLE
1470         do       
1471                 check_fs_local_grouping $svc
1472                 if [ $? -ne 0 ]
1473                 then
1474                         # NOTE: check_fs_local_grouping sets CORRECT_GROUPING
1475                         # To avoid this issue in the future, always administer
1476                         # the services using dscfgadm.
1477                         printf "Warning: Fixing dependency for $svc.\n"
1478                         set_fs_local_grouping $svc $CORRECT_GROUPING
1479                         if [ $? -ne 0 ]
1480                         then
1481                                 return 1
1482                         fi
1483                 fi
1484         done
1485 
1486         # give the user the chance to startup AVS services, if not started
1487         check_enabled
1488         if [ $? = 1 ]; then
1489                 if [ $OLD_VALID_LOCAL_DB = 0 ]; then
1490                         printf "WARNING: AVS services are running on a system "
1491                         printf "which had no valid configuration\ndatabase\n"
1492                 fi
1493                 show_enabled
1494         else
1495                 ask_to_enable
1496                 if [ $? = 1 ]; then
1497                         enable_services
1498                         if [ $? != 0 ]
1499                         then
1500                                 return 1
1501                         fi
1502                 fi
1503         fi
1504 
1505 elif [ $enable = 1 ]
1506 then
1507         enable_services
1508         if [ $? != 0 ]
1509         then
1510                 return 1
1511         fi
1512 
1513 elif [ $disable = 1 ]
1514 then
1515         disable_services
1516         if [ $? != 0 ]
1517         then
1518                 return 1
1519         fi
1520 
1521 elif [ $get_info = 1 ]
1522 then
1523         display_info
1524 
1525 elif [ $set_location = 1 ]
1526 then
1527         if [ $CLUSTER_CONFIGURED = 1 ]
1528         then
1529                 # ask the user for a cluster database location
1530                 set_cluster_config
1531 
1532                 # initialize the new db
1533                 initialize_cluster_db
1534                 if [ $? != 0 ]; then
1535                         return 1
1536                 fi
1537         else
1538                 echo "$PROG -s is only available on Sun Cluster OE systems" >&2
1539                 return 1
1540         fi
1541 fi
1542 
1543 return 0
1544 
1545 
1546 ########################## MAIN ######################################
1547