Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

624 lines
14 KiB
Bash

#!/bin/ksh
# @(#)27 1.22 src/bos/usr/lib/nim/methods/c_sync_root.sh, cmdnim, bos41J, 9516A_all 4/18/95 09:19:02
#
# COMPONENT_NAME: CMDNIM
#
# FUNCTIONS: ./usr/lib/nim/methods/c_sync_root.sh
#
# ORIGINS: 27
#
#
# (C) COPYRIGHT International Business Machines Corp. 1993
# 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 --------------------------------
#---------------------------- module globals --------------------------------
REQUIRED_ATTRS="location"
OPTIONAL_ATTRS="installp_flags filesets bundle"
location=""
installp_flags=""
filesets=""
bundle=""
# The following are names of files that will hold lists of fileset names
# for a full root sync op.
cleanup_sync_list=${TMPDIR}/$$.cleanup
apply_sync_list=${TMPDIR}/$$.applies
commit_sync_list=${TMPDIR}/$$.commits
deinstl_sync_list=${TMPDIR}/$$.deinstls
reject_sync_list=${TMPDIR}/$$.rejects
#---------------------------- ck_instroot_cust_sz ----------------------------
#
# NAME: ck_instroot_cust_sz
#
# FUNCTION:
# Uses the value saved in INSTROOT_CUST_SZ during c_instspot
# to ensure that enough space exists in /usr for the
# root_sync on the inst_root of the SPOT. Expands if
# necessary.
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
# o No checking is done for auto-expand flag since by now,
# after the cust has been done on the SPOT, it would be silly
# to fail due to a shortage of a few hundred K (which is all
# there is likely to be short for the root_sync).
#
# o calls error if cannot expand filesystem
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
# parameters:
# global:
# INSTROOT_CUST_SZ
#
# RETURNS: (int)
# 0 = success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function ck_instroot_cust_sz {
# May as well keep going if no root size to work with.
[[ -s "${INSTROOT_CUST_SZ}" ]] || return 0
# NOTE: required space should already contain a fudge factor
required=`${CAT} ${INSTROOT_CUST_SZ}`
available=`${DF} /usr | ${AWK} '(NR>1) {print $3}'`
# expand if necessary
if (( ${required} > ${available} ))
then
let "additional=required-available"
# try to expand the filesystem
${CHFS} -a size=+${additional} /usr 2>${ERR} 1>&2 || \
err_from_cmd ${CHFS}
fi
rm ${INSTROOT_CUST_SZ}
return 0
} # end of ck_instroot_cust_sz
#---------------------------- prep_bundle --------------------------------
#
# NAME: prep_bundle
#
# FUNCTION:
# prepares environment to use an installp bundle file
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
# calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
# parameters:
# global:
# bundle
# bundle_access
#
# RETURNS: (int)
# 0 = success
#
# OUTPUT:
#-------------------------------------------------------------------------------
function prep_bundle {
[[ -z "${bundle}" ]] && return 0
bundle_access=${TMPDIR}/bundle
# local or remote file?
if [[ ${bundle} = ?*:/* ]]
then
# remote - setup local access
nim_mount ${bundle}
# copy the bundle into /tmp so installp will have access to it
${CP} ${access_pnt} ${bundle_access} 2>${ERR} || \
err_from_cmd "${CP} ${access_pnt} ${bundle_access}"
# unmount
nim_unmount ${access_pnt}
else
# already local - just copy it
${CP} ${bundle} ${bundle_access} 2>${ERR} || \
err_from_cmd "${CP} ${bundle} ${bundle_access}"
fi
} # end of prep_bundle
#---------------------------- lppchk_uv_root --------------------------------
#
# NAME: lppchk_uv_root
#
# FUNCTION:
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
# calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
# parameters:
# 1 = pathame of the root directory to sync
# global:
# installp_flags
# filesets
# bundle
# tmp_files
# chroot
#
# RETURNS: (int)
# 0 = success
# 1 = failure
#
# OUTPUT:
#-------------------------------------------------------------------------------
function lppchk_uv_root {
typeset root=${1}
typeset op=""
typeset name=""
typeset lev=""
# setup the chroot environment using the specified root directory
setup_chroot_env ${root}
# perform the lppchk operation to find out what needs to be done
# to sync up the current root.
${chroot} ${LPPCHK} -uv | \
while read op name lev
do
case ${op} in
-C) echo ${name} ${lev} >> ${cleanup_sync_list}
;;
-a) echo ${name} ${lev} >> ${apply_sync_list}
;;
-ac) echo ${name} ${lev} >> ${apply_sync_list}
echo ${name} ${lev} >> ${commit_sync_list}
;;
-c) echo ${name} ${lev} >> ${commit_sync_list}
;;
-u) echo ${name} ${lev} >> ${deinstl_sync_list}
;;
-r) echo ${name} ${lev} >> ${reject_sync_list}
;;
ERR) # do nothing
;;
\?) # do nothing
;;
esac
done
} # end of lppchk_uv_root
#---------------------------- sync_root --------------------------------
#
# NAME: sync_root
#
# FUNCTION:
# performs the specified installp operation on the specified root directory
# by setting up a chroot environment
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
# calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
# parameters:
# 1 = pathame of the root directory to sync
# global:
# installp_flags
# filesets
# bundle
# tmp_files
# chroot
#
# RETURNS: (int)
# 0 = success
# 1 = failure
#
# OUTPUT:
#-------------------------------------------------------------------------------
function sync_root {
typeset root=${1}
typeset name=${root##*/}
typeset f_flag=""
# Setup the chroot environment using the specified root directory.
# (if we're doing a full_sync, we should have already done this.)
if [[ -z "${full_sync}" ]]
then
setup_chroot_env ${root}
fi
# use a bundle file?
if [[ -n "${bundle}" ]]
then
# copy the bundle into the root directory
${CP} ${bundle} ${root}/bundle 2>${ERR} || err_from_cmd ${CP}
tmp_files="${tmp_files} ${root}/bundle"
# use the bundle
f_flag="-f /bundle"
fi
# perform the installp operation
export INUCLIENTS=yes
${chroot} ${INSTALLP} -e ${INSTALLP_LOG} ${installp_flags} ${f_flag} \
${filesets} </dev/null 2>${ERR} 1>&2
rc=$?
# Don't exit if doing a complete sync op
if [[ -n "${full_sync}" ]]
then
if [[ $rc -ne 0 ]]
then
warning_from_cmd ${INSTALLP}
fi
else
if [[ $rc -ne 0 ]]
then
err_from_cmd ${INSTALLP}
fi
exit 0
fi
} # end of sync_root
#---------------------------- full_sync_root -------------------------------
#
# NAME: full_sync_root
#
# FUNCTION:
#
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
#
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
# parameters:
# 1 = pathame of the root directory to sync
# global:
# installp_flags
# filesets
# bundle
# tmp_files
# chroot
#
# RETURNS: (int)
# 0 = success
# 1 = failure
#
# OUTPUT:
#-------------------------------------------------------------------------------
function full_sync_root {
typeset orig_flags="${installp_flags}"
lppchk_uv_root ${1}
if [[ -s "${cleanup_sync_list}" ]]
then
installp_flags="-C ${orig_flags}"
sync_root ${1}
fi
if [[ -s "${apply_sync_list}" ]]
then
installp_flags="-aXg ${orig_flags}"
bundle="${apply_sync_list}"
sync_root ${1}
fi
if [[ -s "${commit_sync_list}" ]]
then
installp_flags="-cg ${orig_flags}"
bundle="${commit_sync_list}"
sync_root ${1}
fi
if [[ -s "${deinstl_sync_list}" ]]
then
installp_flags="-ugX ${orig_flags}"
bundle="${deinstl_sync_list}"
sync_root ${1}
fi
if [[ -s "${reject_sync_list}" ]]
then
installp_flags="-rgX ${orig_flags}"
bundle="${reject_sync_list}"
sync_root ${1}
fi
exit 0
} # end of full_sync_root
#---------------------------- lslpp_root --------------------------------
#
# NAME: lslpp_root
#
# FUNCTION:
# displays LSLPP info for the specified root
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
# calls error on failure
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
# parameters:
# 1 = pathame of the root directory to sync
# global:
# chroot
#
# RETURNS: (int)
# 0 = success
# 1 = failure
#
# OUTPUT:
#-------------------------------------------------------------------------------
function lslpp_root {
typeset root=${1}
# setup the chroot environment using the specified root directory
setup_chroot_env ${root}
# display the LSLPP info
${chroot} ${LSLPP} -al 2>${ERR} || err_from_cmd ${LSLPP}
exit 0
} # end of lslpp_root
#---------------------------- c_sync_root --------------------------------
#
# NAME: c_sync_root
#
# FUNCTION:
# performs installp operations on diskless/dataless root parts
# this is done by mounting the SPOT over each clients root, then chrooting
# into the client's root and performing the requested installp operation
#
# EXECUTION ENVIRONMENT:
#
# NOTES:
# this script will stop when the first time installp returns an error
#
# RECOVERY OPERATION:
#
# DATA STRUCTURES:
# parameters:
# global:
#
# RETURNS: (int)
# 0 = installp success on all roots
# 1 = installp or other error encountered
#
# OUTPUT:
#-------------------------------------------------------------------------------
# signal processing
trap cleanup 0
trap err_signal 1 2 11 15
# NIM initialization
nim_init
# initialize local variables
typeset c=""
typeset sync_one=""
typeset list_only=""
typeset params=""
typeset root=""
typeset name=""
typeset rc=0
typeset bundle_access=""
typeset full_sync=""
# set parameters from command line
while getopts :a:lqsvf 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}\"
;;
f) # Doing a full sync op
full_sync=TRUE
;;
l) # list LPP info
list_only=TRUE
;;
q) # show attr info
cmd_what
exit 0
;;
s) # perform one root sync only
sync_one=TRUE
;;
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
shift OPTIND-1
# check for missing attrs
ck_attrs
# do lslpp stuff and exit if that's what we were called to do
if [[ -n "${list_only}" ]]
then
lslpp_root ${1}
fi
# were neither filesets nor bundle file specified?
if [[ -z "${filesets}" ]] && [[ -z "${bundle}" ]]
then
if [[ -z "${installp_flags}" ]]
then
full_sync=TRUE
elif [[ "${installp_flags}" = *a* ]]
then
filesets=all
fi
# either filesets or bundles were specified, how about installp flags?
elif [[ -z "${installp_flags}" ]]
then
# nope, assume apply operation.
installp_flags="-agX"
fi
# make sure "Or" is in the installp_flags
[[ "${installp_flags}" != *Or* ]] && installp_flags="-Or ${installp_flags}"
# make sure dashes are acceptable
installp_flags=$( ck_installp_flags "${installp_flags}" )
# perform one root sync (if that's what we were called to do)
if [[ -n "${sync_one}" ]]
then
if [[ -n "${full_sync}" ]]
then
# perform all installp ops necessary to sync root
full_sync_root ${1}
else
# If syncing the inst_root of a /usr SPOT,
# a) do some space checking and auto-expand if necessary.
# b) prep bundle file if necessary (since we didn't follow
# the normal path of execution for this sync op).
if [[ ${1} = "/usr/lpp/bos/inst_root" ]]
then
[[ "${installp_flags}" = *a* ]] && ck_instroot_cust_sz
[[ -n "${bundle}" ]] && prep_bundle && \
bundle=${bundle_access}
fi
# perform installp op that was specified
sync_root ${1}
fi
fi
# else, perform multiple root syncs in parallel
# Before doing multiple root syncs, do some semantic checking on any user
# specified arguments. (Do it here rather than prior to sync_root call so
# that it's not performed for every client -- not necessary.)
# was bundle specified?
if [[ -n "${bundle}" ]]
then
# check for errors
[[ -n "${filesets}" ]] && \
error ${ERR_ATTR_CONFLICT} bundle filesets
# setup local access
prep_bundle
elif [[ ${installp_flags} = *u* ]] || [[ ${installp_flags} = *c* ]] || \
[[ ${installp_flags} = *+([ -])r* ]]
then
# this is a remove or commit operation: filesets must be specified
[[ -z "${filesets}" ]] && error ${ERR_MISSING_ATTR} filesets
fi
# for each root pathname given as an operand...
for root
do
# sync this root directory in the background
${C_SYNC_ROOT} -s -a location=${location} \
-a installp_flags="${installp_flags}" \
${bundle:+"-abundle=${bundle_access}"} \
${filesets:+-afilesets="${filesets}"} \
${full_sync:+-f} \
${root} 2>${TMPDIR}/${root##*/}.failed &
done
# wait for all syncs to finish
wait
# look for failures
failed=$( ${LS} -1 ${TMPDIR}/*.failed 2>/dev/null )
if [[ -n "${failed}" ]]
then
for root in ${failed}
do
# make sure the operation really failed (ie, there's output in the file)
[[ ! -s ${root} ]] && continue
name=${root%.failed}
name=${name##*/}
print "\t${name}"
rc=${ERR_ROOT_SYNC}
done
fi
# all done
exit ${rc}