#!/bin/ksh93
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/usr/sbin/cluster/events/utils/cl_nfs4smctl.sh 1.10.1.2 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2007,2013 
# 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 
# @(#)66    1.10.1.2 src/43haes/usr/sbin/cluster/events/utils/cl_nfs4smctl.sh, hacmp.events, 61haes_r714 7/11/13 22:25:16
#
#   COMPONENT_NAME: EVENTUTILS
#
#   FUNCTIONS: none
#
#   ORIGINS: 27
#
###############################################################################

###############################################################################
#
#  Name:  RegisterNode
#
#  Registers (creates) a node with the specified parameters
#  
#
#  Returns:
#    0 - Success
#    1 - Any runtime errors (unable to export, startsrc failures)
#    2 - Incorrect number of arguments was passed.
#
#  Arguments:  
#     -N nodename -P sspath -s service_label
#
###############################################################################

function RegisterNode
{
  [[ "$VERBOSE_LOGGING" == "high" ]] && set -x
  (( $# != 6 )) && return 2

  typeset RC arg nodename sspath address ipaddr

  while (( $# > 0 )) ; do
    arg=$1
    shift

    case "$arg" in
      -N) nodename=$1 ; shift  ;;
      -P) sspath=$1   ; shift  ;;
      -s) address=$1  ; shift  ;;
      *)  return 2
    esac
  done

  if [[ -z "$nodename" ]] || [[ -z "$sspath" ]] || [[ -z "$address" ]] ; then
    return 2
  fi

  ipaddr=$(LANG=C host $address | head -1 | cut -d' ' -f3 | tr -d ',')

  if [[ -z "$ipaddr" ]] ; then
    : IP address label "$address" did not resolve to a numeric address.
    return 1
  fi

  setenvnode $nodename

  if [[ "$ARG_N" == "$nodename" ]] ; then
    if [[ "$ARG_P" != "$sspath" ]] ; then
      return 1
    fi

    for addr in $ARG_s $ARG_n ; do
      if [[ "$addr" == "$ipaddr" ]] ; then
        : the address "$addr" is already registered.
        return 0
      fi
    done

    return 1
  fi

  # Make sure that the nfs extensions for HACMP are enabled
  nfso -H enable_ha
  RC=$?
  if (( $RC ))
  then
    : nfso -H enable_ha failed, RC=$RC
    return 1
  fi

  [[ ! -d $sspath ]] && mkdir -p $sspath
  [[ ! -d $sspath ]] && return 1

  nfs4smctl -R -N $nodename -P $sspath -s $address
  RC=$?
  case $RC in
    0)  return 0  ;;
    *)  return 1  ;;
  esac
}

###############################################################################
#
#  Name:  AddAddress
#
#  Adds an additional address to a node
#  
#
#  Returns:
#    0 - Success
#    1 - Any runtime errors (unable to export, startsrc failures)
#    2 - Incorrect number of arguments was passed.
#
#  Arguments:  
#     -N nodename -n service_label
#
###############################################################################

function AddAddress
{
  [[ "$VERBOSE_LOGGING" == "high" ]] && set -x
  (( $# != 4 )) && return 2

  typeset RC arg nodename address ipaddr

  while (( $# > 0 )) ; do
    arg=$1
    shift

    case "$arg" in
      -N) nodename=$1 ; shift  ;;
      -n) address=$1  ; shift  ;;
      *)  return 2
    esac
  done

  if [[ -z "$nodename" ]] || [[ -z "$address" ]] ; then
    return 2
  fi

  ipaddr=$(LANG=C host $address | head -1 | cut -d' ' -f3 | tr -d ',')

  if [[ -z "$ipaddr" ]] ; then
    : IP address label "$address" did not resolve to a numeric address.
    return 1
  fi

  setenvnode $nodename

  if [[ -z "$ARG_N" ]] ; then
    : The node "$nodename" is not registered.
    return 0
  fi

  for addr in $ARG_s $ARG_n ; do
    if [[ "$addr" == "$ipaddr" ]] ; then
      : the address "$addr" is already registered.
      return 0
    fi
  done

  nfs4smctl -A -N $nodename -n $address
  RC=$?
  case $RC in
    0)  return 0 ;;
    *)  return 1 ;;
  esac
}

###############################################################################
#
#  Name:  UnregisterNode
#
#  Unregisters (destroys) the node
#  
#
#  Returns:
#    0 - Success
#    1 - Any runtime errors (unable to export, startsrc failures)
#    2 - Incorrect number of arguments was passed.
#
#  Arguments:  
#     -N nodename
#
###############################################################################

function UnregisterNode
{
  [[ "$VERBOSE_LOGGING" == "high" ]] && set -x
  (( $# != 2 )) && return 2

  typeset RC arg nodename

  while (( $# > 0 )) ; do
    arg=$1
    shift

    case "$arg" in
      -N) nodename=$1 ; shift  ;;
      *)  return 2
    esac
  done

  if [[ -z "$nodename" ]] ; then
    return 2
  fi

  setenvnode $nodename

  if [[ -z "$ARG_N" ]] ; then
    : The node "$nodename" is not registered.
    return 0
  fi

  nfs4smctl -U -N $nodename
  RC=$?
  case $RC in
    0)  return 0  ;;
    *)  return 1  ;;
  esac
}

#####################################################################
#Description:                                                       #
#               returns the IPV6 address by adding zeros            #
#               i/p=  fe80::214:5eff:fe97:a603                      #
#               #0/p=  fe80:0:0:0:214:5eff:fe97:a603                #
#Name:                                                              #
#   isipv6addr <address>                                            #
#                                                                   #
#Returns :                                                          #
#   0 for success                                                   #
#   1 for failure (when the address is not IPv6)                    #
#####################################################################

function isipv6addr
{
    typeset addr v6addr
    addr=${1:-}
    v6addr=$(echo $addr|awk '
                        { n=split($1, A, ":")
                          if(n==1)
                          {
                                print n
                                exit
                          }
                            for(i=1; i<=n; i++)
                            {
                                if(length(A[i]))
                                {
                                    if(i == n)
                                        printf "%s", A[i]
                                    else
                                        printf "%s:", A[i]
                                }
                                else
                                {
                                        if(i==1)
                                            s=1
                                        else if(length(A[n]))
                                            s = 9-n
                                        else
                                        {
                                            s=10-n
                                            last=1
                                        }
                                        if(last)
                                        {
                                            for(j=1; j<s; j++)
                                                printf "%s:", "0"
                                            printf "%s", "0"
                                            i=n
                                        }
                                        else
                                            for(j=1; j<=s; j++)
                                                printf "%s:", "0"

                                }
                            }
                        }')

    if [[ $v6addr == 1 ]]
    then
        return 1
    else
        return 0
    fi

} # Function close isipv6addr

###############################################################################
#
#  Name:  QueryNode
#
#  Prints information about nodename, or all nodes if nodename is not
#  specified.  The -d flag specifies a delimiter.
#
#  Returns:
#    0 - Success
#    1 - Any runtime errors (unable to export, startsrc failures)
#    2 - Incorrect number of arguments was passed.
#
#  Arguments:  
#     [-N nodename] [-d delimiter]
#
###############################################################################

function QueryNode
{
  [[ "$VERBOSE_LOGGING" == "high" ]] && set -x
  typeset RC nodename result delimiter cmd arg
  cmd="-Q"

  while (( $# > 0 )) ; do
    arg=$1
    shift

    case "$arg" in
      -N) nodename=$1  ; shift ; cmd="$cmd -N $nodename" ;;
      -d) delimiter="$1" shift ;;
       *) return 2 ;;
    esac
  done


  if [[ -z $delimiter ]]; then
    # get the plain-text version of the report
    nfs4smctl $cmd
    RC=$?
  else
    # Delimiter specified; Try with Separator flag first
    # the below command checks whether nfs4smctl can be used
    # with -S flag. If yes we use -S flag or else we use -c flag
    result=$(nfs4smctl $cmd -S"$delimiter")
    RC=$?
    if [[ $RC == 0 ]]; then
      # The command worked, print the results
      echo "$result"
    else
      : missing support for Separator flag, so IPv6 not supported anyway
      : Use colon-separated output and convert to desired delimiter
      result=$(nfs4smctl $cmd -c)
      RC=$?
      echo "$result" | sed -e "s/:/${delimiter:-:}/g"
    fi
  fi

  case $RC in
    0) return 0 ;;
    *) return 1 ;;
  esac

}

###############################################################################
#
#  Name:  HaBypass
#
#    Turn habypass mode on or off for a specific NFSv4 node.  If the -N
#    flag is not specified, then the command operates on the base node.
#
#  Returns:
#    0 - Success
#    1 - Any runtime errors (unable to export, startsrc failures)
#    2 - Incorrect number of arguments was passed.
#
#  Arguments:  
#     {on|off} [-N nodename]
#
###############################################################################

function HaBypass
{
  [[ "$VERBOSE_LOGGING" == "high" ]] && set -x
  (( $# > 3 )) && return 2
  typeset arg RC mode nodename

  mode=

  while (( $# > 0 )) ; do
    arg=$1
    shift

    case "$arg" in
      -N) nodename="-N $1"  ; shift ;;
      on) mode=on                   ;;
     off) mode=off                  ;;
      *)  return 2
    esac
  done

  [[ -z "$mode" ]] && return 2

  nfs4smctl -habypass $mode $nodename
  RC=$?
  case $RC in
    0) return 0 ;;
    *) return 1 ;;
  esac
}
  
###############################################################################
#
#  Name:  setenvnode
#
#  Sets environment variables for the specified node.
#
#  Returns:
#    0 - Success
#
#  Arguments:  
#     nodename
#
###############################################################################

function setenvnode
{
  [[ "$VERBOSE_LOGGING" == "high" ]] && set -x
  typeset line   # assignment must be separate from typeset to capture RC
  line=$(QueryNode -N ${1:-___} -d '|')
  : QueryNode RC=$?
  ARG_N=$(echo $line | cut -d'|' -f2)
  ARG_P=$(echo $line | cut -d'|' -f3)
  ARG_s=$(echo $line | cut -d'|' -f5 | cut -d' ' -f1)
  ARG_n=$(echo $line | cut -d'|' -f5 | cut -d' ' -f2-)
}

###############################################################################
#
#  Name:  usage
#
#  Print the usage to stderr
#
#  Returns:
#    Success
#
#  Arguments:  
#    None
#
###############################################################################

function usage
{
  cat 1>&2 <<-EOF
	usage: $PROGNAME
	  -R -N nodename -P sspath -s address
	      Registers (creates) a node with the specified parameters

	  -A -N nodename -n address
	      Adds an additional service label to a node

	  -U -N nodename
	      Unregisters (destroys) the node

	  -Q [-N nodename] [-d delimiter]
	      Prints information about nodename, or all nodes if nodename is not
	      specified.  The -d flag specifies a delimiter.

    -habypass {on|off} [-N nodename]
        Turn habypass mode on or off for a specific NFSv4 node.  If the -N
        flag is not specified, then the command operates on the base node.

	EOF
}

###############################################################################
#
#  Name:  cl_nfs4smctl
#
#  Wrapper for nfs4smctl.  nfs4smctl controls the NFSv4 State Manager.
#
#  Returns:
#    0 - Success
#    1 - Any runtime errors (unable to export, startsrc failures)
#    2 - Incorrect number of arguments was passed.
#
#  Arguments:  
#     -R -N nodename -P sspath -s service_label
#         Registers (creates) a node with the specified parameters
#
#     -A -N nodename -n service_label
#         Adds an additional service label to a node
#
#     -U -N nodename
#         Unregisters (destroys) the node
#
#     -Q [-N nodename] [-d delimiter]
#         Prints information about nodename, or all nodes if nodename is not
#         specified.  The -d flag specifies a delimiter.
#
#     -habypass {on|off} [-N nodename]
#         Turn habypass mode on or off for a specific NFSv4 node.  If the -N
#         flag is not specified, then the command operates on the base node.
#
#  Environment: PATH, VERBOSE_LOGGING, EMULATE
#
###############################################################################

PROGNAME=$(basename ${0})

[[ "$VERBOSE_LOGGING" == "high" ]] && set -x
[[ "$VERBOSE_LOGGING" == "high" ]] && version='1.10.1.2'

PATH="/usr/sbin:$PATH"

KERNEL_BITS=$(bootinfo -K 2> /dev/null)
if (( KERNEL_BITS != 64 )) ; then
  : The nfs4smctl command is supported only on 64-bit kernels.
  exit 0
fi

typeset -i STATUS
typeset command
command=$1

shift

case $command in
  -R) RegisterNode "$@"
      STATUS=$?
      ;;

  -A) AddAddress "$@"
      STATUS=$?
      ;;

  -U) UnregisterNode "$@"
      STATUS=$?
      ;;

  -Q) QueryNode "$@"
      STATUS=$?
      ;;

  -habypass)
      HaBypass "$@"
      STATUS=$?
      ;;

  -?) usage
      STATUS=0
      ;;

  *)  STATUS=2
      ;;
esac

if (( STATUS == 2 )) ; then
  usage
fi

exit $STATUS
