#!/bin/bash
#
# Init file for the A-REX service
#
# chkconfig: 2345 55 25
# description: NorduGrid grid-manager
#
# config: /etc/sysconfig/globus
# config: /etc/sysconfig/nordugrid
# config: /usr/etc/arc.conf
# config: /etc/arc.conf
#
#  This startup script takes ARC0 configuration file as
# its input and generates ARC1 arched configuration file
# which contains commands to start A-REX service. Service
# is either run isolated or with WS interface enabled.
#  To enable WS interface ARC0 configuration file must 
# contain undocumented option in [grid-manager] section:
#
#    arex_mount_point="a_rex_url"

### BEGIN INIT INFO
# Provides:          a-rex
# Required-Start:    $local_fs $remote_fs
# Required-Stop:     $local_fs $remote_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: ARC grid manager
# Description:       The unit of the NorduGrid's ARC middleware to 
#                    accept and control jobs. 
### END INIT INFO


#  
#
# source function library
if [ -f /etc/init.d/functions ]; then
  . /etc/init.d/functions
else
  success() { echo -n "OK"
  }
  failure() { echo -n "FAILURE"
  }
  status() {
    pid=`pidof -o $$ -o $PPID -o %PPID -x $1`
    if test "x$pid" != "x"; then
      echo "$1 (pid $pid) is running..."
      return 0
    fi

    if test -f "$PID_FILE"; then
      read pid < "$PID_FILE"
      if test "$pid" != ""; then
        echo "$1 stopped but pid file exists"
        return 1
      fi
    fi
    if test -f $LOCKFILE; then
      echo "$1 stopped but lockfile exist"
      return 2
    fi
    echo "$1 is stopped"
    return 3
  }
fi

add_library_path() {
  location="$1"
  if [ ! "x$location" = "x" ] ; then
    if [ ! "$location" = "/usr" ] ; then
      libdir="$location/lib"
      libdir64="$location/lib64"
      if [ -d "$libdir64" ] ; then
        if [ "x$LD_LIBRARY_PATH" = "x" ]; then
          LD_LIBRARY_PATH="$libdir64"
        else
          LD_LIBRARY_PATH="$libdir64:$LD_LIBRARY_PATH"
	fi
      fi
      if [ -d "$libdir" ] ; then
        if [ "x$LD_LIBRARY_PATH" = "x" ]; then
          LD_LIBRARY_PATH="$libdir"
        else
          LD_LIBRARY_PATH="$libdir:$LD_LIBRARY_PATH"
        fi
      fi
    fi
  fi
}

# sysconfig files
if [ -f /etc/sysconfig/globus ]; then
    . /etc/sysconfig/globus
fi
if [ -f /etc/sysconfig/nordugrid ]; then
    . /etc/sysconfig/nordugrid
fi

prog=arched

# GLOBUS_LOCATION
GLOBUS_LOCATION=${GLOBUS_LOCATION:-/usr}
if [ ! -d "$GLOBUS_LOCATION" ]; then
  echo "GLOBUS_LOCATION ($GLOBUS_LOCATION) not found"
  exit 1
fi
export GLOBUS_LOCATION

# ARC_LOCATION
ARC_LOCATION=${ARC_LOCATION:-/usr}
if [ ! -d "$ARC_LOCATION" ]; then
  echo "ARC_LOCATION ($ARC_LOCATION) not found"
  exit 1
fi
export ARC_LOCATION

readconfigvar()
{
  fname=$1
  if [ ! -r "$fname" ]; then
    return
  fi
  bname="[$2]"
  vname=$3
  value=
  cat "$fname" | grep -e '^\[' -e "^${vname}=" | {
    while true; do
      read line
      if [ ! $? = 0 ] ; then
        return
      fi
      if [ "$line" = "$bname" ] ; then
        while true ; do
          read line
          if [ ! $? = 0 ] ; then
            return
          fi
          lstart=`echo "$line" | head -c 1`
          if [ "$lstart" = '[' ] ; then
            return
          fi
          vlname=`echo "$line" | sed 's/=.*//;t;s/.*//'`
          if [ "$vlname" = "$vname" ] ; then
            val=`echo "$line" | sed 's/[^=]*=//'`
            eval "echo $val"
            return
          fi
        done
      fi
    done
  }
}

# PID and lock file
PID_FILE=`readconfigvar "$ARC_CONFIG" grid-manager pidfile`

if [ `id -u` = 0 ] ; then
  # Debian does not have /var/lock/subsys
  if test -d /var/lock/subsys; then
    LOCKFILE=/var/lock/subsys/$prog
  else
    LOCKFILE=/var/lock/$prog
  fi
  if test "x$PID_FILE" = "x"; then 
    PID_FILE=/var/run/$prog.pid
  fi
else
  LOCKFILE=$HOME/$prog.lock
  if test "x$PID_FILE" = "x"; then 
    PID_FILE=$HOME/$prog.pid
  fi
fi 


prepare() 
{

CMD="$ARC_LOCATION/sbin/$prog"
if ! test -x "$CMD"; then
    failure "Missing executable"
    echo
    exit 1
fi

# ARC_CONFIG
if test "x$ARC_CONFIG" = "x"; then
  if [ -r $ARC_LOCATION/etc/arc.conf ]; then
    ARC_CONFIG=$ARC_LOCATION/etc/arc.conf
  elif [ -r /etc/arc.conf ]; then
    ARC_CONFIG=/etc/arc.conf
  fi
fi
if [ ! -r "$ARC_CONFIG" ]; then
  echo "NorduGrid configuration not found (usually /etc/arc.conf)"
  exit 1
fi

# Creating configuration file of arched
# Reading following information from config file:
#  Log file
#  Debug level
#  User name

LOGFILE=`readconfigvar "$ARC_CONFIG" grid-manager logfile`
LOGLEVEL=`readconfigvar "$ARC_CONFIG" grid-manager debug`
LOGSIZE=`readconfigvar "$ARC_CONFIG" grid-manager logsize`
USERNAME=`readconfigvar "$ARC_CONFIG" grid-manager user`
X509_USER_CERT=`readconfigvar "$ARC_CONFIG" grid-manager x509_user_cert`
X509_USER_KEY=`readconfigvar "$ARC_CONFIG" grid-manager x509_user_key`
X509_CERT_DIR=`readconfigvar "$ARC_CONFIG" grid-manager x509_cert_dir`
GRIDMAP=`readconfigvar "$ARC_CONFIG" grid-manager gridmap`
GLOBUS_TCP_PORT_RANGE=`readconfigvar "$ARC_CONFIG" grid-manager globus_tcp_port_range`
GLOBUS_UDP_PORT_RANGE=`readconfigvar "$ARC_CONFIG" grid-manager globus_udp_port_range`
if [ -z "$X509_USER_CERT" ] ; then
 X509_USER_CERT=`readconfigvar "$ARC_CONFIG" common x509_user_cert`
fi
if [ -z "$X509_USER_KEY" ] ; then
 X509_USER_KEY=`readconfigvar "$ARC_CONFIG" common x509_user_key`
fi
if [ -z "$X509_CERT_DIR" ] ; then
 X509_CERT_DIR=`readconfigvar "$ARC_CONFIG" common x509_cert_dir`
fi
if [ -z "$GRIDMAP" ] ; then
 GRIDMAP=`readconfigvar "$ARC_CONFIG" common gridmap`
fi
if [ -z "$GLOBUS_TCP_PORT_RANGE" ] ; then
 GLOBUS_TCP_PORT_RANGE=`readconfigvar "$ARC_CONFIG" common globus_tcp_port_range`
fi
if [ -z "$GLOBUS_UDP_PORT_RANGE" ] ; then
 GLOBUS_UDP_PORT_RANGE=`readconfigvar "$ARC_CONFIG" common globus_udp_port_range`
fi

# Exporting collected variables
if [ ! -z "$X509_USER_CERT" ] ; then export X509_USER_CERT ; fi
if [ ! -z "$X509_USER_KEY" ] ; then export X509_USER_KEY ; fi
if [ ! -z "$X509_CERT_DIR" ] ; then export X509_CERT_DIR ; fi
if [ ! -z "$GRIDMAP" ] ; then export GRIDMAP ; fi
if [ ! -z "$GLOBUS_TCP_PORT_RANGE" ] ; then export GLOBUS_TCP_PORT_RANGE ; fi
if [ ! -z "$GLOBUS_UDP_PORT_RANGE" ] ; then export GLOBUS_UDP_PORT_RANGE ; fi

# Required defaults
if [ -z "$GRIDMAP" ] ; then
 GRIDMAP=/etc/grid-security/grid-mapfile
fi
if [ -z "$X509_USER_CERT" ] ; then
 X509_USER_CERT=/etc/grid-security/hostcert.pem
fi
if [ -z "$X509_USER_KEY" ] ; then
 X509_USER_KEY=/etc/grid-security/hostkey.pem
fi
if [ -z "$X509_CERT_DIR" ] ; then
 X509_CERT_DIR=/etc/grid-security/certificates
fi

# Web Service configuration
arex_mount_point=`readconfigvar "$ARC_CONFIG" grid-manager arex_mount_point`
arex_mount_point=${arex_mount_point:-`readconfigvar "$ARC_CONFIG" cluster arex_mount_point`}
if [ ! -z "$arex_mount_point" ] ; then
  arex_proto=`echo "$arex_mount_point" | sed 's/^\([^:]*\):\/\/.*/\1/;t;s/.*//'`
  arex_host=`echo "$arex_mount_point" | sed 's/^[^:]*:\/\/\([^:\/]*\).*/\1/;t;s/.*//'`
  arex_port=`echo "$arex_mount_point" | sed 's/^[^:]*:\/\/[^:]*:\([^\/]*\)\(.*\)/\1/;t;s/.*//'`
  arex_path=`echo "$arex_mount_point" | sed 's/^[^:]*:\/\/[^\/]*\/\(.*\)/\1/;t;s/.*//'`
  if [ -z "$arex_port" ] ; then arex_port="60000" ; fi
fi
#echo "arex_mount_point=$arex_mount_point"
#echo "arex_proto=$arex_proto"
#echo "arex_host=$arex_host"
#echo "arex_port=$arex_port"
#echo "arex_path=$arex_path"

AREX_CONFIG=`mktemp -t arex.xml.XXXXXX`
if [ -z "$AREX_CONFIG" ] ; then
  echo "Failed to create temporary file"
  exit 1
fi

CMD="$CMD -c '$AREX_CONFIG'"

# VOMS_LOCATION
VOMS_LOCATION=${VOMS_LOCATION:-@DEFAULT_VOMS_LOCATION@}

# GRIDSITE_LOCATION
GRIDSITE_LOCATION=${GRIDSITE_LOCATION:-@DEFAULT_GRIDSITE_LOCATION@}

add_library_path "$LFC_LOCATION"
add_library_path "$GRIDSITE_LOCATION"
add_library_path "$VOMS_LOCATION"
add_library_path "$GLOBUS_LOCATION"
if [ "x$LD_LIBRARY_PATH" = "x" ]; then
  LD_LIBRARY_PATH=$ARC_LOCATION/lib
else
  LD_LIBRARY_PATH=$ARC_LOCATION/lib:$LD_LIBRARY_PATH
fi
SASL_PATH=${SASL_PATH:-$GLOBUS_LOCATION/lib/sasl}
export LD_LIBRARY_PATH SASL_PATH

case "$LOGLEVEL" in 
  0) LOGLEVEL="FATAL" ;;
  1) LOGLEVEL="ERROR" ;;
  2) LOGLEVEL="WARNING" ;;
  3) LOGLEVEL="INFO" ;;
  4) LOGLEVEL="VERBOSE" ;;
  5) LOGLEVEL="DEBUG" ;;
  *) LOGLEVEL="WARNING" ;;
esac

if [ "$USERNAME" = "root" ] ; then
  USERNAME=""
fi

LOGFILE=${LOGFILE:-/var/log/grid-manager.log}
LOGSIZE=${LOGSIZE:--1 -1}
LOGNUM=`echo "$LOGSIZE" | sed 's/^ *[-+0-9]* *//'`
LOGSIZE=`echo "$LOGSIZE" | sed 's/^ *\([-+0-9]*\).*/\1/'`

if [ ! -z "$USERNAME" ] ; then
  CMD="su '$USERNAME' -c \"$CMD\""
fi

# A-Rex without WS interface
AREXCFG="\
<?xml version=\"1.0\"?>\
<ArcConfig\
  xmlns=\"http://www.nordugrid.org/schemas/ArcConfig/2007\"\
  xmlns:arex=\"http://www.nordugrid.org/schemas/a-rex/Config\">\
  <Server>\
    <PidFile>$PID_FILE</PidFile>\
    <Logger>\
      <File>$LOGFILE</File>\
      <Level>$LOGLEVEL</Level>\
      <Backups>$LOGNUM</Backups>\
      <Maxsize>$LOGSIZE</Maxsize>\      
    </Logger>\
  </Server>\
  <ModuleManager>\
    <Path>$ARC_LOCATION/lib/arc/</Path>\
  </ModuleManager>\
  <Plugins><Name>arex</Name></Plugins>\
  <Chain>\
    <Service name=\"a-rex\" id=\"a-rex\">\
      <arex:gmconfig>$ARC_CONFIG</arex:gmconfig>\
    </Service>\
  </Chain>\
</ArcConfig>\
"

# A-Rex with WS interface over HTTPS
AREXCFGWSS="\
<?xml version=\"1.0\"?>\
<ArcConfig\
  xmlns=\"http://www.nordugrid.org/schemas/ArcConfig/2007\"\
  xmlns:tcp=\"http://www.nordugrid.org/schemas/ArcMCCTCP/2007\"
  xmlns:arex=\"http://www.nordugrid.org/schemas/a-rex/Config\">\
  <Server>\
    <PidFile>$PID_FILE</PidFile>\
    <Logger>\
      <File>$LOGFILE</File>\
      <Level>$LOGLEVEL</Level>\
      <Backups>$LOGNUM</Backups>\
      <Maxsize>$LOGSIZE</Maxsize>\      
    </Logger>\
  </Server>\
  <ModuleManager>\
    <Path>$ARC_LOCATION/lib/arc/</Path>\
  </ModuleManager>\
  <Plugins><Name>mcctcp</Name></Plugins>\
  <Plugins><Name>mcctls</Name></Plugins>\
  <Plugins><Name>mcchttp</Name></Plugins>\
  <Plugins><Name>mccsoap</Name></Plugins>\
  <Plugins><Name>arex</Name></Plugins>\
  <Plugins><Name>identitymap</Name></Plugins>\
  <Plugins><Name>arcshc</Name></Plugins>\
  <Chain>\
    <Component name=\"tcp.service\" id=\"tcp\">\
      <next id=\"tls\"/>\
      <tcp:Listen><tcp:Port>$arex_port</tcp:Port></tcp:Listen>\
    </Component>\
    <Component name=\"tls.service\" id=\"tls\">\
      <next id=\"http\"/>\
      <KeyPath>$X509_USER_KEY</KeyPath>\
      <CertificatePath>$X509_USER_CERT</CertificatePath>\
      <CACertificatesDir>$X509_CERT_DIR</CACertificatesDir>\
      <SecHandler name=\"identity.map\" id=\"map\" event=\"incoming\">\
        <PDP name=\"allow.pdp\"><LocalList>$GRIDMAP</LocalList></PDP>\
        <PDP name=\"allow.pdp\"><LocalName>nobody</LocalName></PDP>\
      </SecHandler>\
    </Component>\
    <Component name=\"http.service\" id=\"http\">\
      <next id=\"soap\">POST</next>\
      <next id=\"plexer\">GET</next>\
      <next id=\"plexer\">PUT</next>\
    </Component>\
    <Component name=\"soap.service\" id=\"soap\">\
      <next id=\"plexer\"/>\
    </Component>\
    <Plexer name=\"plexer.service\" id=\"plexer\">\
      <next id=\"a-rex\">^/$arex_path</next>\
    </Plexer>\
    <Service name=\"a-rex\" id=\"a-rex\">\
      <arex:gmconfig>$ARC_CONFIG</arex:gmconfig>\
    </Service>\
  </Chain>\
</ArcConfig>\
"

if [ -z "$arex_proto" ] ; then
  echo "$AREXCFG" > "$AREX_CONFIG"
elif [ "$arex_proto" = "https" ] ; then
  echo "$AREXCFGWSS" > "$AREX_CONFIG"
else
  failure "Unsupported protocol: $arex_proto"
fi

if [ ! -z "$USERNAME" ] ; then
  test -f $AREX_CONFIG && chown $USERNAME $AREX_CONFIG
fi

#cat "$AREX_CONFIG"

}


start()
{
    if [ -r /etc/default/a-rex ]; then
      if egrep -q '[ \t]*disable' /etc/default/a-rex 2>/dev/null ; then
         echo "Start of $prog disabled"
         return 0
      fi
    fi
    echo -n "Starting $prog: "

    # Check if we are already running
    if test -f $PID_FILE; then
      read pid < $PID_FILE
      if test "x$pid" != "x"; then
        ps -p "$pid" -o comm 2>/dev/null | grep "^$prog$" 1>/dev/null 2>/dev/null
        if [ "$?" == '0' ] ; then
          success "Error: already running ($pid)"
          echo
          return 0
        fi
      fi
      rm -f "$PID_FILE" "$LOCKFILE"
    fi

    prepare

    eval "$CMD"
    RETVAL=$?
    rm -f "$AREX_CONFIG"

    if [ $RETVAL -ne 0 ]; then
        failure "$prog startup"
    else
       touch $LOCKFILE
       success "$prog startup"
    fi
    echo
    return $RETVAL
}

stop()
{
    echo -n "Stopping $prog: "

    if test -f "$PID_FILE"; then
      PID=`cat "$PID_FILE"`
      if [ ! -z "$PID" ] ; then
        kill "$PID" && success "$prog shutdown" || failure "$prog shutdown"
        RETVAL=$?
        sleep 1
        kill -9 "$PID" 1>/dev/null 2>&1
        rm -f "$PID_FILE" "$LOCKFILE"
      else
        RETVAL=1
        failure "$prog shutdown - pidfile is empty"     
      fi
    else
      RETVAL=0
      success "$prog shutdown - already stopped"
    fi
    echo
    return $RETVAL
}

case "$1" in
  start)
        start "$1"
        ;;
  stop)
        stop
        ;;
  status)
	status $prog
        ;;
  restart|reload|force-reload)
        stop
        start
        ;;
  condrestart)
        test -f $LOCKFILE && stop && start
        ;;
  *)
        echo "Usage: $0 {start|stop|status|restart|reload|force-reload|condrestart}"
        exit 1
esac

exit $?
