#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,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 
# @(#)18 1.39.1.1 src/avs/fs/mmfs/ts/admin/mmsdrfsdef.Linux.sh, mmfs, avs_rgpfs24, rgpfs24s007a 9/20/06 11:22:28
#########################################################################
#
#  This file contains declarations and functions that are
#  unique to the Linux operating system environment.
#
#########################################################################


#######################################################################
#
# Function:  Check whether prerequisite software is installed.
#
# Input:     $1 -  Environment type
#
# Output:    None
#
# Returns:   0 - the prerequisite software for the specified
#                environment is installed
#            1 - the prerequisite software for the specified
#                environment is not installed
#
#######################################################################
function checkPrereqs  # <environmentType>
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGcheckPrereqs ]] && set -x
  # $mmTRACE_ENTER "$*"
  typeset environmentType=$1

  if [[ $environmentType = lc2 ]]
  then
    : # There are no special prereqs for cluster type lc2.

  elif [[ $environmentType = single ]]
  then
    : # There are no special prereqs for cluster type single.

  else
    # We should never get called for a cluster type other than
    # the ones we handle above.  Return with a failure code if we do.
    return 1
  fi

  return 0

}  #-------- end of function checkPrereqs ------------------------


####################################################################
#
# Function:  Create a version of the /etc/fstab file with
#            all of the mmfs file system stanzas removed
#
# Input:     $1 - output file name
#
# Output:    None
#
# Returns:   0 - processing completed successfully
#            1 - unexpected error
#
####################################################################
function removeAllStanzas  # <outputFile>
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGremoveAllStanzas ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset outfile=$1

  $rm -f $outfile

  #---------------------------------------------------------
  # Linux file system stanzas consist of 6 fields.
  # The third field is fs_vfstype and for GPFS file
  # systems its value is 'gpfs'.
  #---------------------------------------------------------
  $awk '                                               \
     # If this is a gpfs file system stanza, skip it.  \
     $3 == "gpfs" { next }                             \
     # All other lines are passed through as is.       \
     { print $0 >> "'$outfile'" }                      \
  ' $etcFilesystems
  checkForErrors "removeAllStanzas:awk" $?

  return 0

}  #------------- end of function removeAllStanzas ----------------


####################################################################
#
# Function:  Remove a file system from /etc/fstab.
#
# Input:     $1 - fully qualified file system device name
#
# Output:    /etc/fstab is rewritten.
#
# Returns:   0 - processing completed successfully
#            1 - unexpected error
#
####################################################################
function removeStanza  # <deviceName>
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGremoveStanza ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset fqDeviceName=$1

  typeset rc

  $rm -f $newstanza

  #---------------------------------------------------------
  # Linux file system stanzas consist of 6 fields.
  # The first field is the fully qualified device name.
  #---------------------------------------------------------
  $awk '                                                    \
     # If this is the stanza to be removed, skip the line.  \
     $1 == "'$fqDeviceName'" && $3 == "gpfs" { next }       \
     # All other lines are passed through as is.            \
     { print $0 >> "'$newstanza'" }                         \
  ' $etcFilesystems
  checkForErrors "removeStanza:awk" $?

  # If newstanza is missing or empty, something must have gone very wrong.
  [[ ! -s $newstanza ]] && \
    checkForErrors "removeStanza: missing or empty $newstanza file" 1

  # Replace /etc/fstab with its new version.
  $cp $newstanza $etcFilesystems
  rc=$?
  $mmsync $etcFilesystems
  checkForErrors "cp $newstanza $etcFilesystems" $rc

  return 0

}  #------------- end of function removeStanza ----------------


####################################################################
#
# Function:  Create a list of the gpfs file systems currently
#            defined in /etc/fstab.  Make the list look like
#            the output of the AIX lsfs -c command, i.e.,
#
#  #MountPoint:Device:Vfs:Nodename:Type:Size:Options:AutoMount:Acct
#  /gpfs/gpfsA:/dev/gpfsA:mmfs:-:mmfs:0:rw:no:no
#  /gpfs/gpfsB:/dev/gpfsB:mmfs:-:mmfs:0:rw:no:no
#
# Input:     $1 - output file name
#
# Output:    None
#
# Returns:   0 - processing completed successfully
#
####################################################################
function getCurrentStanzaList  # <outputFile>
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGgetCurrentStanzaList ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset outfile=$1

  $rm -f $outfile

  #---------------------------------------------------------------
  # Linux file system stanzas consist of 6 fields.  The first
  # three fields are fs_spec (device name), fs_file (mount point)
  # and fs_vfstype ('gpfs' for us).
  #---------------------------------------------------------------
  print -- "#MountPoint:Device:Vfs:junk" >$outfile
  $awk '                                                     \
     # If this is a gpfs file system stanza,                 \
     # write its device name and mount point to the file.    \
     $3 == "gpfs" { print $2":"$1":mmfs:" >> "'$outfile'" }  \
     # Skip all other lines                                  \
     { next }                                                \
  ' $etcFilesystems
  checkForErrors "getCurrentStanzaList:awk" $?

  return 0

}  #------------- end of function getCurrentStanzaList ----------------


#############################################################################
#
# Function:  Create the device and mountpoint for a file system
#
# Input:     $1 - fully qualified device name
#            $2 - mount point to be created
#            $3 - major number for the /dev entry
#            $4 - minor number for the /dev entry
#            $5 - mount type (automount or not)
#            $6 - automount directory
#
# Output:    None
#
# Returns:   Zero if successful, non-zero otherwise.
#
#############################################################################
function createMountPoint  # <device> <mountpnt> <majorNumber> <minorNumber>
                           #   <mountType> <automountDir>
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGcreateMountPoint ]] && set -x
  $mmTRACE_ENTER "$*"
  typeset fqDeviceName=$1
  typeset mountPoint=$2
  typeset majorNumber=$3
  typeset minorNumber=$4
  typeset mountType=$5
  typeset automountDir=$6


  typeset stillMounted existingMajorNumber mkdirError deviceName
  typeset mountPointParentDir mountPointExists
  typeset devType='b'


  # Strip away the /dev/ prefix from the device name.
  deviceName=${fqDeviceName##+(/)dev+(/)}

  # Ensure the device name exists and has the correct major number.
  existingMajorNumber=$(LC_ALL=C $ls -l $fqDeviceName 2>/dev/null | \
                                 $awk ' { print $5 } ' )
  existingMajorNumber=${existingMajorNumber%,*}

  if [[ $existingMajorNumber -ne $majorNumber ]]
  then
    # If the major number is not the same as the caller wants it to be,
    # remove the currently existing /dev entry, if any, and recreate it
    # with the correct major and minor numbers.
    [[ -n $existingMajorNumber ]] && $rm -f $fqDeviceName
    createDevEntry $fqDeviceName $majorNumber $minorNumber
    checkForErrors "createDevEntry $fqDeviceName $majorNumber $minorNumber" $?
  fi

  # Note that if the file system still shows as mounted, which can
  # happen after a previous gpfs invocation ends abnormally, the
  # normal check for existence can not be used - it fails with ESTALE.
  # In this case though, we can safely assume that the mount point
  # still exists.
  stillMounted=$($mount -t gpfs | \
      $awk '{ if ($1 == "'"$fqDeviceName"'") print $1 }')

  [[ -n $stillMounted ]] && return 0


  # If the file system is not mounted, ensure the mount
  # point is present.
  if [[ $mountType = automount ]]
  then
    # The mount point must be a symlink.
    if [[ -L $mountPoint ]]
    then
      # This is indeed a symlink.  Verify the target is correct.
      linkTarget=$(LC_ALL=C $ls -l $mountPoint 2>/dev/null)
      linkTarget=${linkTarget##*$BLANKchar}
      if [[ $linkTarget = ${automountDir}/${deviceName} ]]
      then
        # The link looks good.
        mountPointExists=yes
      else
        # The link needs to be rebuild.
        $rm -f $mountPoint
      fi
    else
      # This is not a symlink.  If a directory exists, remove
      # it so that a link can be created in its place.  If it
      # some other object, we do not know what to do.
      if [[ -e $mountPoint ]]
      then
        $rmdir $mountPoint
        if [[ $? -ne 0 ]]
        then
          print -u2 "$mmcmd: Unable to create symlink $mountPoint"
          return 1
        fi
      fi  # end of if [[ -e $mountPoint ]]
    fi  # end of if [[ -L $mountPoint ]]

  else
    # The mount point must be a directory.
    if [[ -L $mountPoint ]]
    then
      # This is a symlink (presumably from a file system that
      # used to have the automount mount attribute specified).
      # Remove the link so that we can create a directory in its place.
      $rm -f $mountPoint
    elif [[ -e $mountPoint ]]
    then
      # Things look good.
      mountPointExists=yes
    else
      : # Nothing found; we need to create a mount point.
    fi  # end of if [[ -L $mountPoint ]]
  fi  # end of if [[ $mountType = automount ]]

  # If missing, recreate the mount point.
  if [[ -z $mountPointExists ]]
  then
    if [[ $mountType = automount ]]
    then
      mountPointParentDir=$(dirname $mountPoint)
      mkdirError=$(LC_ALL=C $mkdir -p $mountPointParentDir 2>&1)
      [[ -n $mkdirError ]] && \
        print -- $mkdirError | $grep -v "File exists" 1>&2
      $ln -s ${automountDir}/${deviceName} $mountPoint
    else
      mkdirError=$(LC_ALL=C $mkdir -m 0755 -p $mountPoint 2>&1)
      [[ -n $mkdirError ]] && \
        print -- $mkdirError | $grep -v "File exists" 1>&2
    fi
  fi  # end of if [[ -z $mountPointExists ]]

  return 0

}  #------------- end of function createMountPoint ---------------


###############################################################
#
# Function:  Determine the major number needed for proper
#            fs operations and the major number currently
#            assigned to /dev entries.  Assign the two values
#            to the appropriate global variables.
#
# Input:     None
#
# Output:    None
#
# Returns:   Always zero.
#
###############################################################
function checkVfsNumber
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGcheckVfsNumber ]] && set -x
  $mmTRACE_ENTER "$*"

  typeset device deviceList majorNumber


  # Determine the major number that is presently required.
  # This is required for kernel version 2.4 and earlier.
  # If the current kernel is 2.5 or later, use the default
  # values since the major number is largely irrelevant.
  [[ -z $version24 ]] && return 0

  # If the daemon is running, the major number should be the one that
  # was assigned by the kernel when the mmfs extension was loaded.
  # Otherwise, use the default number.
  neededMajorNumber=$($awk ' $2=="gpfs" {print $1} ' /proc/devices)
  [[ -z $neededMajorNumber ]] && \
    neededMajorNumber=$defaultMajorNumber

  # Determine the major number that has been used last, i.e.,
  # determine the major number of the existing /dev entries.

  # If file mmfsVfsNumber* exists, its suffix is the major number.
  majorNumber=$($ls ${mmfsVfsNumber}+([0-9]) 2>/dev/null)
  majorNumber=${majorNumber#$mmfsVfsNumber}
  if [[ -n $majorNumber ]]
  then
    currentMajorNumber=$majorNumber
    return 0
  fi

  # If the file has been lost somehow, create a list
  # of the file systems in the cluster and see what
  # major number is being used for their /dev entries.

  # Create a list of the file systems in the cluster.
  deviceList=$($grep -e ":$SG_HEADR:" $mmsdrfsFile |  \
               $GETVALUE $DEV_NAME_Field)

  # Go down the list of file systems until you find a corresponding
  # /dev entry from which to get the major number.
  for device in $deviceList
  do
    majorNumber=$(LC_ALL=C $ls -l /dev/$device 2>/dev/null | \
                           $awk ' { print $5 } ' )
    majorNumber=${majorNumber%,*}
    [[ -n $majorNumber ]] && break
  done

  # If there are no file systems in this nodeset, or if all
  # file systems are missing their /dev entries for some reason,
  # assume the default major device number.
  [[ -z $majorNumber ]] && majorNumber=$defaultMajorNumber

  $touch ${mmfsVfsNumber}${majorNumber} 2>/dev/null
  currentMajorNumber=$majorNumber
  return 0

}  #------------- end of function checkVfsNumber ----------------


######################################################################
#
# Function:  Make sure there is an entry for mmfs in /etc/auto_master
#
# Input:     None
#
# Output:    None
#
# Returns:   0 - mmfs entry in /etc/auto_master confirmed.
#
######################################################################
function checkAutomountDefine
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGcheckAutomountDefine ]] && set -x
  $mmTRACE_ENTER "$*"

  # Applies only to the AIX environment.

  return 0

} #-------- end of function checkAutomountDefine ----------------


######################################################################
#
# Function:  Remove the entry for mmfs from /etc/auto_master
#
# Input:     None
#
# Output:    None
#
# Returns:   0 - mmfs entry in /etc/auto_master removed.
#
######################################################################
function clearAutomountDefine
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGclearAutomountDefine ]] && set -x
  $mmTRACE_ENTER "$*"

  # Applies only to the AIX environment.

  return 0

} #-------- end of function clearAutomountDefine ----------------


########################################################################
#
# Function:  Obtain K5 (DCE) and/or K4 credentials.
#            Applies only to the SP environment.
#
# Input:     None
#
# Output:    None
#
# Returns:   0 - command completed successfully
#
########################################################################
function getCred
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGgetCred ]] && set -x
  # $mmTRACE_ENTER "$*"

  return 0

}  #---------------- end of function getCred ---------------------------


#############################################################################
#
# Function:  Destroy K5 (DCE) and/or K4 credentials obtained by this command
#            Applies only to the SP environment.
#
# Input:     None
#
# Output:    None
#
# Returns:   0 - command completed successfully
#
#############################################################################
function freeCred
{
  typeset sourceFile="mmsdrfsdef.Linux.sh"
  [[ -n $DEBUG || -n $DEBUGfreeCred ]] && set -x
  # $mmTRACE_ENTER "$*"

  getCredCalled=no
  return 0

}  #---------------- end of function freeCred ---------------

