#!/bin/bash
#
# Init file for the A-REX cache service
#
# This startup script takes ARC0 configuration file as
# its input and generates ARC1 arched configuration file
# which contains commands to start A-REX cache service.

# chkconfig: 2345 87 13
# description: ARC cache service
# processname: arched

### BEGIN INIT INFO
# Provides:          cache-service
# 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 cache service
# Description:       ARC cache service
### 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
  }
}

# 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

# PID and lock file
PID_FILE=

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


prepare() 
{

CMD="$ARC_LOCATION/sbin/$prog"
if ! test -x "$CMD"; then
    failure "Missing executable"
    echo
    exit 1
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:
#  Debug level
#  User name
#  Log file is currently hard-coded

#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
host=`readconfigvar "$ARC_CONFIG" common hostname`
cache_endpoint=https://$host:60001/cacheservice

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

echo "cache service endpoint: $cache_endpoint"

CMD="$CMD -c '$CACHE_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/arc/cache-service.log}
if [ ! -d `dirname $LOGFILE` ]; then
 mkdir -p `dirname $LOGFILE` ]
fi
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

# Cache service XML config
CACHECFG="\
<?xml version=\"1.0\"?>\
<ArcConfig\
  xmlns=\"http://www.nordugrid.org/schemas/ArcConfig/2007\"\
  xmlns:tcp=\"http://www.nordugrid.org/schemas/ArcMCCTCP/2007\"
  xmlns:cacheservice=\"urn:cacheservice_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>identitymap</Name></Plugins>\
  <Plugins><Name>arcshc</Name></Plugins>\
  <Plugins><Name>cacheservice</Name></Plugins>\
  <Chain>\
    <Component name=\"tcp.service\" id=\"tcp\">\
      <next id=\"tls\"/>\
      <tcp:Listen><tcp:Port>60001</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=\"cacheservice\">^/cacheservice</next>\
    </Plexer>\
    <Service name=\"cacheservice\" id=\"cacheservice\">\
      <!-- Put sec handler in here so that sensible error message can\
           be returned -->\
      <SecHandler name=\"arc.authz\" id=\"map\" event=\"incoming\">\
        <PDP name=\"simplelist.pdp\" location=\"$GRIDMAP\"/>\
      </SecHandler>\
      <cacheservice:cache>\
        <cacheservice:config>$ARC_CONFIG</cacheservice:config>\
        <cacheservice:maxload>5</cacheservice:maxload>\
      </cacheservice:cache>\
    </Service>
  </Chain>\
</ArcConfig>\
"

echo "$CACHECFG" > "$CACHE_CONFIG"

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

}


start()
{
    if [ -r /etc/default/cache-service ]; then
      if egrep -q '[ \t]*disable' /etc/default/cache-service 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
          failure "Error: already running (pid $pid)"
          echo
          return 1
        fi
      fi
      rm -f "$PID_FILE" "$LOCKFILE"
    fi

    prepare

    eval "$CMD"
    RETVAL=$?
    rm -f "$CACHE_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 $?
