#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos72Q src/bos/usr/lib/nim/methods/c_mkbosi.sh 1.25.3.5 # # Licensed Materials - Property of IBM # # Restricted Materials of IBM # # COPYRIGHT International Business Machines Corp. 1995,2019 # 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 # @(#)97 1.25.3.5 src/bos/usr/lib/nim/methods/c_mkbosi.sh, cmdnim, bos72Q, q2019_03A2 1/10/19 15:30:08 # # COMPONENT_NAME: CMDNIM # # FUNCTIONS: ./usr/lib/nim/methods/c_mkbosi.sh # # ORIGINS: 27 # # # (C) COPYRIGHT International Business Machines Corp. 1995 # 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 -------------------------------- EXCLUDE_ROOTVG=/etc/exclude.rootvg EXCLUDE_PACKVG=/etc/exclude_packing.rootvg SAVEVG=/usr/bin/savevg MKSYSB=/usr/bin/mksysb mksysb_mnt_dir="" #---------------------------- module globals -------------------------------- REQUIRED_ATTRS="location" OPTIONAL_ATTRS="server mksysb_flags exclude_files size_preview verbose force mount_opts" location="" server="" name="" source="" mksysb_flags="" exclude_files="" 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} # if "e" in flags, use exclude files USE_EXCLUDE_FILE=$(expr "${mksysb_flags}" : ".*e") # counts occurences of "e" => exclude 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 ${C_ERRMSG} ${MSG_SPACE_MKSYSB} ${C_ERRMSG_MSG} $MAX_SPACE_REQ \ $REQ_MEG $FREE_SPACE $FREE_MEG > ${TMPDIR}/msg 2>&1 if [[ `expr "${mksysb_flags}" : ".*p"` -eq 0 ]] 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 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 if [[ -f ${EXCLUDE_ROOTVG} ]]; then ${CAT} ${EXCLUDE_ROOTVG} | ${SED} 's/ //g;s/^ *//g;s/ *$//g;/^$/d' > ${TEF} fi ${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 -f ${TEF} fi return 0 } #---------------------------- process_exclude_file ---------------------------- # # NAME: process_exclude_file # # FUNCTION: Sets up access to the exclude file that we are # using and copies it to /etc/exclude.rootvg so # that the savevg command will use it when backing # up the system. If a previous exclude file exists # it will be saved and restored after the backup. # # Updated to also process /etc/exclude_packing.rootvg # # EXECUTION ENVIRONMENT: # # NOTES: # calls error on failure # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: (int) # 0 = success # # OUTPUT: #------------------------------------------------------------------------------- function process_exclude_file { # save the old exclude file if [ -f ${EXCLUDE_ROOTVG} ] then ${CP} ${EXCLUDE_ROOTVG} ${EXCLUDE_ROOTVG}.nim_save.$$ || err_from_cmd "${CP} ${EXCLUDE_ROOTVG} ${EXCLUDE_ROOTVG}.nim_save.$$" fi # save the old exclude file if [ -f ${EXCLUDE_PACKVG} ] then ${CP} ${EXCLUDE_PACKVG} ${EXCLUDE_PACKVG}.nim_save.$$ || err_from_cmd "${CP} ${EXCLUDE_PACKVG} ${EXCLUDE_PACKVG}.nim_save.$$" fi # set up access to the exclude file if [[ ${exclude_files} = ?*:?* ]] then # mount remote exclude_files resource nim_mount ${exclude_files} exclude_access=${access_pnt} else # the exclude_files resource is local exclude_access=${exclude_files} fi # just to be extra safe, in the case that the exclude_files # resource is local AND already meets the name/location that # savevg would use if [[ "${exclude_access}" != "${EXCLUDE_ROOTVG}" ]] then echo ${exclude_files} > /tmp/.nim_pack LANG=C ${EGREP} exclude_packing /tmp/.nim_pack RC=$? if [ "$RC" -ne 0 ] then # put the exclude file in /etc/exclude.${VG} # so that the savevg command will read it ${CP} ${exclude_access} ${EXCLUDE_ROOTVG} || err_from_cmd "${CP} ${exclude_access} ${EXCLUDE_ROOTVG}" # add the -e flag since we have a exclude_rootvg file mksysb_flags=e${mksysb_flags} else ${CP} ${exclude_access} ${EXCLUDE_PACKVG} || err_from_cmd "${CP} ${exclude_access} ${EXCLUDE_PACKVG}" fi ${RM} /tmp/.nim_pack fi nim_unmount ${access_pnt} } # end process_exclude_file #---------------------------- format_mksysb_flags ---------------------------- # # NAME: format_mksysb_flags # # FUNCTION: The options to mksysb_flags are "AVXab:ePimpZ". This function # makes sure that the flags are in the correct format to # pass to savevg no matter what order they are entered # by the user. # # EXECUTION ENVIRONMENT: # # NOTES: # The -b option to mksysb takes a numeric argument. # Make sure that there is a space after the -b flag # and it's argument. If not, savevg will take everything # after the -b flag as the block_size argument. # # RECOVERY OPERATION: # # DATA STRUCTURES: # parameters: # global: # # RETURNS: # # OUTPUT: #------------------------------------------------------------------------------- function format_mksysb_flags { in_flags=${1} fmt_flags="" i=1 # get number of characters in flags num_flags=`echo ${in_flags} | ${WC} -c | ${AWK} '{print $1}'` # Loop through the flags and make sure that there is # a space after the -b flag and it's argument. while [ $i -lt $num_flags ] do flag=`echo ${in_flags} | ${CUT} -c $i` # if digit print and set digit flag if [[ "${flag}" = +([0-9]) ]] then fmt_flags=${fmt_flags}`echo "${flag}\c"` isdigit=true # if not digit print mksysb flag elif [ ! "$isdigit" ] then fmt_flags=${fmt_flags}`echo "${flag}\c"` else # last thing printed was a digit so # print space before next mksysb flag isdigit= # if space just print it if [[ "${flag}" = " " ]] then fmt_flags=${fmt_flags}`echo " \c"` # if flag print with hyphen else fmt_flags=${fmt_flags}`echo " -${flag}\c"` fi fi let i=i+1 done echo ${fmt_flags} } # end format_mksysb_flags #---------------------------- c_mkbosi_cleanup ---------------------------- # # NAME: c_mkbosi_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_mkbosi_cleanup { # copy the old exclude file back if [ -f ${EXCLUDE_ROOTVG}.nim_save.$$ ] then ${MV} ${EXCLUDE_ROOTVG}.nim_save.$$ ${EXCLUDE_ROOTVG} > /dev/null 2>&1 || err_from_cmd "${MV} ${EXCLUDE_ROOTVG}.nim_save.$$ ${EXCLUDE_ROOTVG}" else # remove the exclude file we installed if [ -n "${exclude_files}" ] && [ -f "${EXCLUDE_ROOTVG}" ] then ${RM} ${EXCLUDE_ROOTVG} || warning_from_cmd "${RM} ${EXCLUDE_ROOTVG}" fi fi # copy the old exclude packing file back if [ -f ${EXCLUDE_PACKVG}.nim_save.$$ ] then ${MV} ${EXCLUDE_PACKVG}.nim_save.$$ ${EXCLUDE_PACKVG} > /dev/null 2>&1 || err_from_cmd "${MV} ${EXCLUDE_PACKVG}.nim_save.$$ ${EXCLUDE_PACKVG}" else # remove the exclude file we installed if [ -n "${exclude_files}" ] && [ -f "${EXCLUDE_PACKVG}" ] then ${RM} ${EXCLUDE_PACKVG} || warning_from_cmd "${RM} ${EXCLUDE_PACKVG}" fi fi # 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_mkbosi_cleanup #------------------------------- MAIN --------------------------------------- # signal processing trap c_mkbosi_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 error ${ERR_BAD_OPT} ${OPTARG} ;; esac done # check for missing attrs ck_attrs # check that bos.sysmgt.sysbr is installed STATE=`${LSLPP} -qcIL bos.sysmgt.sysbr 2>/dev/null | ${CUT} -d":" -f6` if [ "${STATE}" != "C" ] then nim_name=`${GREP} NIM_NAME ${NIMINFO} | ${CUT} -d"=" -f2` error ${ERR_NO_SYSBR} ${nim_name} fi # handle exclude file resource [ -n "${exclude_files}" ] && process_exclude_file # is this machine the image server? if [ -n "${server}" ] then # 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}` else # location is local to this machine location_access=${location} fi # do space checking for mksysb image check_space # check mksysb_flags format and content if [ -n "${mksysb_flags}" ] then # put hyphens in front of all flags mksysb_flags=$( ck_installp_flags "${mksysb_flags}" ) # make sure all flags are valid /usr/bin/getopt "AVXab:ePimpvZT" ${mksysb_flags} > /dev/null 2>&1 || error ${ERR_BAD_MKSYSB_FLAG} # verify that flags are in correct format mksysb_flags=$( format_mksysb_flags "${mksysb_flags}" ) fi DWPAR=`/usr/sbin/lswpar -q -s D -a name` if [ -n "$DWPAR" ] then # call mksysb with the -N flag ${MKSYSB} -i ${mksysb_flags} -N ${location_access} 2>&1 else # call savevg to create the image ${SAVEVG} -i -f ${location_access} ${mksysb_flags} rootvg 2>&1 fi # exit with return code from savevg or mksysb RC=$? # all done exit $RC