#!/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 
# @(#)97 1.23 src/avs/fs/mmfs/ts/admin/mmsetrcmd.sh, mmfs, avs_rgpfs24, rgpfs240610b 12/5/05 15:41:55
##############################################################################
#
#  Usage:
#    mmsetrcmd {[-r RemoteShellCommand] [-R RemoteFileCopyCommand]} [-f]
#  or
#    mmsetrcmd -C ClusterName
#
#  where:
#
#    -r remoteShellCommand     specifies the fully qualified pathname for
#                              the remote shell program to be used by GPFS.
#                              The default is /usr/bin/rsh.
#
#    -R remoteFileCopyCommand  specifies the fully qualified pathname for
#                              the remote file copy program to be used
#                              by GPFS.  The default is /usr/bin/rcp.
#
#    -f                  Force option.  Make the change only on the node on
#                        which the command is executed.  Do not fail if the
#                        local copy of /var/mmsdrfs cannot be refreshed.
#                        This option is intended to be used on nodes that
#                        were not available when the mmchcluster command
#                        was executed.  The option is not documented.
#
#    -C ClusterName      specifies a new name for the cluster.  If the name
#                        contains dots it is assumed to be a fully qualified
#                        domain name.  Otherwise, the domain will default
#                        to the domain of the primary configuration server.
#
##############################################################################

# Include global declarations and service routines
. /usr/lpp/mmfs/bin/mmglobfuncs
. /usr/lpp/mmfs/bin/mmsdrfsdef

sourceFile="mmsetrcmd.sh"
[[ -n $DEBUG || -n $DEBUGmmsetrcmd ]] && set -x
$mmTRACE_ENTER "$*"


# Local work files.  Names should be of the form:
#   fn=${tmpDir}fn.${mmcmd}.$$

LOCAL_FILES=" "


# Local declarations

usageMsg=425
fflag=""
rflag=""
Rflag=""
rarg=""
Rarg=""
rc=0


# Local routines

#####################################################################
#
# This function simulates the real gpfsInit and extracts the global
# variable information from the local mmsdrfs file.  It is intended
# for use when the real gpfsInit fails for some reason.
#
# Note: Locking makes no sense in this context.
#
#####################################################################
function gpfsInit_Local
{
  typeset sourceFile="mmsetrcmd.sh"
  [[ -n $DEBUG || -n $DEBUGgpfsInit_Local ]] && set -x
  $mmTRACE_ENTER "$*"

  typeset localGenNumber localGenTimestamp versionLine mmmode
  typeset primaryServer backupServer gpfsObjectInfo
  typeset sdrfsFormatLevel rshPath rcpPath environmentType


  versionLine=$($head -1 $mmsdrfsFile)
  IFS=':'
  set -f ; set -A v -- - $versionLine ; set +f
  IFS="$IFS_sv"

  # Perform a quick sanity check.
  [[ ${v[$LINE_TYPE_Field]} != $VERSION_LINE ]] && \
    corruptedSdrFileExit 144 "$versionLine"

  # Retrieve cluster environment information.
  mmmode=${v[$CLUSTER_TYPE_Field]}
  if [[ $mmmode != lc && $mmmode != single ]]
  then
    # Unknown GPFS execution environment
    printErrorMsg 338 $mmcmd $mmmode
    cleanupAndExit
  fi

  sdrfsFormatLevel=${v[$SDRFS_FORMAT_Field]}
  localGenNumber=${v[$SDRFS_GENNUM_Field]}
  gpfsObjectInfo="${sdrfsFormatLevel}:${localGenNumber}:"
  primaryServer=${v[$PRIMARY_SERVER_Field]}
  [[ -z $primaryServer ]] && primaryServer="_NOPRIMARY_"
  backupServer=${v[$BACKUP_SERVER_Field]}
  [[ -z $backupServer ]] && backupServer="_NOSECONDARY_"
  localGenTimestamp=${v[$GENNUM_TSTAMP_Field]}
  [[ -z $localGenTimestamp ]] && localGenTimestamp=0
  rshPath=${v[$RSH_PATH_Field]}
  [[ -z $rshPath ]] && rshPath="_DEFAULT_"
  rcpPath=${v[$RCP_PATH_Field]}
  [[ -z $rcpPath ]] && rcpPath="_DEFAULT_"
  environmentType=${v[$CLUSTER_SUBTYPE_Field]}
  [[ -z $environmentType ]] && environmentType=$mmmode
  [[ $mmmode != $environmentType && $environmentType != lc2 ]] && \
    environmentType="rpd"

  # Make the mode value globally available
  export MMMODE=$mmmode
  export environmentType=$environmentType

  # Export remote commands if necessary.
  if [[ -n $rshPath && $rshPath != "_DEFAULT_" ]]
  then
    rsh="$rshPath"
    export GPFS_rshPath="$rshPath"
  fi
  if [[ -n $rcpPath && $rcpPath != "_DEFAULT_" ]]
  then
    rcp="$rcpPath"
    export GPFS_rcpPath="$rcpPath"
  fi

  # Locking does not work if we need this function.
  sdrLocked=no

  # Determine the local node data.  If file mmfsNodeData is
  # missing, there is a need for manual intervention.
  [[ ! -f $mmfsNodeData ]] && \
    checkForErrors "gpfsInit_Local: Missing file $mmfsNodeData" 1
  getLocalNodeData

  print -- "$MMMODE $sdrLocked $HOME_CLUSTER $ourNodeNumber" \
           "$gpfsObjectInfo $primaryServer $backupServer"    \
           "$ourNodeName $rshPath $rcpPath $localGenNumber"  \
           "$localGenTimestamp $environmentType"             \
           "$ourShortName $sdrfsFormatLevel"
  return 0

}  #------------ end of function gpfsInit_Local ------------------------



########################
# Mainline processing
########################


#################################
# Process the command arguments.
#################################
[[ $arg1 = '-?' || $arg1 = '-h' || $arg1 = '--help' || $arg1 = '--' ]] && \
  syntaxError "help" $usageMsg

[[ $argc -lt 2  ]] && \
  syntaxError "missingArgs" $usageMsg

while getopts :C:fr:R: OPT
do
  case $OPT in

    C) # cluster name
       [[ -n $Cflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       Cflag="-$OPT"
       Carg=$OPTARG
       ;;

    f) # force flag
       [[ -n $fflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       fflag="-$OPT"
       ;;

    r) # remote shell command
       [[ -n $rflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       rflag="-$OPT"
       rarg=$OPTARG
       [[ $rarg = ${rarg#/} ]] && \
         syntaxError "absolutePath_2" $noUsageMsg "-$OPT" "$rarg"
       [[ ! -x $rarg ]] && \
         syntaxError "cannotOpenFile" $noUsageMsg "$OPTARG"
       newRshPath=$rarg
       ;;

    R) # remote file copy command
       [[ -n $Rflag ]] && syntaxError "multiple" $noUsageMsg "-$OPT"
       Rflag="-$OPT"
       Rarg=$OPTARG
       [[ $Rarg = ${Rarg#/} ]] && \
         syntaxError "absolutePath_2" $noUsageMsg "-$OPT" "$Rarg"
       [[ ! -x $Rarg ]] && \
         syntaxError "cannotOpenFile" $noUsageMsg "$OPTARG"
       newRcpPath=$Rarg
       ;;

    +[CfrR]) # Invalid option
       syntaxError "invalidOption" $usageMsg $OPT
       ;;

    :) # Missing argument
       syntaxError "missingValue" $usageMsg $OPTARG
       ;;

    *) # Invalid option
       syntaxError "invalidOption" $usageMsg $OPTARG
       ;;

  esac

done

# Complete the parameter checking.
shift OPTIND-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.
# If this process fails, and the -f flag is specified, ignore the
# error and proceed anyway.
#######################################################################
trap pretrap HUP INT QUIT KILL
gpfsInitOutput=$(gpfsInit $lockId)
rc=$?
if [[ -z $fflag ]]
then
  setGlobalVar $rc $gpfsInitOutput
elif [[ $rc -eq 0 ]]
then
  setGlobalVar $rc $gpfsInitOutput
else
  if [[ -f $mmsdrfsFile ]]
  then
    # gpfsInit failed but -f is specified.
    # Parse the local mmsdrfs file to set up the global variables.
    gpfsInitOutput=$(gpfsInit_Local nolock)
    setGlobalVar $? $gpfsInitOutput
  else
    checkForErrors "Missing local file $mmsdrfsFile" $?
  fi
fi
nodesetId=$nsId


############################################################################
# Make a new copy of the current mmsdrfs file with the appropriate changes.
############################################################################
$rm -f $newsdrfs $nodefile $tmpCfg
IFS=":"         # Change the field separator to ':'.
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 )
      # Increment the generation number if this is going
      # to be a global change (-f flag is not specified).
      if [[ -z $fflag ]]
      then
        newGenNumber=${v[$SDRFS_GENNUM_Field]}+1
        v[$SDRFS_GENNUM_Field]=$newGenNumber
      fi

      # Change the remote commands as needed.
      [[ -n $newRshPath ]] &&  \
        v[$RSH_PATH_Field]=$newRshPath
      [[ -n $newRcpPath ]] &&  \
        v[$RCP_PATH_Field]=$newRcpPath

      # Change the cluster name if asked.
      if [[ -n $Cflag ]]
      then
        if [[ $Carg = "." ]]
        then
          clusterName=$primaryServer
        elif [[ $Carg = *.* ]]
        then
          clusterName=$Carg
        else
          primaryServer=${v[$PRIMARY_SERVER_Field]}
          clusterName=${Carg}.${primaryServer#*.}
        fi
        v[$CLUSTER_NAME_Field]=$clusterName
        clusterId=${v[$CLUSTERID_Field]}
      fi  # end if [[ -n $Cflag ]]
      ;;

    $MEMBER_NODE )
      # Add the node's reliable name to the list of reliable names.
      print -- "${v[$REL_HOSTNAME_Field]}" >> $nodefile
      checkForErrors "writing to file $nodefile" $?
      ;;

    $MMFSCFG )
      # If changing the cluster name, extract the mmfs.cfg data.
      if [[ -n $Cflag ]]
      then
        # Remove the line from the mmsdrfs file for now.  The mmfs.cfg
        # information will be added back before committing the changes.
        printLine=false

        # Extract the mmfs.cfg information.
        # It is everything past the first 4 fields.
        cfgLine="${v[5]}:${v[6]}:${v[7]}:${v[8]}:${v[9]}:${v[10]}:${v[11]}"
        cfgLine="$cfgLine:${v[12]}:${v[13]}:${v[14]}:${v[15]}:${v[16]}"
        cfgLine="$cfgLine:${v[17]}:${v[18]}:${v[19]}:${v[20]}:${v[21]}:${v[22]}"

        # To preserve tabs, temporarily set IFS to new line only.
        IFS="
"
        # Strip trailing colons and write the line to the file.
        print -- "${cfgLine%%+(:)}" >> $tmpCfg
        checkForErrors "writing to file $tmpCfg" $?
        IFS="$IFS_sv"  # restore the default IFS settings
      fi
      ;;

    * )
      # If changing the cluster name, make sure we do not
      # already have some remote cluster with the same name.
      if [[ -n $Cflag && ${v[$NODESETID_Field]} = $clusterName ]]
      then
        print -u2 "$mmcmd: The name $clusterName is already in use."
        # Command failed.
        printErrorMsg 389 $mmcmd
        cleanupAndExit
      fi
      ;;

  esac  # end Change some of the fields

  # 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


###################################################################
# If changing the cluster name, there are a few more things to do.
###################################################################
if [[ -n $Cflag ]]
then
  # Verify GPFS is stopped on all nodes.
  printInfoMsg 339
  verifyDaemonInactive $nodefile $mmcmd
  [[ $? -ne 0 ]] && cleanupAndExit

  # Change the clusterName parameter in the mmfs.cfg file.
  $mmfixcfg "clusterName" "$clusterName" <$tmpCfg >$newcfg
  checkForErrors "mmfixcfg clusterName $clusterName" $?

  # Ensure the clusterId parameter is in the mmfs.cfg file.
  $mv $newcfg $tmpCfg
  checkForErrors "mv $newcfg $tmpCfg" $?
  $mmfixcfg "clusterId" "${clusterId#gpfs}" <$tmpCfg >$newcfg
  checkForErrors "mmfixcfg clusterName $clusterName" $?

  # Put the new version of mmfs.cfg back into the mmsdrfs file.
  appendCfgFile $nodesetId $newcfg $newsdrfs
  checkForErrors "appendCfgFile" $?

  # Sort the new version of the mmsdrfs file.
  LC_ALL=C $SORT_MMSDRFS $newsdrfs -o $newsdrfs
  checkForErrors sort $?
fi  # end if [[ -n $Cflag ]]

##############################################################
# If this is a local change only, copy the file and return.
##############################################################
if [[ -n $fflag ]]
then
  $mv $newsdrfs $mmsdrfsFile
  checkForErrors "mv $newsdrfs $mmsdrfsFile" $?
  cleanupAndExit 0
fi


#########################################################################
# Put the new mmsdrfs file into the sdr.
#########################################################################
trap "" HUP INT QUIT KILL
gpfsObjectInfo=$(commitChanges \
   $HOME_CLUSTER $nsId $gpfsObjectInfo $newGenNumber $newsdrfs $primaryServer)
rc=$?
if [[ $rc -ne 0 ]]
then
  # Cannot replace 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


#########################################################################
# Asynchronously propagate the changes to all nodes.
#########################################################################
propagateSdrfsFile async $nodefile $newsdrfs $newGenNumber

cleanupAndExit 0

