#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos720 src/bos/usr/lib/nim/methods/nim_update_all.sh 1.10 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2002,2005 
# 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 
# @(#)02 1.10 src/bos/usr/lib/nim/methods/nim_update_all.sh, cmdnim, bos720 9/26/05 15:39:14

#
#   COMPONENT_NAME: CMDNIM
#
#   FUNCTIONS: ./usr/lib/nim/methods/nim_update_all.sh
#
#   ORIGINS: 27
#

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

# Set PROGRAM_NAME variable for error reporting.
PROGRAM_NAME="nim_update_all"

# --------------------------- module globals
def_lpp=""
def_spot=""
device="/dev/cd0"
mksysb="yes"
mult_vol="-b \"S\""
mac_grp=""
no_update=""
sys_backup=""
update_lpp=""
update_master=""
LOG="/var/adm/ras/nim.update"
EZLOG="/var/adm/ras/eznim.cfg"
CD_MNT_DIR="/tmp/picaso_mnt_pt"
# ------------------------------------------------------------------ #

# ------------------------------------- create_sysb
# NAME: create_sysb
#
# FUNCTION: Create system backup image
#
# -------------------------------------------------------------------------- #
function create_sysb {

	typeset -i MAX_SPACE_REQ=0
	typeset -i USED=0

	# is there a mksysb resource to update
	/usr/sbin/lsnim ${sys_backup} >/dev/null 2>&1
	[[ $? -ne 0 ]] && return 1


	# get the location for the existing backup
	sysb_loc=`/usr/sbin/lsnim -a location ${sys_backup} | /usr/bin/awk 'NR==2{print $3}'`
	fs_loc=`/usr/bin/df ${sysb_loc} | /usr/bin/awk 'NR==2{print $7}'`

	# remove the old mksysb
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_REMOVE_MKSYSB} 'Removing old mksysb resource %s...' ${sys_backup} \
	  | /usr/bin/tee -a ${LOG}
	/usr/bin/rm ${sysb_loc} >/dev/null 2>&1
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_DONE} 'done\n' | /usr/bin/tee -a ${LOG}


    # create image.data file
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_CREATE_IMG_DATA} 'Creating image.data file...' | /usr/bin/tee -a ${LOG}
    /usr/bin/mkszfile -X 2>/dev/null 
    [ $? -ne 0 ] && \
	  ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_CREATE_IMG_DATA} 'Error creating image.data file for mksysb.\n' \
	   | /usr/bin/tee -a ${LOG} \
	  || ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_DONE} 'done\n' | /usr/bin/tee -a ${LOG}


	# get amount of space required
	# for the mksysb image
	/usr/sbin/lsvg -l rootvg | /usr/bin/grep jfs | /usr/bin/grep -v "N\/A" | 
	/usr/bin/grep -v "${fs_loc}" | /usr/bin/grep -v "\/tftpboot" | 
	/usr/bin/awk '{print $7}' |
	while read filesystem
	do
        # get the used space in each filesystem
        # (in 1024-byte blocks)
        let USED=$( /usr/bin/df -IM $filesystem | /usr/bin/tail +2l | /usr/bin/awk '{print $4}' )
        let MAX_SPACE_REQ=`expr $MAX_SPACE_REQ + $USED`
	done
	[[ -z "${MAX_SPACE_REQ}" ]] && \
	  ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_CALC_SB} 'Error calculating space requirement for mksysb.\n' \
	   | /usr/bin/tee -a ${LOG} && return 1

	# add fudge factor
	let MAX_SPACE_REQ=`expr $MAX_SPACE_REQ + 65536`

	/usr/sbin/mount | /usr/bin/grep "${fs_loc}" >/dev/null 2>&1
    [ $? -ne 0 ] && /usr/sbin/mount ${fs_loc}

    # make sure ${fs_loc} has desired space (${MAX_SPACE_REQ})
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_SPACE_FS} 'Checking %s space requirement...' ${fs_loc} \
	 | /usr/bin/tee -a ${LOG}

    free_space="$( /usr/bin/df ${fs_loc} | /usr/bin/awk 'NR==2{print $3}' 2>/dev/null )"
    if (( free_space < MAX_SPACE_REQ )); then
        /usr/sbin/chfs -a size=+$(( MAX_SPACE_REQ - free_space )) ${fs_loc} >/dev/null 2>&1
		[ $? -ne 0 ] && \
		    ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_EXP} 'Error expanding %s directory - Exiting.\n' ${fs_loc} \
			 | /usr/bin/tee -a ${LOG} \
			 && return 1
    fi
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_DONE} 'done\n' | /usr/bin/tee -a ${LOG}

	# perform system backup
	/usr/bin/mksysb -X -e ${sysb_loc} 

	# if creating image fails, remove backup 
	# -    no mksysb resource to define
	if [[ $? -ne 0 ]]; then
		${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_CREATE_SB} 'Error creating system backup image.\n' \
		 | /usr/bin/tee -a ${LOG}
		${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_NO_CREATE_SB} 'No mksysb resource will be created.\n' \
		 | /usr/bin/tee -a ${LOG}
		/usr/sbin/nim -o remove ${sys_backup} >/dev/null 2>&1 
		return 1
	fi

    return 0
}


# ------------------------------------- nim_update_all
#
# NAME: nim_update_all
#
# FUNCTION:	 Updates the install resources in the NIM environment.
#            Flags may be used to specify particular NIM objects
#            for updating and also to disable update_all for NIM clients.
#
# NOTES:
#
#   The following outline gives an overview:
#     1) Export environment variable NIM_LICENSE_ACCEPT
#        - necessary for software license agreement
#     2) Set NSORDER in /etc/environment
#        - necessary for name resolution (if host exists in /etc/hosts)
#     3) Obtain the vrmf from the media
#        - default location is /dev/cd0
#        - modify using the (-d) flag
#     4) Update lpp_source, spot, and mksysb resource
#        - modify lpp_source by specifying NIM lpp_source object (-l) flag
#        - modify spot by specifying NIM spot object (-s) flag
#        - disable creating the mksysb resource using the (-B) flag 
#     5) Perform update_all on NIM clients
#        - disable using the (-u) flag
#
# RETURNS: (int)
#	0	= SUCCESS
#	1	= FAILURE
#
# --------------------------------------------------------------------------- #
#
# set parameters from command line
while getopts :d:l:s:BL:Mmuv x
do
	case ${x} in

		d)      # location of install media
		        device=${OPTARG}
				;;

		l)		# validate the lpp_source assignment
				def_lpp=${OPTARG}
				
				/usr/sbin/lsnim ${lpp_res} >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
						${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_OBJ_NOT_FOUND} 'NIM object %s not found.\n' ${lpp_res} \
						 | /usr/bin/tee -a ${LOG}
						exit 1
				fi
				;;

		s)		# validate the spot assignment
				def_spot=${OPTARG}
				
				/usr/sbin/lsnim ${spot_res} >/dev/null 2>&1
				if [[ $? -ne 0 ]]; then
						${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_OBJ_NOT_FOUND} 'NIM object %s not found.\n' ${spot_res} \
						 | /usr/bin/tee -a ${LOG}
						exit 1
				fi
				;;

		B)		# do not create new mksysb
				mksysb=""
				;;
		
		L)		# create new update lpp_source location
				update_lpp=${OPTARG}
				;;
		
		M)		# called from eznim, update master
				update_master="yes"
				;;
		
		m) 		# process multi-volume CDs
				mult_vol=""
				;;

		u)		# do not perform update all on clients
				no_update="yes"
				;;
		
		v)		# verbose mode (for debugging)
				set -x
				for i in $(typeset +f)
				do
					typeset -ft $i
				done
				;;

		\?)		# unknown option
				${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_NIM_UPDATE_ALL_USAGE} 'Usage nim_update_all: Updates NIM resources and customizes NIM clients\n\tnim_update_all [-d <device>] [-l <lpp_source resource>]\n\t               [-s <spot resource>] [-B] [-u] [-m] [-v] <client object(s)>\n\n-d    specify device location for updates.\n-l    update the specified lpp_source resource object name.\n-s    update the specified spot resource object name.\n-B    do not create a new mksysb resource.\n-u    do not perform update_all on NIM client objects.\n-m    allow multiple volume processing for updates.\n-v    Enables debug output.\n\nDefault values:\ndevice         = /dev/cd0\nlpp_source     = 520lpp_res\nspot           = 520spot_res\nnew mksysb     = yes\nupdate clients = yes\n\nNote: If no client object names are given, or the -u flag\n\tis not specified, then all clients in the\n\tNIM environment are enabled for update_all.\n'
				exit 1
				;;
	esac
done

shift $((OPTIND - 1))
mac_grp="$*"

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

# informational banner
#
${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_NIM_UPDATE_ALL} '\n############################## NIM update all ###############################\n#                                                                            #\n#  During script execution, NIM client and resource updating times           #\n#  may vary. To view the install log at any time during nim_update_all,      #\n#  run the command: tail -f /var/adm/ras/nim.update in a separate screen.    #\n#                                                                            #\n##############################################################################\n\n'

# readme
/usr/bin/sleep 10

# Set accept_licenses attribute for >5.1.x.x installs
export NIM_LICENSE_ACCEPT=yes

# Append NSORDER variable for local network defs
if ! grep NSORDER /etc/environment; then 
	echo "NSORDER=local,bind" >> /etc/environment
fi

# pause for a bit
/usr/bin/sleep 1

# determine the vrmf for the update
# -   lets get the vrmf from $device locale
vrmf=`/usr/sbin/installp -Ld ${device} | awk -F: '$2 == "bos\.rte\.install" \
  {gsub("\\\.","",$3) ; level = $3} ; END {printf "%.3s",level}'`
def_lpp="${def_lpp:-${vrmf}lpp_res}"
def_spot="${def_spot:-${vrmf}spot_res}"

# does an lpp_source exist with the default name
# or are we creating a new update lpp_source?
# - if so, lets add the updates
/usr/sbin/lsnim ${def_lpp} >/dev/null 2>&1
if [[ $? -eq 0 ]]; then
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ADD_UPDTS} 'Adding updates to %s lpp_source...' ${def_lpp} \
	 | /usr/bin/tee -a ${LOG}

	# use gencopy to add updates
	loc=`/usr/sbin/lsnim -a location ${def_lpp} | /usr/bin/awk 'NR==2{print $3}'`
	/usr/sbin/gencopy ${mult_vol} -X -t ${loc} -d ${device} all 2>&1 | tee ${LOG}
	
	# remove any duplicate updates or supercedes
	lpp_location=`/usr/sbin/lsnim -a location ${def_lpp} | /usr/bin/grep "location =" | \
		      /usr/bin/cut -d'=' -f2 | /usr/bin/sed 's/^ //g'`
	/usr/lib/instl/lppmgr -d ${lpp_location} -X -t -q >>${LOG} 2>&1

	# remove .toc file
	/usr/bin/rm ${loc}/installp/ppc/.toc >>${LOG} 2>&1

	# check validity of lpp_source
	/usr/sbin/nim -Fo check ${def_lpp} >>${LOG} 2>&1
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_DONE} 'done\n' | /usr/bin/tee -a ${LOG}

elif [[ -n ${update_lpp} ]]; then
	# create an update lpp_source
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ADD_UPDTS} 'Adding updates to %s lpp_source...' ${def_lpp} \
	 | /usr/bin/tee -a ${LOG}

	 /usr/sbin/nim -o define -t lpp_source \
	   -a server=master -a location=${update_lpp} \
	   -a source=${device} -a packages=all \
	   ${def_lpp} >>${LOG} 2>&1

	# remove any duplicate updates or supercedes
	/usr/lib/instl/lppmgr -d ${update_lpp} -X -t -q >>${LOG} 2>&1

	# check validity of lpp_source
	/usr/sbin/nim -Fo check ${def_lpp} >>${LOG} 2>&1
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_DONE} 'done\n' | /usr/bin/tee -a ${LOG}

	# add lpp_source to basic_res_grp
	/usr/sbin/nim -o change -a lpp_source=${def_lpp} basic_res_grp >>${LOG} 2>&1

else
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_LOCATE_RES} 'Unable to locate %1$s resource %2$s - Exiting.\n' "lpp_source" ${def_lpp} \
	 | /usr/bin/tee -a ${LOG}
	exit 1
fi


# does a spot exist with the default name
# - if so, lets perform an update_all
/usr/sbin/lsnim ${def_spot} >/dev/null 2>&1
if [[ $? -eq 0 ]]; then
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_UPDT_SPOT} 'Updating %1$s using updated lpp_source %2$s...' ${def_spot} ${def_lpp} \
	 | /usr/bin/tee -a ${LOG}

	/usr/sbin/nim -o cust -a lpp_source=${def_lpp} \
	    -a fixes="update_all" ${def_spot} >>${LOG} 2>&1
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_DONE} 'done\n' | /usr/bin/tee -a ${LOG}
else
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_LOCATE_RES} 'Unable to locate %1$s resource %2$s - Exiting.\n' "spot" ${def_spot} \
	 | /usr/bin/tee -a ${LOG}
	exit 1
fi



if [[ -z ${no_update} ]]; then
	# perform update_all on NIM client objects
	if [[ -z $mac_grp ]]; then
		${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_CLIENT_OBJ_LIST} '\nGenerating list of client objects in NIM environment...' \
		| /usr/bin/tee -a ${LOG}
		mac_grp=`/usr/sbin/lsnim -t standalone | /usr/bin/cut -f1 -d" "`
	fi

	# we should have a list of machines by now..
	if [[ -z $mac_grp ]]; then
		${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_CLIENT_OBJ_LIST} '\nUnable to obtain NIM client objects list - Exiting.' \
		| /usr/bin/tee -a ${LOG}
		exit 1
	else
		${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_LOCATE_MACS} '\nLocating %s...' ${mac_grp} | /usr/bin/tee -a ${LOG}
	fi

	# pause for a bit
	/usr/bin/sleep 1

	# check for resource group - created from nim_master_setup script
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_UPDT_CLIENT_OBJ_LIST} '\nPreparing to update clients...' | /usr/bin/tee -a ${LOG}

	# pause for a bit
	/usr/bin/sleep 1

	#--------------------------------------------------------------#
	#                Update client objects                        #
	#--------------------------------------------------------------#

	# lets initiate "update_all" for clients -or- lpar_grp members
	/usr/sbin/nim -o cust -a lpp_source=${def_lpp} \
		-a fixes="update_all" ${mac_grp} 2>&1 \
		| /usr/bin/tee -a ${LOG}
	#--------------------------------------------------------------#
	#--------------------------------------------------------------#
fi

# if called from eznim, we should update NIM master
if [[ -n $update_master ]]; then
	/usr/sbin/nim -o cust -a lpp_source=${def_lpp} \
		-a fixes="update_all" master 2>&1 \
		| /usr/bin/tee -a ${LOG}
fi

# should we attempt to update the mksyb resource
if [[ -n ${mksysb} ]]; then
	# source the eznim config file
	. ${EZLOG} 
	sys_backup=${EZNIM_SYSB:-master_sysb}

	#update mksysb resource
	${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_REPLACE_MKSYSB} 'Attempting to replace mksysb resource %s...' ${sys_backup} \
	 | /usr/bin/tee -a ${LOG}

	# variable EZNIM_SYSB exists when called from EZNIM
	# -  otherwise, just use the default_name in NIM env
	create_sysb ${sys_backup}
	[ $? -ne 0 ] && \
	  ${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_ERR_REPLACE_MKSYSB} 'Unable to create new mksysb resource %s\n' ${sys_backup} \
	   | /usr/bin/tee -a ${LOG}
fi

# finished.
${DSPMSG} -s ${MSG_SET} cmdnim.cat ${MSG_NIM_UPDATE_ALL_COMPLETE} '\nNIM update_all is complete - enjoy!' \
 | /usr/bin/tee -a ${LOG}

# end of script