#!/bin/ksh # IBM_PROLOG_BEGIN_TAG # This is an automatically generated prolog. # # # # Licensed Materials - Property of IBM # # (C) COPYRIGHT International Business Machines Corp. 1997,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 # @(#)29 1.290.1.9 src/avs/fs/mmfs/ts/admin/mmremote.sh, mmfs, avs_rgpfs24, rgpfs24s008a 11/25/06 00:29:43 ####################################################################### # Include global declarations and service routines. . /usr/lpp/mmfs/bin/mmglobfuncs . /usr/lpp/mmfs/bin/mmsdrfsdef . /usr/lpp/mmfs/bin/mmfsfuncs sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGmmremote ]] && set -x $mmTRACE_ENTER "$*" # Local work files. Names should be of the form: # fn=${tmpDir}fn.${mmcmd}.$$ LOCAL_FILES=" " # Local variables typeset -l kword_lc typeset -l arg3_lc rc=0 # Local functions #################################################################### # # Function: Take a snapshot of the currently-running trace. # # Input: $1 - action to perform # # Output: None # # Returns: 0 # #################################################################### function traceSnapshot { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGtraceSnapshot ]] && set -x $mmTRACE_ENTER "$*" typeset action=$1 typeset tracePid if [[ -z $(print -- " off on offon log " | $fgrep " $action ") ]] then # Invalid value for flag printErrorMsg 153 $mmcmd tsnap return 1 fi if [[ $action != off ]] then $mmfsadm showtrace >/dev/null if [[ $? -eq 0 ]] then $mmfsadm trace all 9 $mmfsadm trace tm 2 thread 1 mutex 1 vnode 1 ksvfs 1 klockl 0 $mmfsadm trace io 3 pgalloc 1 mb 1 lock 2 dfs 2 fsck 3 fi fi tracePid=$($ps -eo "pid args" | $awk '/trace / && !/this process/ {print $1}') if [[ ($action = off || $action = offon) && -n $tracePid ]] then $trcstop $mv /var/adm/ras/trcfile /var/adm/ras/trcfile.$(date +"%H.%M.%S") fi if [[ $action = offon || $action = on ]] then $trace -a -l -L 12000000 -T 4000000 -j 306,307,308,309 \ -o /var/adm/ras/trcfile >/dev/null 2>&1 & fi date=$(date +"%y%m%d") $mkdir -p /log/$date 2>/dev/null for trcname in $($ls /var/adm/ras | $grep trcfile.) do time=$(print -- $trcname | $awk -F. '{print $2}') $cp -p /var/adm/ras/trcfile.$time \ /log/$date/trcfile.$date.$time."$($hostname -s)" $rm -f /var/adm/ras/trcfile.$time done return 0 } #------ end of function traceSnapshot ------------------- ############################################################################### # # Function: Send the local mmsdrfs file to the node that is requesting it. # Do this only if the client's generation number is smaller than # the generation number of the mmsdrfs file on this node. # If requested, get the lock. # # Input: $1 - generation number of the sdr file on the client # $2 - name of client requesting the file # $3 - name to use on the client for the retrieved file # $4 - lockId or nolock # # Output: gpfsObject or 'fail'. # # Returns: Zero if successful, non-zero otherwise. # ############################################################################### function sendClusterSDRFiles # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGsendClusterSDRFiles ]] && set -x $mmTRACE_ENTER "$*" typeset clientGenNumber=$1 typeset client=$2 typeset fileName=$3 typeset lockId=$4 typeset rc=0 typeset lockObtained="" typeset lockResult gpfsObjectInfo serverGenNumber junk typeset pid getObjectPort # Get the lock if requested if [[ $lockId != nolock ]] then lockResult=$(getLock $lockId) # Look at the result from the lock request. # If it is more than one word, we assume it is an error message. set -f ; set -- $lockResult ; set +f gpfsObjectInfo=$1 junk=$2 if [[ -z $gpfsObjectInfo || -n $junk ]] then # If unexpected output, give up [[ -n $junk ]] && \ print -u2 "$lockResult" return 1 fi if [[ $lockResult = fail ]] then print -- "fail" return 1 else lockObtained=yes fi fi # If we are here, either the caller did not need the lock or the lock # was successfully obtained. Make sure the caller has the latest data. # Get the server's generation number. gpfsObjectInfo=$(getGpfsObject) rc=$? IFS=':' set -f ; set -- $gpfsObjectInfo ; set +f IFS="$IFS_sv" serverGenNumber=$2 if [[ $rc -ne 0 || -z $serverGenNumber ]] then # Unexpected value for the Gpfs object [[ $rc -eq 0 ]] && \ printErrorMsg 286 sendClusterSDRFiles $gpfsObjectInfo [[ $lockObtained = yes ]] && \ freeLock 0 > /dev/null print -- "fail" return 1 fi # If the client's local generation number is smaller than # the one we have here, copy our version to the client. if [[ $clientGenNumber -lt $serverGenNumber ]] then $rcp $mmsdrfsFile ${client}:${fileName} rc=$? fi # If everything is OK so far, return the Gpfs object. if [[ $rc -eq 0 ]] then print -- "$gpfsObjectInfo" else [[ $lockObtained = yes ]] && \ freeLock 0 > /dev/null print -- "fail" fi return $rc } #------ end of function sendClusterSDRFiles ------------ ############################################################################ # # Function: Determine whether this node is new to GPFS and whether the # GPFS code on this node can support clustering. If it can, # create a skeleton version of the sdrfs file that reflects # the passed key attributes and a generation number of 1. # # Input: cltype - cluster and environment type (e.g., "lc/lc2") # primaryServer - primary server # backupServer - secondary server or _NOSECONDARY_ # localNodeData - hostname, node number, etc. for the node # rshPath - remote shell command or _DEFAULT_ # rcpPath - remote file copy command or _DEFAULT_ # clusterIdAndSt - cluster id and cluster subtype # # Output: A colon-separated list of the following fields: # keyword - checkNewClusterNode # status - success, not_new, etc. # adapter type - e.g., eth0 # daemon version - e.g., 800 # product version - e.g., 2.3.0.0 # OS name - AIX or Linux # # Note: The adapter type and subsequent fields have meaningful # information only if status is "success". # # Returns: zero if success, non-zero otherwise # ############################################################################ function checkNewClusterNode # # # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGcheckNewClusterNode ]] && set -x $mmTRACE_ENTER "$*" typeset cltype=$1 typeset primary=$2 typeset secondary=$3 typeset localNodeData=$4 typeset rshPath=$5 typeset rcpPath=$6 typeset clusterIdAndSt=$7 typeset clusterType environmentType result hostResult typeset initialSystemFiles sdrfsLine nodeNumber ipa adminNodeName adminIpa typeset clusterId clusterSubtype adapterType nodeStatus typeset newGenNumber=1 typeset rc=0 initialSystemFiles="$mmsdrfsFile ${mmfsEnvLevel}$newGenNumber $mmfsNodeData" [[ $secondary = "_NOSECONDARY_" ]] && secondary="" [[ $rshPath = "_DEFAULT_" ]] && rshPath="" [[ $rcpPath = "_DEFAULT_" ]] && rcpPath="" export GPFS_rshPath="$rshPath" export GPFS_rcpPath="$rcpPath" # Check that no sdrfs file exists on this node; # report "not new" if an sdrfs file already exists. if [[ -f $mmsdrfsFile ]] then print -- "checkNewClusterNode:not_new:" return 1 fi # Parse the overloaded input parameters. IFS='/' set -f ; set -- $cltype ; set +f IFS="$IFS_sv" clusterType=$1 environmentType=$2 [[ -z $environmentType ]] && environmentType=$clusterType IFS=':' set -f ; set -- $clusterIdAndSt ; set +f IFS="$IFS_sv" clusterId=$1 clusterSubtype=$2 [[ -z $clusterSubtype ]] && clusterSubtype=$environmentType # Check whether the prerequisite software for the specified # cluster type is installed. checkPrereqs $environmentType if [[ $? -ne 0 ]] then print -- "checkNewClusterNode:not_supported:" return 1 fi # Create a skeleton sdrfs file on this node. $mkdir -p $mmsdrfsDir sdrfsLine="$GLOBAL_ID:$VERSION_LINE::$CURRENT_SDRFS_FORMAT:$CURRENT_SDRFS_VERSION" sdrfsLine="$sdrfsLine:$newGenNumber::$clusterType:$primary:$secondary" sdrfsLine="$sdrfsLine::$rshPath:$rcpPath:$clusterId:$clusterSubtype:" print -- "$sdrfsLine" > $mmsdrfsFile # Add threatening comment lines: DO NOT MESS WITH THIS FILE! sdrfsLine="$GLOBAL_ID:$COMMENT_LINE::1:" print -- "$sdrfsLine" >> $mmsdrfsFile sdrfsLine="$GLOBAL_ID:$COMMENT_LINE::2:$warningText" print -- "$sdrfsLine" >> $mmsdrfsFile sdrfsLine="$GLOBAL_ID:$COMMENT_LINE::3:" print -- "$sdrfsLine" >> $mmsdrfsFile # Add the local node information. print -- "$localNodeData" >> $mmsdrfsFile rc=$? if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkNewClusterNode" "writing to file $mmsdrfsFile" $rc print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi # Create a file with the MEMBER_NODE line for this node. # It will be used later to quickly determine the node's # node number, reliable hostname, and other information. print -- "$localNodeData" > $mmfsNodeData rc=$? if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkNewClusterNode" "writing to file $mmfsNodeData" $rc print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi # Remember the current level of the system files. $touch ${mmfsEnvLevel}$newGenNumber # Flush the important files to disk. $mmsync $mmsdrfsFile $mmfsNodeData ${mmfsEnvLevel}$newGenNumber # Retrieve needed information from the local node data. IFS=':' set -f ; set -A v -- - $localNodeData ; set +f IFS="$IFS_sv" nodeNumber=${v[$NODE_NUMBER_Field]} ipa=${v[$IPA_Field]} adapterType=${v[$ADAPTER_TYPE_Field]} adminNodeName=${v[$REL_HOSTNAME_Field]} daemonNodeName=${v[$DAEMON_NODENAME_Field]} if [[ -z $adapterType ]] then # Get the node's adapter information. $ifconfig -a > $adfile rc=$? if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkNewClusterNode" "ifconfig -a" $rc print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi # Find the adapter type for the primary GPFS network. # The assumptions are that the ifconfig output is organized in stanzas. # Each stanza begins with the adapter type starting in column 1. # All other lines are indented by at least one space or tab character. if [[ $osName = Linux ]] then adapterType=$($awk ' \ $0 !~ /^[ ]/ { adapterType = $1 } \ / addr:'$ipa' / { print adapterType ; exit } \ ' $adfile) rc=$? elif [[ $osName = AIX ]] then adapterType=$($awk ' \ $0 !~ /^[ ]/ { adapterType = $1 } \ /[ ]inet '$ipa' / { print adapterType ; exit } \ ' $adfile) rc=$? adapterType=${adapterType%:} else # Should never get here. printErrorMsg 171 "checkNewClusterNode" "unsupported OS $osName" 1 print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkNewClusterNode" "awk" $rc print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi # Verify that the adapter exists. if [[ -z $adapterType ]] then # Print error type and return. printErrorMsg 154 $mmcmd $ipa $adminNodeName print -- "checkNewClusterNode:ipa_missing" $rm -f $initialSystemFiles return 1 fi # If this is an IP alias, use the name of the main device. adapterType=${adapterType%%:*} # Add the new information to the local node data. v[$ADAPTER_TYPE_Field]=$adapterType localNodeData=$(print_newLine) print -- "$localNodeData" > $mmfsNodeData rc=$? if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkNewClusterNode" "writing to file $mmfsNodeData" $rc print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi fi # end of if [[ -z $adapterType ]] # Check that the admin interface name is valid # if it is different than the one we just checked. if [[ $adminNodeName != $daemonNodeName ]] then # Determine the IP address for the specified admin node name. hostResult=$($host $adminNodeName) set -f ; set -- $hostResult ; set +f adminIpa=${3%%,*} # Check that the admin node name has a valid IP address. if [[ -z $adminIpa ]] then # An invalid node name was specified. printErrorMsg 54 $mmcmd $adminNodeName $rm -f $initialSystemFiles return 1 fi # Find the adapter type for the admin network. # The assumptions are that the ifconfig output is organized in stanzas. # Each stanza begins with the adapter type starting in column 1. # All other lines are indented by at least one space or tab character. if [[ $osName = Linux ]] then adapterType=$($awk ' \ $0 !~ /^[ ]/ { adapterType = $1 } \ / addr:'$adminIpa' / { print adapterType ; exit } \ ' $adfile) rc=$? elif [[ $osName = AIX ]] then adapterType=$($awk ' \ $0 !~ /^[ ]/ { adapterType = $1 } \ /[ ]inet '$adminIpa' / { print adapterType ; exit } \ ' $adfile) rc=$? adapterType=${adapterType%:} else # Should never get here. printErrorMsg 171 "checkNewClusterNode" "unsupported OS $osName" 1 print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkNewClusterNode" "awk" $rc print -- "checkNewClusterNode:unexpected_error:" $rm -f $initialSystemFiles return 1 fi # Verify that the adapter exists. if [[ -z $adapterType ]] then # Print error type and return. printErrorMsg 154 $mmcmd $adminIpa $adminNodeName print -- "checkNewClusterNode:ipa_missing" $rm -f $initialSystemFiles return 1 fi # If this is an IP alias, use the name of the main device. adapterType=${adapterType%%:*} fi # end of if [[ $adminNodeName != $daemonNodeName ]] # Report success and return to caller. result="checkNewClusterNode:success:$adapterType:$currentDaemonVersion" result="$result:$productVersion:$osName:" print -- "$result" return 0 } #------ end of function checkNewClusterNode -------------- ############################################################################ # # Function: Verify that the specified adapter exists. # # Input: IP address of the adapter to check # # Output: The word "success" or a keyword representing the type # of failure: "unexpected_error", "ipa_missing", etc. # # Returns: zero if success, non-zero otherwise # ############################################################################ function checkAdapter # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGcheckAdapter ]] && set -x $mmTRACE_ENTER "$*" typeset ipa=$1 typeset adapterType="" typeset rc=0 # Get the node's adapter information. $ifconfig -a > $adfile rc=$? if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkAdapter" "ifconfig -a" $rc print -- "unexpected_error" return 1 fi # Find the adapter type from the ifconfig output. # The assumptions are that the output is organized in stanzas. # Each stanza begins with the adapter type starting in column 1. # All other lines are indented by at least one space or tab character. if [[ $osName = Linux ]] then adapterType=$($awk ' \ $0 !~ /^[ ]/ { adapterType = $1 } \ / addr:'$ipa' / { print adapterType ; exit } \ ' $adfile) rc=$? elif [[ $osName = AIX ]] then adapterType=$($awk ' \ $0 !~ /^[ ]/ { adapterType = $1 } \ /[ ]inet '$ipa' / { print adapterType ; exit } \ ' $adfile) rc=$? adapterType=${adapterType%:} else # Should never get here. printErrorMsg 171 "checkAdapter" "unsupported OS $osName" 1 print -- "unexpected_error" return 1 fi if [[ $rc -ne 0 ]] then printErrorMsg 171 "checkAdapter" "awk" $rc print -- "unexpected_error" return 1 fi # Verify that the adapter exists. if [[ -z $adapterType ]] then # Print error type and return. print -- "ipa_missing" return 1 fi # Report success and return to caller. print -- "success" return 0 } #------ end of function checkAdapter --------------------- ################################################################ # # Function: Run an administration command. # # Input: Command name and arguments # # Output: Depends on the command # # Returns: 127 Command not supported # Return code from the command # ################################################################ function runCommand # [] { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGrunCommand ]] && set -x $mmTRACE_ENTER "$*" typeset adminCmd=${1##*/} # get the basename part of typeset arguments="$2" typeset rc=0 # Verify the command belongs to the set of allowed commands. case $adminCmd in "cat" ) adminCmd=$cat ;; "head" ) adminCmd=$head ;; "lspv" ) adminCmd=$lspv ;; "lssrc" ) adminCmd=$lssrc ;; "lsvsd" ) adminCmd=$lsvsd ;; "mmfsadm" ) adminCmd=$mmfsadm ;; "mmtrace" ) adminCmd=$mmtrace ;; "mount" ) adminCmd=$mount ;; "removevsd" ) adminCmd="$removevsd -f -v " ;; "touch" ) adminCmd=$touch ;; "tsaddrmap" ) adminCmd=$tsaddrmap ;; "tsctl" ) adminCmd=$tsctl ;; "tspreparedisk" ) adminCmd=$tspreparedisk ;; "umount" ) adminCmd=$umount ;; "unmount" ) adminCmd=$unmount ;; * ) return 127 ;; # invalid command esac # Run the command and propagate back the return code. $adminCmd $arguments rc=$? [[ $adminCmd = ts* || $adminCmd = mm* ]] && \ rc=$(remapRC $?) return $rc } #------ end of function runCommand ------------------- ############################################################################## # # Function: Determine the state of the GPFS daemon and other node info. # # Input: $1 - (optional) Extended output (-L option) # # Output: # mmGetState:nsId:nodeNum:name:tsQuorum:up:total:state:quorumDesignation: # # Returns: Zero if successful, non-zero otherwise. # ############################################################################## function mmGetState # [-L] { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGmmGetState ]] && set -x $mmTRACE_ENTER "$*" typeset extendedOutput=$1 typeset tsctlOutput="" typeset rc tsQuorum nodesUp totalNodes daemonState quorumDesignation result typeset gpfsInitOutput if [[ -n $extendedOutput ]] then # Extended output is requested. # Make sure that the local copies of the mmsdrfs, mmfs.cfg, # and the rest of the system files are up to date. gpfsInitOutput=$(gpfsInit nolock) setGlobalVar $? $gpfsInitOutput # Determine the total nodes value and whether or not this is a quorum node. totalAndType=$($awk -F: ' \ BEGIN { \ { total = 0 } \ { type = "" } \ } \ /':$NODESET_HDR:'/ { \ if ( $'$NODESETID_Field' == "'$nsId'" ) { \ { total = $'$NODE_COUNT_Field' } \ } \ } \ /':$MEMBER_NODE:'/ { \ if ( $'$REL_HOSTNAME_Field' == "'$ourNodeName'" ) { \ { type = $'$CORE_QUORUM_Field' } \ { exit } \ } \ } \ END { print total ":" type } \ ' $mmsdrfsFile) checkForErrors awk $? IFS=':' set -f ; set -- $totalAndType ; set +f totalNodes=$1 quorumDesignation=$2 IFS="$IFS_sv" else # Regular output is requested. Return fake values # for quorum designation and total nodes. totalNodes=0 quorumDesignation=unknown fi # end of if [[ -n $extendedOutput ]] # Determine the quorum state of the daemon. tsctlOutput=$(LC_ALL=C $tsctl quorumState 2>$errMsg) rc=$(remapRC $?) # Interpret the results from the tsctl command. if [[ -z $tsctlOutput ]] then # The command failed. Filter out "Failed to connect" messages. # Show any other error messages that might be there. $grep -v -e "6027-665" -e "Failed to connect to file system daemon" $errMsg >$errMsg2 [[ -s $errMsg2 ]] && $cat $errMsg2 1>&2 # Provide default values to be returned to the caller. tsQuorum=0 nodesUp=0 if [[ $rc -eq $MM_DaemonDown ]] then daemonState="down" else daemonState="unknown" fi else # The tsctl command seemed to work. Parse the output. # We intentionally override the totalNodes value found prior to # the tsctl call because the daemon value may include remote nodes # not reflected in the value we obtained from the sdrfs file. IFS=':' set -f ; set -- $tsctlOutput ; set +f tsQuorum=$1 nodesUp=$2 totalNodes=$3 daemonState=$4 IFS="$IFS_sv" # Remap the daemon status strings. case $daemonState in "Initial" ) daemonState="arbitrating" ;; "Active" ) daemonState="active" ;; * ) : ;; # Unknown string; leave it as is. esac fi # end of if [[ -z $tsctlOutput ]] # Build and print the result string. result="mmGetState:$nsId:$ourNodeNumber:$ourShortName:$tsQuorum" result="${result}:$nodesUp:$totalNodes:$daemonState:$quorumDesignation:" print -- "$result" return 0 } #------ end of function mmGetState ------------------- ################################################################### # # Function: Determine the state of the specified subsystem. # # Input: $1 - subsystem name # # Output: mmgetSubsysState::: # # Returns: Always zero. # ################################################################### function getSubsysState # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGgetSubsysState ]] && set -x $mmTRACE_ENTER "$*" typeset subsys=$1 typeset subsysState="" # Determine whether the subsystem is active. if [[ $subsys = rvsd ]] then subsysState=$(LC_ALL=C $lssrc -ls $subsys | $grep 'active=1, state=idle' 2>/dev/null) [[ -n $subsysState ]] && subsysState=active elif [[ $subsys = mmfs ]] then $ps -e | $grep -w mmfsd >/dev/null 2>&1 rc=$? if [[ $rc -eq 0 ]] then print -- "active" else print -- "inactive" fi else subsysState=$(LC_ALL=C $lssrc -s $subsys | \ $awk ' BEGIN { state = "inactive" } $1 == "'$subsys'" { if ( $NF == "active" ) { state = "active" } } END { print state } ') fi # end if [[ $subsys = rvsd ]] [[ -z $subsysState ]] && subsysState=down # Build and print the result string. result="mmgetSubsysState:$ourNodeName:$subsysState:" print -- "$result" return 0 } #------ end of function getSubsysState ------------------- ########################################################################### # # Function: Verifies that the RVSD subsystem is active on all nodes # on which the GPFS daemon is running and then sets the # wait4RVSD parameter to yes. # # Input: none # # Output: none # # Returns: 0 - RVSD operational on all nodes # 1 - Error detected, or RVSD inactive on one or more nodes # ########################################################################### function setWait4RVSD # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGsetWait4RVSD ]] && set -x $mmTRACE_ENTER "$*" typeset subsysStateLine kword nodeName rvsdState failedNodes junk typeset errorFound="" typeset rc=0 ################################################################## # Use tsdsh to find the state of RVSD on all active GPFS nodes. ################################################################## $tsdsh $mmremote getSubsysState rvsd >$tmpfile 2>&1 rc=$(remapRC $?) if [[ ! -s $tmpfile ]] then # If there is no output at all, something is very wrong. [[ $rc -eq 0 ]] && rc=1 checkForErrors "setWait4RVSD" $rc else # If we have output, ignore the rc from tsdsh. rc=0 fi # Parse the output from the RVSD active test. $rm -f $errMsg exec 3<&- exec 3< $tmpfile while read -u3 subsysStateLine do IFS=':' set -f ; set -- $subsysStateLine ; set +f IFS="$IFS_sv" junk=$1 kword=$2 nodeName=$3 rvsdState=$4 if [[ $kword = ?( )mmgetSubsysState ]] then [[ $rvsdState != active ]] && \ failedNodes="$failedNodes\n\t$nodeName" elif [[ -n $subsysStateLine ]] then # Unexpected output - must be an error. # Collect the lines in a separate file for later. print -- "$subsysStateLine" >> $errMsg checkForErrors "writing to file $errMsg" $? else : # do nothing fi # end of if [[ $kword = mmgetSubsysState ]] done # end of while read -u3 subsysStateLine if [[ -n $failedNodes ]] then # RVSD is not yet ready on at least one node. printErrorMsg 474 $mmcmd RVSD "$failedNodes" rc=1 fi if [[ -s $errMsg ]] then # Show the unexpected errors. $cat $errMsg 1>&2 rc=1 fi $rm -f $errMsg # If things look OK so far, change the value of the wait4RVSD parameter. if [[ $rc -eq 0 ]] then $tsctl setCfgValue wait4RVSD yes rc=$(remapRC $?) if [[ $rc -ne 0 ]] then # The tsctl command failed. printErrorMsg 104 "$mmcmd" "tsctl setCfgValue wait4RVSD yes" fi fi return $rc } #------ end of function setWait4RVSD ------------------ ########################################################################### # # Function: Determines the range of GPFS release levels on the # nodes on which the daemon is currently running. # # Input: None # # Output: A string with the following format: # getCodeRange:rc:status:maxDaemonVers:minDaemonVers # # Returns: 0 - Success # 1 - Error detected # ########################################################################### function getCodeRange # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $getCodeRange ]] && set -x $mmTRACE_ENTER "$*" typeset mmVersion2output nodeName nodeNumber kword cmdVersion typeset installedDaemonVersion installedProductVersion installedOsName typeset maxDaemonVersion=0 typeset minDaemonVersion=100000 typeset rc=0 # Request the release level information for all of the nodes. $tsdsh $mmremote mmVersion2 >$tmpfile 2>&1 rc=$(remapRC $?) if [[ ! -s $tmpfile ]] then # If there is no output at all, something is very wrong. [[ $rc -eq 0 ]] && rc=1 print -- "getCodeRange:$rc:unexpected_failure:0:0:" printErrorMsg 171 $mmcmd "tsdsh mmremote mmVersion2" $rc return $rc else # If we have output, ignore the rc from tsdsh. rc=0 fi # Parse the output from mmremote mmVersion2. $rm -f $errMsg IFS=":" exec 3<&- exec 3< $tmpfile while read -u3 mmVersion2output do IFS=':' set -f ; set -- $mmVersion2output ; set +f nodeName=$1 kword=$2 cmdVersion=$3 nodeNumber=$4 installedDaemonVersion=$5 installedProductVersion=$6 installedOsName=$7 IFS="$IFS_sv" if [[ $kword != *( )mmVersion2 ]] then # Unexpected output; it must be an error. # Collect the lines in a separate file for later. print -- "$mmVersion2output" >> $errMsg checkForErrors "writing to file $errMsg" $? continue fi # Keep track of highest and lowest daemon versions found. [[ $installedDaemonVersion -gt $maxDaemonVersion ]] && \ maxDaemonVersion=$installedDaemonVersion [[ $installedDaemonVersion -lt $minDaemonVersion ]] && \ minDaemonVersion=$installedDaemonVersion IFS=":" # Change the separator back to ":" for the next iteration. done # end of while read -u3 mmVersion2output IFS="$IFS_sv" # Print out the results string and exit. if [[ $maxDaemonVersion -eq 0 ]] then # We did not get back any release level information. # The output must have been only error messages. [[ $rc -eq 0 ]] && rc=1 $cat $errMsg 1>&2 print -- "getCodeRange:$rc:unexpected_failure:0:0:" else # Everything looks good. rc=0 print -- "getCodeRange:$rc:complete:$maxDaemonVersion:$minDaemonVersion:" fi $rm -f $errMsg return $rc } #------ end of function getCodeRange ------------------ ##################################################################### # # Function: Ensure local system configuration files are up-to-date. # # Input: $1 -f rebuild all files # # Output: None # # Returns: Zero if successful, non-zero otherwise. # ##################################################################### function refreshSysconfig # [-f] { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGrefreshSysconfig ]] && set -x $mmTRACE_ENTER "$*" typeset option=$1 typeset gpfsInitOutput typeset rc=0 # If the -f option was specified, force mmfsNodeData # and the rest of the GPFS files to be rebuilt. if [[ $option = "-f" ]] then $rm -f $mmfscfgFile $mmfsNodeData $nsdpvol ${mmfsEnvLevel}+([0-9]) \ ${mmfsNewKeyLevel}+([0-9]) ${mmfsCommittedKeyLevel}+([0-9]) getLocalNodeData fi # Verify there is an mmfs entry in /etc/vfs. checkVfsNumber rc=$? [[ $rc -ne 0 ]] && \ return $rc # Make sure that the local copies of the mmsdrfs, mmfs.cfg, # and the rest of the system files are up-to-date. gpfsInitOutput=$(gpfsInit nolock) rc=$? [[ $rc -ne 0 ]] && printErrorMsg 171 "$mmcmd" "gpfsInit" $rc setGlobalVar $rc $gpfsInitOutput return $rc } #------ end of function refreshSysconfig ------------------- ################################################################### # # Function: Tell the daemon to reread the authorized_keys list. # # Input: None. # # Output: None. # # Returns: Zero if successful, non-zero otherwise. # ################################################################### function refreshAuth { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGrefreshAuth ]] && set -x $mmTRACE_ENTER "$*" typeset gpfsInitOutput="" # Retrieve the latest mmsdrfs file and rebuild the environment. gpfsInitOutput=$(gpfsInit nolock) setGlobalVar $rc $gpfsInitOutput # Tell the daemon to reread the authorized_keys list. $tsauth return 0 } #------ end of function refreshAuth ------------------- ################################################################### # # Function: Determine the generation number of a sdrfs file. # # Input: $1 - (optional) sdrfs file. If not specified, # /var/mmfs/gen/mmsdrfs is assumed. # # Output: : # # Returns: Zero if successful, non-zero otherwise. # ################################################################### function getGenNumber { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGgetGenNumber ]] && set -x $mmTRACE_ENTER "$*" typeset sdrfs=$1 typeset versionLine="" # If file not specified, use /var/mmfs/gen/mmsdrfs. [[ -z $sdrfs ]] && sdrfs=$mmsdrfsFile # Parse the version line of the mmsdrfs file. versionLine=$($head -1 $sdrfs) IFS=':' set -f ; set -A v -- - $versionLine ; set +f IFS="$IFS_sv" # Perform a quick sanity check. [[ ${v[$LINE_TYPE_Field]} != $VERSION_LINE ]] && \ corruptedSdrFileExit 137 "$versionLine" # Make sure the time stamp field has a value. [[ -z ${v[$GENNUM_TSTAMP_Field]} ]] && \ v[$GENNUM_TSTAMP_Field]=0 # Generate and display the result. print "${v[$SDRFS_GENNUM_Field]}:${v[$GENNUM_TSTAMP_Field]}:${v[$PRIMARY_SERVER_Field]}" return 0 } #------ end of function getGenNumber ------------------- ################################################################### # # Function: Move and rename the specified file. # Verify its checksum. # # Input: $1 - source file name # $2 - target file name # $3 - expected checksum # $4 - source host name # # Output: None # # Returns: Zero if successful, non-zero otherwise. # ################################################################### function mvSGDescFile # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGmvSGDescFile ]] && set -x $mmTRACE_ENTER "$*" typeset source=$1 typeset target=$2 typeset checksum=$3 typeset sourceNodeName=$4 typeset sumOutput newSum typeset rc=0 # Make sure the target directory exists. $mkdir -p ${target%/*} # Retrieve the file. if [[ $sourceNodeName = $ourNodeName ]] then $cp $source $target rc=$? else $rcp ${sourceNodeName}:$source $target rc=$? fi if [[ $rc -ne 0 ]] then print -- "mvSGDescFile:error:copyfile:" return 1 fi $mmsync $target # Verify the checksum. sumOutput=$($sum $target) checkForErrors "sum $target" $? set -f ; set -- $sumOutput ; set +f newSum=$1 if [[ $checksum -ne $newSum ]] then print -- "mvSGDescFile:error:checksum:" return 1 fi print -- "mvSGDescFile:success::" return 0 } #------ end of function mvSGDescFile ------------------- ################################################################### # # Function: Mount the specified file system(s). # # Input: $1 - file system device name or all, all_local, or all_remote # $2 - mount point or DEFAULT # $3 - default mount options # $4 - new mount options or DEFAULT # $5 - do not remount indicator (optional) # # Output: None # # Returns: 0 - mount command issued # non-zero - unexpected error # ################################################################### function mountFileSystems # { typeset sourceFile="mmremote.sh" [[ -n $DEBUG || -n $DEBUGmountFileSystems ]] && set -x $mmTRACE_ENTER "$*" typeset deviceName=$1 typeset mountPoint=$2 typeset defaultOptions=$3 typeset newOptions=$4 typeset doNotRemount=$5 typeset nodeIndex=0 typeset ourNodeIndex=0 typeset fsNumber=0 typeset n=0 typeset rc=0 typeset gpfsInitOutput fsType fsName tsstatusOutput mountedFileSystems typeset mountDeviceList mountDeviceList_A mountDeviceList_B vfsType typeset nodeOptions mountAllRequested # Ensure the GPFS system data is up to date. # Note: To avoid undesired side effects, tell gpfsInit to restrict mount # point checking only to the file system(s) that we care about. export MOUNT_POINT_CHECK="$deviceName" gpfsInitOutput=$(gpfsInit nolock) setGlobalVar $? $gpfsInitOutput unset MOUNT_POINT_CHECK # See if there are additional mount options to specify. if [[ $newOptions = DEFAULT ]] then newOptions="" else newOptions="-o $newOptions" fi if [[ $deviceName = all || $deviceName = all_local || $deviceName = all_remote ]] then mountPoint="" mountAllRequested=yes fi # Process the mount point parameter. Its value will also determine # whether it will be necessary to explicitly specify on the mount command # the vfs type and options string or if it is OK to let the mount # command figure out those things on its own. [[ $mountPoint = DEFAULT ]] && mountPoint="" if [[ -n $mountPoint ]] then defaultOptions="-o $defaultOptions" if [[ $osName = AIX ]] then vfsType="-v mmfs" elif [[ $osName = Linux ]] then vfsType="-t gpfs" else # Should never get here. printErrorMsg 171 "mountFileSystems" "unsupported OS $osName" 1 return 1 fi # end of if [[ $osName = AIX ]] else defaultOptions="" fi # end of if [[ -n $mountPoint ]] # Go through the local mmsdrfs file and create # a list of the file systems to be mounted. 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" # Change some of the fields depending on the type of line. case ${v[$LINE_TYPE_Field]} in $MEMBER_NODE ) # Determine the index of this node relative # to the rest of the nodes in the cluster. [[ ${v[$NODE_NUMBER_Field]} = $ourNodeNumber ]] && \ ourNodeIndex=$nodeIndex (( nodeIndex += 1 )) ;; $SG_HEADR ) # See if we want to mount this file system. if [[ ${v[$DEV_NAME_Field]} = $deviceName || $deviceName = all || $deviceName = all_local && ${v[$FS_TYPE_Field]} = $localfs || $deviceName = all_remote && ${v[$FS_TYPE_Field]} = $remotefs ]] then mountDeviceList="$mountDeviceList /dev/${v[$DEV_NAME_Field]}" (( fsNumber += 1 )) fi ;; * ) # Not interested in any other lines. ;; esac # end of Change some of the fields IFS=":" # Change the separator back to ":" for the next iteration. done # end while read -u3 mmsdrfsFile IFS="$IFS_sv" # Ensure the requested file systems were found. # This should always be the case at this point. if [[ $fsNumber -eq 0 ]] then if [[ $deviceName = all || $deviceName = all_local ]] then # No file systems found in the cluster. printErrorMsg 200 $mmcmd elif [[ $deviceName = all_remote ]] then # No remote file systems found in the cluster. printErrorMsg 193 $mmcmd else # The requested file system was not found. printErrorMsg 288 $mmcmd $deviceName fi # Give up; nothing more to do. return $MM_FsNotFound fi # end of if [[ $fsNumber -eq 0 ]] # If more than one file system will be mounted, order the list # based on the index of the local node within the cluster. # This is done to avoid the simultaneous mounting of the same # file system from all of the nodes in the cluster. if [[ $fsNumber -gt 1 ]] then # Calculate our node's index in the file system list. (( ourNodeIndex = ourNodeIndex % fsNumber )) # Break the list of file systems into two parts # based on the above calculated index. for fsName in $mountDeviceList do if [[ $n -ge $ourNodeIndex ]] then mountDeviceList_A="$mountDeviceList_A $fsName" else mountDeviceList_B="$mountDeviceList_B $fsName" fi (( n += 1 )) done # end of for fsName in $mountDeviceList # Combine the two parts of the mount list. mountDeviceList="$mountDeviceList_A $mountDeviceList_B" fi # end of if [[ $fsNumber -gt 1 ]] # Create a list of the currently mounted file systems on this node. if [[ $osName = AIX ]] then $mount >$tmpfile 2>/dev/null mountedFileSystems=$tmpfile elif [[ $osName = Linux ]] then mountedFileSystems=/proc/mounts else # Should never get here. printErrorMsg 171 "mountFileSystems" "unsupported OS $osName" 1 return 1 fi # end of if [[ $osName = AIX ]] # Ensure the local GPFS daemon is accepting commands. tsstatusOutput=$(LC_ALL=C $tsstatus -1 2>&1) print -- "$tsstatusOutput" | $grep -qe 'file system daemon is running' >/dev/null 2>&1 if [[ $? -ne 0 ]] then # GPFS daemon is not ready for commands yet. printErrorMsg 110 $mmcmd return $MM_DaemonDown fi # Mount the file systems. for fsName in $mountDeviceList do # See if this file system is already mounted. $grep -qw $fsName $mountedFileSystems > /dev/null 2>&1 if [[ $? -eq 0 ]] then # The file system appears to be already mounted. Verify that # everythig is OK by doing an internal remount if the stat on # mount point returns with a non-zero errno. activeMountPoint=$(findMountpoint $fsName) $perl -e ' $! = 0; stat "'$activeMountPoint'"; exit $!;' rc=$? if [[ $rc -ne 0 && -z $doNotRemount ]] then $tsremount ${fsName#/dev/} rc=$? if [[ $rc -ne 0 ]] then # The remount attempt failed. printErrorMsg 399 $mmcmd $fsName $rc [[ -n $mountAllRequested ]] && rc=0 fi fi # end of if [[ $rc -ne 0 && -z $doNotRemount ]] # If a specific mount point has been requested, see if it matches # the currently active mount point for the file system. if [[ -n $mountPoint ]] then [[ $mountPoint != $activeMountPoint ]] && \ printErrorMsg 280 $mmcmd $fsName $activeMountPoint fi # There is nothing more to do for this file system. continue fi # end of if [[ $? -eq 0 ]] # See if there are local override mount options for this file system. if [[ -s ${localMountOptions}.${fsName#/dev/} ]] then nodeOptions="-o $($tail -n -1 ${localMountOptions}.${fsName#/dev/} 2>/dev/null)" else nodeOptions="" fi # Mount the file system. If the overall request is to mount a single # file system, show all messages from the mount command. If the request # is to mount all GPFS file systems, hide the "already mounted" messages. if [[ -n $mountAllRequested ]] then $mount $vfsType $defaultOptions $nodeOptions $newOptions $fsName $mountPoint 2>&1 | \ $grep -i -v "already mounted" rc=0 # ignore errors else $mount $vfsType $defaultOptions $nodeOptions $newOptions $fsName $mountPoint rc=$? fi done # end of for fsName in $mountDeviceList return $rc } #------ end of function mountFileSystems ------------------- ########################################################### # # Mainline processing # ########################################################### kword=$arg1 kword_lc=$arg1 arg3_lc=$arg3 if [[ -z $kword ]] then # Missing keyword printErrorMsg 133 mmremote NULL cleanupAndExit fi # Set up silent trap exception handling. trap pretrap3 HUP INT QUIT KILL # Parse the caller's version information. If missing, # assume the request comes from a 3.1 compatible node. [[ -z $mmrpc ]] && mmrpc="mmrpc:1:1:901:" IFS=':' set -f ; set -- $mmrpc ; set +f rpcVersion=$2 rpcMinVersion=$3 daemonVersion=$4 IFS="$IFS_sv" # Determine the execution environment and set needed global variables. if [[ $kword_lc = checknewclusternode ]] then # The request is for a function that runs prior to the node becoming # a member of the GPFS cluster. Use the function arguments to set # some global variables. if [[ -z $MMMODE ]] then IFS='/' set -f ; set -- $arg2 ; set +f export MMMODE=$1 IFS="$IFS_sv" fi [[ -z $primaryServer ]] && \ primaryServer=$arg3 elif [[ $arg3_lc = checknewclusternode* || $arg3_lc = removefromclustercr ]] then # If the node is not yet a member of the GPFS cluster, # the functions to determine the local data do not work. [[ -z $ourNodeName ]] && ourNodeName=$($hostname) [[ -z $MMMODE ]] && export MMMODE=$arg4 else # In all other cases, file mmsdrfs should already exist # and we can use it as a starting point. [[ -z $MMMODE || -z $environmentType || -z $primaryServer ]] && \ determineMode getLocalNodeData fi # Restore the original positional parameters. set -f ; set -- $cmdline ; set +f # Initialize the local version information string. rpcMinSupported=1 rpcMaxSupported=1 localVersionInfo="$MM_Version3:$ourNodeNumber:$currentDaemonVersion:$productVersion" localVersionInfo="${localVersionInfo}:$osName:$rpcMinSupported:$rpcMaxSupported" # Ensure we know how to interpret the request. if [[ $rpcMinVersion -gt $rpcMaxSupported ]] then # The caller is running incompatible GPFS version. # Tell him what our capabilities are and let him decide what to do. print -u2 "mmremote:incompatibleGPFScode:$ourNodeName:$localVersionInfo:" cleanupAndExit $MM_IncompatibleCode fi # Make sure we have the proper credentials. [[ $getCredCalled = no ]] && getCred # Reset the remote commands if necessary. [[ -n $GPFS_rshPath ]] && rsh=$GPFS_rshPath [[ -n $GPFS_rcpPath ]] && rcp=$GPFS_rcpPath # Depending on the keyword, perform the requested action. case $kword_lc in #---------------------------------------- mmversion ) # mmremote mmVersion [] #---------------------------------------- # Determine whether the daemon is running. tsstatusOutput=$(LC_ALL=C $tsstatus -1 2>&1) print -- "$tsstatusOutput" | $grep -e 'file system daemon is running' >/dev/null if [[ $? -eq 0 ]] then daemonStatus=active else print -- "$tsstatusOutput" | $grep -e 'Waiting for quorum' >/dev/null if [[ $? -eq 0 ]] then daemonStatus=waitingForQuorum else daemonStatus=down fi fi # Get the level of the installed fileset. # If not specified by the caller, look for mmfs.gpfs.rte. if [[ -n $arg2 ]] then fileset=$arg2 else fileset="mmfs.gpfs.rte" fi # The output of the lslpp -c -Lq command has the following format: # #Package Name:Fileset:Level:State:PTF Id:Fix State:Type:Description: lslppOutput=$(LC_ALL=C $lslpp -c -Lq $fileset 2>/dev/null) IFS=':' set -f ; set -- $lslppOutput ; set +f package=$1 fileset=$2 level=$3 IFS="$IFS_sv" [[ $package != mmfs* ]] && level="" # Return the string 'mmVersion', the version of the commands (2), the level # of the currently-installed fileset, and the status of the daemon. print -- "mmVersion:$MM_Version3:$level:$daemonStatus" rc=0 ;; #--------------------- mmversion2 ) # mmremote mmVersion2 #--------------------- # Return the keyword 'mmVersion2', the version of the commands (2), # the level of the currently-installed fileset (must match prod.h), # the OS name, and the fileset or rpm release string identifier for # the current level of the code. print -- "mmVersion2:$localVersionInfo" rc=0 ;; #-------------------------------------------------- unlock ) # mmremote unlock [] [] #-------------------------------------------------- # Find our node number. if [[ -z $arg2 ]] then nodeNumber=$ourNodeNumber else nodeNumber=$arg2 fi # Find the lock server. if [[ -z $arg3 ]] then lockServer=$primaryServer else lockServer=$arg3 fi # Release the lock. freeLock $nodeNumber $lockServer rc=0 ;; #------------------------------------------------------ copyremotefile ) # mmremote copyRemoteFile # #------------------------------------------------------ if [[ $argc -lt 5 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi copyRemoteFileOutput=$(copyRemoteFile "$arg2" "$arg3" "$arg4" "$arg5") rc=$? print -- "$copyRemoteFileOutput" ;; #------------------------------------------------- committoprimaryserver ) # mmremote commitToPrimaryServer # # #------------------------------------------------- if [[ $argc -lt 7 ]] then operands=" " operands=$operands" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Check required system files. commitToPrimaryServer "$arg2" "$arg3" "$arg4" "$arg5" "$arg6" "$arg7" "$arg8" rc=$? ;; #---------------------------------------- # mmremote vfs vfs | checkvfsnumber ) # mmremote checkVfsNumber #---------------------------------------- # Verify there is an mmfs entry in /etc/vfs. checkVfsNumber rc=$? ;; #---------------------------------------- fs ) # mmremote fs [optionalTasks] #---------------------------------------- # Verify there is an mmfs entry in /etc/vfs. checkVfsNumber rc=$? [[ $rc -ne 0 ]] && cleanupAndExit $rc # Make sure that the local copies of the mmsdrfs, mmfs.cfg, # and the rest of the system files are up-to-date. gpfsInitOutput=$(gpfsInit nolock) checkForErrors gpfsInit $? # Perform additional tasks as per the propagate options parameter. [[ -n $arg2 ]] && handlePropagateOptions $arg2 rc=0 ;; #---------------------------------------- cfg ) # mmremote cfg [-f] #---------------------------------------- # Ensure local config data is up-to-date. refreshSysconfig $arg2 rc=$? ;; #---------------------------------------------------- upgradesystemfiles ) # mmremote upgradeSystemFiles # [] #---------------------------------------------------- if [[ $argc -lt 3 ]] then operands=" []" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi upgradeSystemFiles $arg2 $arg3 NULL 0 rc=$? # Perform additional tasks as per the propagate options parameter. [[ -n $arg4 ]] && handlePropagateOptions $arg4 ;; #---------------------------------------------------- upgradesystemfiles2 ) # mmremote upgradeSystemFiles2 # #---------------------------------------------------- if [[ $argc -lt 5 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi upgradeSystemFiles $arg2 $arg3 $arg4 $arg5 rc=$? ;; #--------------------------------------------- updategpfsobject ) # mmremote updateGpfsObject [] #--------------------------------------------- if [[ $argc -lt 2 ]] then operands=" [] - Specify at least one change" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi updateGpfsObject "$arg2" "$arg3" rc=$? ;; #---------------------------------------- getgpfsobjectfromfile ) # mmremote getGpfsObjectFromFile #---------------------------------------- # Retrieve the information. gpfsObjectInfo=$(getGpfsObjectFromFile) rc=$? print -- "$gpfsObjectInfo" ;; #------------------------------------------------ sendclustersdrfiles ) # mmremote sendClusterSDRFiles # #------------------------------------------------ if [[ $argc -lt 5 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi sendClusterSDRFiles "$arg2" "$arg3" "$arg4" "$arg5" rc=$? ;; #------------------------------------------------------------- createshadow ) # mmremote createShadow #------------------------------------------------------------- if [[ $argc -lt 4 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi createShadow "$arg2" "$arg3" "$arg4" rc=$? ;; #-------------------------------------------------- removeuncommitted ) # mmremote removeUncommitted #-------------------------------------------------- if [[ $argc -lt 2 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi $rm -f $uncommitted.$arg3 ${mmsdrfsPrev}.$arg2 rc=$? ;; #---------------------------- removefromcluster | removefromclustercr ) # mmremote removeFromCluster #---------------------------- # Remove (almost) all traces. removeFromCluster rc=0 ;; #------------------------------------------- rmfs ) # mmremote rmfs #------------------------------------------- if [[ $argc -lt 2 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Remove the file system stanza from /etc/filesystems. # Remove the device and mount point. Ignore errors. removeStanza $arg2 >/dev/null 2>&1 removeMountPoint $arg2 $arg3 0 >/dev/null 2>&1 rc=0 ;; #---------------------------------------- pid ) # mmremote pid #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # See if the specified process still exists. $ps "$arg2" >/dev/null 2>/dev/null rc=$? if [[ $rc -eq 0 ]] then print -- "alive" else print -- "died" fi rc=0 ;; #---------------------------------------- active ) # mmremote active #---------------------------------------- $ps -e | $grep mmfsd >/dev/null 2>&1 rc=$? if [[ $rc -eq 0 ]] then print -- "active" else print -- "down" fi rc=0 ;; #---------------------------------------- quorum ) # mmremote quorum #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Set the node quorum to the specified value. $mmfsadm quorum $arg2 rc=$? ;; #----------------------------------------- tschpool ) # mmremote tschpool #----------------------------------------- if [[ $argc -lt 3 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Collect the input parameters and invoke the command. shift 1 commandArguments=$* $tschpool $commandArguments rc=$(remapRC $?) ;; #---------------------------------------- tsctl ) # mmremote tsctl #---------------------------------------- if [[ $argc -lt 3 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Collect the input parameters and invoke the command. shift 1 commandArguments=$* $tsctl $commandArguments rc=$(remapRC $?) ;; #---------------------------------------- tsnap ) # mmremote tsnap #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Take a trace snapshot. traceSnapshot $arg2 rc=$? ;; #------------------------------------------------------ checknewclusternode ) # mmremote checkNewClusterNode # # # #------------------------------------------------------ if [[ $argc -lt 8 ]] then operands=" " operands=${operands}" " operands=${operands}" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine whether the node is new and supports clusters. checkNewClusterNode "$arg2" "$arg3" "$arg4" "$arg5" "$arg6" "$arg7" "$arg8" rc=$? ;; #----------------------------- checkadapter ) # mmremote checkAdapter #----------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Verify the adapter exists. checkAdapter $arg2 rc=0 ;; #----------------------------------------------- admincmd ) # mmremote adminCmd [] #----------------------------------------------- if [[ $argc -lt 2 ]] then operands=" []" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Get the command name and collect its arguments. adminCommand=$2 shift 2 argList=$@ # Run the requested command. runCommand $adminCommand "$argList" rc=$? ;; #--------------------------------------- exectsmcommand ) # mmremote execTSMcommand [] #--------------------------------------- if [[ $argc -lt 10 ]] then operands=" []" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Shift the command's arguments to remove the execTSMcommand verb. shift 1 argList=$@ # Run the requested command. $mmexectsmcmd $argList rc=$? ;; #---------------------------------------------------- startsubsys ) # mmremote startSubsys [-e ] [-E ] # [-f] [-t ] [-T ] #---------------------------------------------------- # Parse the optional parameters. shift 1 while getopts :e:E:fT:t: OPT do case $OPT in e) expirationData="$OPTARG" ;; E) envString=${envString}" $OPTARG " ;; f) argString='-a "-f"' ;; t) envString=${envString}" mmScriptTrace=$OPTARG " ;; T) envString=${envString}" MMTRACE=$OPTARG " ;; *) printErrorMsg 13 "$mmcmd" $OPTARG ;; esac done # Process the expirationData parameter. if [[ -n $expirationData && ! -s mmSdrLockExp ]] then # Create a file with the sdr expiration data. print -- "$expirationData" > $mmSdrLockExp # Start the background process that will remove the file. $mmcommon expirationDataCleanup $expirationData doNotUnlock >/dev/null 2>&1 & fi # Check whether GPFS is running. pid=$($ps -eo "pid args" | \ $awk '/\/runmmfs/ && !/this process/ {print $1}') if [[ -n $pid ]] then # GPFS has already been started. printInfoMsg 586 GPFS else # Start GPFS. if [[ -n ${envString} ]] then $daemonize -e "$envString" -c $runmmfs $argString else $daemonize -c $runmmfs $argString fi fi # end if [[ -n $pid ]] ;; #------------------------------------------ startautomounter ) # mmremote startAutomounter #------------------------------------------ if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Run the OS automount command. startAutomounter $arg2 rc=$? ;; #----------------------------------------------- getlocaldiskname ) # mmremote getLocalDiskName #----------------------------------------------- if [[ $argc -lt 3 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the physical disk with the specified pvid and nsdSubtype. getLocalDiskName $arg2 $arg3 rc=0 ;; #-------------------------------------- getlocaldisknamevg ) # mmremote getLocalDiskNameVG #-------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the physical disk with the specified volume group name. getLocalDiskNameVG $arg2 rc=0 ;; #---------------------------------------- findpvid ) # mmremote findPvid #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the pvid of the disk with the specified lvname. findPvid $arg2 rc=$? ;; #---------------------------------------- findvgpvid ) # mmremote findVgPvid #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the pvid of the disk with the specified vgname. findVgPvid $arg2 rc=$? ;; #---------------------------------------- findhdiskpvid ) # mmremote findHdiskPvid #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the pvid of the specified physical disk. findHdiskPvid $arg2 rc=$? ;; #---------------------------------------- mmgetstate ) # mmremote mmGetState #---------------------------------------- # Determine the quorum state. mmGetState $arg2 rc=$? ;; #---------------------------------------- getsubsysstate ) # mmremote getSubsysState #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the state of the specified subsystem. getSubsysState $arg2 rc=$? ;; #---------------------------------------- killsdrserv ) # mmremote killSdrServ #---------------------------------------- # Kill the currently-running mmsdrserv daemon. killSdrServ rc=$? ;; #---------------------------------------- startsdrserv ) # mmremote startSdrServ #---------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # If this is a server node, start the mmsdrserv daemon. if [[ $ourNodeName = $primaryServer || $ourNodeName = $backupServer ]] then startSdrServ $arg2 rc=$? else rc=132 # ESDR_NOT_SERVER "Node is not a server" fi ;; #---------------------------------------- setwait4rvsd ) # mmremote setWait4RVSD #---------------------------------------- # Set the wait4RVSD parm across the currently-active GPFS nodes. setWait4RVSD rc=$? ;; #---------------------------------------- refreshauth ) # mmremote refreshAuth #---------------------------------------- # Refresh the auth key files. refreshAuth rc=$? ;; #---------------------------------------- getcoderange ) # mmremote getCodeRange #---------------------------------------- # Determines the range of GPFS release levels on the # nodes on which the daemon is currently running. getCodeRange rc=$? ;; #---------------------------------------- postmount ) # mmremote postMount #---------------------------------------- # Perform post-mount processing. Currently, this is a no-op. rc=0 ;; #---------------------------------------- getgennumber ) # mmremote getGenNumber [] #---------------------------------------- # Retrieve the generation number of the specified sdrfs file. getGenNumber $arg2 rc=$? ;; #---------------------------------------- rmdeventry ) # mmremote rmDevEntry #---------------------------------------- # Get the list of devices to delete. shift 1 deviceNameList=$@ # Loop through the list and delete the /dev entries. for devName in $deviceNameList do removeMountPoint $devName _NO_MOUNT_POINT_DELETE_ 0 done ;; #------------------------------------------------------ determinedisksubtype ) # mmremote determineDiskSubtype [] #------------------------------------------------------ if [[ $argc -lt 2 ]] then operands=" []" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the disk type. determineDiskSubtype $arg2 $arg3 rc=$? ;; #----------------------------------------- determinensdsubtype ) # mmremote determineNsdSubtype #----------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the disk type. determineNsdSubtype $arg2 rc=$? ;; #------------------------------------ getlocalnsddata ) # mmremote getLocalNsdData [] #------------------------------------ # Send the colon-delimited local nsd data from tspreparedisk -s # back to the requestor via stdout. getLocalNsdData $arg2 rc=0 ;; #--------------------------------------- creatensd ) # mmremote createNsd # #--------------------------------------- if [[ $argc -lt 5 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Make an NSD out of the disk. createNsd $arg2 $arg3 $arg4 $arg5 rc=$? ;; #---------------------------------------------------- mvsgdescfile ) # mmremote mvSGDescFile # #---------------------------------------------------- if [[ $argc -lt 5 ]] then operands=" " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Move the specified file and verify its checksum. mvSGDescFile $arg2 $arg3 $arg4 $arg5 rc=$? ;; #---------------------------------------------------- lssgdescfile ) # mmremote lsSGDescFile #---------------------------------------------------- # Return a list of all disk descriptor recovery files. [[ -d ${tmpDir}mmimportfs ]] && \ $ls -1 ${tmpDir}mmimportfs/tspreparedisk.diskDesc.* 2>/dev/null rc=0 ;; #---------------------------------------------------- rmsgdescfile ) # mmremote rmSGDescFile #---------------------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Remove all disk descriptor recovery files for the specified disk. $rm -f ${tmpDir}mmimportfs/tspreparedisk.diskDesc.${arg2}.* rc=0 ;; #------------------------------------------- getgpfsdiskname ) # mmremote getGpfsDiskName #------------------------------------------- if [[ $argc -lt 2 ]] then operands="" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Determine the GPFS disk name of the specified physical disk. gpfsDiskName=$(getGpfsDiskName $arg2) rc=$? print -- "$gpfsDiskName" ;; #------------------------------------------- unfencedisks ) # mmremote unfenceDisks #------------------------------------------- if [[ $argc -lt 2 ]] then operands=" | " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Unfence the specified disks and clear the PR registrations. unfenceDisksOutput=$(unfenceDisks $arg2) rc=$? print -- "$unfenceDisksOutput" # If this is invoked by mmimportfs, cleanup the input file. # Otherwise, leave the file alone. The decision is based on # the input file's name. [[ $arg2 = ${tmpDir}disksToUnfence.mmimportfs.*tmp ]] && \ $rm -f $arg2 ;; #-------------------------------------------------- mountfilesystems ) # mmremote mountFileSystems # [doNotRemount] #-------------------------------------------------- if [[ $argc -lt 5 ]] then operands=" {|DEFAULT} " operands="${operands} {|DEFAULT} [doNotRemount]" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Mount the specified file systems. mountFileSystems $arg2 "$arg3" "$arg4" "$arg5" $arg6 rc=$? ;; #--------------------------------------------- unmountfilesystems ) # mmremote unmountFileSystems [-f] #--------------------------------------------- if [[ $argc -lt 2 ]] then operands=" [-f]" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Invoke the preunmount user exit. [[ -x ${mmfscfgDir}preunmount ]] && \ $mmcommon preunmount $arg2 umount # Unmount the specified file systems. unmountFileSystems $arg2 "$arg3" rc=$? ;; #---------------------------------------------- unmountmountpoint ) # mmremote unmountMountpoint [-f] #---------------------------------------------- if [[ $argc -lt 2 ]] then operands=" [-f]" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Unmount the specified file systems. unmountMountpoint $arg2 "$arg3" rc=$? ;; #------------------------------------------------------------- lsmount ) # mmremote lsmount [norefresh] #------------------------------------------------------------- if [[ $argc -lt 4 ]] then operands=" [norefresh]" printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Find out who has the file systems mounted. lsmount "$arg2" "$arg3" $arg4 $arg5 rc=$? ;; #--------------------------------- shutdowndaemon ) # mmremote shutdownDaemon #--------------------------------- # Remove the rerunmmfsFile file. # If not done, runmmfs will restart mmfsd. $rm -f $rerunmmfsFile # Shut down the GPFS daemon. $mmfsadm shutdown 2>&1 | $grep -v -e "mmfs daemon not running" $sleep 3 # Kill the runmmfs and mmfsenv processes if they are still running. # This would be the case if we were in a backoff respawn # or the daemon was never started in the first place. pidNumbers=$($ps -eo "pid args" | \ $awk '( /\/runmmfs/ || /\/mmfsenv/ ) && !/this process/ {print $1}') [[ -n $pidNumbers ]] && $kill -s KILL $pidNumbers $rm -f "${respawnlog}".* # If this is a server node, start the mmsdrserv daemon. [[ $ourNodeName = $primaryServer || $ourNodeName = $backupServer ]] && \ startSdrServ CURRENT >> $mmsdrservLog 2>&1 # Unload the kernel extensions (in Linux only). [[ $osName = Linux ]] && $mmfsenv -u # Always return OK. rc=0 ;; #--------------------------------- cleanupdaemon ) # mmremote cleanupDaemon #--------------------------------- # If this file is present, GPFS will be respawned. $rm -f $rerunmmfsFile >/dev/null 2>&1 # Shut down the daemon. $mmfsadm cleanup 2>&1 | $grep -v -e "mmfs daemon not running" $sleep 3 # If this is a server node, start the mmsdrserv daemon. [[ $ourNodeName = $primaryServer || $ourNodeName = $backupServer ]] && \ startSdrServ CURRENT >> $mmsdrservLog 2>&1 # Unload the kernel extensions. [[ $osName = Linux ]] && $mmfsenv -u # Always return OK. rc=0 ;; #------------------------------------------------------------------ onbehalf) # mmremote onbehalf # [] #------------------------------------------------------------------ if [[ $argc -lt 9 ]] then operands=" " operands="$operands [] " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Shift past all positional parameters and collect the command arguments. shift 9 arguments="$@" # Setup the environment. export MMMODE=$arg4 # If there is a file to copy, get it. fileCopied=no if [[ $arg5 != $NO_FILE_COPY ]] then rcpResult=$(LC_ALL=C $rcp ${arg2}:${arg5} $arg5 2>&1) rc=$? if [[ $rc -eq 0 ]] then fileCopied=yes else # If there was no need to copy the file, that's fine. print -- "$rcpResult" | $grep -e "refer to the same file" >/dev/null if [[ $? -ne 0 ]] then # Show the error from the rcp command and issue a message # that the rcp command failed. print -u2 "$rcpResult" printErrorMsg 171 $mmcmd "$rcp ${arg2}:${arg5} $arg5" $rc else fileCopied=yes rc=0 fi fi # end of if [[ $rc -eq 0 ]] fi # end of if [[ $arg5 != $NO_FILE_COPY ]] # If the copy worked, execute the command and return the return code. # The return code is reported by creating a temporary file in a scratch # directory on the caller's machine. This temporary "return code" file # has the return code as the trailing part of its name. It is the # caller's responsibility to look for this file to get the return code. # This mechanism is used because rsh does not return return codes. if [[ $rc -eq 0 ]] then runLocalCommand $arg6 $arg7 $arg8 $arg9 $arguments rc=$? rshResult=$($rsh $arg2 $mmremote adminCmd touch ${tmpDir}${arg3}.${rc} 2>&1) ec=$? if [[ $ec -ne 0 ]] then # Show the error from the rsh command and issue a message # that the rsh command failed. print -u2 $rshResult printErrorMsg 171 $mmcmd \ "$rsh ${arg2} mmremote adminCmd touch ${tmpDir}${arg3}.${rc}" $ec fi # Remove the input file if it was not created on this node. [[ $fileCopied = yes && $arg2 != $ourNodeName ]] && $rm -f $arg5 fi # end of if [[ $rc -eq 0 ]] ;; #----------------------------------------------------------- onbehalf2) # mmremote onbehalf2 # [] #----------------------------------------------------------- if [[ $argc -lt 6 ]] then operands=" " operands="$operands [] " printErrorMsg 260 mmremote $kword "$operands" cleanupAndExit fi # Shift past all positional parameters and collect the command arguments. shift 6 arguments="$@" # Setup the environment. export MMMODE=$arg4 # Execute the command and return the return code. # The return code is reported by creating a temporary file in a scratch # directory on the caller's machine. This temporary "return code" file # has the return code as the trailing part of its name. It is the # caller's responsibility to look for this file to get the return code. # This mechanism is used because rsh does not return return codes. runLocalCommand2 $arg5 $arg6 $arguments rc=$? rshResult=$($rsh $arg2 $mmremote adminCmd touch ${tmpDir}${arg3}.${rc} 2>&1) ec=$? if [[ $ec -ne 0 ]] then # Show the error from the rsh command and issue a message # that the rsh command failed. print -u2 -- $rshResult printErrorMsg 171 $mmcmd \ "$rsh ${arg2} mmremote adminCmd touch ${tmpDir}${arg3}.${rc}" $ec fi ;; #---------------------------------------- * ) # Unknown action requested #---------------------------------------- # Invalid keyword. The caller is running incompatible GPFS version. # Tell him what our capabilities are and let him decide what to do. printErrorMsg 133 mmremote $kword print -u2 "mmremote:incompatibleGPFScode:$ourNodeName:$localVersionInfo:" cleanupAndExit $MM_IncompatibleCode ;; esac # end first case $kword_lc in cleanupAndExit $rc doNotUnlock