#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos720 src/bos/usr/lib/nim/methods/c_backupios.sh 1.2 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2011 
# 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 
# @(#)45 1.2 src/bos/usr/lib/nim/methods/c_backupios.sh, cmdnim, bos720 4/22/11 11:31:46 
#   COMPONENT_NAME: CMDNIM
#
#   FUNCTIONS: ./usr/lib/nim/methods/c_backupios.sh
#
#   ORIGINS: 27
#
#
#   (C) COPYRIGHT International Business Machines Corp. 2011
#   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.
#

# include common NIM shell defines/functions
NIMPATH=${0%/*}
NIMPATH=${NIMPATH%/*}
[[ ${NIMPATH} = ${0} ]] && NIMPATH=/usr/lpp/bos.sysmgt/nim
NIM_METHODS="${NIMPATH}/methods"
. ${NIM_METHODS}/c_sh_lib

#---------------------------- local defines     --------------------------------
BACKUPIOS="/usr/ios/cli/ioscli backupios"
mksysb_mnt_dir=""

#---------------------------- module globals    --------------------------------
REQUIRED_ATTRS="location" 
OPTIONAL_ATTRS="server backupios_flags size_preview verbose force mount_opts"
backupios_flags=""
location=""
server=""
name=""
source=""
size_preview=""
force=""
verbose=""
#------------------------------- check_space -----------------------------------
#
# NAME: check_space
#
# FUNCTION:  Calculate the maximum amount of space required for 
#            the mksysb image along with the free space available
#            in the target location.  If the maximum required is 
#            greater than the space available, give an error and 
#            exit.  Otherwise, show the user the space 
#            requirements and continue.
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#       calls error on failure
#       NOTE: The mksysb image is packed, so the maximum amount
#             of space required will probably never be completely
#             used.  The compression rate varies widely depending
#             on the type of data that is being backed up. 
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#       parameters:
#       global:
#
# RETURNS: (int)
#       0                           = success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function check_space {

	typeset MAX_SPACE_REQ=0
	typeset FREE_SPACE=0
	typeset USE_EXCLUDE_FILE=0  #default does not use exclude files

	# get the free space in the target filesystem 
	# (in 1024-byte blocks)
	FREE_SPACE=`${DF} -k \`${DIRNAME} ${location_access}\` | ${AWK} 'NR==2{print $3}'`
	[[ -z "${FREE_SPACE}" ]] && err_from_cmd ${DF}

	# Since backupios does not preview, the -nomedialib flag will
	# exclude "/var/vio/VMLibrary" with backupios.  If -nomedialib is passed,
	# check space without /var/vio/VMLibrary.
	USE_EXCLUDE_FILE=$(expr "${backupios_flags}" : ".*-nomedialib") 

	MAX_SPACE_REQ=$(calculate_vg_space rootvg ${USE_EXCLUDE_FILE})
	(( REQ_MEG = ${MAX_SPACE_REQ} / 1024 + 1 ))
	(( FREE_MEG = ${FREE_SPACE} / 1024 + 1 ))

	# print the space information 
	# +---------------------------------------------------------------------+
	#                 System Backup Image Space Information
	#               (Sizes are displayed in 1024-byte blocks.)
	# +---------------------------------------------------------------------+
	#
	# Required = <MAX_SPACE_REQ> (<REQ_MEG> MB)    Available = <FREE_SPACE> (<FREE_MEG> MB)
	#
	${C_ERRMSG} ${MSG_SPACE_MKSYSB} ${C_ERRMSG_MSG} $MAX_SPACE_REQ \
		$REQ_MEG $FREE_SPACE $FREE_MEG > ${TMPDIR}/msg 2>&1
	if [[ $size_preview = "yes" ]]; then
		cat ${TMPDIR}/msg
	else
		head -8 ${TMPDIR}/msg
	fi


	# if just previewing space then exit 
	if [[ "${size_preview}" = "yes" ]]; then
		exit 0
	fi

	# is there enough space for the mksysb? 
	if (( MAX_SPACE_REQ > FREE_SPACE )); then
		# if force ignore space requirements 
		if [[ "${force}" != "yes" ]]; then
			# 0042-210 <method>: The maximum space required for the backup is greater
			# 	than the amount of free space in the target filesystem.  To ignore
			# 	space requirements use the "-F" flag when defining the mksysb
			# 	resource.
			error ${ERR_SPACE_MKSYSB}
		fi
	fi 

} # end check_space

#--------------------------- calculate_vg_space --------------------------------
#
# NAME: calculate_vg_space
#
# FUNCTION:  Calculate space ${VG} takes up excluding files if asked
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#       VG = $1      name of volume group
#       EF = $2      0  => do not exclude files (default) 
#                    >0 => exclude files
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#       parameters:
#       global:
#
# RETURNS: (int)
#       0                           = success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function calculate_vg_space {
	typeset VG=$1 EF=${2:-0}
	typeset lv fs LVLIST
	typeset BUF                   # command output buffer
	typeset TEF=$TMPDIR/ef.nim.$$ # temporary exclude file
	typeset LSVG=/usr/sbin/lsvg
	typeset LSVG=/usr/sbin/lsvg

	cd / 
	BUF=$(${LSVG} -l ${VG} | ${AWK} '$6 ~ "^open" && ($2 == "jfs2" || $2 == "jfs") {print $1,$7}') 

	if [[ ${EF} == 0 ]] ; then
		echo "${BUF}" | while read lv fs; do
			typeset LVLIST="/dev/${lv} ${LVLIST}"
		done
		${DF} -kIM ${LVLIST} | ${AWK} 'NR > 1 {tot = tot + $4} END {printf "%d",tot+1}'
	else
		echo "${BUF}" | while read lv fs; do
		# this seems ugly but we really need to match how mksysb/savevg works, so...
		# the long pipeline follows the logic:
		# - find command to get the files and sizes per FS
		# - awk to reorder in a manner egrep and we can use (eg, $11=filename first, $2=size)
		# - egrep out based on the exclude file
		# - awk to calculate total and buffer by 512K for the header

		# setup a temporary exclude_file
		> ${TEF}

		# process the same as savevg
		echo "/var/vio/VMLibrary" > ${TEF}

		${FIND} .$fs ! -type s \( -fstype jfs -o -fstype jfs2 \) -xdev -ls |
		${AWK} '{print $11,$2}' | ${EGREP} -v -f ${TEF} |
		${AWK} -v fs=".$fs" '{tot=tot+$2} END {printf ("%s\t%d\n",fs,tot)}'
		done  | ${AWK} '{tot=tot+$2} END {printf ("%.0d",tot+512)}' 

		# cleanup the temporary exclude file
		[[ -r ${TEF} ]] && ${RM} -r ${TEF}
	fi

	return 0
}

#---------------------------- c_backupios_cleanup ----------------------------
#
# NAME: c_backupios_cleanup 
#
# FUNCTION:  Replace the exclude file as it was before we ran
#            and call the generic cleanup function to make sure
#            everything gets unmounted.
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#       calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
#       parameters:
#       global:
#
# RETURNS: 
#
# OUTPUT:
#-------------------------------------------------------------------------------
function c_backupios_cleanup {

	# clean up the mount point if we mounted the mksysb write directory over.
	# we need to do this here since if the unmount fails the entire directory 
	# might get erased.  
	if [[ -n "${mksysb_mnt_dir}" ]]; then
		nim_unmount ${mksysb_mnt_dir}

		# Check to see if the unmount failed.  If it failed then
		# leave the temporary directory there.  We don't want to 
		# inadvertently erase extra files.
		${MOUNT} | ${EGREP} -q ${mksysb_mnt_dir}
		if [[ $? -ne 0 ]]; then
			${RM} -r ${mksysb_mnt_dir}
		fi
	fi

	cleanup

} # end c_backupios_cleanup

#-------------------------------  MAIN  ---------------------------------------

# signal processing
trap c_backupios_cleanup 0
trap err_signal 1 2 11 15

# NIM initialization
nim_init

# set parameters from command line
while getopts :a:qv c; do
	case ${c} in

		a)	# validate the attr ass
			parse_attr_ass "${OPTARG}"

			# include the assignment for use in this environment
			eval ${variable}=\"${value}\"
			;;

		q)	# show attr info
			cmd_what
			exit 0
			;;

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

		\?)	# unknown option
			# 0042-016 <method>: "-<OPTARG>" is not a valid option for this
			# operation
			# 	<>
			error ${ERR_BAD_OPT} ${OPTARG}
			;;
	esac
done

# check for missing attrs
ck_attrs

# return ioslevel only and exit
if [[ $backupios_flags = "ioslevel" ]]; then
	${MKDIR} /tmp/c_backupios.$$ >/dev/null 2>&1 || exit 1
	cd /tmp/c_backupios.$$ 2>/dev/null
	${RESTORE} -xqf "$location" ./usr/ios/cli/ios.level >/dev/null 2>&1 || exit 1
	typeset output=`${CAT} ./usr/ios/cli/ios.level 2>/dev/null`
	cd / 2>/dev/null
	${RM} -r /tmp/c_backupios.$$ >/dev/null 2>&1

	echo $output	
	exit 0
fi

# mount the remote location 

# going to create a tmp directory at "/tmp/$$.mnt"
# look for lowest, unused seqno
typeset -i idx=0
while (( ${idx} < ${MAX_MNT} )); do
	mksysb_mnt_dir="/tmp/$$.mnt${idx}"
	[[ ! -d ${mksysb_mnt_dir} ]] && break
	let idx=idx+1
done
(( ${idx} >= ${MAX_MNT} )) && error ${ERR_GEN_SEQNO} /tmp/$$.mnt

${MKDIR} ${mksysb_mnt_dir} 2>${ERR} || err_from_cmd ${MKDIR}

nim_mount ${server}:`${DIRNAME} ${location}` ${mksysb_mnt_dir}
location_access=${access_pnt}/`${BASENAME} ${location}`

# do space checking for ios_mksysb image
check_space

# call backupios 
eval ${BACKUPIOS} -file "${location_access}" -mksysb "${backupios_flags}"

# exit with return code from backupios
RC=$?

# all done
exit $RC
