Home | History | Annotate | Download | only in dscfg
      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 2008 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=/var/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 
   1548