#!/bin/bash
#
# sccl_start_bg Startet ein Paket im Script-Cluster
#
# Aufruf:
#
# sccl_start_bg [--simulate] [--force] [--boot] [-r] [--norst] [-p <startpars>] [-x <envvars>] [-i <initignore>] <paketname> [<node>]
#
#    --simulate: Start nur simulieren
#    --force: Platten werden gemountet, auch wenn noch Lockdateien von andren Knoten vorhanden sind
#    --norst: kein Restarten bzw. Starten der RST Pakete
#    -r     : als letzte Zeile den RETURNVALUE ausgeben (Aufruf über WEB)
#    -S     : ist bei RST gesetzt -> Paket wird schon gestartet nicht als Fehler werten
#    -p <p> : bei PRG und PRGP Parameter <p> mit übergeben
#    -x <x> : setzen von Variablen in sccl_start_res (-x "VAR=val")
#    -i <n> : verhinderung zyklischer starts (<n> ist ursprüngliches Paket)
# Das Paket <paketname> wird auf dem Knoten <node> gestartet, wenn angegeben,
# sonst auf dem einzigen Knoten, auf dem das Paket gestartet werden darf
# oder bei MULTI auf dem Kntoen, auf dem das Skript sccl_start ausgefuehrt wird.
#
########################################################################################
#
. $(dirname $0)/globals.settings
#
unset SCCLINITIGNORE CALLPARS FORCE RETVALUE RETERROR STARTPARS ENVVARS SIMULATE CALLEXT SCCLBOOT IGNORESTARTING SCCLNORST
while getopts I:rRi:x:p:P:S-:? op; do
  case "$op" in
   i) SCCLINITIGNORE="$OPTARG";;
   I) export scclinitiated="$OPTARG";;
   x) ENVVARS="$ENVVARS $OPTARG"
      for i in $OPTARG; do
        CALLPARS="$CALLPARS -x $i"
      done;;
   p) STARTPARS="$STARTPARS $OPTARG"
      for i in $OPTARG; do
        CALLPARS="$CALLPARS -p $i"
      done;;
   P) PIDSIG="$OPTARG";;
   r) RETVALUE=1;;
   R) RETERROR='SCCL-Error: '
      unset RETVALUE;;
   S) IGNORESTARTING='-S';;
   -) case "$OPTARG" in
       force) FORCE='--force';;
       simulate) SIMULATE='--simulate'
                 CALLEXT='_simulate';;
       boot)  export SCCLBOOT='--boot';;
       norst) export SCCLNORST='--norst';;
       *)     echo "usage: $MYPRG [--simulate] [--force] [--boot] [--norst] [-p <startpars>] [-x <envvars>] [-i <initignore>] [-S] <package> [<node>]"
              exit 1;;
      esac;;
   ?) echo "usage: $MYPRG [--simulate] [--force] [--boot] [--norst] [-p <startpars>] [-x <envvars>] [-i <initignore>] [-S] <package> [<node>]"
      exit 1;;
  esac
done
#
shift $(( $OPTIND - 1))
#
if [[ $# -lt 1 ]]; then
  echo "usage: $MYPRG [--simulate] [--force] [--boot] [--norst] [-p <startpars>] [-x <envvars>] [-i <initignore>] [-S] <package> [<node>]"
  [[ -n "$RETERROR" ]] && echo "SCCL-Error: Fehlerhafter Aufruf"
  exit 1
fi
#
if [[ "$SCCLINITIGNORE" = "$1:$THISHOSTNAME" ]]; then
  echo "ignoring starting loop."
  exit 0
fi
#
PACKAGE=$1
trap '' 1 2 3 6
if [[ "$2" = "THISNODE" ]]; then
  if [[ ! -f $PACKAGES ]]; then
    echo "$RETERROR$PACKAGES fehlt." >&2
    exit 1
  fi
  LOGFILENAME=$SCCLLOGNAME${1}_start.log
  LOGFILE=$SCCLLOGBASE/$LOGFILENAME.$$
  #
  if [[ -f "$LOCKDIR/node.STOPPED" ]]; then
    echo "${RETERROR}Der Knoten $THISHOSTNAME ist heruntergefahren"
    exit 1
  fi
  if [[ -f "$LOCKDIR/node.DISABLED" ]]; then
    echo "${RETERROR}Der Knoten $THISHOSTNAME ist disabled"
    exit 1
  fi
  #
  export THISINITIGNORE="$1:$THISHOSTNAME"
  export SCCLINITIGNORE="${SCCLINITIGNORE:-$THISINITIGNORE}"
  #
  export PACKAGE
  if ! ./sccl_my_packages "$1" | grep -Eq "[,[:blank:]]$THISHOSTNAME[,[:blank:]]|[,[:blank:]]$THISHOSTNAME\$|[,[:blank:]]$THISFQDN[,[:blank:]]|[,[:blank:]]$THISFQDN\$"; then
    if grep -q '^'$1'[[:blank:]]' $PACKAGES; then
      echo "${RETERROR}Das Paket '$PACKAGE' darf auf diesem Knoten oder Gruppe nicht laufen!"
    else
      echo "${RETERROR}Das Pakete '$PACKAGE' ist nicht definiert."
    fi
    exit 1
  fi
  #
  if [[ -n "$ULS" ]]; then
    if grep -q '^'$1'[[:blank:]].*[[:blank:]]EXECUTE' $RESOURCES; then
      method='Execute'
      message='Executed'
      inprogress='Executing'
    else
      method='Start'
      message='Started'
      inprogress='Starting'
    fi
    DATETIME=`date '+%Y-%m-%d %H:%M:%S'`
    #                                            Sektion  Teststep          Detail       Date Time  Wert            Einheit
    send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE Server       $DATETIME  $THISHOSTNAME   "_"
    send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "start-stop" $DATETIME  "$method"       "_"
    if [[ -n "$scclinitiated" ]]; then
      send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "initiated" $DATETIME  "$scclinitiated" "_"
    fi
  fi
  [[ -n "$PIDSIG" ]] && [[ ! -f "$LOCKDIR/${PACKAGE}_start_progress" ]] && echo "$PIDSIG sccl_start_bg $$" >>"$LOCKDIR/${PACKAGE}_start_progress"
  set -o pipefail
  ./sccl_start_package ${SIMULATE:-$FORCE} $IGNORESTARTING $CALLPARS $PACKAGE $PIDSIG 2>&1 | tee "$LOGFILE"
  RET=$?
  [[ -n "$PIDSIG" && -f "$LOCKDIR/${PACKAGE}_start_progress" ]] && head -1 "$LOCKDIR/${PACKAGE}_start_progress" | grep -q "^$PIDSIG " && rm "$LOCKDIR/${PACKAGE}_start_progress"
  if [[ $RET = 0 ]]; then
    echo
    if [[ -n "$ULS" ]]; then
      FDATETIME=`date '+%Y-%m-%d %H:%M:%S'`
      send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "message" $DATETIME "$message" "_"
      send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "finished" $DATETIME  "$FDATETIME"     "{DT}"
    fi
    if grep -q '^'$1'[[:blank:]].*[[:blank:]]SETSTATE' $RESOURCES; then
      echo "Die Nachbearbeitung des Paketes '$PACKAGE' wurde auf $THISHOSTNAME beendet."
    elif grep -q '^'$1'[[:blank:]].*[[:blank:]]EXECUTE' $RESOURCES || [[ $RET = 3 ]]; then
      if [[ -n "$SIMULATE" ]]; then
        echo "Die Ausführung des Paketes '$PACKAGE' wurde auf $THISHOSTNAME simuliert."
      else
        echo "Das Paket '$PACKAGE' wurde auf $THISHOSTNAME ausgeführt."
      fi
    elif [[ -n "$SIMULATE" ]]; then
      echo "Der Start des Paketes '$PACKAGE' wurde auf $THISHOSTNAME simuliert."
    else
      echo "Das Paket '$PACKAGE' wurde auf $THISHOSTNAME gestartet."
    fi
    mv $LOGFILE ${LOGFILE%.*}
  elif [[ $RET -ne 1 ]]; then
    echo
    if [[ -n "$ULS" ]]; then
      FDATETIME=`date '+%Y-%m-%d %H:%M:%S'`
      send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "finished" $DATETIME  "$FDATETIME"     "{DT}"
      if [[ $RET = 3 ]]; then
        send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "message" $DATETIME "ERROR (Running)" "_"
        exit 0
      elif [[ $RET = 4 ]]; then
        send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "message" $DATETIME "Info ($inprogress)" "_"
      else
        send_test_value -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "message" $DATETIME "ERROR ($method)" "_"
        if which xz &>/dev/null; then
          xz -c "$LOGFILE" | send_stdin_file -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "logfile" $DATETIME "$LOGFILENAME.xz"
        else
          gzip -c "$LOGFILE" | send_stdin_file -h DOMAIN:$THISHOSTNAME:SCCL $CLUSTER Packages:$PACKAGE "logfile" $DATETIME "$LOGFILENAME.gz"
        fi
      fi
    fi
    if [[ "$RET" != "4" || -z "$IGNORESTARTING" ]]; then
      if grep -q '^'$1'[[:blank:]].*[[:blank:]]EXECUTE' $RESOURCES; then
        echo "${RETERROR}Das Paket '$PACKAGE' konnte nicht ausgeführt werden."
      else
        echo "${RETERROR}Das Paket '$PACKAGE' konnte nicht gestartet werden."
      fi
    fi
    if [[ -n "$RETVALUE" ]]; then
      echo "RETURNVALUE 1"
    fi
    mv $LOGFILE ${LOGFILE%.*}.err.$RET
    exit 1
  else
    # Paket läuft schon, dann Logfile löschen
    rm $LOGFILE
    exit 0
  fi
else
  # ist [<node>] angegeben? wenn ja, dann sccl_start auf $2 ausfuehren
  if [[ -n "$2" ]]; then
    NODE=$(tr '[:upper:]' '[:lower:]' <<<$2)
  else
    SINGLENODE=$(sed -n "s/^$1[[:blank:]][[:blank:]]*[+-]*[[:blank:]]*\\([^,[:blank:]]*\\)[[:blank:]]*\$/\\1/p" $PACKAGES)
    if [[ -z "$SINGLENODE" ]] && [[ -z "$(./sccl_my_packages $1)" ]]; then
      if grep -q '^'$1'[[:blank:]]' $PACKAGES; then
        echo "Das Paket $PACKAGE darf auf mehreren Knoten laufen, aber nicht auf diesem Knoten."
      else
        echo "Das paket $PACKAGE ist nicht definiert"
      fi
      exit 1
    fi
    NODE=${SINGLENODE:-$THISHOSTNAME}
  fi
  if [[ -n "$PIDSIG" && -w "$LOCKDIR" && ! -f "$LOCKDIR/${PACKAGE}_start_progress" ]]; then
    echo "$PIDSIG $NODE $$ CALLNODE" >>"$LOCKDIR/${PACKAGE}_start_progress"
  fi
  if [[ "$NODE" = "$THISHOSTNAME" ]]; then
    if callnode $NODE "sccl_node.s2w" | grep -q "$THISHOSTNAME"; then
      callnode $NODE "sccl_start$CALLEXT.s3w?paket=$1&force=$FORCE&norst=$SCCLNORST&node=$NODE&initignore=$SCCLINITIGNORE&startpars=$STARTPARS&initiated=${scclinitiated:-$THISHOSTNAME}&scclerrorflag=-R&pidsig=$PIDSIG&ignorestarting=$IGNORESTARTING" | sed '/^SCCL-Error/h;/^RETURNVALUE [12]/h;${x;/./{x;q1};x;q0}'
    elif [[ -r /etc/sccl/localadminpwd.dat ]]; then
      echo "Warnung: Kann keine Verbindung zum $NODE herstellen"
      ./sccl_start_bg $SIMULATE $FORCE $CALLPARS $1 THISNODE
    else
      echo 'Nur "root" oder User der Gruppe "sccl" können Pakete starten.'
    fi
  else
    callnode $NODE "sccl_start$CALLEXT.s3w?paket=$1&force=$FORCE&norst=$SCCLNORST&node=$NODE&initignore=$SCCLINITIGNORE&startpars=$STARTPARS&initiated=${scclinitiated:-$THISHOSTNAME}&scclerrorflag=-R&pidsig=$PIDSIG&ignorestarting=$IGNORESTARTING" | sed '/^SCCL-Error/h;/^RETURNVALUE [12]/h;${x;/./{x;q1};x;q0}'
  fi
  RET=$?
  [[ -n "$PIDSIG" && -f "$LOCKDIR/${PACKAGE}_start_progress" ]] && head -1 "$LOCKDIR/${PACKAGE}_start_progress" | grep -q "^$PIDSIG " && rm "$LOCKDIR/${PACKAGE}_start_progress"
  exit $RET
fi
