#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 2001,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 # @(#)10 1.39.1.2 src/avs/fs/mmfs/ts/admin/mmchnsd.sh, mmfs, avs_rgpfs24, rgpfs24s005a 6/14/06 14:39:52 ############################################################################### # # Usage: # mmchnsd {"DiskDesc[;DiskDesc...]" | -F DescFile} # # where # DiskDesc is a descriptor for the disk to be changed # -F DescFile specifies a file containing the disk descriptors for # the network shared disks to be changed # # Notes: # You cannot change the name of a disk. # # Changing the failure group and disk usage is a no-op for mmchnsd. # Instead, use the mmchdisk command for this purpose. # # You must explicitly specify the desired new values # for both primary and backup server even if changing # only one of them. # # The following operations are allowed: # # - Changing the primary and/or backup server for a disk. # # - Defining a backup server for a disk that up to this # moment did not have one. # # - Deleting the backup server for a disk. # # - Removing the primary and backup servers for a disk, # thereby converting it to a directly-attached disk. # # - Assigning a primary and an optional backup server to # a directly-attached disk. # ############################################################################### # Include global declarations and service routines. . /usr/lpp/mmfs/bin/mmglobfuncs . /usr/lpp/mmfs/bin/mmsdrfsdef . /usr/lpp/mmfs/bin/mmfsfuncs sourceFile="mmchnsd.sh" [[ -n $DEBUG || -n $DEBUGmmchnsd ]] && set -x $mmTRACE_ENTER "$*" # Local work files. Names should be of the form: # fn=${tmpDir}fn.${mmcmd}.$$ descfile=${tmpDir}descfile.${mmcmd}.$$ existingDisks=${tmpDir}existingDisks.${mmcmd}.$$ affectedFileSystems=${tmpDir}affectedFileSystems.${mmcmd}.$$ LOCAL_FILES=" $descfile $existingDisks $affectedFileSystems " # Local variables usageMsg=438 noUsageMsg=0 hadSuccess=false ###################### # Mainline processing ###################### ###################################### # Process the command line arguments. ###################################### [[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] && \ syntaxError "help" $usageMsg [[ $argc -lt 1 ]] && \ syntaxError "missingArgs" $usageMsg if [[ $arg1 != "-F" ]] then # If the first argument is not -F, it must be a disk descriptor list. desclist=$arg1 # Ensure that semi-colon is used as a disk name separator. [[ "$desclist" = *+([,${BLANKchar}${TABchar}])* ]] && \ syntaxError "badSeparator_notSemicolon" $noUsageMsg else # -F specified. The second argument must be a file name. if [[ -z $arg2 ]] then syntaxError "missingFile" $usageMsg else # Verify the existence of the file and create our own copy. checkUserFile $arg2 $descfile [[ $? -ne 0 ]] && cleanupAndExit shift fi # end of if [[ -z $arg2 ]] fi # end of if [[ $arg1 != "-F" ]] # Move past the required parameters. shift 1 [[ $# != 0 ]] && syntaxError "extraArg" $usageMsg $1 ##################################################################### # 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) ########################################################### # If a descriptor list is specified on the command line, # create a file with one disk descriptor per line. # Note: If the input is in a file, descfile was created # by the checkUserFile function. ########################################################### if [[ -n $desclist ]] then # Move the descriptors into a temporary file. $rm -f $descfile IFS=";" for diskDesc in $desclist do [[ -z $diskDesc ]] && continue print -- "$diskDesc" >> $descfile checkForErrors "writing to file $descfile" $? done # end for diskDesc in $desclist IFS="$IFS_sv" fi # end of if [[ -n $desclist ]] ######################################################################### # Create a new version of the mmsdrfs file with a new generation number. # Generate a file containing the names of the nodes in the cluster. # Generate files containing the nodes in the different nodesets. ######################################################################### $rm -f $nodefile $newsdrfs $existingDisks 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. printLine=true # Assume the line will be printed. # 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 ) # this line describes a node # Add the node to the file with all nodes in the cluster. print -- "${v[$REL_HOSTNAME_Field]}" >> $nodefile checkForErrors "writing to file $nodefile" $? ;; $SG_DISKS ) # this line describes a disk that belongs to some file system # Generate a file with SG_DISKS lines for all disks in the cluster. print -- $sdrfsLine >> $existingDisks checkForErrors "writing to file $existingDisks" $? printLine=false ;; * ) # 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. # Give up if there are no NSDs in the cluster. if [[ ! -s $existingDisks ]] then # Issue message that the requested disks are not known to GPFS. printErrorMsg 481 $mmcmd cleanupAndExit fi ######################################################## # Process the descriptors with the new disk attributes. ######################################################## foundErrors=false $rm -f $affectedFileSystems exec 3<&- exec 3< $descfile while read -u3 mmDiskDesc do # Skip empty and comment lines. [[ $mmDiskDesc = *([$BLANKchar$TABchar]) ]] && continue [[ $mmDiskDesc = *([$BLANKchar$TABchar])#* ]] && continue # Parse mmDiskDesc to get the name of the disk. IFS=':' set -f ; set -- $mmDiskDesc ; set +f diskName=$1 IFS="$IFS_sv" if [[ -z $diskName ]] then # The disk name must be specified in the disk descriptor. printErrorMsg 23 $mmcmd # Show the bad descriptor. printErrorMsg 386 $mmcmd "$mmDiskDesc" # The command will fail, but before giving up, we will check the # remainder of the descriptors to flush out as many errors as possible. foundErrors=true [[ $sdrLocked = yes ]] && \ freeLockOnServer $primaryServer $ourNodeNumber >/dev/null sdrLocked=no # Move to the next descriptor. continue fi # Locate and extract the SG_DISK line for this disk. $rm -f $tmpfile currentDiskLine=$($awk -F: ' \ # If the line is for our disk, assigned it to currentDiskLine. \ # Do not put the line in the temp file. \ $'$DISK_NAME_Field' == "'$diskName'" { \ { print $0 } \ { next } \ } \ # If the line is for some other disk, add it to tmpfile. \ { print $0 >> "'$tmpfile'" } \ ' $existingDisks) checkForErrors awk $? # Prepare the existingDisks file for the next iteration. # It will contain all of its original lines except the line # that describes the disk that is currently being processed. $touch $tmpfile # Ensure file exists even if empty. $mv $tmpfile $existingDisks checkForErrors "mv $tmpfile $existingDisks" $? # If not found, issue an appropriate error message. if [[ -z $currentDiskLine ]] then # Check whether the disk was processed earlier. alreadyProcessed=$(getDiskInfo $DISK_NAME_Field $diskName $newsdrfs) if [[ -n $alreadyProcessed ]] then # This disk was already processed; it must be a duplicate entry. printErrorMsg 88 $mmcmd $diskName else # Print error stating disk descriptor should refer to an existing NSD. printErrorMsg 415 $mmcmd "$mmDiskDesc" fi # The command will fail, but before giving up, we will check the # remainder of the descriptors to flush out as many errors as possible. foundErrors=true [[ $sdrLocked = yes ]] && \ freeLockOnServer $primaryServer $ourNodeNumber >/dev/null sdrLocked=no # Move to the next descriptor. continue fi # end of if [[ -z $currentDiskLine ]] # Find out the file system and nodeset to which this disk belongs. # Parse the line. IFS=":" set -f ; set -A v -- - $currentDiskLine ; set +f IFS="$IFS_sv" print -- "${v[$DEV_NAME_Field]}" >> $affectedFileSystems checkForErrors "writing to file $affectedFileSystems" $? # Check the correctness of the disk descriptor. If everything is OK, # validateAndConvertNsdDescriptor will create an SG_DISKS line with # the new parameters for the disk. validateDescriptorOutput=$(validateAndConvertNsdDescriptor "$mmDiskDesc" \ $currentDiskLine $CHANGE_NSD ${v[$NODESETID_Field]} NULL) rc=$? if [[ $rc -ne 0 ]] then # If an error was found, the validate routine issued a message. # We will now print the entire descriptor to help the guy some more. printErrorMsg 386 $mmcmd "$mmDiskDesc" # The command will fail, but before giving up, we will check the remainder # of the descriptors to flush out as many errors as possible. foundErrors=true [[ $sdrLocked = yes ]] && \ freeLockOnServer $primaryServer $ourNodeNumber >/dev/null sdrLocked=no else # If the descriptor seems to be OK, parse the output # from the validateAndConvertNsdDescriptor routine. set -f ; set -- $validateDescriptorOutput ; set +f updatedDiskLine="$1" #esjrm Add tspreparedisk connectivity verification ??? #esjrm Do it based on the pvid (see backup server checking in mmcrnsd) #esjrm Make it conditional on some input flag ( -v yes|no ??) #esjrm Is this the right place ? # Add the SG_DISKS line for the disk to the mmsdrfs file. print -- $updatedDiskLine >> $newsdrfs checkForErrors "writing to file $newsdrfs" $? fi # end of if [[ $rc -ne 0 ]] done # end of while read -u3 mmDiskDesc # Give up if there were errors with one or more of the descriptors. if [[ $foundErrors = true ]] then # Command failed. printErrorMsg 389 $mmcmd cleanupAndExit fi ################################################ # Lock the gpfs object to prevent daemons # from starting while things are being changed. ################################################ [[ $getCredCalled = no ]] && getCred setRunningCommand "$mmcmd" $primaryServer checkForErrors setRunningCommand $? gpfsLocked=yes ################################################## # Verify all affected file systems are unmounted. ################################################## $sort -u -o $affectedFileSystems $affectedFileSystems checkForErrors "sort -u $affectedFileSystems" $? exec 3<&- exec 3< $affectedFileSystems while read -u3 fsLine do set -f ; set -- $fsLine ; set +f fsToCheck=$1 [[ $fsToCheck = $NO_DEVICE ]] && continue # Make sure the file system is not mounted on any of the nodes. $mmcommon onactive $preferredNode $nodefile \ $NO_FILE_COPY $fsToCheck $CHECK_ALL $NO_LINK $MOUNT_CHECK_ONLY 2>$errMsg rc=$? if [[ $rc -eq $MM_FsMounted ]] then # File system is still mounted; messages 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 # The command failed. printErrorMsg 389 $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 $fsToCheck" $rc fi # The command was unable to determine whether the file system is mounted. printErrorMsg 564 $mmcmd $fsToCheck cleanupAndExit $rc fi # end if [[ $rc -eq $MM_FsMounted ]] $rm -f $errMsg done # end of while read -u3 fsLine #################################################### # Put the unchanged disks back in the mmsdrfs file. #################################################### $cat $existingDisks >> $newsdrfs checkForErrors "cat $existingDisks >> $newsdrfs" $? ############################################ # Sort the new version of the mmsdrfs file. ############################################ LC_ALL=C $SORT_MMSDRFS $newsdrfs -o $newsdrfs #################################################### # Replace the mmsdrfs file. This makes the changes # to the disks visible to the rest of the world. #################################################### trap "" HUP INT QUIT KILL gpfsObjectInfo=$(commitChanges \ $FREE_DISK $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 posttrap HUP INT QUIT KILL ################################################################# # Propagate the new mmsdrfs file. This process is asynchronous. ################################################################# propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber rereadnsd ################################################### # If installed, invoke the syncfsconfig user exit. ################################################### if [[ -x $syncfsconfig ]] then print -- "$mmcmd: Starting $syncfsconfig ..." $syncfsconfig print -- "$mmcmd: $syncfsconfig finished." fi cleanupAndExit 0