#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2004,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 # @(#)76 1.2.3.2 src/avs/fs/mmfs/ts/admin/mmfsctl.sh, mmfs, avs_rgpfs24, rgpfs24s005a 6/14/06 14:40:21 ################################################################################ # # Usage: # # mmfsctl Device {suspend | resume} # or # mmfsctl Device {exclude | include} # {-d DiskList | -F DiskFile | -G FailureGroup} # or # mmfsctl Device syncFSconfig # {-n RemoteNodes | -C RemoteCluster} [-S SpecFile] # # where # # Device The device name of the affected GPFS file system. # # suspend Suspend the execution of all new I/O requests coming # from user applications, flush all pending requests # on all nodes, bring the file system to a consistent # state on disk. # # resume Resume normal processing of I/O requests on all nodes. # # exclude Exclude the specified disks when determining the # most recent file system control data structures. # This has the effect of overriding the normal GPFS # quorum requirements for on-disk file system data # and stops the disks from participating into normal # file systems operations. # # include Restore the specified disks for normal file system # operations. # # -d DiskList The names of the disks to be excluded or included. # If there is more than one disk, delimit each name with # a semicolon (;) and enclose the list in quotation marks. # # -F DiskFile A file that contains, one per line, the names of the # disks to be excluded or included. # # -G FailureGroup Exclude or include all disks that belong to the # specified failure group. # # syncFSconfig Synchronize the file system configuration information # in a remote cluster with the file system information # in the local cluster. # # -C RemoteCluster The name of the remote cluster where the file system # information is to be imported. The cluster must # already be registered with the mmremotecluster command. # # -n RemoteNodes The path name to a file containing, one per line, # hostnames or IP addresses of nodes that belong to # the remote cluster. # # -S SpecFile The path name to a file with the NSD server designations # in the remote cluster for all affected disks. The file # format is the same as for the -S parameter of mmimportfs. # Note that SpecFile refers to a file in the remote cluster # and must exist on all nodes in the contact node list. # ################################################################################ # Include global declarations and service routines. . /usr/lpp/mmfs/bin/mmglobfuncs . /usr/lpp/mmfs/bin/mmsdrfsdef . /usr/lpp/mmfs/bin/mmfsfuncs sourceFile="mmfsctl.sh" [[ -n $DEBUG || -n $DEBUGmmfsctl ]] && set -x $mmTRACE_ENTER "$*" # Local work files. Names should be of the form: # fn=${tmpDir}fn.${mmcmd}.$$ tmpDiskFile=${tmpDir}tmpDiskFile.${mmcmd}.$$ LOCAL_FILES=" $tmpDiskFile " # Local variables usageMsg=484 typeset -l action # Local functions ##################################################################### # # Function: Depending on the specified action, either suspend # or resume I/O activity for a given file system. # # Input: $1 - file system device name # $2 - action: suspend, suspendandflush, or resume # # Output: None. # # Returns: 0 - no errors encountered # 1 - unexpected error # ##################################################################### function fsSuspendOrResume # { typeset sourceFile="mmfsctl.sh" [[ -n $DEBUG || -n $DEBUGfsSuspendOrResume ]] && set -x $mmTRACE_ENTER "$*" typeset device=$1 typeset action=$2 typeset gpfsInitOutput findFSoutput fqDeviceName fsHomeCluster typeset nodeCount preferredNode typeset rc=0 [[ $action = suspend ]] && action=suspendandflush ##################################################################### # Set up trap exception handling and ensure that the local copy of # the mmsdrfs is up-to-date. There is no need to lock mmsdrfs file. ##################################################################### trap pretrap2 HUP INT QUIT KILL gpfsInitOutput=$(gpfsInit nolock) setGlobalVar $? $gpfsInitOutput ########################################################### # Make sure the specified file system exists and is local. ########################################################### findFSoutput=$(findFS "$device" $mmsdrfsFile) [[ -z $findFSoutput ]] && cleanupAndExit # Parse the output from the findFS function. set -f ; set -- $findFSoutput ; set +f fqDeviceName=$1 fsHomeCluster=$3 # Exit with a message if the command was invoked for a remote file system. if [[ $fsHomeCluster != $HOME_CLUSTER ]] then # Command is not allowed for remote file systems. printErrorMsg 106 $mmcmd $device $fsHomeCluster cleanupAndExit 1 fi ################################################## # First try to run the command on the local node. ################################################## ${mmcmdDir}/${links}/mmfsctl $fqDeviceName $action rc=$(remapRC $?) # If acceptable error (daemon not running, waiting for quorum), # try some other node. Otherwise, get out; the command either # worked or the errors are not acceptable. [[ $rc -ne $MM_DaemonDown && $rc -ne $MM_QuorumWait || $MMMODE = single ]] && \ return $rc ############################################################################ # If the local daemon is not available, send the command to an active node. ############################################################################ # Create a file with the reliable names of the nodes in the cluster. nodeCount=$(getNodeFile $REL_HOSTNAME_Field $GLOBAL_ID $mmsdrfsFile $nodefile) [[ $nodeCount = 0 ]] && \ checkForErrors "$mmcmd: No nodes found in the cluster." 1 # Try the nodes one by one until you find a node that can execute the command. preferredNode=0 # We have no idea where to go first; let mmcommon decide. $mmcommon linkCommand $preferredNode $nodefile mmfsctl $fqDeviceName $action rc=$? return $rc } #-------- end of function fsSuspendOrResume ---------------------- ##################################################################### # # Function: Mark the specified disks as excluded from stripe # group descriptor operations. # # Input: None explicit. This function uses the global variables # device, diskList, diskFile, and failureGroup. # # Output: None. # # Returns: 0 - no errors encountered # 1 - unexpected error # ##################################################################### function fsExcludeDisks # (parms passed via global variables) { typeset sourceFile="mmfsctl.sh" [[ -n $DEBUG || -n $DEBUGfsExcludeDisks ]] && set -x $mmTRACE_ENTER "$*" typeset gpfsInitOutput findFSoutput fqDeviceName fsHomeCluster deviceName typeset diskName disksToExclude sdrfsLine preferredNode tempList typeset excludeThisDisk typeset includedDisksFound="" typeset rc=0 ############################################################# # Create a blank-separated list of the disks to be excluded. ############################################################# if [[ -n $diskList ]] then # The input is specified in the form of a list of disk names. IFS=';' for diskName in $diskList do disksToExclude="${disksToExclude}${diskName}${BLANKchar}" done IFS="$IFS_sv" disksToExclude="${disksToExclude% }" elif [[ -n $diskFile ]] then # The disks are specified in a file. exec 3< $diskFile while read -u3 diskName do # Skip empty and comment lines. [[ $diskName = *([$BLANKchar$TABchar]) ]] && continue [[ $diskName = *([$BLANKchar$TABchar])#* ]] && continue # Put the disk name in the list. disksToExclude="${disksToExclude}${diskName}${BLANKchar}" done # end while read -u3 diskDesc disksToExclude="${disksToExclude% }" elif [[ -n $failureGroup ]] then : # The input must be a failure group; nothing to do for now. else # Something is very wrong. checkForErrors "fsExcludeDisks: Missing input parameters" 1 fi # end if [[ -n $diskList ]] # Is there anything to do? if [[ -z $disksToExclude && -z $failureGroup ]] then # No disks were specified. printErrorMsg 264 $mmcmd cleanupAndExit fi ####################################################################### # 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 and will obtain the sdr lock. ####################################################################### trap pretrap HUP INT QUIT KILL gpfsInitOutput=$(gpfsInit $lockId) setGlobalVar $? $gpfsInitOutput # Determine the lookup order for resolving host names. [[ $osName != AIX ]] && resolveOrder=$(setHostResolveOrder) ########################################################### # Make sure the specified file system exists and is local. ########################################################### findFSoutput=$(findFS "$device" $mmsdrfsFile) [[ -z $findFSoutput ]] && cleanupAndExit # Parse the output from the findFS function. set -f ; set -- $findFSoutput ; set +f fqDeviceName=$1 deviceName=$2 fsHomeCluster=$3 # Exit with a message if the command was invoked for a remote file system. if [[ $fsHomeCluster != $HOME_CLUSTER ]] then # Command is not allowed for remote file systems. printErrorMsg 106 $mmcmd $device $fsHomeCluster cleanupAndExit 1 fi ############################################## # Create the new version of the mmsdrfs file. ############################################## $rm -f $newsdrfs $nodefile IFS=":" exec 3<&- exec 3< $mmsdrfsFile while read -u3 sdrfsLine do # Parse the line. set -f ; set -A v -- - $sdrfsLine ; set +f IFS="$IFS_sv" # Restore the default IFS settings. # Change some of the fields depending on the type of line. case ${v[$LINE_TYPE_Field]} in $VERSION_LINE ) # This is the global header line. # Increment the generation number. newGenNumber=${v[$SDRFS_GENNUM_Field]}+1 v[$SDRFS_GENNUM_Field]=$newGenNumber ;; $MEMBER_NODE ) # Add the reliable node name to nodefile. print -- "${v[$REL_HOSTNAME_Field]}" >> $nodefile checkForErrors "writing to file $nodefile" $? # If this is the line for the node that is executing # this command, set the preferredNode variable. [[ ${v[$NODE_NUMBER_Field]} = $ourNodeNumber ]] && \ preferredNode=${v[$REL_HOSTNAME_Field]} ;; $SG_DISKS ) if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then # This is an SG_DISKS line that belongs to our filesystem. # See if this disk is one of the disks to be excluded. if [[ -n $failureGroup ]] then # Disks are to be excluded based on failure group. [[ ${v[$FAILURE_GROUP_Field]} = $failureGroup ]] && \ v[$EXCLUDE_Field]=$excludedDisk else # The disks to be excluded are specified in the disksToExclude list. tempList="" excludeThisDisk=no for diskName in $disksToExclude do if [[ $diskName = ${v[$DISK_NAME_Field]} ]] then # The disk represented by the current SG_DISKS line # is one of the disks that must be excluded. if [[ $excludeThisDisk = no ]] then # Mark the disk as excluded. v[$EXCLUDE_Field]=$excludedDisk excludeThisDisk=yes else # We have already seen this name during the current iteration. # It must be a duplicate entry in the command line list. printErrorMsg 88 $mmcmd $diskName cleanupAndExit fi # end of if [[ $excludeThisDisk = no ]] else # diskName does not match the name of the disk in the current # SG_DISKS line. Add diskName to the temporary list. tempList="$tempList $diskName" fi # end of if [[ $diskName = ${v[$DISK_NAME_Field]} ]] done # end of for diskName in $disksToExclude # If this disk will be excluded, its name does not appear in # tempList. In other words, tempList contains only the names of # the disks that are to be excluded but for which the corresponding # SG_LINES have not been encountered yet. Initialize the list # for the next iteration. disksToExclude=$tempList fi # end of if [[ -n $failureGroup ]] # Keep an overall track of the EXCLUDE field to prevent # marking all disks as excluded. [[ ${v[$EXCLUDE_Field]} = $includedDisk ]] && includedDisksFound=yes fi # end of if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] ;; * ) # Pass all other lines without a change. ;; esac # end of "Change some of the fields . . . " # Build and write the line to the new mmsdrfs file. print_newLine >> $newsdrfs checkForErrors "writing to file $newsdrfs" $? IFS=":" # Change the separator back to ":" for the next iteration. done # end while read -u3 sdrfsLine IFS="$IFS_sv" # Restore the default IFS settings. # If there are still entries left in the disksToExclude list, this means # that the user-specified disks that do not belong to the file system. if [[ -n $disksToExclude ]] then for diskName in $disksToExclude do printErrorMsg 315 $mmcmd $diskName $device done cleanupAndExit fi # Make sure that at least one disk will remain included. if [[ -z $includedDisksFound ]] then # All of the disks cannot be excluded. print -u2 "$mmcmd: You cannot exclude all of the disks in a file system." cleanupAndExit fi # Make sure the file system is not mounted on any of the nodes. $mmcommon onactive $preferredNode $nodefile \ $NO_FILE_COPY $fqDeviceName $CHECK_ALL $NO_LINK $MOUNT_CHECK_ONLY 2>$errMsg rc=$? if [[ $rc -eq $MM_FsMounted ]] then # The file system is still mounted; messages were issued by mmcommon. cleanupAndExit elif [[ $rc -eq $MM_DaemonDown ]] then # GPFS is down on all nodes that we care about; that's just fine. rc=0 elif [[ $rc -eq $MM_ConnectionReset ]] then # An internode connection was reset. printErrorMsg 257 $mmcmd cleanupAndExit $rc elif [[ $rc -ne 0 ]] then # An unexpected error occurred during the mount check. if [[ -s $errMsg ]] then # Show the error messages from the daemon. $cat $errMsg 1>&2 else # The mount check failed and there were no messages from the daemon. printErrorMsg 171 $mmcmd "mount check for $fqDeviceName" $rc fi # The command was unable to determine whether the file system is mounted. printErrorMsg 564 $mmcmd $fqDeviceName # The command failed. printErrorMsg 389 $mmcmd cleanupAndExit $rc fi $rm -f $errMsg ############################### # Commit the new mmsdrfs file. ############################### trap "" HUP INT QUIT KILL gpfsObjectInfo=$(commitChanges \ $nodesetId $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer) rc=$? if [[ $rc -ne 0 ]] then # We were unable to replace the file in the sdr. printErrorMsg 381 $mmcmd cleanupAndExit fi ################## # Unlock the sdr. ################## [[ $sdrLocked = yes ]] && \ freeLockOnServer $primaryServer $ourNodeNumber >/dev/null sdrLocked=no trap localPosttrap HUP INT QUIT KILL ################################################################## # Propagate the new mmsdrfs file. This process is asynchronous. ################################################################## propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber return $rc } #-------- end of function fsExcludeDisks ---------------------- ##################################################################### # # Function: Mark the specified disks as included for stripe group # descriptor operations. # # Input: None explicit. This function uses the global variables # device, diskList, diskFile, and failureGroup. # # Output: None. # # Returns: 0 - no errors encountered # 1 - unexpected error # ##################################################################### function fsIncludeDisks # (parms passed via global variables) { typeset sourceFile="mmfsctl.sh" [[ -n $DEBUG || -n $DEBUGfsIncludeDisks ]] && set -x $mmTRACE_ENTER "$*" typeset gpfsInitOutput findFSoutput fqDeviceName fsHomeCluster deviceName typeset diskName disksToInclude sdrfsLine preferredNode tempList typeset includeThisDisk typeset rc=0 tsDiskFile=${tmpDir}tsDiskFile.${mmcmd}.$$ LOCAL_FILES="$LOCAL_FILES $tsDiskFile" ############################################################# # Create a blank-separated list of the disks to be included. ############################################################# if [[ -n $diskList ]] then # The input is specified in the form of a list of disk names. IFS=';' for diskName in $diskList do disksToInclude="${disksToInclude}${diskName}${BLANKchar}" done IFS="$IFS_sv" disksToInclude="${disksToInclude% }" elif [[ -n $diskFile ]] then # The disks are specified in a file. exec 3< $diskFile while read -u3 diskName do # Skip empty and comment lines. [[ $diskName = *([$BLANKchar$TABchar]) ]] && continue [[ $diskName = *([$BLANKchar$TABchar])#* ]] && continue # Put the disk name in the list. disksToInclude="${disksToInclude}${diskName}${BLANKchar}" done # end while read -u3 diskDesc disksToInclude="${disksToInclude% }" elif [[ -n $failureGroup ]] then : # The input must be a failure group; nothing to do for now. else # Something is very wrong. checkForErrors "fsIncludeDisks: Missing input parameters" 1 fi # end if [[ -n $diskList ]] # Is there anything to do? if [[ -z $disksToInclude && -z $failureGroup ]] then # No disks were specified. printErrorMsg 264 $mmcmd cleanupAndExit fi ####################################################################### # 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 and will obtain the sdr lock. ####################################################################### trap pretrap HUP INT QUIT KILL gpfsInitOutput=$(gpfsInit $lockId) setGlobalVar $? $gpfsInitOutput # Determine the lookup order for resolving host names. [[ $osName != AIX ]] && resolveOrder=$(setHostResolveOrder) ########################################################### # Make sure the specified file system exists and is local. ########################################################### findFSoutput=$(findFS "$device" $mmsdrfsFile) [[ -z $findFSoutput ]] && cleanupAndExit # Parse the output from the findFS function. set -f ; set -- $findFSoutput ; set +f fqDeviceName=$1 deviceName=$2 fsHomeCluster=$3 # Exit with a message if the command was invoked for a remote file system. if [[ $fsHomeCluster != $HOME_CLUSTER ]] then # Command is not allowed for remote file systems. printErrorMsg 106 $mmcmd $device $fsHomeCluster cleanupAndExit 1 fi ############################################## # Create the new version of the mmsdrfs file. ############################################## $rm -f $newsdrfs $nodefile $tsDiskFile IFS=":" exec 3<&- exec 3< $mmsdrfsFile while read -u3 sdrfsLine do # Parse the line. set -f ; set -A v -- - $sdrfsLine ; set +f IFS="$IFS_sv" # Restore the default IFS settings. # Change some of the fields depending on the type of line. case ${v[$LINE_TYPE_Field]} in $VERSION_LINE ) # This is the global header line. # Increment the generation number. newGenNumber=${v[$SDRFS_GENNUM_Field]}+1 v[$SDRFS_GENNUM_Field]=$newGenNumber ;; $MEMBER_NODE ) # Add the reliable node name to nodefile. print -- "${v[$REL_HOSTNAME_Field]}" >> $nodefile checkForErrors "writing to file $nodefile" $? # If this is the line for the node that is executing # this command, set the preferredNode variable. [[ ${v[$NODE_NUMBER_Field]} = $ourNodeNumber ]] && \ preferredNode=${v[$REL_HOSTNAME_Field]} ;; $SG_DISKS ) if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] then # This is an SG_DISKS line that belongs to our filesystem. # See if this disk is one of the disks to be included. if [[ -n $failureGroup ]] then # Disks are to be included based on failure group. if [[ ${v[$FAILURE_GROUP_Field]} = $failureGroup ]] then # Mark the disk as included. v[$EXCLUDE_Field]=$includedDisk # Add the disk to the list of disks for tsfsctl. print -- "${v[$DISK_NAME_Field]}" >> $tsDiskFile checkForErrors "writing to file $tsDiskFile" $? fi # end if [[ ${v[$FAILURE_GROUP_Field]} = $failureGroup ]] else # The disks to be included are specified in the disksToInclude list. tempList="" includeThisDisk=no for diskName in $disksToInclude do if [[ $diskName = ${v[$DISK_NAME_Field]} ]] then # The disk represented by the current SG_DISKS line # is one of the disks that must be included. if [[ $includeThisDisk = no ]] then # Mark the disk as included. v[$EXCLUDE_Field]=$includedDisk includeThisDisk=yes # Add the disk to the list of disks for tsfsctl. print -- "${v[$DISK_NAME_Field]}" >> $tsDiskFile checkForErrors "writing to file $tsDiskFile" $? else # We have already seen this name during the current iteration. # It must be a duplicate entry in the command line list. printErrorMsg 88 $mmcmd $diskName cleanupAndExit fi # end of if [[ $includeThisDisk = no ]] else # diskName does not match the name of the disk in the current # SG_DISKS line. Add diskName to the temporary list. tempList="$tempList $diskName" fi # end of if [[ $diskName = ${v[$DISK_NAME_Field]} ]] done # end of for diskName in $disksToInclude # If this disk will be included, its name does not appear in # tempList. In other words, tempList contains only the names of # the disks that are to be included but for which the corresponding # SG_LINES have not been encountered yet. Initialize the list # for the next iteration. disksToInclude=$tempList fi # end of if [[ -n $failureGroup ]] fi # end of if [[ ${v[$DEV_NAME_Field]} = $deviceName ]] ;; * ) # Pass all other lines without a change. ;; esac # end of "Change some of the fields . . . " # Build and write the line to the new mmsdrfs file. print_newLine >> $newsdrfs checkForErrors "writing to file $newsdrfs" $? IFS=":" # Change the separator back to ":" for the next iteration. done # end while read -u3 sdrfsLine IFS="$IFS_sv" # Restore the default IFS settings. # If there are still entries left in the disksToInclude list, this means # that the user-specified disks that do not belong to the file system. if [[ -n $disksToInclude ]] then for diskName in $disksToInclude do printErrorMsg 315 $mmcmd $diskName $device done cleanupAndExit fi ############################## # Invoke the tsfsctl command. ############################## $mmcommon onactive $preferredNode $nodefile \ $tsDiskFile $NO_MOUNT_CHECK NULL $NO_LINK \ tsfsctl "$fqDeviceName include -F $tsDiskFile" rc=$? if [[ $rc -ne 0 ]] then # tsfsctl failed. printErrorMsg 104 "$mmcmd" "tsfsctl include" cleanupAndExit $rc fi ############################### # Commit the new mmsdrfs file. ############################### trap "" HUP INT QUIT KILL gpfsObjectInfo=$(commitChanges \ $nodesetId $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer) rc=$? if [[ $rc -ne 0 ]] then # We were unable to replace the file in the sdr. printErrorMsg 381 $mmcmd cleanupAndExit fi ################## # Unlock the sdr. ################## [[ $sdrLocked = yes ]] && \ freeLockOnServer $primaryServer $ourNodeNumber >/dev/null sdrLocked=no trap localPosttrap HUP INT QUIT KILL ################################################################## # Propagate the new mmsdrfs file. This process is asynchronous. ################################################################## propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber return $rc } #-------- end of function fsIncludeDisks ---------------------- ########################################################################### # # Function: Synchronize the file system configuration information # in the target cluster with the file system config data # in the local cluster. # # Input: None explicit. This function uses the global variables # remoteNodes, remoteCluster, and Sflag. # # Output: None. # # Returns: 0 - no errors encountered # 1 - unexpected error # ########################################################################### function syncFSconfig # (parms passed via global variables) { typeset sourceFile="mmfsctl.sh" [[ -n $DEBUG || -n $DEBUGsyncFSconfig ]] && set -x $mmTRACE_ENTER "$*" typeset contactNodes nodeName typeset rc=0 typeset activeNodeFound="" fsExportData=${tmpDir}fsExportData.${mmcmd}.$$ LOCAL_FILES="$LOCAL_FILES $fsExportData" # Determine where to send the data. if [[ -n $remoteCluster ]] then # If a cluster name was specified, get the contact nodes # from the mmsdrfs file. contactNodes=$($mmcommon getContactNodes $remoteCluster) $rm -f $nodefile IFS="," for nodeName in $contactNodes do [[ $nodeName != tcpPort* ]] && \ print -- "$nodeName" >> $nodefile done IFS="$IFS_sv" # Restore the default IFS settings. if [[ ! -s $nodefile ]] then # No contact nodes were provided for the cluster. printErrorMsg 177 $mmcmd $remoteCluster cleanupAndExit fi else : # The contact nodes are in $nodefile (created by checkUserFile). fi # end if [[ -n $remoteCluster ]] # Extract the requested file system information from the local cluster. # Collect the output in a file and show it only if there is an error. # printInfoMsg xyz $mmcmd print -u2 "$mmcmd: Exporting file system information from the source cluster . . ." $mmexportfs $device -o $fsExportData -P rc=$? if [[ $rc -ne 0 ]] then printErrorMsg 389 "$mmcmd: mmexportfs" cleanupAndExit fi # Import the file system information into the remote cluster. # Collect the output in a file and show it only if there is an error. exec 3<&- exec 3< $nodefile while read -u3 nodeName do isNodeReachable $nodeName [[ $? -ne 0 ]] && continue activeNodeFound=yes # printInfoMsg wxy $mmcmd print -u2 "$mmcmd: Importing file system information into the target cluster on node $nodeName . . ." $mmdsh -svL $nodeName -I $fsExportData \ "$mmimportfs $device -i $fsExportData $Sflag -R ; $rm -f $fsExportData" rc=$? [[ $rc -eq 0 ]] && break done # end of while read -u3 nodeName do # Did we fail to run mmimportfs succesfully anywhere? if [[ $rc -ne 0 ]] then # The command failed. Examine prior error messages. printErrorMsg 389 "syncFSconfig: mmimportfs" cleanupAndExit fi if [[ -z $activeNodeFound ]] then if [[ -n $remoteCluster ]] then # None of the contact nodes in the cluster can be reached. printErrorMsg 178 $mmcmd $remoteCluster else print -u2 "$mmcmd: None of the nodes in the peer cluster can be reached." fi cleanupAndExit fi return $rc } #------ end of function syncFSconfig --------------------- ####################### # Mainline processing ####################### ###################################### # Process the command line arguments. ###################################### [[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] && \ syntaxError "help" $usageMsg # Process the positional parameters. device=$arg1 kword=$arg2 action=$arg2 # action keyword in lower case only [[ -z $action ]] && syntaxError "missingArgs" $usageMsg shift 2 # Move past the fs name and action parameters. # Process the rest of the parameters. if [[ $action = suspend || $action = suspendandflush || $action = resume ]] then [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 elif [[ $action = exclude || $action = include ]] then while getopts :d:F:G: OPT do case $OPT in d) [[ -n $dflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" dflag="-$OPT" [[ -n $Fflag || -n $Gflag ]] && \ syntaxError "invalidCombination" $usageMsg $dflag $Fflag $Gflag diskList="$OPTARG" ;; F) [[ -n $Fflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Fflag="-$OPT" [[ -n $dflag || -n $Gflag ]] && \ syntaxError "invalidCombination" $usageMsg $dflag $Fflag $Gflag Farg="$OPTARG" ;; G) [[ -n $Gflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Gflag="-$OPT" [[ -n $dflag || -n $Fflag ]] && \ syntaxError "invalidCombination" $usageMsg $dflag $Fflag $Gflag failureGroup=$(checkIntRange "-G" "$OPTARG") [[ $? -ne 0 ]] && cleanupAndExit ;; +[dfG]) # Invalid option. syntaxError "invalidOption" $usageMsg $OPT ;; :) # Missing argument. syntaxError "missingValue" $usageMsg $OPTARG ;; *) # Invalid option. syntaxError "invalidOption" $usageMsg $OPTARG ;; esac done shift OPTIND-1 [[ -z $dflag && -z $Fflag && -z $Gflag ]] && \ syntaxError "missingArgs" $usageMsg [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 # If -F was specified, ensure the disk names file exists and is not empty. if [[ -n $Fflag ]] then checkUserFile $Farg $tmpDiskFile [[ $? -ne 0 ]] && cleanupAndExit diskFile=$tmpDiskFile fi # end of if [[ -n $Fflag ]] elif [[ $action = syncfsconfig ]] then while getopts :C:n:S: OPT do case $OPT in C) # Name of the target cluster. [[ -n $Cflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" remoteCluster=$OPTARG Cflag=yes ;; n) # Name of contact nodes file. [[ -n $nflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" narg=$OPTARG nflag=yes ;; S) # Name of disk specifications file. [[ -n $Sflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Sflag="-S $OPTARG" ;; :) syntaxError "missingValue" $usageMsg $OPTARG ;; +[CnS]) syntaxError "invalidOption" $usageMsg $OPT ;; *) # Invalid option specified. syntaxError "invalidOption" $usageMsg $OPTARG ;; esac done shift OPTIND-1 [[ -n $Cflag && -n $nflag ]] && \ syntaxError "invalidCombination" $usageMsg "-C" "-n" [[ -z $Cflag && -z $nflag ]] && \ syntaxError "missingArgs" $usageMsg [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 # If -n was specified, ensure the contact nodes file exist and is not empty. # This will also copy the names into $nodefile (needed by function syncfsconfig). if [[ -n $nflag ]] then checkUserFile $narg $nodefile [[ $? -ne 0 ]] && cleanupAndExit fi # end of if [[ -n $nflag ]] else syntaxError "keyword" $usageMsg $kword fi # end if [[ $action = suspend || $action = suspendandflush || $action = resume ]] ################################################## # Invoke the appropriate function to do the work. ################################################## case $action in suspend | suspendandflush | resume ) fsSuspendOrResume $device $action rc=$? ;; exclude ) fsExcludeDisks # Parms are passed via global variables. rc=$? ;; include ) fsIncludeDisks # Parms are passed via global variables. rc=$? ;; syncfsconfig ) syncFSconfig # Parms are passed via global variables. rc=$? ;; *) syntaxError "keyword" $usageMsg $kword ;; esac # end case $action in cleanupAndExit $rc