xref: /titanic_41/usr/src/cmd/avs/dscfg/dscfgadm.sh (revision c241e58373bcc331158a6c1172d9d42abc03e0af)
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
26typeset -r PROG=$(basename $0)
27typeset -r CTAG_NULL="-"
28
29#
30# help message
31#
32help()
33{
34	$xopt
35
36	cluster_configured
37	CLUSTER_CONFIGURED=$?
38
39	echo "\
40usage:
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
74PKG_INSTALL_ROOT=""
75export PKG_INSTALL_ROOT
76
77# set lib path
78LD_LIBRARY_PATH=/usr/lib:/usr/lib
79export LD_LIBRARY_PATH
80
81# set dscfg
82DSCFG="/usr/sbin/dscfg"
83export DSCFG
84
85# set parser config location
86PCONFIG="/etc/dscfg_format"
87export PCONFIG
88
89# set local dscfg location
90export LOCAL_DSCFG="/etc/dscfg_local"
91
92# set cluster dscfg reference file
93export CLUSTER_REF="/etc/dscfg_cluster"
94
95# a service that has a dependency on us
96FS_LOCAL_SVC="svc:/system/filesystem/local"
97
98NODELIST="/tmp/nodelist"
99DSCFGLOCKDCF="/etc/dscfg_lockdb"
100DSCFG_DEPEND_NOCHK="/tmp/.dscfgadm_pid"
101
102# SMF defines
103MANIFEST_PATH=/lib/svc/manifest/system
104
105# SMF services (enable and disable)
106SMF_ENABLE="nws_scm nws_sv nws_ii nws_rdc nws_rdcsyncd"
107SMF_DISABLE="nws_rdcsyncd nws_rdc nws_ii nws_sv nws_scm"
108
109# state of each service
110nws_scm_enabled=0
111nws_sv_enabled=0
112nws_ii_enabled=0
113nws_rdc_enabled=0
114nws_rdcsyncd_enabled=0
115
116# set path
117PATH=/usr/bin:/usr/sbin:/sbin/sh
118export PATH
119
120# set architecture
121ARCH=`uname -p`
122export ARCH
123OS_MINOR=`uname -r | cut -d '.' -f2`
124
125# number of sectors required for database
126# 1024*1024*5.5/512
127REQUIRED=11264
128
129# must set here, else seen as null in MAIN
130VALID_DB_ENTERED=0
131
132NO_ARGS=0
133
134# for debugging
135xopt=
136
137# set lengthy message here
138CLUST_LOC_MESS="The current location is invalid for a Sun StorageTek \
139Data Services configuration database.  Once a valid location is \
140entered (raw slice on \"did\" device), you may upgrade the existing \
141database to this new location - following the procedure outlined \
142in 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
151error()
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
177get_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#
203in_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#
222cluster_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#
237check_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#
274is_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#
291check_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#
316valid_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#
333valid_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#
348contains_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#
397keep_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#
440preserve_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#
492get_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#
520check_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#
568ask_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#
594ask_to_enable()
595{
596    $xopt
597
598    echo "\
599\nIf you would like to start using the Availability Suite immediately, you may
600start the SMF services now.  You may also choose to start the services later
601using 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#
620display_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#
694initialize_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#
721initialize_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#
753set_cluster_config()
754{
755
756$xopt
757
758REPEAT=0
759while [ $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
847done
848
849}
850
851########################## MAIN FUNCTIONS ############################
852
853######################## SMF HELPER FUNCTIONS ########################
854#
855# check if any SMF service is online (enabled)
856#
857check_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#
876show_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#
900is_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#
922no_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#
960rm_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#
975set_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#
1016check_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#
1064svc_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#
1172enable_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#
1231disable_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#
1308is_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#
1326import_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#
1342import_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
1368enable=0
1369disable=0
1370set_location=0
1371get_info=0
1372r_flag=0
1373p_flag=0
1374while getopts "xedsirp" opt 2>/dev/null
1375do
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
1403done
1404
1405# at most one option (besides -x) may be specified at a time
1406options_count=$((enable + disable + set_location + get_info))
1407if [ $options_count -gt 1 ]
1408then
1409	help
1410elif [ $options_count = 0 ]
1411then
1412	NO_ARGS=1
1413fi
1414
1415if (( ((r_flag + p_flag) > 0) && ((enable | disable) == 0) ))
1416then
1417	echo "-r and -p options may only be used with -d or -e options" >&2
1418	return 1
1419elif (( p_flag && disable ))
1420then
1421	echo "The -p option may not be used with the -d option" >&2
1422	return 1
1423fi
1424
1425
1426
1427# set all the system information variables
1428get_system_state
1429
1430# if we're enabling, we need to make sure we have a valid dscfg out there.
1431if [ $enable = 1 -a $VALID_LOCAL_DB != 1 ]
1432then
1433	echo "Cannot find a valid configuration database" >&2
1434	return 1
1435fi
1436
1437if [ $NO_ARGS = 1 ]
1438then
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
1505elif [ $enable = 1 ]
1506then
1507	enable_services
1508	if [ $? != 0 ]
1509	then
1510		return 1
1511	fi
1512
1513elif [ $disable = 1 ]
1514then
1515    	disable_services
1516	if [ $? != 0 ]
1517	then
1518		return 1
1519	fi
1520
1521elif [ $get_info = 1 ]
1522then
1523	display_info
1524
1525elif [ $set_location = 1 ]
1526then
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
1541fi
1542
1543return 0
1544
1545
1546########################## MAIN ######################################
1547
1548