#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2005,2006 # 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 # @(#)93 1.1.1.3 src/avs/fs/mmfs/ts/admin/mmsdrrestore.sh, mmfs, avs_rgpfs24, rgpfs240610b 2/17/06 16:51:07 ############################################################################## # # Ensure that the GPFS system files on the specified nodes are at the # most recent level. If the local mmsdrfs file is missing, use the file # specified with the -F option from the node specified with the -p option. # # Usage: # mmsdrrestore [-p NodeName] [-F mmsdrfsFile] [-R remoteFileCopyCommand] # [-a | -N {Node[,Node...] | NodeFile | NodeClass}] # # where: # -p NodeName specifies the node from which to obtain a valid # mmsdrfs file. This should be either the primary # configuration server or a node that contains a # valid backup copy of the mmsdrfs file. # If not specified, the local node is assumed. # # -F mmsdrfsFile specifies the pathname of the mmsdrfs file to use. # If not specified, /var/mmfs/gen/mmsdrfs is assumed. # # -R remoteFileCopyCommand specifies the fully-qualified pathname for # the remote file copy program to be used for staging # the mmsdrfs file. The default is /usr/bin/rcp. # # Future options: # -a Restore all nodes in the GPFS cluster. # # -N Node,Node,... specifies the affected nodes in a list or in a file. # -N NodeFile NodeClass may be one of several possible node classes # -N NodeClass (e.g., quorumnodes, managernodes, nsdnodes, etc.) # # Notes: # If not explicitly specified otherwise, only the local node is affected. # # If the -p and/or -F parameters are specified, i.e., if the local mmsdrfs # file will be replaced, the command must be first run on the primary and # backup cluster configuration servers. # # If the local mmsdrfs file is going to be replaced, the command saves # the original file as /var/mmfs/gen/mmsdrfs.mmsdrrestore.backup # # The -R option has to be specified only if the mmsdrfs file needs to be # copied from a different node and the cluster was set to use ssh/scp. # Once the correct mmsdrfs file is staged, the rest of the code will use # the remote commands that have been defined for the cluster. In other # words, you can not change the remote shell and file copy programs with # the mmsdrrestore command; use mmchcluster for this purpose once the # cluster has been restored. # ############################################################################## # Include global declarations and service routines. . /usr/lpp/mmfs/bin/mmglobfuncs . /usr/lpp/mmfs/bin/mmsdrfsdef . /usr/lpp/mmfs/bin/mmfsfuncs sourceFile="mmsdrrestore.sh" [[ -n $DEBUG || -n $DEBUGmmsdrrestore ]] && set -x $mmTRACE_ENTER "$*" # Local variables usageMsg=284 rc=0 # Local routines ##################################################################### # # Function: Verifies that a command executed successfully. If the # return code from the command is not zero, the function # issues a message, restores the original mmsdrfs file, # and exits. # # Input: $1 - text to be printed in the message # $2 - return code from the execution of the command # ##################################################################### function checkForErrorsAndRestoreOldFile { sourceFile="mmsdrrestore.sh" [[ -n $DEBUG || -n $DEBUGcheckForErrorsAndRestoreOldFile ]] && set -x $mmTRACE_ENTER "$*" typeset msgSub=$1 typeset rc=$2 if [ $rc != "0" ] then # If asked, issue an "unexpected error" message. [[ $msgSub != NOMSG ]] && \ printErrorMsg 171 "$mmcmd" "$msgSub" $rc # Remove the mmsdrfs file if it was copied from another place. [[ -n $userProvidedFile ]] && \ $rm -f $mmsdrfsFile # Restore the original mmsdrfs file. [[ -f ${mmsdrfsFile}.${mmcmd}.backup ]] && \ $mv -f ${mmsdrfsFile}.${mmcmd}.backup $mmsdrfsFile cleanupAndExit $2 fi } #------ end of function checkForErrorsAndRestoreOldFile ------- ####################### # Mainline processing ####################### ################################## # Process each of the arguments. ################################## [[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] && \ syntaxError "help" $usageMsg while getopts :aF:N:p:R: OPT do case $OPT in a) [[ -n $aflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" aflag="-$OPT" [[ -n $Nflag ]] && \ syntaxError "invalidCombination" $usageMsg $aflag $Nflag syntaxError "invalidOption" $usageMsg $OPT #esjx option not allowed yet ;; F) # source mmsdrfs file [[ -n $Farg ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Farg=$OPTARG ;; N) [[ -n $Nflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Nflag="-$OPT" nodenames="$OPTARG" [[ -n $aflag ]] && \ syntaxError "invalidCombination" $usageMsg $Nflag $aflag syntaxError "invalidOption" $usageMsg $OPT #esjx option not allowed yet ;; p) # primary server [[ -n $parg ]] && syntaxError "multiple" $noUsageMsg "-$OPT" parg=$OPTARG ;; R) # remote file copy command [[ -n $Rarg ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Rarg=$OPTARG [[ $Rarg != /* ]] && \ syntaxError "absolutePath_2" $noUsageMsg "-$OPT" "$OPTARG" ;; :) syntaxError "missingValue" $usageMsg $OPTARG ;; +[aFNpR]) syntaxError "invalidOption" $usageMsg "$OPT" ;; *) syntaxError "invalidOption" $usageMsg $OPTARG ;; esac done # end of while getopts :afF:N:p:r:R: OPT do shift OPTIND-1 [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 ########################################################### # Process the optional remote file copy command parameter. ########################################################### if [[ -n $Rarg ]] then if [[ ! -x $Rarg ]] then # The specified remote file copy command is incorrect # (it is not an executable). printErrorMsg 423 $mmcmd ${Rarg%% *} cleanupAndExit fi rcp="$Rarg" export GPFS_rcpPath="$rcp" fi ################################################################### # If an mmsdrfs file exists and we are told not to use it, create # a backup of the local mmsdrfs file before proceding any further. ################################################################### if [[ ( -n $parg || -n $Farg && $Farg != $mmsdrfsFile ) && -f $mmsdrfsFile ]] then $cp $mmsdrfsFile ${mmsdrfsFile}.${mmcmd}.backup checkForErrors "cp $mmsdrfsFile ${mmsdrfsFile}.${mmcmd}.backup" $? fi ############################################################## # If we are told where to find the good mmsdrfs file, get it. ############################################################## sourceNode=$parg sourceFile=$Farg [[ -z $sourceFile ]] && sourceFile=$mmsdrfsFile if [[ -n $parg ]] then # The file must be copied from a remote node. isNodeReachable $sourceNode if [[ $? -ne 0 ]] then # The node is not reachable. printErrorMsg 340 $mmcmd $sourceNode checkForErrorsAndRestoreOldFile NOMSG 1 fi rcpResult=$(LC_ALL=C $rcp ${sourceNode}:${sourceFile} $mmsdrfsFile 2>&1) rc=$? if [[ $rc -ne 0 ]] then # If there was no need to copy the file, that's fine. print -- "$rcpResult" | $grep -e "refer to the same file" >/dev/null if [[ $? -ne 0 ]] then # Show the error from the rcp command and give up. print -u2 "$rcpResult" checkForErrorsAndRestoreOldFile \ "$rcp ${sourceNode}:${sourceFile} $mmsdrfsFile" $rc fi fi # end of if [[ $rc -ne 0 ]] userProvidedFile=yes elif [[ $sourceFile != $mmsdrfsFile ]] then # The file must be copied from some other place within the local node. $cp $sourceFile $mmsdrfsFile checkForErrorsAndRestoreOldFile "cp $sourceFile $mmsdrfsFile" $? userProvidedFile=yes else : # The local mmsdrfs file is supposed to be good. fi # end of if [[ -n $parg ]] # At this point we must have an mmsdrfs file to work with. if [[ ! -f $mmsdrfsFile ]] then # Either the node does not belong to a cluster # or the config information is lost/corrupted. printErrorMsg 282 $mmcmd checkForErrors "$mmcmd: Missing /var/mmfs/gen/mmsdrfs" 1 fi # If this is a user-specified mmsdrfs file, perform a quick sanity check. if [[ -n $userProvidedFile ]] then checkSdrfsFile $mmsdrfsFile checkForErrorsAndRestoreOldFile "$mmcmd: Invalid input file" $? fi ######################################################################## # See if this node belongs to the cluster defined by this mmsdrfs file. ######################################################################## # Remove the local mmfsNodeData file. We will derive the information # based on the currently active IP addresses of the node. $rm -f $mmfsNodeData # Determine the node's GPFS node number by checking all local addresses. nodeData=$(guessLocalNodeNumber) rc=$? set -f ; set -- $nodeData ; set +f ourNodeNumber=$1 ourNodeName=$3 if [[ -z $ourNodeNumber ]] then # The node does not appear to belong to the cluster rpresented # by this mmsdrfs file. Either the file is from a different # cluster, or not all adapter interfaces have been activated. # Or the node indeed is not part of the cluster. # Determine the name of the source file for the message. sdrfs="$sourceFile" [[ -n $sourceNode ]] && sdrfs="${sourceNode}:${sourceFile}" # There is no record for this node in the file. printErrorMsg 283 $mmcmd $sdrfs checkForErrorsAndRestoreOldFile NOMSG 1 fi ############################################################################# # At this point, the current mmsdrfs file is assumed to be the correct one. # The code continues with the standard gpfsInit processing. This means # that the primary or backup servers, as per the current mmsdrfs file, # will be consulted to ensure this is indeed the latest version of the file. ############################################################################# # Remove the current versions of the system files to force the environment # to be rebuilt based on the information in the new mmsdrfs file. $rm -f $mmfscfgFile $mmfsNodeData ${mmfsEnvLevel}+([0-9]) \ ${mmfsNewKeyLevel}+([0-9]) ${mmfsCommittedKeyLevel}+([0-9]) \ $nsdpvol ######################################################################## # Set up trap exception handling and call the gpfsInit function. # It will ensure that the local copy of the mmsdrfs and the rest of the # GPFS system files are up-to-date. There is no need to lock the sdr. ######################################################################## trap pretrap2 HUP INT QUIT KILL gpfsInitOutput=$(gpfsInit nolock) setGlobalVar $? $gpfsInitOutput ########################################################### # Ensure the sdrserv daemon is running on this node only # if the node is a primary or backup configuration server. ########################################################### killSdrServ >/dev/null 2>&1 [[ $ourNodeName = $primaryServer || $ourNodeName = $backupServer ]] && \ startSdrServ CURRENT # The node was successfully restored. printErrorMsg 285 $mmcmd $ourNodeName # Done for now. The -a and -N options are not implemented yet. cleanupAndExit 0 ####################################################### # Create a file containing all of the affected nodes. ####################################################### if [[ -n $aflag ]] then # Get a list of all nodes in the cluster. getNodeList $REL_HOSTNAME_Field $GLOBAL_ID $mmsdrfsFile > $nodefile elif [[ -n $Nflag ]] then # Convert the passed data into a file containing admin node names. createVerifiedNodefile $nodenames $REL_HOSTNAME_Field no $nodefile [[ $? -ne 0 ]] && cleanupAndExit else : # Only the local node is affected. fi # end of if [[ -n $aflag ]] # Ensure we have the proper credentials. [[ $getCredCalled = no ]] && getCred #esjxx - If more than one node is involved AND a new mmsdrfs file was copied, #esjxx push the file to the rest of the affected nodes. This will be done #esjxx with a new mmremote call that will take care of mmsdrserv as well. #esjxx We will need to pass the names of the primary and backup servers #esjxx and clusterID to ensure that the individual nodes will go to the #esjxx right place for the correct version of the mmsdrfs file. #esjxx If the individual nodes have different information, they should go #esjxx to the correct primary only and specify current gen number 0 or 1. #esjxx This should apply to the backup too ??? ########################## # Restore the GPFS nodes. ########################## if [[ ! -s $nodefile ]] then : # This is a request to restore only the local node. We are done. else # This is a request to restore other nodes as well. $mmcommon onall $nodefile $unreachedNodes cfg -f rc=$? fi # end of if [[ ! -s $nodefile ]] # If any nodes could not be reached, tell the user which ones. if [[ -s $unreachedNodes ]] then # The following nodes could not be reached: . . . printErrorMsg 270 $mmcmd $cat $unreachedNodes 1>&2 fi cleanupAndExit $rc