#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # bos720 src/bos/usr/sbin/corrals/restwpar/restwpar.sh 1.19.2.12 # # Licensed Materials - Property of IBM # # COPYRIGHT International Business Machines Corp. 2007,2015 # 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 # @(#)80 1.19.2.12 src/bos/usr/sbin/corrals/restwpar/restwpar.sh, cmdcorral, bos720, 1519A_720 4/9/15 10:09:36 # ################# # # FILE NAME: restwpar # # Purpose # # Restores a workload partition. # Syntax # # restwpar [ -a ] [ -A ] [ -b devexportsFile ] [ -B Blocks ] [ -C ] \ # [ -d Directory ] [ -f Device ] [ -F ] [ -h hostName ] \ # [ -i imagedataFileName ] [ -M mkwparFlags ] [ -n wparName ] # [ -r ] [ -s ] [ -S { a | A | f | F | n } ] [ -U ] # [ -w wparSpecificationFile ] # # Description # # The restwpar command creates workload partition wparName from a workload # partition backup image created by the savewpar, mkcd, or mkdvd command. # # A workload partition backup image contains an image.data file and a workload # partition specification file which are used by default to establish the # characteristics of workload partition wparName. The -i and -w options can be # used to override these default files. # # If -f device is not specified, /dev/rmt0 is used as the input device. # # If a yes value has been specified in the EXACT_FIT field of the # logical_volume_policy stanza of the /tmp/wpardata/wparname/image.data file, # the restwpar command uses the map files to preserve the placement of the # physical partitions for each logical volume. # # Note: # To view the files in the backup image or to restore individual files from # the backup image, the user must use the lssavewpar command, the # restwparfiles command, or the restore command with the -T or -x flag, # respectively. (Refer to the restore command for more information.) ## . /usr/lib/wpars/libcor_sh init_baselib "restwpar" cor_init_vars wpar_msg_init "$*" wpar_FAIL_if_corralled wpar_FAIL_if_lvup ################################# cleanup_restwpar ####################################### # # NAME: cleanup_restwpar () # # DESCRIPTION: Unset traps, issue error message and exit w/ an error code # # INPUT: # $1 = exit code # $2 = error message if not null # # OUTPUT: # Error messages (Standard Error) # # RETURN VALUE DESCRIPTION: # exits with a return code of $1 # # NOTE: This function will not return (i.e., it will exit the entire # script with an exit value of $1) # cleanup_restwpar () { ec=$1 error=$2 case "$ec" in "$USAGE_EC" ) # restwpar usage error error="`${dspmsg} -s "$MSGSET_USAGE" "$MF_WPARS" "$USAGE_RESTWPAR" ' Usage: %s [-a] [-A] [-b Blocks] [-B devexportsFile ] [-C] [-d directory] [-f Device] [-F] [-h hostName] [-i imagedataFileName] [-k] [-K postInstallationScript] [-M mkwparFlags] [-n WPARName] [-r] [-s] [-S {a|A|f|F|n}] [-U] [-v] [-w wparSpecificationFile]\n -a\tAutomatically resolve erroneous/conflicting settings. -A\tStart automatically on system boot. -b\tNumber of 512-byte blocks to read in a single input operation. -B\tPath to permitted device exports file. -C\tContinue installation if compatibility check fails. -d\tBase directory. -f\tName of device to restore the information from. \tDefault is /dev/rmt0. -F\tForce creation of workload partition if it already exists. -h\tHostname. -i\tPath to alternate image.data file. -k\tCreate logical volumes with minimum sizes from the backup. -K\tPost-installation customization script. -M\tAdditional flags to pass to the mkwpar command. -n\tWorkload partition name. -r\tCopy global network name resolution configuration. -s\tStart after creation. -S {a|A|f|F|n} \tSpecifies type of synchronization to use to make software \tlevels in workload partition compatible with the global environment: \t a\tInstall additional software if required, but do not remove (default). \t A\tInstall additional software if required, but do not remove. \t \tDo not fail installation if synchronization fails. \t f\tFull synchronization - install or remove software as required. \t F\tFull synchronization - install or remove software as required. \t \tDo not fail installation if synchronization fails. \t n\tDo not perform any software synchronization. -U\tDo not use any existing MAP files. -v\tVerbose mode. -w\tPath to alternate mkwpar input specification file.\n\n' $NAME`" 1>&2 ;; "$EXIT_EC" | "$TRAP_EC") ;; *) ;; esac cd / ${rm} -r $WPARDATA_TMPDIR > /dev/null 2>&1 # Remove $WORKDIR, if any, created by init_baselib [ -n "$WORKDIR" ] && rm -rf "$WORKDIR" > /dev/null 2>&1 [ -n "$error" ] && echo "\n${error}\n" trap '' 1 2 15 exit "$ec" } #################################################### getoptions () { DEVICE=/dev/rmt0 # Parse command line arguments set -- `${getopt} aAb:B:Cd:f:Fh:i:K:kM:n:rsS:Uvw:? $*` # restwpar options if [ $? -ne 0 ] then cleanup_restwpar "$USAGE_EC" "" ## Display usage message fi while [ $1 != -- ] ## Parse flag arguements do case $1 in -a|-A|-r|-s) ## Passtrough flags to mkwpar MKWPAR_FLAGS="$MKWPAR_FLAGS $1";; -d|-h) ## Passtrough flags with args to mkwpar MKWPAR_FLAGS="$MKWPAR_FLAGS $1 $2"; shift;; -B) ## Passtrough flags with args to mkwpar MKWPAR_FLAGS="$MKWPAR_FLAGS -b $2"; shift;; -K) ## Passtrough flags with args to mkwpar MKWPAR_FLAGS="$MKWPAR_FLAGS -k $2"; shift;; -n) ## Note new name to check WPAR_NAME=$2 MKWPAR_FLAGS="$MKWPAR_FLAGS $1 $2"; shift;; -b) BOPT="-b $2"; shift ;; ## get number of blocks -C) FORCE_COMPAT="yes";; ## Ignore system incompatibility ## get backup device: -f) DEVICE=$2; shift ;; ## User provided vgname.data: -F) FORCE_REMOVE="yes";; ## Remove wpar with same name -i) IMAGEDATAFLAG="yes"; IMAGE_DATA=$2; shift IMAGE_DATA=$(${relative_to_absolute} $IMAGE_DATA) ;; -k) SHRINK="shrink=yes" ;; ## Shrink file systems -M) MKWPAR_FLAGS="$MKWPAR_FLAGS $2"; shift;; -S) ## Synchronization setting case $2 in a) CPOPSYNC="apply";; A) CPOPSYNC="apply"; CPOPFORCE="yes";; f) CPOPSYNC="full";; F) CPOPSYNC="full"; CPOPFORCE="yes";; n) CPOPSYNC="none";; *) cleanup_restwpar "$USAGE_EC" "";; ## Display usage message esac;; -U) IGNORE_MAPS="ignore_maps=yes" ;; ## Do not use maps -v) VFLAG=-v ;; -w) WPARSPECFLAG="yes"; WPAR_SPEC=$2; shift WPAR_SPEC=$(${relative_to_absolute} $WPAR_SPEC) ;; "-?") cleanup_restwpar "$USAGE_EC" "";; ## Display usage message esac shift done [ $VFLAG ] && wpar_msg_init shift # "--" if [ "$#" -gt 0 ] then cleanup_restwpar "$USAGE_EC" "" fi RESTWFILEFLAGS="$BOPT" } #################################################### # check_cre - # check to see if the ostype associated with # the backup is non-zero. If ostype is defined # and != 0, return 0. Otherwise, return 1. #################################################### function check_cre { # Use awk to extract attribute of ostype field from # stanza-format WPAR specification file CRE_LEVEL=`${awk} ' BEGIN { n=0 } { # Find the general stanza if ($0 ~ /^[^#*:[:space:]]+:[[:space:]]*$/) { if ( $0 ~ /^general:[[:space:]]*$/ ) { n = 1 } else { n = 0 } } # If in the general stanza, locate the ostype attribute if ( ( n == 1 ) && ( /^[[:space:]]+ostype[[:space:]]*=[[:space:]]*/ ) ) { # Remove everything up-to the value, including a double-quote gsub(/^[^=]*=[[:space:]]*"?/,"") # Remove final double-quote, and any trailing spaces after the value gsub(/"?[[:space:]]*$/,"") # Print the ostype value and cease parsing immediately print $0 exit } }' $WPAR_SPEC` # Now use awk to extract value of convert2 field from # stanza-format WPAR specification file CONVERT2=`${awk} ' BEGIN { n=0 } { # Find the general stanza if ($0 ~ /^[^#*:[:space:]]+:[[:space:]]*$/) { if ( $0 ~ /^general:[[:space:]]*$/ ) { n = 1 } else { n = 0 } } # If in the general stanza, locate the convert2 attribute if ( ( n == 1 ) && ( /^[[:space:]]+convert2[[:space:]]*=[[:space:]]*/ ) ) { # Remove everything up-to the value, including a double-quote gsub(/^[^=]*=[[:space:]]*"?/,"") # Remove final double-quote, and any trailing spaces after the value gsub(/"?[[:space:]]*$/,"") # Print the convert2 value and cease parsing immediately print $0 exit } }' $WPAR_SPEC` if [[ -z "$CRE_LEVEL" ]] || [[ "$CRE_LEVEL" = "0" ]] || [[ "$CONVERT2" = "vwpar_0" ]] then return 1 fi return 0 } #################################################### # check_compatibility - # check to see if the libc of the wpar # is the same as the level of the global. # If not, issue a message. If the -C option # is specified continue, else error off. #################################################### function check_compatibility { typeset imagelibclvl typeset systemlibclvl typeset compat_fail= typeset cp_bos_update_fail= # Extract colon-separated libc line out of backup.data file, # which is of this this form: # bos:bos.rte.libc:5.4.0.0: : :C: :libc Library: : : : : : :1:0:/ imagelibclvl=`${awk} -F: '/^bos:bos\.rte\.libc:/ {print $3}' $WPARDATA_TMPDIR/backup.data` systemlibclvl=`${lslpp} -qlc -Ou bos.rte.libc | ${awk} -F':' '{print $3}'` if [ -z "$imagelibclvl" ] || [ -z "$systemlibclvl" ] then compat_fail="yes" wpar_print_msg "$WARNING_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_REST_SYS_COMPAT" \ '%s: 0960-506 Could not perform system compatibility check.\n' $NAME else if [ "$imagelibclvl" != "$systemlibclvl" ] then # Issue informational message wpar_print_msg "$WARNING_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_REST_LVL_SAVED_IMG" \ '%s: 0960-507 Level %s of bos.rte.libc in saved image does not match level %s on the running system.\n' \ $NAME $imagelibclvl $systemlibclvl compat_fail="yes" fi fi ### 7H8 securityVRMF=`${lslpp} -Or -Ilqc bos.rte.security | cut -d: -f3` ### if this directory doesn't exist we know cp_bos_updates has not run, ### so neither will /usr/lpp/bos/bos.rte/$VRMF/inst_root exist ### bos.rte.security has had a root part since 6.1.0.1 and 7.1.0.1 ### and I verified both first updates actually had inst_root parts if [[ ! -d /usr/lpp/bos/bos.rte.security/$securityVRMF/inst_root ]] then ### Now we need to check if there are other updates for bos.rte rteVRMF=`${lslpp} -Or -Ilqc bos.rte | cut -d: -f3` latestrteVRMF=`${lslpp} -Or -lqc bos.rte | cut -d: -f3` if [[ $rteVRMF = $latestrteVRMF ]] then cp_bos_update_fail="yes" fi fi # If compatibility test failed, error off unless -C specified if [ "$compat_fail" = "yes" ] then if [ "$FORCE_COMPAT" != "yes" ] then wpar_print_msg "$ERROR_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_REST_COMPAT_FAILED" \ '%s: 0960-508 Compatibility check between saved and running system failed.\n\tUse the -C option to ignore system compatibility levels.\n' $NAME if [ "$cp_bos_update_fail" = "yes" ] then wpar_print_msg "$WARNING_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_RESTWPAR_CP_BOS_UPDATES_READ" \ '%s: 0960-754 Please run cp_bos_updates before you continue.\nSee /usr/lpp/bos/README.cp_bos_updates for information.\n' $NAME fi cleanup_restwpar "$EXIT_EC" else if [ "$cp_bos_update_fail" = "yes" ] then wpar_print_msg "$WARNING_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_RESTWPAR_CP_BOS_UPDATES_RUN" \ '%s: 0960-755 The command cp_bos_updates has not been run on this system.\nSee /usr/lpp/bos/README.cp_bos_updates for information.\n' $NAME fi fi fi return 0 } #################################################### # check_overwrite - # check to see if a wpar already exists with the # given name. If so, then emit an error message # and exit if the -F flag was not specified. # If -F, remove the previous version. If the # removal fails, error off. #################################################### function check_overwrite { WPAR=$1 if [[ ! -n "$WPAR" ]] then wpar_print_msg "$ERROR_MSG_LVL" "$WPAR" "$MSGSET_ERRWARN" "$MSG_REST_NAME_TO_CREATE" \ '%s: 0960-509 Could not determine name to create for workload partition. Use -n to specify a name.\n' $NAME cleanup_restwpar "$EXIT_EC" fi /usr/sbin/lswpar -qca name $WPAR >/dev/null 2>&1 || return 0 # WPAR exists. Error off unless force flag is set if [ "$FORCE_REMOVE" != "yes" ] then wpar_print_msg "$ERROR_MSG_LVL" "$WPAR" "$MSGSET_ERRWARN" "$MSG_REST_WP_ALREADY_EXISTS" \ '%s: 0960-510 Workload partition %s already exists. Use the -F option to force removal.\n' $NAME $WPAR cleanup_restwpar "$EXIT_EC" fi /usr/sbin/rmwpar -F $WPAR || { wpar_print_msg "$ERROR_MSG_LVL" "$WPAR" "$MSGSET_ERRWARN" "$MSG_REST_CANNOT_REMOVE_WP" \ '%s: 0960-511 Could not remove %s. Exiting.\n' $NAME $WPAR cleanup_restwpar "$EXIT_EC" } return 0 } #################################################### function create_tmp_dir { dirname=$1 oumask=`umask` umask 077 /usr/bin/mkdir $dirname if [[ $? -ne 0 ]] then umask $oumask wpar_print_msg "$ERROR_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_REST_TEMP_DIR" \ '%s: 0960-512 Could not create temporary directory %s\n' $NAME $dirname cleanup_restwpar "$EXIT_EC" fi umask $oumask return 0 } ###### end of function declarations ############### ###### start of main (Main) routine ############### if [ "$RESTWPARDEBUG" ]; then set -x for i in $(typeset +f); do typeset -ft $i done fi # # set up environment # export PATH="/usr/bin:/usr/sbin:/etc:$PATH" export RESTWPAR="true" ## Flag to indicate restwpar is running ## (Used by mkwpar and populate) NAME=`/usr/bin/basename $0` USAGE_EC=1 ## Exit code for usage error EXIT_EC=2 ## Exit code TRAP_EC=4 ## Exit code for trap DEVICE="/dev/rmt0" ## Initialize backup device to rmt0 BOPT= ## Blocks for the B option to restore USEMAP="yes" ## Option to not use existing map files WPARDATA_TMPDIR=/tmp/wpardata.$$ IMAGE_DATA="" ## Initialize vgname.data file to null IMAGEDATAFLAG="no" ## Set IMAGEDATAFLAG to no unless -d flag is given. CDMOUNTPT=$WPARDATA_TMPDIR/cdmount CPOPSYNC= CPOPFORCE= FORCE_COMPAT= WPAR_NAME= PRIVATEUSR= SHRINK= IGNORE_MAPS= IGNORE_LVS="ignore_lvs=no" ## Full-Path to commands used relative_to_absolute=/usr/lib/instl/realpath awk=/usr/bin/awk dspmsg=/usr/bin/dspmsg getopt=/usr/bin/getopt grep=/usr/bin/grep egrep=/usr/bin/egrep ls=/usr/bin/ls mkdir=/usr/bin/mkdir mount=/usr/sbin/mount perl=/usr/bin/perl rm=/usr/bin/rm restore=/usr/sbin/restore sed=/usr/bin/sed mt=/usr/bin/mt umount=/usr/sbin/umount lslpp=/usr/bin/lslpp # # Trap on exit/interrupt/break to clean up # trap "cleanup_restwpar $TRAP_EC \"`${dspmsg} -s "$MSGSET_ERRWARN" "$MF_WPARS" "$MSG_REST_ABNORMAL_TERM" \ '%s: 0960-513 Abnormal program termination.\n' $NAME`"\" 1 2 15 # Before performing normal option processing, extract any passthrough -M # options out of the argument list before processing via getopt # ${getopt} aAb:B:Cd:f:Fh:i:klM:n:rsS:Uvw:? $*` # restwpar options CMDARGS="" MKWPAR_FLAGS="" while [ $# -gt 0 ] do if [ "$1" = '-M' ] then MKWPAR_FLAGS="$MKWPAR_FLAGS $2" shift; shift else CMDARGS="$CMDARGS $1" shift fi done getoptions $CMDARGS # Parse the commandline arguements DEVICE=$(${relative_to_absolute} $DEVICE) create_tmp_dir $WPARDATA_TMPDIR ln -sf $WPARDATA_TMPDIR $WPARDATA_TMPDIR/.savewpar_dir # Restore control files. Even if -i and -f were specified # we still need the backup.data file for the # compatibility check /usr/bin/restwparfiles -d $WPARDATA_TMPDIR -m -f $DEVICE rc=$? if [[ $rc -ne 0 ]] then wpar_print_msg "$ERROR_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_REST_EXITED_RC" \ '%s: 0960-514 %s exited with return code %s.\n' $NAME /usr/sbin/mkwpar $rc cleanup_restwpar "$EXIT_EC" fi if [[ "$IMAGEDATAFLAG" != "yes" ]] then IMAGE_DATA=$WPARDATA_TMPDIR/image.data fi if [[ "$WPARSPECFLAG" != "yes" ]] then WPAR_SPEC=$WPARDATA_TMPDIR/wpar.spec fi for infile in $IMAGE_DATA $WPAR_SPEC do [ -f $infile ] || { wpar_print_msg "$ERROR_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_REST_OPEN_FILE" \ '%s: 0960-515 Could not open file %s.\n' $NAME $infile cleanup_restwpar "$EXIT_EC" } done [ -n "$CPOPSYNC" ] && export CPOPSYNC [ -n "$CPOPFORCE" ] && export CPOPFORCE export RESTWFILEFLAGS # If not specified, extract name of wpar from the general.name stanza if [ ! -n "$WPAR_NAME" ] then # Use awk to extract attribute of name field from # stanza-format WPAR specification file export WPAR_SPEC WPAR_NAME=`${awk} ' BEGIN { n=0 } { # Find the general stanza if ($0 ~ /^[^#*:[:space:]]+:[[:space:]]*$/) { if ( $0 ~ /^general:[[:space:]]*$/ ) { n = 1 } else { n = 0 } } # If in the general stanza, locate the name attribute if ( ( n == 1 ) && ( /^[[:space:]]+name[[:space:]]*=[[:space:]]*/ ) ) { # Remove everything up-to the value, including a double-quote gsub(/^[^=]*=[[:space:]]*"?/,"") # Remove final double-quote, and any trailing spaces after the value gsub(/"?[[:space:]]*$/,"") # Print the name and cease parsing immediately print $0 exit } }' $WPAR_SPEC` fi # Find out if this is a private WPAR export WPAR_SPEC PRIVATEUSR=`${awk} ' BEGIN { n=0 } { # Find the general stanza if ($0 ~ /^[^#*:[:space:]]+:[[:space:]]*$/) { if ( $0 ~ /^general:[[:space:]]*$/ ) { n = 1 } else { n = 0 } } # If in the general stanza, locate the privateusr attribute if ( ( n == 1 ) && ( /^[[:space:]]+privateusr[[:space:]]*=[[:space:]]*/ ) ) { # Remove everything up-to the value, including a double-quote gsub(/^[^=]*=[[:space:]]*"?/,"") # Remove final double-quote, and any trailing spaces after the value gsub(/"?[[:space:]]*$/,"") # Print the name and cease parsing immediately print $0 exit } }' $WPAR_SPEC` # Check to see if it is restoring a compatibility runtime environment backup. check_cre if [[ $? -ne 0 ]] then check_compatibility fi check_overwrite $WPAR_NAME cd $WPARDATA_TMPDIR /usr/bin/grep -q "^fs_data:" $IMAGE_DATA if [[ $? -ne 0 ]] then # If there are no local file systems, and this is a private WPAR, then # we check to see if the backup includes the data from /usr # If not, then we should use -p on mkwpar to preserve the existing /usr data if [[ "$PRIVATEUSR" == "yes" ]] then /usr/sbin/restore -Tq -f $DEVICE 2>/dev/null | /usr/bin/grep -q "\/usr\/ccs\/lib\/libc.a.min" # If libc.a.min not included in backup, we better preserve the existing data if [[ $? -ne 0 ]] then PRESERVE="-p" fi fi fi # by default mkwpar -L options is built with: # "-L image_data=$IMAGE_DATA $SHRINK $IGNORE_MAPS" # except if all or part of related attributes are specified in the MKWPAR_FLAGS # so those lines are merging the options as one set. typeset need_L=1; typeset need_image=1; if [[ "$MKWPAR_FLAGS" == *image_data=* ]]; then need_L=0 need_image=0; fi if [[ "$MKWPAR_FLAGS" == *shrink=* ]]; then need_L=0 fi if [[ "$MKWPAR_FLAGS" == *ignore_maps=* ]]; then need_L=0 fi if [[ "$MKWPAR_FLAGS" == *ignore_lvs=* ]]; then need_L=0 IGNORE_LVS= fi [ $need_L -eq 1 ] && IMAGE_DATA_SETUP="-L " [ $need_image -eq 1 ] && IMAGE_DATA_SETUP="$IMAGE_DATA_SETUP image_data=$IMAGE_DATA" IMAGE_DATA_SETUP="$IMAGE_DATA_SETUP $SHRINK $IGNORE_MAPS $IGNORE_LVS" if [ $need_L -eq 0 ]; then flag1=${MKWPAR_FLAGS%%L *}; flag1="${flag1}L" flag2=${MKWPAR_FLAGS#*L } MKWPAR_FLAGS="$flag1 $IMAGE_DATA_SETUP $flag2" else MKWPAR_FLAGS="$MKWPAR_FLAGS $IMAGE_DATA_SETUP" fi # restwpar regurgitates the WPAR spec for mkwpar, since the invoking user might # might not have all of the necessary DAC privileges. /usr/sbin/mkwpar $MKWPAR_FLAGS $PRESERVE -B $DEVICE -f - <$WPAR_SPEC rc=$? if [ $rc -ne 0 ] then wpar_print_msg "$ERROR_MSG_LVL" "$WPAR_NAME" "$MSGSET_ERRWARN" "$MSG_REST_EXITED_RC" \ '%s: 0960-514 %s exited with return code %s.\n' $NAME /usr/sbin/mkwpar $rc cleanup_restwpar "$EXIT_EC" fi cleanup_restwpar 0