#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos72Q src/bos/usr/lib/nim/methods/nim_master_recover.sh 1.18.1.14 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2002,2018 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)91 1.18.1.14 src/bos/usr/lib/nim/methods/nim_master_recover.sh, cmdnim, bos72Q, q2018_46A2 10/31/18 12:30:55
#
#   COMPONENT_NAME: CMDNIM
#
#   FUNCTIONS: ./usr/lib/nim/methods/nim_master_recover.sh
#
#   ORIGINS: 27
#
#
#   (C) COPYRIGHT International Business Machines Corp. 2002
#   All Rights Reserved
#   Licensed Materials - Property of IBM
#   US Government Users Restricted Rights - Use, duplication or
#   disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
#

# ------------------------ NIM defines and functions ---------------------------

NIMPATH=/usr/lpp/bos.sysmgt/nim
NIM_METHODS="${NIMPATH}/methods"
export NIMPATH NIM_METHODS
. ${NIM_METHODS}/c_sh_lib

#------------------------------ local defines ----------------------------------

C_CKSPOT=${NIM_METHODS}/c_ckspot
C_SWITCH_MSTR=${NIM_METHODS}/c_switch_master
DATE=/usr/bin/date
IFCONFIG=/usr/sbin/ifconfig
LOG=/var/adm/ras/nim.recover
LSCFG=/usr/sbin/lscfg
LSNIM=/usr/sbin/lsnim
M_CHATTR=${NIM_METHODS}/m_chattr
M_RMMAC=${NIM_METHODS}/m_rmmac
NIM=/usr/sbin/nim
NIMCONFIG=/usr/sbin/nimconfig
NIMDEF=/usr/sbin/nimdef
NIM_RESTORE=${NIM_METHODS}/m_restore_db
ODMDEL=/usr/bin/odmdelete
ODMGET=/usr/bin/odmget
TEST=/usr/bin/test
UNAME=/usr/bin/uname
EXEMPT="/tmp/._nim_fs_exempt.list"

#----------------------- module global variables ------------------------------

host_name=            # hostname of the new master
nim_name=             # NIM name of the new master in the NIM database
new_host_name=		  # future hostname if changing the master's if1 only
exit_rc=0

# The following variables are set based on the arguments passed
ATTEMPT_UNEXPORT=
DELETE_CLIENTS=
INSTALL_MSTR_FILESETS=
INTERFACE=
MSTR_FILESET_DIR=
NIMDB_FILE=
NIMDEF_FILE=
NO_CK_RESOURCES=
NO_CK_SPOT=
PRINT_MAC_INFO=
RESTORE_NIM_DB=
SWITCH_MSTR=

#--------------------------------- check_init ----------------------------------
#
#  FUNCTION:    Checks if the NIM master is configured.
#
#  PARAMETERS:  None.
#
#  RETURNS:     -1 if the NIM master is configured.
#                0 if the NIM master is not configured.
#
#-------------------------------------------------------------------------------
check_init ()
{
	ODMDIR=/etc/objrepos odmget -q "name=master" nim_object 2>/dev/null | \
	$GREP master > /dev/null
	# grep RC is NULL if needle is found.
	if [[ $? = 0 ]]
	then
		return -1
	else
		return 0
	fi
}

#-----------------------------replicate_resources---------------------------------------
#
# FUNCTION:
#  Replicates each resource on to the alternate master. If and only if the resource
#  is not already in Alternate master and the resource is served by master.
#
# PARAMETERS:  None.
#
# NOTES:
#     a) for lpp_sources, we run geninstall to see if lpp's exist in the dir
#                if it does not exist, replicate it using c_mk_lpp_source
#     b) for spots, we run c_ckspot to do a check without rebuilding boot images
#                if the spot is not present at the location specified,
#                replicate it using c_mkspot.
#     c) for files, see if it exists, it it does not exist, replicate it using
#               m_cpfile
#         d) for directories, see if it exists, if it does not exist, create it
#                using c_mkdir
#
# RETURNS:     0
#
#
#---------------------------------------------------------------------------------


function replicate_resources {

	typeset nim_resources=
	typeset mac_host_name=
	typeset resource=
	typeset location=
	typeset server=
	typeset type=
	typeset CHECK_CMD=
	typeset REP_CMD=

	# get the name of alternate master
	host_name=$( $HOSTNAME )
	alternate_master=$( /usr/bin/host $nim_name | awk '{print $1}' )

	echo "Replicating NIM resources. Please wait, takes time...." | /usr/bin/tee -a ${LOG} #MSG

	# this function calls the c_rsh method which relies on the NIM master
	# database to determine the connect type (nimsh vs. shell/rsh). Since
	# the other master isn't defined yet (it is created in c_sync, the
	# script that called this script) we'll create a temporary standalone
	# machine representing the primary master and remove it later.
	primarymaster=primarymaster$RANDOM$RANDOM
	$NIM -o define -t standalone -a connect=nimsh -a if1="find_net ${main_master} 0" -a cpuid=`${CAT} /etc/NIM.primary.cpuid` $primarymaster > /dev/null 2>&1
	[[ $? -ne 0 ]] && echo "error defining temporary alternate master standalone"|/usr/bin/tee -a ${LOG} #MSG

	#
	# Get the NIM resources
	#
	nim_resources=$( $LSNIM -c resources | $AWK '{print $1}' )
	#
	# Loop through each resource and replicate them onto the alternate master
	# if they are not already existing.
	#
	#
	
	# ensure that the server is set up to receive remote commands
	${C_RSH} ${main_master} "\"$ECHO >/dev/null\"" 2>/dev/null
	if [[ $? -ne 0 ]]
	then
		echo "error replicating resources: unable to $C_RSH ${main_master}" \
		| /usr/bin/tee -a ${LOG} #MSG
		return -1
	fi

	>${EXEMPT}
	for resource in $nim_resources
	do

		if [[ $resource != "boot" && $resource != "nim_script" ]]
		then
			$DATE
			location=$($LSNIM -l $resource | $AWK '$1 ~ /location/ {print $3}' )
			server=$($LSNIM -l $resource | $AWK '$1 ~ /server/ {print $3}' )
			type=$($LSNIM -l $resource | $AWK '$1 ~ /type/ {print $3}' )
	        	sync_stat=$($LSNIM -l $resource | $AWK '$1 ~ /sync_required/ {print $3}' )

			if [[ $server = "master" ]] && [[ $sync_stat != "no" ]]
			then

				if [[ -f "${EXEMPT}" ]]; then
					skip=no
					for entry in `${CAT} ${EXEMPT}`
					do
						if [[ "${location#*$entry}" != "$location" ]]; then
							echo "Skipping resource replication of $resource (fs exempt)"
							skip=yes
						fi
					done
					[[ "$skip" = "yes" ]] && continue
				fi

				if [[ $type = "lpp_source" ]]
				then
					REP_CMD="${NIM_METHODS}/c_mk_lpp_source -a location=$location \
						-a packages=all -a source=${main_master}:${location}"
						
					CHECK_CMD="$GENINSTALL -L -d $location"

				elif [[ $type = "spot" ]]
				then

					# use the c_ckspot method to see if spot exists
					CHECK_CMD="$C_CKSPOT -a name=$resource -a location=$location \
						-a st_applied=3 -a st_committed=5 -a no_mkbooti=yes \
						-a if_remove=no"

					# remove usr and spot name from the spot location path.
					# e.g., location=/export/spot/spot_test/usr
					# after removing spot name and usr, the new location
					# becomes location=/export/spot
				
					usr_removed=${location%/*}
					loc_name=${usr_removed%/*}

					REP_CMD="${NIM_METHODS}/c_mkspot -a location=$loc_name \
						-a source=${main_master}:${location} \
						-a name=$resource -a st_applied=3 -a st_committed=5 \
						-a auto_expand=yes  -a type=spot -a nim_sync=yes -f"

				elif [[ $type = "file_res" ]]
				then
					# check if the source dir exists
					CHECK_CMD="$FIND $location"

					REP_CMD="${NIM_METHODS}/c_file_transfer \
						-a location=${main_master}:${location} \
						-a dest_dir=$location"

				else

					pp=$( ${C_RSH} ${main_master} "\"$TEST -d $location && echo directory\"" )
					if [[ $? -eq 0 ]]
					then
						if [[ $pp = "directory" ]]
						then
							CHECK_CMD="$FIND $location"
							REP_CMD="${C_MKDIR} -a location=${location}"

						else
							CHECK_CMD="$FIND $location"
							REP_CMD="${NIM_METHODS}/m_cpfile \
								-a source=${main_master}:${location} \
								-a location=${location}"
						fi
					fi # if [[ $? -eq 0 ]]
				fi # if [[ $type = "lpp_source" ]]

				# check that the resource exists on alternate master
				$CHECK_CMD >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then

					echo "Replicating resource $resource" | /usr/bin/tee -a ${LOG} #MSG

					NFS_CMD="${NIM_METHODS}/c_ch_nfsexp -a location=${location} \
						-a grant=${alternate_master} -a nfs_perms=ro"
					${C_RSH} ${main_master} "\"$NFS_CMD >/dev/null\"" 2>/dev/null
					if [[ $? -ne 0 ]]; then
						echo "failed exporting $location on $main_master: error in $C_CH_NFSEXP" \
								| /usr/bin/tee -a ${LOG} #MSG 
						${C_RSH} ${main_master} "\"$M_CHATTR -a sync_required=yes $resource \""
						continue
					fi

					$REP_CMD 2>&1
					if [[ $? -ne 0 ]]; then
						echo "Replication failed on resource $resource" | /usr/bin/tee -a ${LOG} #MSG
						# change sync_required to yes 
						$M_CHATTR -a sync_required=yes $resource	
						${C_RSH} ${main_master} "\"$M_CHATTR -a sync_required=yes $resource \""
						exit_rc=1

					else
						echo "Replicated resource $resource" | /usr/bin/tee -a ${LOG} #MSG
						# change sync_required back to no
				        	$M_CHATTR -a sync_required=no $resource	 
						# reset the boot support for replicated spots
						[[ $type = "spot" ]] && $M_CHATTR -a if_supported= $resource
					fi

					NFS_CMD="${NIM_METHODS}/c_ch_nfsexp -a location=${location} \
						-a revoke=${alternate_master} -a nfs_perms=ro"
					${C_RSH} ${main_master} "\"$NFS_CMD >/dev/null\"" 2>/dev/null
					if [[ $? -ne 0 ]]; then
						echo "failed unexporting $location, on $main_master: error in $C_CH_NFSEXP" \
								| /usr/bin/tee -a ${LOG} #MSG
					fi
				else
					echo "  Resource $resource already exists on alternate_master" | /usr/bin/tee -a ${LOG} #MSG
					# change sync_required back to no
				        $M_CHATTR -a sync_required=no $resource	 
				fi

			fi #if [[ $server = "master" ]]
		else
			# change sync_required back to no
			$M_CHATTR -a sync_required=no $resource	 
		fi # ! boot or nim_script
	done

	# remove the temporary primary master standalone object, -o preserves
	# the /etc/niminfo file on the machine.
	$M_RMMAC -o $primarymaster > /dev/null 2>&1

	echo "Finished Replicating NIM resources" | /usr/bin/tee -a ${LOG} #MSG
	return 0
}

#------------------------------- check_resources -------------------------------
# 
# FUNCTION:
#   Checks that each resource in the NIM database exists, otherwise deletes it
#
# PARAMETERS:  None.
#
# NOTES:
#     a) for lpp_sources, we run geninstall to see if lpp's exist in the dir
#     b) for spots, we run c_ckspot to do a check without rebuilding boot images
#     c) for other resources, except boot and nim_script, see if the file exists
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function check_resources {

	typeset nim_resources=
	typeset mac_host_name=
	typeset resource=
	typeset location=
	typeset server=
	typeset type=
	typeset CHECK_CMD=

	echo "Checking NIM resources" | /usr/bin/tee -a ${LOG} #MSG

	#
	# Get the NIM resources
	#
	nim_resources=$( $LSNIM -c resources | $AWK '{print $1}' )

	#
	# Loop through each resource and remove all resources that don't exist
	#
	for resource in $nim_resources
	do

		if [[ $resource != "boot" && $resource != "nim_script" ]]
		then
			location=$($LSNIM -l $resource | $AWK '$1 ~ /location/ {print $3}' )
			server=$($LSNIM -l $resource | $AWK '$1 ~ /server/ {print $3}' )
			type=$($LSNIM -l $resource | $AWK '$1 ~ /type/ {print $3}' )
	        	sync_stat=$($LSNIM -l $resource | $AWK '$1 ~ /sync_required/ {print $3}' )

			# Determine the command to check the resource
			if [[ $type = "lpp_source" ]]
			then
				# use geninstall to see if packages exist in lpp_source
				CHECK_CMD="$GENINSTALL -L -d $location"
			elif [[ $type = "spot" ]]
			then
				# use the c_ckspot method to see if spot exists
				CHECK_CMD="$C_CKSPOT -aname=$resource -alocation=$location \
					-ast_applied=3 -ast_committed=5 -ano_mkbooti=yes \
					-aif_remove=no"
			else
				# Other resources are files; see if the file exists
				CHECK_CMD="$FIND $location"
			fi
				

			if [[ $server = "master" ]] && [[ $sync_stat != "no" ]]
			then

				# check that the resource exists on the master
				$CHECK_CMD >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
					remove_resource $resource
				else
					echo "  Keeping $resource" | /usr/bin/tee -a ${LOG} #MSG
				fi

			elif [[ $server != "master" ]] && [[ -z $ONLY_CK_MSTR_RES ]]
			then
				# use C_RSH to check for resource on server

				# get the host_name of the server
				mac_host_name=$($LSNIM -l $server |$AWK '$1 ~ /if1/ {print $4}')

				# ensure that the server is set up to receive rsh commands
				${C_RSH} ${mac_host_name} "\"$ECHO >/dev/null\"" 2>/dev/null
				if [[ $? -ne 0 ]]
				then
					echo "  error $resource: unable to C_RSH ${mac_host_name}" \
					| /usr/bin/tee -a ${LOG} #MSG

					remove_resource $resource
				else
					# check the resource remotely
					rc=$(${C_RSH} ${mac_host_name} "\"$CHECK_CMD >/dev/null 2>&1 && print 0 || print 1\"" )

					if [[ $rc -ne 0 ]]; then
						remove_resource $resource
					else
						echo "  Keeping $resource" | /usr/bin/tee -a ${LOG} #MSG
					fi
				fi
			fi # server = master
		fi # ! boot or nim_script
	done

	echo "Finished checking NIM resources" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#--------------------------------- check_spots ---------------------------------
# 
# FUNCTION:  Runs a check on each SPOT to ensure the boot images get built
#
# PARAMETERS:  None.
#
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function check_spots {

	typeset nim_spots=

	echo "Checking NIM SPOTs" | /usr/bin/tee -a ${LOG} #MSG

	#
	# Get the NIM SPOTs
	#
	nim_spots=$( $LSNIM -t spot | $AWK '{print $1}' )

	#
	# Check each SPOT
	#
	for spot in $nim_spots
	do
		echo "  checking $spot" | /usr/bin/tee -a ${LOG} #MSG
		$NIM -Fo check $spot 2>&1 | /usr/bin/tee -a ${LOG} 
	done

	echo "Finished checking SPOTs" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#---------------------------- new_mstr_from_client -----------------------------
# 
# FUNCTION:    Updates the master's information from its client definition
#
# PARAMETERS:  None.
#
# NOTES:
#     1) determine the client definition corresponding to the new master
#     2) replace the old master's attributes with the new master's attributes
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function new_mstr_from_client {

	typeset platform=
	typeset netboot=
	typeset ring_speed=
	typeset cable_type=
	typeset if1=
	typeset mstr_ifs=
	typeset mstr_cts=
	typeset mstr_rss=
	typeset ct=
	typeset rs=

	echo "Updating master definition in database from $nim_name definition" \
		| /usr/bin/tee -a ${LOG} #MSG

	#
	# Get the platform and netboot_kernel; then update master's attributes
	#
	platform=`$BOOTINFO -p`
	netboot="64"

	$NIM -o change -a platform="${platform}" master
	echo "  Updated master attribute platform to ${platform}" \
		| /usr/bin/tee -a ${LOG} #MSG

	$NIM -o change -a netboot_kernel="${netboot}" master
	echo "  Updated master attribute netboot_kernel to ${netboot}" \
		| /usr/bin/tee -a ${LOG} #MSG

	# Update the NIM master's CPUID
	$M_CHATTR -acpuid="`$UNAME -m`" master
	#
	# Remove all interfaces besides if1 of the old master
	# Set the corresponding variable if cable_type1 or ring_speed1 is set
	# This information will be used when updating the net attributes
	#
	mstr_ifs=$( $LSNIM -l master | $AWK '$1 ~ /if[0-9]+/ { print $1 }' )
	for i in $mstr_ifs
	do
		[[ $i != "if1" ]] && $M_CHATTR -a$i= master
	done

	mstr_cts=$( $LSNIM -l master | $AWK '$1 ~ /cable_type[0-9]+/ { print $1 }' )
	for j in $mstr_cts
	do
		if [[ $j = "cable_type1" ]]; then
			ct=1
		else
			$M_CHATTR -a$j= master
		fi
	done

	mstr_rss=$( $LSNIM -l master | $AWK '$1 ~ /ring_speed[0-9]+/ { print $1 }' )
	for k in $mstr_rss
	do
		if [[ $k = "ring_speed1" ]]; then
			rs=1
		else
			$M_CHATTR -a$k= master
		fi
	done

	#
	# Get the network attributes of the new master from its client definition
	#
	if1=$( $LSNIM -l $nim_name | $AWK '$1 ~ /if1/ {print $0}' )
	ring_speed1=$( $LSNIM -l $nim_name | $AWK '$1 ~ /ring_speed1/ {print $0}' )
	cable_type1=$( $LSNIM -l $nim_name | $AWK '$1 ~ /cable_type1/ {print $0}' )

	#
	# Replace the old master's net attributes with the new master's attributes
	# If the old master had a different primary interface type, then remove
	# the old master's cable_type or ring_speed
	#
	$M_CHATTR -a if1="${if1##*= }" master
	echo "  Updated master attribute if1 to ${if1##*= }" \
		| /usr/bin/tee -a ${LOG} #MSG

	if [[ -n $ring_speed1 ]]; then
		$M_CHATTR -a ring_speed1="${ring_speed1##*= }" ${ct:+"-acable_type1="} master
		echo "  Updated master attribute ring_speed1 to ${ring_speed1##*= }" \
			| /usr/bin/tee -a ${LOG} #MSG
	fi

	if [[ -n $cable_type1 ]]; then
		$M_CHATTR -a cable_type1="${cable_type1##*= }" ${rs:+"-aring_speed1="} master
		echo "  Updated master attribute cable_type1 to ${cable_type1##*= }" \
			| /usr/bin/tee -a ${LOG} #MSG
	fi

	echo "Finished updating master definition" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#---------------------------- new_mstr_define -------------------------------
# 
# FUNCTION:    Define the new NIM master on the corresponding interface
#
# PARAMETERS:  None.
#
# RETURNS:     0 - SUCCESS
#              1 - FAILURE
#
#-------------------------------------------------------------------------------
function new_mstr_define {

	typeset platform=
	typeset netboot=
	typeset ring_speed=
	typeset cable_type=
	typeset newmstr_net=
	typeset net_type=
	typeset if1=
	typeset if2=
	typeset if_op2=
	typeset ip_addr=
	typeset submask=
	typeset gateway=
	typeset mstr_ifs=
	typeset mstr_cts=
	typeset mstr_rss=
	typeset ct=
	typeset rs=
	typeset tmp_var=
	typeset mac_addr=
	typeset mstr_hn=

	echo "Updating master definition" | /usr/bin/tee -a ${LOG} #MSG

	#
	# Get the platform and netboot_kernel; then update master's attributes
	#
	platform=`$BOOTINFO -p`
	netboot="64"

	$NIM -o change -a platform="${platform}" master
	echo "  Updated master attribute platform to ${platform}" \
		| /usr/bin/tee -a ${LOG} #MSG

	$NIM -o change -a netboot_kernel="${netboot}" master
	echo "  Updated master attribute netboot_kernel to ${netboot}" \
		| /usr/bin/tee -a ${LOG} #MSG

	#
	# Get the net type and interface specific parameters
	#
	if [[ ${INTERFACE} = tr* ]]; then
		ring_speed=`$MKTCPIP -S ${INTERFACE} 2>&1 | \
			$AWK 'BEGIN { RS="\n"; FS=":" } \
			{ for (i=1;i<=NF;i++) \
			{ if ( match($i,/speed/) ) (j=i) } \
			if (NR==2) {print $j} }'`
		net_type="tok"

	elif [[ ${INTERFACE} = e[nt]* ]]; then
		cable_type=`$MKTCPIP -S ${INTERFACE} 2>&1 | \
			$AWK 'BEGIN { RS="\n"; FS=":" } \
			{ for (i=1;i<=NF;i++) \
			{ if ( match($i,/type/) ) (j=i) } \
			if (NR==2) {print $j} }'`
		net_type="ent"

	elif [[ ${INTERFACE} = at* ]]; then
		net_type="atm"
	elif [[ ${INTERFACE} = fi* ]]; then
		net_type="fddi"
	else
		echo "error determining network type.  Exiting" | /usr/bin/tee -a ${LOG}
		exit 1 #MSG
	fi

	#
	# Get the ip address, subnet mask, and gateway
	#
	ip_addr=$($MKTCPIP -S $INTERFACE  2>&1 | $AWK -F":" '{ if (NR == 2) {print $2} }')
	submask=$($MKTCPIP -S $INTERFACE  2>&1 | $AWK -F":" '{ if (NR == 2) {print $3} }')
	gateway=$($MKTCPIP -S $INTERFACE  2>&1 | $AWK -F":" '{ if (NR == 2) {print $7} }')

	#
	# Get the MAC Address of the adapter
	#
	tmp_var=$( $LSCFG -vl ${net_type}${INTERFACE##*([a-zA-Z])} | \
		$GREP "Network Address" )  
	if [[ -n ${tmp_var##*Network Address*(.)} ]]; then
	    mac_addr=${tmp_var##*Network Address*(.)}
	else
		echo "  can't determine MAC addr" | /usr/bin/tee -a ${LOG} #MSG
		mac_addr=0
	fi

	#
	# Remove all interfaces besides if1
	#
	mstr_ifs=$( $LSNIM -l master | $AWK '$1 ~ /if[0-9]+/ { print $1 }' )
	for i in $mstr_ifs
	do
		[[ $i != "if1" ]] && $M_CHATTR -a$i= master
	done

	mstr_cts=$( $LSNIM -l master | $AWK '$1 ~ /cable_type[0-9]+/ { print $1 }' )
	for j in $mstr_cts
	do
		[[ $j != "cable_type1" ]] && $M_CHATTR -a$j= master
	done

	mstr_rss=$( $LSNIM -l master | $AWK '$1 ~ /ring_speed[0-9]+/ { print $1 }' )
	for k in $mstr_rss
	do
		[[ $k != "ring_speed1" ]] && $M_CHATTR -a$k= master
	done

	#
	# Define the new master's network as if2 and then switch it with if1.
	# do this because find_net doesn't work for if1
	#
	if [[ -n $ring_speed ]]; then
		if_op2="-a ring_speed2=$ring_speed"
	elif [[ -n $cable_type ]]; then
		if_op2="-a cable_type2=$cable_type"
	fi

	$NIM -o change -a if2="find_net $host_name 0" $if_op2 \
		-a net_definition="$net_type $submask" master 2>&1 \
		| /usr/bin/tee -a ${LOG}
	
	if2=$( $LSNIM -l master | $AWK '$1 ~ /if2/ {print $0}' )

	newmstr_net=$( echo "$if2" | $AWK '{print $3}' )
	mstr_hn=$( echo "$if2" | $AWK '{print $4}' )

	$M_CHATTR -a if1="${newmstr_net} ${mstr_hn} ${mac_addr}" master
	echo "  Updated master attribute if1 to ${newmstr_net} ${mstr_hn} ${mac_addr}" \
		| /usr/bin/tee -a ${LOG} #MSG

	$M_CHATTR -a if2=  master
	[[ -n $if_op2 ]] && $M_CHATTR ${if_op2%%=*}=  master


	if [[ -n $ring_speed ]]; then
		ct=$( $LSNIM -l master | $AWK '$1 ~ /cable_type1/ { print 1 }' )
		$M_CHATTR -a ring_speed1="${ring_speed}" ${ct:+"-acable_type1="} master
		echo "  Updated master attribute ring_speed1 to ${ring_speed}" \
			| /usr/bin/tee -a ${LOG}  #MSG
	fi

	if [[ -n $cable_type ]]; then
		rs=$( $LSNIM -l master | $AWK '$1 ~ /ring_speed1/ { print 1 }' )
		$M_CHATTR -a cable_type1="${cable_type}" ${rs:+"-aring_speed1="} master
		echo "  Updated master attribute cable_type1 to ${cable_type}" \
			| /usr/bin/tee -a ${LOG} #MSG
	fi

	#
	# Make sure the default route is correct; ignore output since the network
	# may have already been defined and one of its clients is performing an op
	#
	$NIM -o change -a routing1="default $gateway" $newmstr_net 2>&1 \
		| /usr/bin/tee -a ${LOG}
		echo "  Updated $newmstr_net routing1 to default $gateway" \
			| /usr/bin/tee -a ${LOG} #MSG

	echo "Finished updating master definition" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#---------------------------- remove_client_res --------------------------------
# 
# FUNCTION:    Removes all the NIM resources located on servers
#
# PARAMETERS:  None.
#
# NOTES:
#     1) this function must be executed before clients are removed
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function remove_client_res {

	typeset nim_resources=

	echo "Removing NIM resources on servers" | /usr/bin/tee -a ${LOG} #MSG

	#
	# Get the NIM resources
	#
	nim_resources=$( $LSNIM -c resources | $AWK '{print $1}' )

	#
	# Remove all resources that aren't located on the master
	#
	for resource in $nim_resources
	do
		# reset the alloc_count of the resource to 0
		$M_CHATTR -a alloc_count=0 $resource

		server=$($LSNIM -l $resource | $AWK '$1 ~ /server/ {print $3}' )

		if [[ $server != "master" ]]
		then
		    remove_resource $resource
		fi
	done

	echo "Finished removing resources" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#------------------------------- remove_client --------------------------------
# 
# FUNCTION:    Removes a NIM client from the NIM database
#
# PARAMETERS:  None.
#
# NOTES:
#     1) this function removes the client's resources, therefore the 
#        reset_machines function should have been executed so that no
#        machines will have resources allocated to them that will be removed
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function remove_client {

	typeset client=$1
	typeset resources=
	typeset resource=

	echo "Removing NIM client $client" | /usr/bin/tee -a ${LOG} #MSG

	# first remove any resources that it serves
	resources=$( $LSNIM -l $client | $AWK '$1 ~ /serves/ { print $3 }' )
	for resource in $resources
	do
		# reset the alloc_count of the resource to 0
		$M_CHATTR -a alloc_count=0 $resource

		remove_resource $resource
	done

	$M_RMMAC -o $client >/dev/null 2>&1

	echo "Finished removing $client" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#------------------------------- remove_clients --------------------------------
# 
# FUNCTION:    Removes all the NIM clients from the NIM database
#
# PARAMETERS:  None.
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function remove_clients {

	typeset nim_machines=

	echo "Removing NIM clients" | /usr/bin/tee -a ${LOG} #MSG

	#
	#  Get all the machines in the NIM environment
	# 
	nim_machines=$( $LSNIM -c machines | $AWK '$1 !~ /^master$/ {print $1}')

	#
	# Call the m_rmmac method with "-o" so that nim doesn't attempt
	# to remove the niminfo file
	#
	for mac in $nim_machines
	do
		# if Mstate isn't running, we should ignore ERR_RM_NIMINFO
		$M_RMMAC -o $mac >/dev/null 2>&1
		echo "  Removed $mac" | /usr/bin/tee -a ${LOG} #MSG
	done

	echo "Finished removing NIM clients" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#------------------------------- remove_networks -------------------------------
# 
# FUNCTION:    Removes all networks from the NIM database except the master's
#
# PARAMETERS:  None.
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function remove_networks {

	typeset master_net=
	typeset net_type=
	typeset nim_net=

	echo "Removing NIM networks except master's network" |/usr/bin/tee -a ${LOG} #MSG

	#
	# Get the NIM name of the new master's network
	#
	master_net=$( $LSNIM -a if1 master | $AWK '/if1/ {print $3}')

	#
	# Remove all the NIM networks; except the master's network
	#
	for net_type in tok ent atm fddi generic
	do
		for nim_net in $(lsnim -t $net_type | $AWK '{print $1}')
		do
			if [[ $master_net != $nim_net ]]
			then
				$NIM -o remove $nim_net 2>&1 | /usr/bin/tee -a ${LOG}
				echo "  Removed $nim_net" | /usr/bin/tee -a ${LOG} #MSG
			fi
		done
	done

	echo "Finished removing NIM networks" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#------------------------------- remove_resource -------------------------------
# 
# FUNCTION:    Removes a resource from the NIM database by calling odmdelete
#
# NOTES:
#     1) This function assumes that reset_machines has been run to
#        deallocate all the resources from the clients
#     1) The resources will be removed from the nim database but no files
#        will be deleted
#
# PARAMETERS:  None.
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function remove_resource {

	typeset res=$1
	typeset res_id=
	typeset server=
	typeset serv_id=

	echo "  Removing $res" |/usr/bin/tee -a ${LOG} #MSG
	
	export ODMDIR=/etc/objrepos

	#
	# First, remove any ATTR_SERVES attributes
	#
	server=$( $LSNIM -a server $res | $AWK '$1 ~ /server/ {print $3}' )
	if [[ -z $server ]]; then
		echo "    error determining server, no removal" | /usr/bin/tee -a ${LOG} #MSG
		return 1
	fi

	serv_id=$($ODMGET -q"name=$server" nim_object |$AWK '$1 ~ /id/ {print $3}')
	if [[ -z $serv_id ]]; then
		echo "    error getting $server id, no removal" | /usr/bin/tee -a ${LOG} #MSG
		return 1
	fi

	rc=$($ODMDEL -q"pdattr=96 and id=$serv_id and value=$res" -o nim_attr 2>&1)
	[[ $? != 0 ]] && \
		echo "    error ATTR_SERVES not removed" | /usr/bin/tee -a ${LOG} || \
		echo "    $rc from nim_attr (serves attr)" | /usr/bin/tee -a ${LOG} #MSG

	#
	# Second, remove the resource from any groups
	#
	rc=$( $ODMDEL -q"pdattr=411 and value=$res" -o nim_attr )
	[[ $? != 0 ]] && \
		echo "    error removing attributes" | /usr/bin/tee -a ${LOG} || \
		echo "    $rc from nim_attr (group memberships)" | /usr/bin/tee -a ${LOG} #MSG

	#
	# Third, remove the resource attributes and object
	#
	res_id=$( $ODMGET -q"name=$res" nim_object | $AWK '$1 ~ /id/ {print $3}' )
	if [[ -z $res_id ]]; then
		echo "    error determining $res id, no removal" |/usr/bin/tee -a ${LOG} #MSG
		return 1
	fi

	rc=$( $ODMDEL -q"id=$res_id" -o nim_attr )
	[[ $? != 0 ]] && \
		echo "    error removing attributes" | /usr/bin/tee -a ${LOG} || \
		echo "    $rc from nim_attr (resource attributes)" | /usr/bin/tee -a ${LOG} #MSG

	rc=$( $ODMDEL -q"id=$res_id" -o nim_object )
	[[ $? != 0 ]] && \
		echo "    error removing $res object" | /usr/bin/tee -a ${LOG} || \
		echo "    $rc from nim_object (resource object)" | /usr/bin/tee -a ${LOG} #MSG

	echo "  Finished removing $res" | /usr/bin/tee -a ${LOG}

	return 0
}


#------------------------------- reset_machines --------------------------------
# 
# FUNCTION:    Resets all machines and deallocates all resources
#
# PARAMETERS:  None.
#
# NOTES:
#     This method manipulates the NIM ODM in the following ways
#     a) Resets each client.  If the reset fails we remove the attributes for
#        the boot and nim_script resources, without trying to unexport the
#        resources, and re-execute the reset command.
#     b) Deallocate all resources from each client and the master.  If the 
#        deallocation fails, the resource attributes are removed without
#        attempting to unexport the resources.
#     c) This method will not change the alloc_count of resources since the
#        alloc_count will be set to 0 in the reset_resources function
#     IMPORTANT NOTE: This function will only attempt to unexport resources
#     if the -u flag was passed.  
#     The reason we don't attempt to unexport resources is because 
#     we don't want to interfere with any operations that may complete
#     successfully even though the original master failed.  This means that
#     resources may still remain exported on servers and files created to 
#     support installs may remain.  These files include:
#     /export/nim/scripts/<client>.script, /tftpboot/<client_hostname>,
#     /tftpboot/<client_hostname>.info
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function reset_machines {

	typeset nim_machines=

	echo "Resetting machines" | /usr/bin/tee -a ${LOG} #MSG

	#
	#  Get all the machines in the NIM environment
	# 
	nim_machines=$( $LSNIM -c machines | $AWK '{print $1}')

	#
	# Reset the client and deallocate allocated resources
	#
	for mac in $nim_machines
	do
		if [[ -n $ATTEMPT_UNEXPORT ]]; then
			if [[ $mac != "master" ]]; then
				$NIM -Fo reset $mac >/dev/null 2>&1

				# if the reset failed, it may be due to the boot and nim_script
				# resources.  Attempt to remove the attributes and retry the reset
				if [[ $? -ne 0 ]]; then
					$M_CHATTR -a boot= $mac >/dev/null 2>&1
					$M_CHATTR -a nim_script= $mac >/dev/null 2>&1
					$NIM -Fo reset $mac 2>&1 | /usr/bin/tee -a ${LOG}
				fi
			fi
		
			# deallocate may complain about rcmd or exportfs, so send output to
			# null. We want to make sure the nimdb is updated
			$NIM -Fo deallocate -a subclass=all $mac >/dev/null 2>&1

			# if the dealloc fails, then remove the resource attributes without
			# attempting to unexport them.
			if [[ $? -ne 0 ]]; then
				for attr in $( $LSNIM -l $mac | $AWK '{print $1}')
				do
					if $LSNIM -t $attr >/dev/null 2>&1
					then
						$M_CHATTR -a ${attr}= $mac
					fi
				done
			fi
		else
			if [[ $mac != "master" ]]; then

				# Remove the boot and nim_script resources without trying to
				# unexport them.  Also get rid of at jobs.
				$M_CHATTR -a boot= $mac >/dev/null 2>&1
				$M_CHATTR -a nim_script= $mac >/dev/null 2>&1
				$M_CHATTR -a at_job= $mac >/dev/null 2>&1
				$NIM -Fo reset $mac 2>&1 | /usr/bin/tee -a ${LOG}
			fi

			# Remove the resource attributes without attempting to unexport them
			for attr in $( $LSNIM -l $mac | $AWK '{print $1}')
			do
				if $LSNIM -t $attr >/dev/null 2>&1
				then
					$M_CHATTR -a ${attr}= $mac
				fi
			done
		fi # ATTEMPT_UNEXPORT

		echo "  Reset $mac" | /usr/bin/tee -a ${LOG} #MSG
	done

	echo "Finished resetting machines" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}


#------------------------------- reset_resources -------------------------------
# 
# FUNCTION:    Sets alloc_count to 0 and Rstate to available
#
# PARAMETERS:  None.
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function reset_resources {

	typeset nim_resources=
	typeset resource=

	echo "Resetting NIM resources" | /usr/bin/tee -a ${LOG} #MSG

	#
	# Get the NIM resources
	#
	nim_resources=$( $LSNIM -c resources | $AWK '{print $1}' )

	#
	# Reset the resources
	#
	for resource in $nim_resources
	do
		# reset the alloc_count of the resource to 0
		$M_CHATTR -a alloc_count=0 $resource
		$M_CHATTR -a Rstate=available $resource

	done

	echo "Finished resetting NIM resources" | /usr/bin/tee -a ${LOG} #MSG
}


#---------------------------- switch_clients_mstr ------------------------------
# 
# FUNCTION:    Switches the NIM master on all clients
#
# PARAMETERS:  None.
#
# NOTES:
#     1) Requires that the new master has rhost permissions on all clients
#     2) Makes an rsh call to c_switch_master on the client
#
# RETURNS:     0 
#
#-------------------------------------------------------------------------------
function switch_clients_mstr {

	typeset nim_machines=
	typeset mac_host_name=
	typeset mac=

	echo "Switching master on NIM clients" | /usr/bin/tee -a ${LOG} #MSG

	#
	#  Get all the machines in the NIM environment
	# 
	nim_machines=$( $LSNIM -c machines | $AWK '$1 !~ /^master$/ {print $1}')

	#
	# Determine the hostname of the client and use C_RSH to 
	# call c_switch_master on the client
	#
	for mac in $nim_machines
	do
		# get the host_name of the client
		mac_host_name=$( $LSNIM -l $mac | $AWK '$1 ~ /if1/ {print $4}' )

		# ensure that the client is set up to receive rsh commands
		${C_RSH} ${mac_host_name} "\"$ECHO >/dev/null\"" 2>/dev/null #MSG
		if [[ $? -ne 0 ]]
		then
			echo "  error: unable to C_RSH ${mac_host_name}" \
				| /usr/bin/tee -a ${LOG} #MSG
		else
				rc=$( ${C_RSH} ${mac_host_name} "\"${C_SWITCH_MSTR} -f ${new_host_name:+"-n"} -a \
				new_master=${new_host_name:-$host_name} -a originator=${host_name} \
				>/dev/null 2>&1 && print 0 || print 1\"" )

			if [[ $rc -ne 0 ]]; then
				echo "  error: c_switch_master failed on ${mac_host_name}" \
					| /usr/bin/tee -a ${LOG} #MSG
			else
				echo "  changed master for ${mac_host_name}" \
					| /usr/bin/tee -a ${LOG} #MSG
			fi
		fi
	done

	echo "Finished switching master on NIM clients" | /usr/bin/tee -a ${LOG} #MSG

	return 0
}

#
#FUNCTION: chg_mstr_if1
#
#PARAMETERS: $1="NET_OBJ [new_host_name] [CABLE_TYPE]"
#
# changes the primary network interface of the master
#
function chg_mstr_if1
{
	NET_ATTR=$1 #"net_object hostname mac_addr"
	NET_OBJ=$(echo $NET_ATTR | $AWK '{print $1}')
	new_host_name=$(echo $NET_ATTR | $AWK '{print $2}')
	CABLE_TYPE=$(echo $NET_ATTR | $AWK '{print $3}')
	NET_LIST=$($LSNIM -c networks | $AWK '{print $1}')
	MSTR_NET=$($LSNIM -a if1 master | $SED 1d | $AWK '{print $3}')
	MSTR_HOSTNAME=$($LSNIM -a if1 master | $SED 1d | $AWK '{print $4}')
	MSTR_MAC=$($LSNIM -a if1 master | $SED 1d | $AWK '{print $5}')
	ROUTING=$($LSNIM -a routing | $AWK '$1 !~ /.*:$/ {print}')

	[[ -z $new_host_name ]] && new_host_name=$MSTR_HOSTNAME

	[[ -z $NET_OBJ || -z $new_host_name ]] &&  echo "error"

	#make sure that NET_OBJ exists, if not then error out
	if echo $NET_LIST | $GREP $NET_OBJ 2>&1 > /dev/null
	then 
		:
	else
		echo "ERROR: The NIM network $NET_OBJ was not found." #MSG
		exit 1
	fi
	
	#loop through all networks- if there's a network that has a static route to NET_OBJ, display a warning 
	echo $ROUTING | $GREP $MSTR_NET >/dev/null && echo "warning: Static routes to the master's old network exist and must be changed manually."

	ARGS="$NET_OBJ $new_host_name $MSTR_MAC"

	$M_CHATTR -a if1="$ARGS" master

	#set cable type
	[[ -n $CABLE_TYPE ]] && nim -o change cable_type1=$CABLE_TYPE master
}

#
# FUNCTION: mk_nim_net
#
# PARAMETERS: net_name net_type net_addr snm [gw]
#
# This function creates a new NIM network to later serve as the master's 
#
function mk_nim_net # net_name net_type net_addr snm [gw]
{
	NET_DEFINITION=$1
	NET_NAME=$(echo $NET_DEFINITION | $AWK '{print $1}')
	NET_TYPE=$(echo $NET_DEFINITION | $AWK '{print $2}')
	NET_ADDR=$(echo $NET_DEFINITION | $AWK '{print $3}')
	SNM=$(echo $NET_DEFINITION | $AWK '{print $4}')
	GATEWAY=$(echo $NET_DEFINITION | $AWK '{print $5}')

	if [[ -z $NET_NAME || -z $NET_TYPE || -z $NET_ADDR || -z $SNM || -z $GATEWAY ]] #MSG
	then
		echo "error: an incomplete network definition was provided."
		exit 88
	fi

	if $NIM -o define -t $NET_TYPE -a net_addr=$NET_ADDR -a snm=$SNM -a routing1="default ${GATEWAY}" $NET_NAME
	then
		:
	else
		echo "error: The network $NET_NAME could not be defined."
		exit 99
	fi
}

# -------------------------- nim_master_recover -------------------------------
#
# NAME: nim_master_recover
#
# FUNCTION:	 Used to recover a NIM master
#
# NOTES:
#
#   The following outline gives an overview of the script:
#     1) Installs the NIM master fileset if the "-f" flag is passed with a
#        directory that contains the master fileset.  This fileset can be
#        found in a default lpp_source.
#     2) Restores the NIM database from a backup file if the "-r" flag is
#        passed with the full path to the backup file.  This is a tar file
#        that contains the NIM ODM files and the master's niminfo file.  The
#        file can be created through 'smit nim_backup_db'.
#        a) If the master is configured, it will be unconfigured.
#     3) If the "-p" flag is passed, the current state of all machines will be
#        printed.  This way you will be able to determine if a machine was in
#        the middle of an operation when the database was backed up.
#     4) Gets the hostname of this machine
#     5) If an interface is specified (-i), the script will define the NIM
#        master on this interface.
#        a) Otherwise the script will define the new master based on its client
#           definition in the NIM database being restored.
#        b) ASSUMES the client name in the restored NIM database is the same
#           as its hostname.
#     6) Rebuilds the /etc/niminfo file so that it will contain the correct
#        hostname of the master.
#     7) Resets all of the clients in the NIM database
#        a) If the -u flag is passed, then the script will attempt to 
#           unexport allocated resources and remove any boot files. Otherwise,
#           this script deallocates the resources without trying to unexport
#           the resources or remove any files.  This way if any operations are
#           still able to complete without the master, the operations won't 
#           fail.
#     8) If the -D flag is passed all the resources not located on the master,
#        all clients, and all networks except the master's network will be
#        removed from the NIM environment.
#     9) If a nimdef file is passed with the -n flag, the nimdef command will
#        define the NIM environment from the nimdef file.
#    10) If the master has a client definition left over, it will be removed.
#        The script assumes the client definition is the same as the master's
#        hostname.
#    11) If the "-s" flag is passed, this script will run an rsh command on 
#        each client to switch it's NIM master
#        a) ASSUMES the new master has rhost permissions to the clients
#        b) clients must have bos.sysmgt.nim.client 5.1.0.10 or higher installed
#        c) You can view the log to see which clients were successfully updated
#    12) Next, the script checks all the resources defined in the NIM
#        database to see if they exist.  If a resource doesn't exist, it will
#        be removed.  The -R flag prevents the resources from being checked.
#    13) Finally, the script runs a force check on every SPOT that exists.
#        This ensures that all the required boot images get built.  If you are
#        sure all the SPOTs have the required support, the -S flag will prevent
#        the checks from occurring.
#    14) NOTE: All stdout is also logged in location /var/adm/ras/nim.recover
#
# RETURNS: (int)
#	0	= SUCCESS
#	1	= FAILURE
#
# -----------------------------------------------------------------------------

# set parameters from command line
while getopts :Df:i:n:pr:sRSuvN:t:md c
do
	case ${c} in

        D)		# Deletes all NIM clients, networks, and resources located on
			# clients.
			DELETE_CLIENTS="yes"
			;;
				
        f)		# install Filesets bos.sysmgt.nim.master and bos.sysmgt.nim.spot
			# from the specified directory
			INSTALL_MSTR_FILESETS="yes"
			MSTR_FILESET_DIR=$OPTARG
			if [[ ! -d $MSTR_FILESET_DIR ]]; then
				echo "Not a valid directory : $MSTR_FILESET_DIR"
				exit 1
			fi
			;;
		
        i)		# Interface on which to define the new master if its
			# network isn't defined in the NIM database. 
			INTERFACE=$OPTARG
			$IFCONFIG $INTERFACE | $GREP inet >/dev/null
			if [[ $? -ne 0 ]]; then
				echo "Not a valid interface: ifconfig $INTERFACE"
				exit 1
			fi
			;;

        n)		# Define the NIM environment with the following nimdef file
			NIMDEF_FILE=$OPTARG
			if [[ ! -s $NIMDEF_FILE ]]; then
				echo "Not a valid file : $NIMDEF_FILE"
				exit 1
			fi
			;;

        p)		# Print the machine info before the NIM database is modified
			PRINT_MAC_INFO="yes"
			;;

        r)		# Restore the NIM database from the specified backup file
			RESTORE_NIM_DB="yes"
			NIMDB_FILE=$OPTARG
			if [[ ! -s $NIMDB_FILE ]]; then
				echo "Not a valid file : $NIMDB_FILE"
				exit 1
			fi
			;;

        R)		# The script won't check the NIM resources and won't remove the
			# resources that don't pass the check
			NO_CK_RESOURCES="yes"
			;;

        s)		# calls c_switch_master on each client to update their niminfo
			# with the new master's hostname
			SWITCH_MSTR="yes"
			;;

        S)		# The script won't check all the existing SPOTs at the end
			# Use this flag if you are positive the SPOT is valid
			NO_CK_SPOT="yes"
			;;

	d)		# Replicates resources onto the alternate master from master
			REPLICATE="yes"
			;;

        u)		# when resetting machines attempt to unexport the resources
			ATTEMPT_UNEXPORT="yes"
			;;

	v)		# verbose mode (for debugging)
			set -x
			for i in $(typeset +f)
			do
				typeset -ft $i
			done
			;;

	N)		#existing NIM network
			CHANGE_NETWORK="yes"
			NIM_NET=$OPTARG
			;;

	t)		#new network definition
			NEW_NETWORK="yes"
			NIM_NET_DEF=$OPTARG

			[[ ! $CHANGE_NETWORK = "yes" ]] # && error MSG
			;;

	m)		# only check the resources on the NIM master
			ONLY_CK_MSTR_RES="yes"
			;;

	\?)		# unknown option
			echo "Usage nim_master_recover: Recover the NIM master."
			echo "      nim_master_recover [-f <mstr_fileset_dir>]"
			echo "                         [-n <nimdef_file>]"
			echo "                         [-r <nimdb_file>]"
			echo "                         [-i <mstr_interface>]"
			echo "                         [-N <mstr_net_info> [-t <net_def>]]"
			echo "                         [-D] [-R] [-S] [-p] [-s] [-u] [-v] [-d]\n"
			echo "-D    Delete all clients."
			echo "-f    install NIM mstr fileset."
			echo "-i    interface for master."
			echo "-n    nimdef file to use."
			echo "-p    print initial machine info."
			echo "-r    restore nimdb file."
			echo "-R    do not check resources."
			echo "-S    do not check spots."
			echo "-s    switch clients' master."
			echo "-u    attempt to unexport resources."
			echo "-N	change the primary interface of the master"
			echo "			accepts the following: net_name [hostname] [cable_type]"
			echo "-t	creates a new NIM network to serve as the master's primary"
			echo "			interface, can only be used with -N, and takes the" 
			echo "			following input:"
			echo "			net_name net_type net_addr net_snm default_route"
			echo "-m	only check the resources on the master"
			echo "-d	replicate the resources onto the alternate master"
			echo "-v    verbose debug output.\n"
			exit 1 #MSG
			;;
	esac
done

#
# touch log file - /var/adm/ras/nim.recover
#
> ${LOG}

#if creating a new NIM network to later set as if1
if [[ $NEW_NETWORK = "yes" ]]
then
	if [[ $CHANGE_NETWORK != "yes" ]]
	then
		echo "ERROR: cannot create a new network without changing the master's primary interface" | /usr/bin/tee $LOG #MSG
		exit 77
	fi

	mk_nim_net "$NIM_NET_DEF"
fi

#if changing the master's if1 only
if [[ $CHANGE_NETWORK = "yes" ]]
then
	chg_mstr_if1 "$NIM_NET"
	host_name=$(/usr/bin/host `/usr/bin/hostname` | awk '{print $1}')
	switch_clients_mstr
fi

[[ $NEW_NETWORK = "yes" || $CHANGE_NETWORK = "yes" ]] && exit 0

#
# If the master fileset is not being installed and the database isn't being
# restored, then error out if this isn't already a master
#
if [[ ${INSTALL_MSTR_FILESETS} != "yes" ]] && [[ ${RESTORE_NIM_DB} != "yes" ]]
then
	check_init
	if [[ $? -eq 0 ]]; then
		echo "This is not a NIM master.  Use the -f or -r flag." \
			| /usr/bin/tee -a ${LOG} #MSG
		exit 1
	fi
fi

#
# If the -f flag is passed, then we need to install the master fileset
#
if [[ ${INSTALL_MSTR_FILESETS} = "yes" ]]
then

	${LSLPP} -l bos.sysmgt.nim.master >/dev/null 2>&1

	if [[ $? -ne 0 ]]; then
		echo "Installing the NIM master fileset" | /usr/bin/tee -a ${LOG} #MSG

		$INSTALLP -acgqXd $MSTR_FILESET_DIR bos.sysmgt.nim.master \
			bos.sysmgt.nim.spot 2>&1 | /usr/bin/tee -a ${LOG}

		[[ ! -e /usr/sbin/nimconfig ]] && \
			echo "Error installing NIM master fileset - Exiting." \
			| /usr/bin/tee -a ${LOG} \
			&& exit 1 #MSG

		echo "Finished installing the NIM master fileset" | /usr/bin/tee -a ${LOG} #MSG
	else
		echo "NIM master fileset already installed" | /usr/bin/tee -a ${LOG} #MSG
	fi
fi

#
# If the -r flag is passed, then we need to restore the nim database
#
if [[ ${RESTORE_NIM_DB} = "yes" ]]
then

	# The db backup file is from a different nim master, so m_restore_db and nimconfig
	# have to be given an environment option for disabling startsrc -s nimesis
	# else, the startup will cause errors in the errpt log
	export DISABLE_NIMESIS_RESTART=true

	# Is the master configured
	check_init
	if [[ $? -ne 0 ]]
	then
		#  Make sure that the level of the installed NIM master fileset
		# is at the same level as the backup or higher.
		get_level $NIMDB_FILE
		check_level
		if [[ $? -ne 0 ]]
		then
		  echo 'You can not restore a NIM database backup onto a machine that has an earlier level of the NIM master fileset installed' | /usr/bin/tee -a ${LOG} #MSG
		  exit 1 #MSG
		fi
		# Unconfigure the master so m_restore_db won't fail
		echo "Unconfiguring the master" | /usr/bin/tee -a ${LOG} #MSG
		$NIMCONFIG -r 2>&1 | /usr/bin/tee -a ${LOG}
		$NIM -o unconfig -a stop_nimsh=no master 2>&1 | /usr/bin/tee -a ${LOG}
	fi

	echo "Restoring the NIM database from $NIMDB_FILE" | /usr/bin/tee -a ${LOG} #MSG
	$NIM_RESTORE $NIMDB_FILE
	[[ $? -ne 0 ]] && echo "Error restoring the $NIMDB_FILE - Exiting." \
		| /usr/bin/tee -a ${LOG} \
		&& exit 1 #MSG
	echo "Finished restoring the NIM database" | /usr/bin/tee -a ${LOG} #MSG
fi
main_master=$( $LSNIM -l master |  awk '$1 == "if1" { print $4 }')
#
# Restore the niminfo file so that we will be able to execute NIM commands
# At this point the niminfo file may contain the old nim master's info
# but we will update the NIM database and then rebuild the file correctly
#
[[ -f /etc/niminfo ]] && ${MV} /etc/niminfo /etc/niminfo.nmr
$NIMCONFIG -r 2>&1 | /usr/bin/tee -a ${LOG}
[[ ! -f /etc/niminfo ]] && ${CP} /etc/niminfo.nmr /etc/niminfo

host_name=$( hostname )

#
# First, determine the NIM client definition of this machine in the NIM 
# database, based on this machine's hostname
$LSNIM -t alternate_master 2>>/tmp/$$.nimname.err | /usr/bin/awk '{print $1;exit}' > /tmp/$$.nimname 2>>/tmp/$$.nimname.err
if [[ $? = 0 ]] && [[ -s /tmp/$$.nimname ]]
then
	nim_name=$(/usr/bin/cat /tmp/$$.nimname)
else
	[[ -s /tmp/$$.nimname.err ]] && /usr/bin/cat /tmp/$$.nimname.err 1>&2
	echo "error retrieving nim name, defaulting to host name." | /usr/bin/tee -a ${LOG}

	# ASSUME the nim_name is the same as the host_name for new_mstr_from_client
	#
	nim_name=${host_name%%.*}
fi

$RM -f /tmp/$$.nimname.err /tmp/$$.nimname

#
# If the -p flag was specified, print the machine info before the database is
# modified
#
if [[ -n $PRINT_MAC_INFO ]]; then
	echo "Machine info before database is updated" | /usr/bin/tee -a ${LOG} #MSG
	$LSNIM -l -c machines 2>&1 | /usr/bin/tee -a ${LOG}
	echo "Finished printing machine info" | /usr/bin/tee -a ${LOG} #MSG
fi

#
# Now update the master's definition in the NIM db.
# If the new master was a client of the old master, then we will use its
# client definition to update the master's definition.  Otherwise we expect
# an interface to be specified or a NIM network.
#
if [[ -n $INTERFACE ]]; then
	new_mstr_define
else
	if $LSNIM $nim_name >/dev/null 2>&1
	then
		new_mstr_from_client
	else
		echo "$nim_name is not a valid NIM object, specify an interface" | \
			/usr/bin/tee -a ${LOG}
		exit 1 #MSG
	fi
fi

#
# Now that the master's information has been updated, rebuild the niminfo file
#
unset DISABLE_NIMESIS_RESTART

if lsnim >/dev/null 2>&1
then
	[[ -f /etc/niminfo ]] && ${MV} /etc/niminfo /etc/niminfo.nmr
	$NIMCONFIG -r 2>&1 | /usr/bin/tee -a ${LOG}
	[[ ! -f /etc/niminfo ]] && ${CP} /etc/niminfo.nmr /etc/niminfo
fi

#
# Reset the clients before removing them from the database.  If the clients
# aren't going to be removed, we still need to reset the clients so
# their states won't be inaccurate with a new master.
#
reset_machines

#
# Remove all resources on clients, all clients and networks not on 
# the master's primary interface
#
if [[ -n $DELETE_CLIENTS ]]
then	
	remove_client_res
	remove_clients
	remove_networks
fi

#
# If the user specified a nimdef file, use it to define clients and networks
#
if [[ -n $NIMDEF_FILE ]]
then
	echo "Defining the NIM environment with $NIMDEF_FILE" \
		| /usr/bin/tee -a ${LOG} #MSG
	$NIMDEF -d -f $NIMDEF_FILE 2>&1 | /usr/bin/tee -a ${LOG}

	echo "Finished defining the NIM environment" | /usr/bin/tee -a ${LOG}  #MSG
fi

# 
# If the new master's client definition exists in the NIM database, remove it
#
if $LSNIM $nim_name >/dev/null 2>&1
then
	remove_client $nim_name
fi

#
# if the -s flag was passed we need to call c_switch_master on the clients 
# to update their niminfo file
#
if [[ -n $SWITCH_MSTR ]]; then
	switch_clients_mstr
fi

#
# Ensure that all the NIM resources exist; otherwise remove them
#
reset_resources
# if replicate is enabled call replicate_resources
if [[ $REPLICATE = "yes" ]]
then
        replicate_resources
fi

[[ -z $NO_CK_RESOURCES ]] && check_resources

#
# Attempt to run "nim -Fo check <spot_name>" on all SPOTs.  This needs to
# be done in case no boot images exist on the SPOT server.
#
[[ -z $NO_CK_SPOT ]] && check_spots

#
# finished
#
echo "nim_master_recover Complete" | /usr/bin/tee -a ${LOG} #MSG

exit $exit_rc
