#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2003,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 # @(#)37 1.45.1.2 src/avs/fs/mmfs/ts/admin/mmimportfs.sh, mmfs, avs_rgpfs24, rgpfs24s002a 4/21/06 14:48:31 ############################################################################## # # Usage: # mmimportfs {Device|all} -i ImportfsFile [-S ChangeSpecFile] [-R] # # where # Device is the file system to be imported. # If Device is "all", then all file systems in # the input file are imported. Free disks, if any, # are imported as well. # Note: To request a file system with the name "all", # specify "/dev/all" to distinguish from the # keyword "all" (import all file systems). # # -i ImportfsFile is the name of a file with the file system # information. It must be created by mmexportfs. # # -S ChangeSpecFile a file containing a detailed description of changes # to be made to the file systems during the import step. # # Undocumented option: # # -R remove the specified file system from the mmsdrfs file # and replace it with the data from the import file. # If 'all' is specified, all file system and free disk # information that may currently exist is removed from # the mmsdrfs file and is replaced with the data from # the import file. # ############################################################################## # Include global declarations and service routines. . /usr/lpp/mmfs/bin/mmglobfuncs . /usr/lpp/mmfs/bin/mmsdrfsdef . /usr/lpp/mmfs/bin/mmfsfuncs sourceFile="mmimportfs.sh" [[ -n $DEBUG || -n $DEBUGmmimportfs ]] && set -x $mmTRACE_ENTER "$*" # Local work files. Names should be of the form: # fn=${tmpDir}fn.${mmcmd}.$$ existingDisks=${tmpDir}existingDisks.${mmcmd}.$$ recoveryFiles=${tmpDir}recoveryFiles.${mmcmd}.$$ importedFreeDisks=${tmpDir}importedFreeDisks.${mmcmd}.$$ resetFreeDisks=${tmpDir}resetFreeDisks.${mmcmd}.$$ disksToUnfence=${tmpDir}disksToUnfence.${mmcmd}.$$ aixNodes=${tmpDir}aixNodes.${mmcmd}.$$ # The following declarations are the prefixes for the file names # that will contain information relevant to a specific file system. # The actual file names consist of the prefix followed by a device name. importFile=${tmpDir}importFile.${mmcmd}.$$ resetNSDs=${tmpDir}resetNSDs.${mmcmd}.$$ resetLVs=${tmpDir}resetLVs.${mmcmd}.$$ LOCAL_FILES=" $existingDisks $recoveryFiles $importedFreeDisks $resetFreeDisks \ $aixNodes $disksToUnfence $importFile.* $resetNSDs.* $resetLVs.* " # Local variable declarations usageMsg=571 iflag="" Cflag="" Sflag="" existingMountPoints="" maxDiskNumber=0 # Local functions: ############################################################################## # # Function: Given the source and target cluster types, determine whether # the present version of mmimportfs can import the file system. # # Note: Not all possible cluster type combinations are supported. # In some cases, simplifying assumptions are made. # # Input: $1 - source cluster type # $2 - target cluster type # # Output: None # # Returns: 0 - the two cluster types are compatible. # 1 - the two cluster types are not compatible. # ############################################################################## function checkClusterCompatibility # { sourceFile="mmimportfs.sh" [[ -n $DEBUG || -n $DEBUGcheckClusterCompatibility ]] && set -x $mmTRACE_ENTER "$*" typeset source=$1 typeset target=$2 typeset rc case $source in lc ) [[ $target = lc ]] && rc=0 [[ $target = single ]] && rc=0 ;; sp ) [[ $target = lc ]] && rc=0 [[ $target = single ]] && rc=0 ;; rpd ) [[ $target = lc ]] && rc=0 [[ $target = single ]] && rc=0 ;; hacmp ) [[ $target = lc ]] && rc=0 [[ $target = single ]] && rc=0 ;; single ) [[ $target = lc ]] && rc=0 [[ $target = single ]] && rc=0 ;; * ) # Unknown source cluster type. rc=1 ;; esac return $rc } #----- end of function checkClusterCompatibility ---------------- ########################################################################### # # Function: See if there are any disks that will need to be recovered # because of a previous failure of mmimportfs. # # Input: $1 - source cluster type # $2 - output file name # # Output: File containing the disk names that may have failed a previous # tspreparedisk -m call. Each line has the following format: # # # Returns: 0 - no errors # 1 - error encountered # ########################################################################### function getDiskRecoveryInformation # { sourceFile="mmimportfs.sh" [[ -n $DEBUG || -n $DEBUGgetDiskRecoveryInformation ]] && set -x $mmTRACE_ENTER "$*" typeset source=$1 typeset outputFile=$2 typeset server $rm -f $outputFile # If we are not creating NSDs, there is nothing to worry about. [[ $source = lc || $source = single ]] && \ return 0 # Create a list of all disk recovery files created by tspreparedisk. # Such files, if any, will be stored in /var/mmfs/tmp/mmimportfs on # the primary and backup server configuration nodes. The file names # have the following format: # tspreparedisk.diskDesc... # # Put the results in a file with the following format: # # for server in $(print -- $primaryServer $backupServer) do run onNode $server lsSGDescFile 2>/dev/null | \ $awk -F. ' { print $3" "$4" "$5" '${server}' "$0 } ' >> $outputFile done # Sort the result so that if there is more than one recovery file # for any given disk, the most recent version appears first. $sort -k 1,1 -k 3,3nr -o $outputFile $outputFile checkForErrors "sort $outputFile" $? return 0 } #----- end of function getDiskRecoveryInformation --------------- ######################################################################### # # Function: Restore the disk and SG descriptors of the specified disk. # # Input: $1 - diskName # $2 - file created by function getDiskRecoveryInformation # # Output: None. # # Returns: 0 - no errors # 1 - error encountered # ######################################################################### function recoverOldSGdescriptor # { sourceFile="mmimportfs.sh" [[ -n $DEBUG || -n $DEBUGrecoverOldSGdescriptor ]] && set -x $mmTRACE_ENTER "$*" typeset diskName=$1 typeset recoveryInfoFile=$2 typeset recoveryInfo checksum serverNode fqName sumOutput newSum typeset rc=0 # See if there is a recovery file for this disk. recoveryInfo=$($grep -w $diskName $recoveryInfoFile) # Return if there is nothing to do. [[ -z $recoveryInfo ]] && \ return 0 print -u2 -- "$mmcmd: Recovering SG descriptor area of disk $diskName" # Parse the information from the recoveryInfoFile. set -f ; set -- $recoveryInfo ; set +f checksum=$2 serverNode=$4 fqName=$5 # Retrieve the file if it isn't already on our node. if [[ ! -e $fqName ]] then # Ensure the target directory for rcp exists. $mkdir -p ${fqName%/*} # Copy the file from the server node. $rcp ${serverNode}:${fqName} $fqName checkForErrors "rcp ${serverNode}:${fqName}" $? # Verify the checksum. sumOutput=$($sum $fqName) rc=$? set -f ; set -- $sumOutput ; set +f newSum=$1 if [[ $checksum != $newSum ]] then printErrorMsg 379 $mmcmd $serverNode $ourNodeName return 1 fi fi # end of if [[ ! -e $fqName ]] # Restore the disk and SG descriptors of the disk. $dd if=$fqName of=/dev/$diskName seek=1 2>$errMsg rc=$? if [[ $rc -ne 0 ]] then [[ -s $errMsg ]] && $cat $errMsg 1>&2 $rm -f $errMsg print -u2 "$mmcmd: dd if=$fqName of=/dev/$diskName seek=1 failed with rc $rc." print -u2 "$mmcmd: Error recovering disk $diskName from a previous failure." return $rc fi $rm -f $errMsg print -u2 -- "$mmcmd: Disk $diskName successfully recovered." # At this point the disk was successfully restored. # Remove all SG descriptor files for this disk and return. $rm -f ${fqName%/*}/tspreparedisk.diskDesc.${diskName}.* for server in $(print -- $primaryServer $backupServer) do run onNode $server rmSGDescFile $diskName done return 0 } #----- end of function recoverOldSGdescriptor ------------------- ############################################################################ # # Function: Import a disk into cluster type single. Depending on the # source cluster types, this may also involve the conversion # of the disk into an NSD. # # Note: The disk is assumed to be accessible on the local node. # # Input: $1 - source cluster type # $2 - current SG_DISKS line for the disk # $3 - target nodesetId # # Output: $1 - result: error, success. # $2 - updated SG_DISKS line. # # Returns: 0 - everything worked OK # 1 - error encountered # ############################################################################ function importDisk_single # { sourceFile="mmimportfs.sh" [[ -n $DEBUG || -n $DEBUGimportDisk_single ]] && set -x $mmTRACE_ENTER "$*" typeset sourceCluster=$1 typeset currentDiskLine=$2 typeset targetNodesetId=$3 typeset rc=0 typeset result="success" typeset invokingCommand="mmimportfs" typeset updatedDiskLine createNsdOutput tspreparediskOutput typeset diskName magicWord rc2 pvid nsdSubtype nsdSubtypeDiskname # Parse the current SG_DISKS line for the disk. IFS=":" set -f ; set -A v -- - $currentDiskLine ; set +f IFS="$IFS_sv" diskName=${v[$DISK_NAME_Field]} [[ -z ${v[$NSD_SUBTYPE_Field]} ]] && \ v[$NSD_SUBTYPE_Field]="generic" nsdSubtype=${v[$NSD_SUBTYPE_Field]} aixPvidValue=${v[$PVID_Field]} [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] && \ invokingCommand="mmimportfs_freeDisk" [[ ${v[$NODESETID_Field]} != $FREE_DISK ]] && \ v[$NODESETID_Field]=$targetNodesetId if [[ $sourceCluster != lc && $sourceCluster != single ]] then # The source cluster type is sp, rpd, or hacmp. # In all of these cases we may have to import # the underlying logical volumes and, if applicable, # recreate the VSDs. # For now, we assume that the disks are already in place. # See if this disk needs to be recovered from a previous # partial SG descriptor migration. if [[ -s $recoveryFiles ]] then recoverOldSGdescriptor $diskName $recoveryFiles rc=$? if [[ $rc -ne 0 ]] then print -- "error" return $rc fi fi # Convert the disk into an NSD. createNsdOutput=$(createNsd $diskName no $invokingCommand NULL) rc=$? # The output of createNsd consists of a one-word NSD subtype value, # followed by the output from tspreparedisk. Separate the two parts. nsdSubtype=${createNsdOutput%% *} tspreparediskOutput=${createNsdOutput#* } # Set the value for the nsd subtype diskname if the nsd subtype # is lv or vsd. nsdSubtypeDiskname="" [[ $nsdSubtype = lv || $nsdSubtype = vsd ]] && nsdSubtypeDiskname=$diskName # Parse the output from the tspreparedisk command. IFS=":" set -f ; set -- $tspreparediskOutput ; set +f magicWord=$1 rc2=$2 pvid=$3 IFS="$IFS_sv" if [[ $rc -ne 0 || $nsdSubtype = error || $rc2 -ne 0 || $magicWord != tspreparedisk ]] then # Try to make sense of the error. if [[ $nsdSubtype = error ]] then : # determineNsdSubtype failed. Messages were already issued. elif [[ $magicWord = tspreparedisk ]] then # tspreparedisk was executed but was not happy about something. if [[ $rc2 = 1 ]] # E_PERM then # Permission was denied for disk. printErrorMsg 523 $mmcmd "/dev/$diskName" elif [[ $rc2 = 2 ]] # E_NOENT then # The disk was not found. printErrorMsg 524 $mmcmd "/dev/$diskName" elif [[ $rc2 = 5 ]] # E_IO then # I/O error printErrorMsg 525 $mmcmd "/dev/$diskName" elif [[ $rc2 = $MM_DeviceNotFound ]] # E_NODEV then # A return code of ENODEV was returned for the disk. printErrorMsg 187 $mmcmd $ourNodeName "/dev/$diskName" elif [[ $rc2 = 27 ]] # E_FBIG then # The disk is too large. printErrorMsg 508 $mmcmd "/dev/$diskName" elif [[ $rc2 = 50 ]] # E_NOCONNECT then # The disk is fenced out. printErrorMsg 395 $mmcmd $ourNodeName "/dev/$diskName" else # Show the result from tspreparedisk. print -u2 "$tspreparediskOutput" # Unexpected error from tspreparedisk printErrorMsg 171 "$mmcmd" "tspreparedisk $diskName" $rc2 fi # end if [[ $rc2 = 1 ]] else # Something is really wrong. Output error information if any. [[ -n $createNsdOutput ]] && print -u2 "$createNsdOutput" fi # end if [[ $nsdSubtype = error ]] # We failed to create an NSD from this disk. printErrorMsg 47 $mmcmd $diskName result="error" rc=1 else # At this point the disk was successfully defined as an NSD. # Add the missing or updated information. v[$PVID_Field]=$pvid v[$NSD_SUBTYPE_Field]=$nsdSubtype v[$NSD_SUBTYPE_DISKNAME_Field]=$nsdSubtypeDiskname if [[ $nsdSubtype = lv ]] then v[$AIX_PVID_Field]=$aixPvidValue else v[$AIX_PVID_Field]="" fi # Remove any leftover files from tspreparedisk -m. $rm -f ${fqName%/*}/tspreparedisk.diskDesc.${diskName}.* fi # end if [[ $rc -ne 0 || $nsdSubtype = error || ... fi # end of if [[ $sourceCluster != lc && $sourceCluster != single ]] # Ensure certain fields in the SG_DISKS line have # appropriate values for cluster type single. v[$NSD_PRIMARY_NODE_Field]="" v[$NSD_BACKUP_NODE_Field]="" v[$DAEMON_NSD_PRIMARY_Field]="" v[$DAEMON_NSD_BACKUP_Field]="" v[$DISK_TYPE_Field]="disk" updatedDiskLine=$(print_newLine) # Return to the caller the updated SG_DISKS line. print -- "$result" "$updatedDiskLine" return $rc } #----- end of function importDisk_single ------------------------ ########################################################################### # # Function: Import a disk into an lc cluster. Depending on the source # cluster types, this may involve one or more of the following # operations to make the disk usable in the new cluster: # import the base logical volume, make/redefine a VSD, # make an NSD out of the disk, verify NSD servers belong # to the right nodeset, etc. # # Input: $1 - source cluster type # $2 - current SG_DISKS line for the disk # $3 - target nodesetId # $4 - (optional) disk descriptor spec file # # Output: $1 - result; error, success, successServersRemoved. # $2 - updated SG_DISKS line. # # Returns: 0 - everything worked OK # 1 - error encountered # ########################################################################### function importDisk_lc # [] { sourceFile="mmimportfs.sh" [[ -n $DEBUG || -n $DEBUGimportDisk_lc ]] && set -x $mmTRACE_ENTER "$*" typeset sourceCluster=$1 typeset currentDiskLine=$2 typeset targetNodesetId=$3 typeset specFile=$4 typeset rc=0 typeset diskDesc="" typeset result="success" typeset invokingCommand="mmimportfs" typeset diskName server backup nodesetId validateDescriptorOutput typeset updatedDiskLine createNsdOutput tspreparediskOutput typeset magicWord rc2 pvid nsdSubtype nsdSubtypeDiskname invokedNode # Parse the current SG_DISKS line for the disk. IFS=":" set -f ; set -A v -- - $currentDiskLine ; set +f IFS="$IFS_sv" diskName=${v[$DISK_NAME_Field]} nsdSubtype=${v[$NSD_SUBTYPE_Field]} aixPvidValue=${v[$PVID_Field]} [[ -z $nsdSubtype ]] && nsdSubtype="generic" [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] && \ invokingCommand="mmimportfs_freeDisk" [[ ${v[$NODESETID_Field]} != $FREE_DISK ]] && \ v[$NODESETID_Field]=$targetNodesetId nodesetId=${v[$NODESETID_Field]} # If a change file is specified (-S option), # see if it contains a descriptor for this disk. [[ -s $specFile ]] && \ diskDesc=$($grep -e "[$BLANKchar$TABchar]$diskName:" \ -e "^$diskName:" $specFile 2>/dev/null) if [[ -n $diskDesc ]] then # If a disk descriptor was specified, # parse it to get the server names. IFS=':' set -f ; set -- $diskDesc ; set +f server=$2 backup=$3 IFS="$IFS_sv" # Restore the default IFS setting. # If a primary server was specified, make sure that it is valid # and convert it if necessary to an admin adapter name, since it # may be needed for the subsequent createNsd call. # We don't bother to check the backup server here, since it will # be checked later by the validateAndConvertNsdDescriptor routine. if [[ -n $server ]] then server=$(checkAndConvertNodeValue $server $REL_HOSTNAME_Field) [[ $? -ne 0 ]] && cleanupAndExit fi # if [[ -n $backup ]] # then # backup=$(checkAndConvertNodeValue $backup $REL_HOSTNAME_Field) # [[ $? -ne 0 ]] && cleanupAndExit # fi else # Otherwise, use the current NSD server names, if any. if [[ $sourceCluster = lc ]] then server=${v[$NSD_PRIMARY_NODE_Field]} backup=${v[$NSD_BACKUP_NODE_Field]} else server="" backup="" fi fi # end of if [[ -n $diskDesc ]] if [[ $sourceCluster != lc && $sourceCluster != single ]] then # The source cluster type is sp, rpd, or hacmp. # In all of these cases we may have to import # the underlying logical volumes and, if applicable, # recreate the VSDs. : # For now, we assume that the disks are already in place. fi # end of if [[ $sourceCluster != lc && $sourceCluster != single ]] # If the user did not specify a new disk descriptor, # generate one from the current SG_DISKS line. [[ -z $diskDesc ]] && \ diskDesc="$diskName:$server:$backup:" # If NSD server names were not specified by the user, # or cannot be reasonably defaulted by us, the user # will have to use mmchnsd to assign NSD servers. [[ -z $server ]] && \ result=successServersRemoved # Verify the correctness of the NSD server nodes. validateDescriptorOutput=$(validateAndConvertNsdDescriptor "$diskDesc" \ $currentDiskLine $CHANGE_NSD $nodesetId NULL oldDiskUsage) rc=$? if [[ $rc -eq 0 ]] then # If there are no problems, parse the result to get the new SG_DISKS line. set -f ; set -- $validateDescriptorOutput ; set +f updatedDiskLine="$1" # Parse the line that was returned by the validate function # to pick up fields that may have been changed. IFS=":" set -f ; set -A v -- - $updatedDiskLine ; set +f IFS="$IFS_sv" else # Remove the NSD servers. The user will have to run mmchnsd. v[$NSD_PRIMARY_NODE_Field]="" v[$NSD_BACKUP_NODE_Field]="" v[$DAEMON_NSD_PRIMARY_Field]="" v[$DAEMON_NSD_BACKUP_Field]="" result=successServersRemoved rc=0 fi # Convert the disk into an NSD. if [[ $sourceCluster != lc && $sourceCluster != single ]] then # See if this disk needs to be recovered from a previous # partial SG descriptor migration. if [[ -s $recoveryFiles ]] then recoverOldSGdescriptor $diskName $recoveryFiles rc=$? if [[ $rc -ne 0 ]] then print -- "error" return $rc fi fi # Generate and write an unique NSD volume id on sector 2 of the disk. # If an NSD server is specified, invoke the function on that node. # This rule does not apply when the underlying disk is a VSD. # For VSDs we should have access to the disk from the local node. if [[ $sourceCluster = sp || -z $server || $server = $ourNodeName ]] then invokedNode=$ourNodeName createNsdOutput=$(createNsd $diskName no $invokingCommand NULL) rc=$? else invokedNode=$server createNsdOutput=$(run on1 $server \ createNsd $diskName no $invokingCommand NULL) rc=$? fi # The output of createNsd consists of a one-word NSD subtype value, # followed by the output from tspreparedisk. Separate the two parts. nsdSubtype=${createNsdOutput%% *} tspreparediskOutput=${createNsdOutput#* } # Set the value for the nsd subtype diskname if the nsd subtype # is lv, vsd or file; this name is persistent across the nodes. nsdSubtypeDiskname="" [[ $nsdSubtype = lv || $nsdSubtype = vsd || $nsdSubtype = file ]] && \ nsdSubtypeDiskname=$diskName # Parse the output from the tspreparedisk command. IFS=":" set -f ; set -- $tspreparediskOutput ; set +f magicWord=$1 rc2=$2 pvid=$3 IFS="$IFS_sv" if [[ $rc -ne 0 || $nsdSubtype = error || $rc2 -ne 0 || $magicWord != tspreparedisk ]] then # Try to make sense of the error. if [[ $nsdSubtype = error ]] then : # determineNsdSubtype failed. Messages were already issued. elif [[ $magicWord = tspreparedisk ]] then # tspreparedisk was executed but was not happy about something. if [[ $rc2 = 1 ]] # E_PERM then # Permission was denied for disk. printErrorMsg 523 $mmcmd "/dev/$diskName" elif [[ $rc2 = 2 ]] # E_NOENT then # The disk was not found. printErrorMsg 524 $mmcmd "/dev/$diskName" elif [[ $rc2 = 5 ]] # E_IO then # I/O error printErrorMsg 525 $mmcmd "/dev/$diskName" elif [[ $rc2 = $MM_DeviceNotFound ]] # E_NODEV then # A return code of ENODEV was returned for the disk. printErrorMsg 187 $mmcmd $invokedNode "/dev/$diskName" elif [[ $rc2 = 27 ]] # E_FBIG then # The disk is too large. printErrorMsg 508 $mmcmd "/dev/$diskName" elif [[ $rc2 = 50 ]] # E_NOCONNECT then # The disk is fenced out. printErrorMsg 395 $mmcmd $invokedNode "/dev/$diskName" else # Show the result from tspreparedisk. print -u2 "$tspreparediskOutput" # Unexpected error from tspreparedisk. printErrorMsg 171 "$mmcmd" "tspreparedisk $diskName" $rc2 fi # end if [[ $rc2 = 1 ]] else # Something is really wrong. Output error information if any. [[ -n $createNsdOutput ]] && print -u2 "$createNsdOutput" fi # end if [[ $nsdSubtype = error ]] # We failed to create an NSD from this disk. printErrorMsg 47 $mmcmd $diskName result="error" rc=1 else # At this point the disk was successfully defined as an NSD. # Add missing or updated information. v[$PVID_Field]=$pvid v[$NSD_SUBTYPE_DISKNAME_Field]=$nsdSubtypeDiskname if [[ $nsdSubtype = lv ]] then v[$AIX_PVID_Field]=$aixPvidValue else v[$AIX_PVID_Field]="" fi # Remove any leftover files from tspreparedisk -m. $rm -f ${fqName%/*}/tspreparedisk.diskDesc.${diskName}.* for server in $(print -- $primaryServer $backupServer) do run onNode $server rmSGDescFile $diskName done fi # end if [[ $rc -ne 0 || $nsdSubtype = error || ... ]] fi # end of if [[ $sourceCluster != lc && $sourceCluster != single ]] # Add the remaining missing or updated information and rebuild the line. v[$DISK_TYPE_Field]=nsd v[$NSD_SUBTYPE_Field]=$nsdSubtype updatedDiskLine=$(print_newLine) # Return to the caller the updated SG_DISKS line. print -- "$result" "$updatedDiskLine" return $rc } #----- end of function importDisk_lc ---------------------------- ########################################################################### # # Function: Unfence logical volumes and remove PR registrations. # # Input: $1 - file with the nodes on which to unfence # $2 - SG_DISKS lines for the disks to unfence # # Output: None # # Returns: 0 - everything worked OK # 1 - error encountered # ########################################################################### function unfenceLogicalVolumes # { sourceFile="mmimportfs.sh" [[ -n $DEBUG || -n $DEBUGunfenceLogicalVolumes ]] && set -x $mmTRACE_ENTER "$*" typeset nodefile=$1 typeset diskLines=$2 typeset rc=0 typeset unfenceDisksOutput outputLine nodeName magicWord rc2 typeset failedNode errorFound # Give up if any of the input files is empty. [[ ! -s $nodefile || ! -s $diskLines ]] && \ return 0 $rm -f $tmpfile # Exclude the local host from the list of nodes. $grep -v -w $ourNodeName $nodefile > ${nodefile}tmp # If there are remote nodes left in the file, # unfence the disks on those nodes. if [[ -s ${nodefile}tmp ]] then print -- "$mmcmd: Attempting to unfence the disks. This may take a while ... " # Create a copy of the file to propagate. $cp $diskLines ${diskLines}tmp checkForErrors "cp $diskLines ${diskLines}tmp" $? # Perform the tasks on all remote nodes. $mmdsh -f 10 -vF ${nodefile}tmp -I ${diskLines}tmp \ $mmremote unfenceDisks ${diskLines}tmp >$tmpfile 2>&1 rc=$? fi # Unfence the disks on the local node. # Append the result to the output from the remote nodes. if [[ $osName = AIX ]] then unfenceDisksOutput=$(unfenceDisks $diskLines) rc=$? # Append the output to the output from the remote nodes # so that we can process the overall result. print -- "$ourNodeName: $unfenceDisksOutput" >>$tmpfile fi # Ignore the results and declare a success. If we were not # successful on some node, the mount will fail and the user # will have to run mmremote unfenceDisks or fix the disks # by himself. Our problem is that we do not have a good # way to tell whether the unfence process should work on # any given node or not. And we most definitely do not # want to fail the mmimportfs command for such a reason. $rm -f ${nodefile}tmp ${diskLines}tmp return 0 } #----- end of function unfenceLogicalVolumes -------------------- ####################### # Mainline processing ####################### ################################# # Process the command arguments. ################################# [[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] && \ syntaxError "help" $usageMsg [[ $argc -lt 3 ]] && \ syntaxError "missingArgs" $usageMsg device=$arg1 # Save the stripe group device (always the first parameter). shift 1 # Drop the device name from the parameter list. while getopts :C:i:RS: OPT do case $OPT in C) syntaxError "obsoleteOption" $usageMsg "-$OPT" ;; i) # name of input file [[ -n $iflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" fsImportData=$OPTARG ;; R) # replace existing file systems. [[ -n $Rflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Rflag=yes ;; S) # file with change specifications. [[ -n $Sflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT" Sflag=yes changeSpecFile=$OPTARG ;; :) syntaxError "missingValue" $usageMsg $OPTARG ;; +[CiRS]) syntaxError "invalidOption" $usageMsg $OPT ;; *) # invalid option specified syntaxError "invalidOption" $usageMsg $OPTARG ;; esac done shift OPTIND-1 [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 # Check the input file parameters. if [[ ! -f $fsImportData || ! -r $fsImportData ]] then # Can't read the input file. printErrorMsg 43 $mmcmd $fsImportData cleanupAndExit fi if [[ ! -s $fsImportData ]] then # Input file is empty. printErrorMsg 329 $mmcmd $fsImportData cleanupAndExit fi if [[ -n $Sflag && ( ! -f $changeSpecFile || ! -r $changeSpecFile ) ]] then # Can't read the input file. printErrorMsg 43 $mmcmd $changeSpecFile cleanupAndExit fi if [[ -n $Sflag && ! -s $changeSpecFile ]] then # Input file is empty. printErrorMsg 329 $mmcmd $changeSpecFile cleanupAndExit fi # Process the input device name parameter. [[ $device = all ]] && importAll=true deviceName=${device#/dev+(/)} # Strip /dev from the device name. ##################################################################### # 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 targetNodesetId=$nsId # Determine the lookup order for resolving host names. [[ $osName != AIX ]] && resolveOrder=$(setHostResolveOrder) ###################################################################### # Create a new version of the mmsdrfs file that will receive the data # and collect information for the existing file systems, disks, etc. # If the -R option is specified, remove the affected lines from the # mmsdrfs file. ###################################################################### $rm -f $newsdrfs $existingDisks $allClusterNodes $aixNodes 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" printLine=true # 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 targetCluster=${v[$CLUSTER_TYPE_Field]} if [[ $MMMODE = lc ]] then [[ ${v[$HIGHEST_GPFS_DISK_NBR_Field]} -lt $initialDiskNumber ]] && \ v[$HIGHEST_GPFS_DISK_NBR_Field]=$initialDiskNumber prevMaxDiskNumber=${v[$HIGHEST_GPFS_DISK_NBR_Field]} fi ;; $MEMBER_NODE ) # This line describes a node that belongs to some nodeset. # Create a file with the names of all nodes in the cluster. print -- "${v[$REL_HOSTNAME_Field]}" >> $allClusterNodes checkForErrors "writing to file $allClusterNodes" $? # Create separate files with the names of the AIX nodes. if [[ ${v[$OS_NAME_Field]} = "AIX" ]] then print -- "${v[$REL_HOSTNAME_Field]}" >> $aixNodes checkForErrors "writing to file $aixNodes" $? fi ;; $SG_HEADR ) # This is the header line for some file system. # We are starting the processing of a new file system. If the file # system should be replaced, remove the line from the mmsdrfs file. if [[ (${v[$DEV_NAME_Field]} = $deviceName || $device = all) && -n $Rflag && ${v[$FS_TYPE_Field]} = $localfs ]] then # This file system should be replaced. replaceThisFileSystem=true printLine=false else replaceThisFileSystem="" # Create a list of the already assigned minor numbers. existingMinorNumbers="$existingMinorNumbers ${v[$DEV_MINOR_Field]}" # If this file systems belongs to the nodeset on which we # are running, remember its name. It will be needed shortly # to figure out the value of the GPFS device major number. [[ ${v[$NODESETID_Field]} = $nsId ]] && \ fqDeviceName="/dev/${v[$DEV_NAME_Field]}" fi # end if [[ (${v[$DEV_NAME_Field]} = $deviceName || $device = all) ... ;; $SG_ETCFS ) # This line is a stanza line for one of the filesystems. if [[ -n $replaceThisFileSystem ]] then printLine=false else # If this is the first line in the stanza, # save the device name and mount point. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line ]] then fsInfo="${v[$DEV_NAME_Field]}:${v[$ETCFS_TEXT_Field]}:${v[$NODESETID_Field]}" existingFsInfo="$fsInfo $existingFsInfo" # Note: the trailing blanks in the following lists are important. existingFileSystems="$existingFileSystems ${v[$DEV_NAME_Field]} " existingMountPoints="$existingMountPoints ${v[$ETCFS_TEXT_Field]} " fi fi # end if [[ -n $replaceThisFileSystem ]] ;; $SG_MOUNT ) [[ -n $replaceThisFileSystem ]] && \ printLine=false ;; $SG_DISKS ) # This line describes a disk. # Decide if this disk is to be replaced. If the disk belongs to some # file system, the replaceThisFileSystem flag already has the correct # value. If this is a free disk, it will be replaced only if all file # systems are being replaced. Note that the replaceThisFileSystem flag # is used to control the replacing of disks that are part of some file # system as well as the replacing of free disks. if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] then if [[ $device != all ]] then replaceThisFileSystem="" else replaceThisFileSystem=true fi fi # end if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] if [[ -n $replaceThisFileSystem ]] then printLine=false else # Create a file with the names of all existing disks. # It doesn't matter if the disks are free or not. print -- "${v[$DISK_NAME_Field]}" >> $existingDisks checkForErrors "writing to file $existingDisks" $? # Keep track of the highest NSD number assigned to a disk. if [[ ${v[$DISK_NAME_Field]} = gpfs+([0-9])nsd ]] then nsdName=${v[$DISK_NAME_Field]} nsdNumber=${nsdName#gpfs} nsdNumber=${nsdNumber%nsd} [[ $nsdNumber -gt $maxDiskNumber ]] && maxDiskNumber=$nsdNumber fi fi # end if [[ -n $replaceThisFileSystem ]] ;; * ) # Pass all other lines without a change. ;; esac # end Change some of the fields # Build and write the line to the new mmsdrfs file. if [[ $printLine = true ]] then print_newLine >> $newsdrfs checkForErrors "writing to file $newsdrfs" $? fi IFS=":" # Change the separator back to ":" for the next iteration. done # end while read -u3 sdrfsLine IFS="$IFS_sv" # Restore the default IFS settings. ########################################################################### # Figure out what should the GPFS file systems device major number be. ########################################################################### if [[ $osName = Linux && -n $fqDeviceName ]] then devMajor=$(LC_ALL=C $ls -l $fqDeviceName 2>/dev/null | $awk ' { print $5 } ') devMajor=${devMajor%,*} fi [[ -z $devMajor ]] && devMajor=$defaultMajorNumber ########################################################################### # If the source is hacmp or LV based rpd cluster, make an attempt # to remove any PR settings and unfence the disks on all nodes in # the new cluster. This processing is by necessity time consuming. # # Notes: The main loop is further down. This is preliminary processing # and a necessary evil. Some of the error checking is duplicated # here to allow us to get out faster if there is an obvious error. ########################################################################### $rm -f $disksToUnfence $resetLVs.* IFS=":" exec 3<&- exec 3< $fsImportData while read -u3 sdrfsLine do # Parse the line. set -f ; set -A v -- - $sdrfsLine ; set +f IFS="$IFS_sv" # Restore the default IFS settings. printLine=true # Assume the line will be printed. case ${v[$LINE_TYPE_Field]} in $VERSION_LINE ) # This is the global header line. sourceCluster=${v[$CLUSTER_TYPE_Field]} [[ -z $sourceCluster ]] && sourceCluster=sp checkClusterCompatibility $sourceCluster $targetCluster rc=$? if [[ $rc -ne 0 ]] then # Incompatible cluster types. printErrorMsg 44 $mmcmd $sourceCluster $targetCluster cleanupAndExit fi getDiskRecoveryInformation $sourceCluster $recoveryFiles # Skip the preliminary processing if LVs are not possible. [[ $sourceCluster != rpd && $sourceCluster != hacmp ]] && \ break # Skip the preliminary processing if -R is specified. [[ -n $Rflag ]] && \ break ;; $SG_HEADR ) # This is the header line for some file system. # Starting the processing of a new file system. # See if the file system should be imported. if [[ ${v[$DEV_NAME_Field]} = $deviceName || -n $importAll ]] then importThisFileSystem=true else importThisFileSystem="" fi # Verify that the target cluster does not already # have a file system with the same name. if [[ -n $importThisFileSystem && $existingFileSystems = *" ${v[$DEV_NAME_Field]} "* ]] then importThisFileSystem="" fi ;; $SG_ETCFS ) # This line is a stanza line for one of the file systems. # If this is the first line in the stanza for a file system # being imported, verify that the mount point does not already # exist in the target cluster. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line && -n $importThisFileSystem && $existingMountPoints = *" ${v[$ETCFS_TEXT_Field]} "* ]] then importThisFileSystem="" fi ;; $SG_DISKS ) # This line describes a disk. # Create the device suffix to be used for temp files. if [[ ${v[$DEV_NAME_Field]} = $NO_DEVICE ]] then # Avoid any name collision by using ":", a prohibited character. suffix=_FREEDISK:_ else suffix=${v[$DEV_NAME_Field]} fi # Decide if this disk is to be imported. If the disk belongs to some # file system, the importThisFileSystem flag already has the correct # value. If this is a free disk, it will be imported only if all file # systems are being imported. Note that the importThisFileSystem flag # is used to control the importing of disks that are part of some file # system as well as the importing of free disks. if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] then if [[ -z $importAll ]] then importThisFileSystem="" else importThisFileSystem=true fi fi # If this disk belongs to a file system being imported, verify that # there are no name conflicts. If there is a name conflict with a # disk that is part of a file system, that file system is dropped. # If the conflict is with a free disk, only that disk is dropped. if [[ -n $importThisFileSystem ]] then # Check the name. conflictingDisk=$($grep -w ${v[$DISK_NAME_Field]} $existingDisks 2>/dev/null) if [[ -n $conflictingDisk ]] then # There is already a disk with the same name. if [[ ${v[$DEV_NAME_Field]} != $NO_DEVICE ]] then $rm -f $resetLVs.$suffix fi importThisFileSystem="" fi # end if [[ -n $conflictingDisk ]] fi # end of if [[ -n $importThisFileSystem ]] # If this is a PR-capable logical volume, # add the line to the disks to be unfenced. if [[ -n $importThisFileSystem && ${v[$DISK_TYPE_Field]} = "lv" && ${v[$DISK_SUBTYPE_Field]} != "other" ]] then print -- ${sdrfsLine} >> $resetLVs.$suffix checkForErrors "writing to file $resetLVs.$suffix" $? fi ;; * ) # Pass all other lines without a change. ;; esac # end of case ${v[$LINE_TYPE_Field]} in IFS=":" # Change the separator back to ":" for the next iteration. done # end while read -u3 sdrfsLine IFS="$IFS_sv" # Restore the default IFS settings. # Combine all resetLVs files. for fs in $($ls $resetLVs.* 2>/dev/null) do $cat $fs >> $disksToUnfence checkForErrors "writing to file $disksToUnfence" $? done # If there are disks to unfence, do it now. if [[ -s $disksToUnfence ]] then unfenceLogicalVolumes $aixNodes $disksToUnfence rc=$? fi ########################################################################### # Go through the input file with the exportfs information and extract # in separate files the information for each individual file system # that is to be imported. Verify that there are no name conflicts and # adjust the target nodeset id if necessary. ########################################################################### $rm -f $importFile.* $resetNSDs.* $importedFreeDisks $resetFreeDisks IFS=":" exec 3<&- exec 3< $fsImportData while read -u3 sdrfsLine do # Parse the line. set -f ; set -A v -- - $sdrfsLine ; set +f IFS="$IFS_sv" # Restore the default IFS settings. printLine=true # Assume the line will be printed. case ${v[$LINE_TYPE_Field]} in # The version line has been processed in the preliminary pass. # $VERSION_LINE ) # This is the global header line. # sourceCluster=${v[$CLUSTER_TYPE_Field]} # checkClusterCompatibility $sourceCluster $targetCluster # rc=$? # if [[ $rc -ne 0 ]] # then # # Incompatible cluster types. # printErrorMsg 44 $mmcmd $sourceCluster $targetCluster # cleanupAndExit # fi # getDiskRecoveryInformation $sourceCluster $recoveryFiles # ;; $SG_HEADR ) # This is the header line for some file system. # Starting the processing of a new file system. # See if the file system should be imported. if [[ ${v[$DEV_NAME_Field]} = $deviceName || -n $importAll ]] then # This file system should be imported. importThisFileSystem=true if [[ -n $importAll ]] then someFsFound=true else specifiedFsFound=true fi # Put an informational message: processing file system ... print -- "" # Output a blank separator line. printInfoMsg 250 $mmcmd ${v[$DEV_NAME_Field]} else # This file system should not be imported. importThisFileSystem="" fi # end of if [[ ${v[$DEV_NAME_Field]} = $deviceName || -n $importAll ]] # Verify that the target cluster does not already # have a file system with the same name. if [[ -n $importThisFileSystem && $existingFileSystems = *" ${v[$DEV_NAME_Field]} "* ]] then # There is already a file system with the same name. printErrorMsg 48 $mmcmd ${v[$DEV_NAME_Field]} failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}" importThisFileSystem="" fi # If the file system will be imported and there are no problems so far, # start building temporary files with the file system information. if [[ -n $importThisFileSystem ]] then # First, figure out what the device minor number should be. # Keep trying until we get an unused minor number. If this # does not work, we'll leave the device minor field null # hoping that mmfsmknod will take care of things later on. rc=0 newDevMinor="" while [[ -z $newDevMinor && rc -eq 0 ]] do # Assign a minor number to the file system. devMinor=$(assignDevMinor "$existingMinorNumbers") rc=$? if [[ $rc -eq 0 ]] then # See if the new device number is not being used by somebody on # the local node. This is a crude check but better than nothing. # Going and checking all nodes in the nodeset is too expensive. inuse=$($ls -lL /dev 2>/dev/null | \ $grep "^${fsDeviceType}.* $devMajor, *$devMinor ") # The number seems to be free, use it. [[ -z $inuse ]] && newDevMinor=$devMinor # Add the number to the list of existing number. existingMinorNumbers="$existingMinorNumbers $devMinor" fi # end of if [[ $rc -eq 0 ]] done # end of while [[ -z $newDevMinor && rc -eq 0 ]] # Change some of the fields as needed and put the line out. v[$NODESETID_Field]=$targetNodesetId v[$DEV_MINOR_Field]=$devMinor print_newLine >> $importFile.${v[$DEV_NAME_Field]} checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $? fi ;; $SG_ETCFS ) # This line is a stanza line for one of the file systems. # If this is the first line in the stanza for a file system # being imported, verify that the mount point does not already # exist in the target cluster. if [[ ${v[$LINE_NUMBER_Field]} = $MOUNT_POINT_Line && -n $importThisFileSystem && $existingMountPoints = *" ${v[$ETCFS_TEXT_Field]} "* ]] then # There is already a file system with the same mount point. # Tell the guy to use mmchfs -T to change the existing mount point. printErrorMsg 49 $mmcmd ${v[$DEV_NAME_Field]} ${v[$ETCFS_TEXT_Field]} failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}" $rm -f $importFile.${v[$DEV_NAME_Field]} $resetNSDs.${v[$DEV_NAME_Field]} importThisFileSystem="" fi # If the file system will be imported and there are no problems so far, # add the lines to the temporary files with the file system information. if [[ -n $importThisFileSystem ]] then v[$NODESETID_Field]=$targetNodesetId print_newLine >> $importFile.${v[$DEV_NAME_Field]} checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $? fi ;; $SG_MOUNT ) # This line has the mount options. # If the file system will be imported and there are no problems so far, # add the line to the temporary file with the file system information. if [[ -n $importThisFileSystem ]] then v[$NODESETID_Field]=$targetNodesetId print_newLine >> $importFile.${v[$DEV_NAME_Field]} checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $? fi ;; $SG_DISKS ) # This line describes a disk. # Decide if this disk is to be imported. If the disk belongs to some # file system, the importThisFileSystem flag already has the correct # value. If this is a free disk, it will be imported only if all file # systems are being imported. Note that the importThisFileSystem flag # is used to control the importing of disks that are part of some file # system as well as the importing of free disks. if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] then if [[ -z $importAll ]] then importThisFileSystem="" else importThisFileSystem=true # If not done already, put an informational message. if [[ -z $freeDiskStartMsg ]] then # Put an informational message: processing free disks ... print -- "" # Output a blank separator line. printInfoMsg 98 $mmcmd freeDiskStartMsg=issued fi fi # end if [[ -z $importAll ]] fi # end if [[ ${v[$NODESETID_Field]} = $FREE_DISK ]] # If this disk belongs to a file system being imported, verify that # there are no name conflicts. If there is a name conflict with a # disk that is part of a file system, that file system is dropped. # If the conflict is with a free disk, only that disk is dropped. if [[ -n $importThisFileSystem ]] then # Put an informational message: processing disk ... printInfoMsg 251 $mmcmd ${v[$DISK_NAME_Field]} # Check the name. conflictingDisk=$($grep -w ${v[$DISK_NAME_Field]} $existingDisks 2>/dev/null) if [[ -n $conflictingDisk ]] then # There is already a disk with the same name. printErrorMsg 51 $mmcmd ${v[$DISK_NAME_Field]} if [[ ${v[$DEV_NAME_Field]} != $NO_DEVICE ]] then failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}" $rm -f $importFile.${v[$DEV_NAME_Field]} $resetNSDs.${v[$DEV_NAME_Field]} fi importThisFileSystem="" fi # end if [[ -n $conflictingDisk ]] fi # end of if [[ -n $importThisFileSystem ]] # If the file system will be imported and there are no problems so far, # add the lines to the temporary files with the file system information. if [[ -n $importThisFileSystem ]] then # Ensure the disk is of the correct type for the cluster. importDiskOutput=$(importDisk_$targetCluster \ $sourceCluster $sdrfsLine $targetNodesetId $changeSpecFile) rc=$? # The output of importDisk consists of a one word overall result, # followed by the updated SG_DISKS line. Separate the two parts. importDiskResult=${importDiskOutput%% *} newDiskLine="${importDiskOutput#* }" if [[ $importDiskResult = success* ]] then if [[ ${v[$DEV_NAME_Field]} = $NO_DEVICE ]] then print -- ${newDiskLine} >> $importedFreeDisks checkForErrors "writing to file $importedFreeDisks" $? else print -- ${newDiskLine} >> $importFile.${v[$DEV_NAME_Field]} checkForErrors "writing to file $importFile.${v[$DEV_NAME_Field]}" $? fi if [[ $importDiskResult = successServersRemoved ]] then if [[ ${v[$DEV_NAME_Field]} = $NO_DEVICE ]] then print -- "\t${v[$DISK_NAME_Field]}" >> $resetFreeDisks checkForErrors "writing to file $resetFreeDisks" $? else print -- "\t${v[$DISK_NAME_Field]}" >> $resetNSDs.${v[$DEV_NAME_Field]} checkForErrors "writing to file $resetNSDs.${v[$DEV_NAME_Field]}" $? fi fi # end if [[ $importDiskResult = successServersRemoved ]] # Keep track of the highest NSD number assigned to a disk. if [[ ${v[$DISK_NAME_Field]} = gpfs+([0-9])nsd ]] then nsdName=${v[$DISK_NAME_Field]} nsdNumber=${nsdName#gpfs} nsdNumber=${nsdNumber%nsd} [[ $nsdNumber -gt $maxDiskNumber ]] && maxDiskNumber=$nsdNumber fi else # There is a problem with this disk; # free disk errors are reported but ignored. printErrorMsg 50 $mmcmd ${v[$DISK_NAME_Field]} if [[ ${v[$DEV_NAME_Field]} != $NO_DEVICE ]] then failedFileSystems="${failedFileSystems}\n\t${v[$DEV_NAME_Field]}" $rm -f $importFile.${v[$DEV_NAME_Field]} $resetNSDs.${v[$DEV_NAME_Field]} importThisFileSystem="" fi fi # end of if [[ $importDiskResult = success* ]] fi # end of if [[ -n $importThisFileSystem ]] ;; * ) # Pass all other lines without a change. ;; esac # end of case ${v[$LINE_TYPE_Field]} in IFS=":" # Change the separator back to ":" for the next iteration. done # end while read -u3 sdrfsLine IFS="$IFS_sv" # Restore the default IFS settings. ################################################################### # Add to the new mmsdrfs file the information for all file systems # that have not encountered any problems so far. ################################################################### for fs in $($ls $importFile.* 2>/dev/null) do $cat $fs >> $newsdrfs checkForErrors "writing to file $newsdrfs" $? fsToImport="$fsToImport\n\t${fs#$importFile.}" done # Add the imported free disks, if any. if [[ -s $importedFreeDisks ]] then $cat $importedFreeDisks >> $newsdrfs checkForErrors "writing to file $newsdrfs" $? fi # If nothing was imported, there is no sense continuing. if [[ -z $fsToImport && ! -s $importedFreeDisks ]] then # There is nothing to do. Issue appropriate messages. if [[ -n $importAll && -z $someFsFound ]] then # There is no file system information in the input file. printErrorMsg 273 $mmcmd $fsImportData elif [[ -z $importAll && -z $specifiedFsFound ]] then # The file system was not found in the input file. printErrorMsg 274 $mmcmd $device $fsImportData else : # nothing here for now fi # Tell the user which file systems had problems. if [[ -n $failedFileSystems ]] then # Report the file systems that were not imported. print -- "" # Output a blank separator line. printErrorMsg 275 $mmcmd "$failedFileSystems" fi # The command failed. printErrorMsg 389 $mmcmd cleanupAndExit fi ######################################################## # Update the HIGHEST_GPFS_DISK_NBR_Field if necessary. ######################################################## $rm -f $tmpfile # Make sure there is nothing in the file. if [[ $maxDiskNumber -gt $prevMaxDiskNumber && $MMMODE = lc ]] then $awk -F: ' \ # If this is the global header line, change the max NSD number. \ /^'$GLOBAL_ID:$VERSION_LINE:'/ { \ { $'$HIGHEST_GPFS_DISK_NBR_Field' = "'$maxDiskNumber'" } \ { print $1":" $2":" $3":" $4":" $5":" $6":" $7":" $8":" $9":"$10":" \ $11":"$12":"$13":"$14":"$15":"$16":"$17":"$18":"$19":"$20":" \ $21":"$22":"$23":"$24":"$25":"$26":"$27":" >> "'$tmpfile'" } \ { next } \ } \ # All other lines are echoed without change. \ { print $0 >> "'$tmpfile'" } \ ' $newsdrfs checkForErrors awk $? # The file was updated successfully. $mv $tmpfile $newsdrfs checkForErrors "mv $outfile $newsdrfs" $? fi ############################################ # Sort the new version of the mmsdrfs file. ############################################ LC_ALL=C $SORT_MMSDRFS $newsdrfs -o $newsdrfs checkForErrors "sorting $newsdrfs" $? ############################################################ # Replace the mmsdrfs file in the sdr with the new version. ############################################################ print -- "" # Output a blank separator line. print -- "$mmcmd: Committing the changes ..." trap "" HUP INT QUIT KILL gpfsObjectInfo=$(commitChanges \ $nsId $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer) rc=$? if [[ $rc -ne 0 ]] then # Cannot replace the file in the sdr. printErrorMsg 381 $mmcmd cleanupAndExit fi ################################################################### # Unlock the sdr. ################################################################### freeLockOnServer $primaryServer $ourNodeNumber >/dev/null sdrLocked=no trap posttrap HUP INT QUIT KILL ###################################################################### # Issue messages summarizing the results and what remains to be done. ###################################################################### print -- "" # Output a blank separator line. # Tell the user which file systems were successfully imported. [[ -n $fsToImport ]] && \ print -u2 "$mmcmd: The following file systems were successfully imported: $fsToImport" # Tell the user which disks may need new server nodes. for fs in $($ls $resetNSDs.* 2>/dev/null) do print -u2 "$mmcmd: The NSD servers for the following disks from file system ${fs#$resetNSDs.} were reset or not defined:" $cat $fs 1>&2 mmchnsdMessageNeeded=true done # Add the imported free disks, if any. if [[ -s $resetFreeDisks ]] then print -u2 "$mmcmd: The NSD servers for the following free disks were reset or not defined:" $cat $resetFreeDisks 1>&2 mmchnsdMessageNeeded=true fi [[ -n $mmchnsdMessageNeeded ]] && \ print -u2 "$mmcmd: Use the mmchnsd command to assign NSD servers as needed." # Tell the user which file systems were not imported. [[ -n $failedFileSystems ]] && \ print -u2 "$mmcmd: The following file systems were not imported: $failedFileSystems" ################################################################# # Propagate the new mmsdrfs file. This process is asynchronous. ################################################################# propagateSdrfsFile async $allClusterNodes $newsdrfs $newGenNumber rereadnsd cleanupAndExit 0