#!/bin/bash

########################################################################
#
#PROJECT:      Unified Sessions Manager
#AUTHOR:       Arno-Can Uestuensoez - acue@UnifiedSessionsManager.org
#MAINTAINER:   Arno-Can Uestuensoez - acue_sf1@sourceforge.net
#SHORT:        ctys
#CALLFULLNAME: Commutate To Your Session
#LICENCE:      GPL3
#VERSION:      01_02_007a17
#
########################################################################
#
# Copyright (C) 2007 Arno-Can Uestuensoez (UnifiedSessionsManager.org)
#
########################################################################

_myPKGNAMEBASH_SOURCE="${BASH_SOURCE}"
_myPKGVERSBASH_SOURCE="01.01.001a00"
hookInfoAdd $_myPKGNAMEBASH_SOURCE $_myPKGVERSBASH_SOURCE




#FUNCBEG###############################################################
#NAME:
#  stackerCancelPM
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  For native cancel. Calls before cancel itself the contained stack.
#
#EXAMPLE:
#
#PARAMETERS:
#  $1: METHOD:ARG
#  $2: <stack>
#  $3: ""|SELF
#GLOBALS:
#
#OUTPUT:
#  RETURN:
#  VALUES:
#
#FUNCEND###############################################################
function stackerCancelPM () {
    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "$FUNCTION:\$@=$@"

    local _METHOD=${1%:*}
    local _ARG=${1#*:}
    shift
    local _force=${1}
    shift
    local _self=${1}

    case $_METHOD in
	INIT)
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "ACTION-MODE=INIT"
	    if [ -z "$_force" ];then
		stackerCancelPropagate "STACK,INIT:${_ARG}";
	    fi
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "delay:${DEFAULT_KILL_DELAY_POWEROFF}"
	    sleep ${DEFAULT_KILL_DELAY_POWEROFF}
	    if [ -n "${_self}" ];then
		printWNG $LINENO $BASH_SOURCE ${ABORT} "INIT ${_ARG}"
		init ${_ARG}
	    fi
	    gotoHell 0
	    ;;

        REBOOT)
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "ACTION-MODE=REBOOT"
	    if [ -z "$_force" ];then
		stackerCancelPropagate "STACK,INIT:0";
	    fi
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "delay:${DEFAULT_KILL_DELAY_POWEROFF}"
	    sleep ${DEFAULT_KILL_DELAY_POWEROFF}
	    if [ -n "${_self}" ];then
		printWNG $LINENO $BASH_SOURCE ${ABORT} "REBOOT"
		reboot
	    fi
	    gotoHell 0
	    ;;

	RESET)
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "ACTION-MODE=RESET"
	    if [ -z "$_force" ];then
		stackerCancelPropagate "STACK,INIT:0";
	    fi
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "delay:${DEFAULT_KILL_DELAY_POWEROFF}"
	    sleep ${DEFAULT_KILL_DELAY_POWEROFF}
	    if [ -n "${_self}" ];then
		printWNG $LINENO $BASH_SOURCE ${ABORT} "RESET"
		init 6
	    fi
	    gotoHell 0
	    ;;

        PAUSE|S3)
	    printWNG $LINENO $BASH_SOURCE ${ABORT} "PAUSE-S3 not yet supported, mapped temporarily to S5"
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "ACTION-MODE=PAUSE-S3"
	    if [ -z "$_force" ];then
		stackerCancelPropagate "STACK,PAUSE";
	    fi
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "delay:${DEFAULT_KILL_DELAY_POWEROFF}"
	    sleep ${DEFAULT_KILL_DELAY_POWEROFF}
            #temporary halt
	    if [ -n "${_self}" ];then
		printWNG $LINENO $BASH_SOURCE ${ABORT} "PAUSE-S3 not yet supported, mapped to S5"
		halt -p
	    fi
	    gotoHell 0
	    ;;

        SUSPEND|S4)
	    printWNG $LINENO $BASH_SOURCE ${ABORT} "SUSPEND-S4 not yet supported, mapped temporarily to S5"
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "ACTION-MODE=SUSPEND-S4"
	    if [ -z "$_force" ];then
		stackerCancelPropagate "STACK,SUSPEND";
	    fi
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "delay:${DEFAULT_KILL_DELAY_POWEROFF}"
	    sleep ${DEFAULT_KILL_DELAY_POWEROFF}
            #temporary halt
	    if [ -n "${_self}" ];then
		printWNG $LINENO $BASH_SOURCE ${ABORT} "SUSPEND-S4 not yet supported, mapped to S5"
		halt -p
	    fi
	    gotoHell 0
	    ;;

        POWEROFF|S5)
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "ACTION-MODE=POWEROFF-S5"
	    if [ -z "$_force" ];then
		stackerCancelPropagate "STACK,INIT:0";
	    fi
  	    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "delay:${_ARG:-DEFAULT_KILL_DELAY_POWEROFF}"
 	    sleep ${_ARG:-$DEFAULT_KILL_DELAY_POWEROFF}
	    if [ -n "${_self}" ];then
		printWNG $LINENO $BASH_SOURCE ${ABORT} "POWEROFF-S5"
		halt -p
	    fi
	    gotoHell 0
	    ;;

	*)

	    ABORT=1;
	    printERR $LINENO $BASH_SOURCE ${ABORT} "Reached unexpected execution tracepoint"
	    printERR $LINENO $BASH_SOURCE ${ABORT} "'seems to be, that a suboption of cancel is missing????"
	    printERR $LINENO $BASH_SOURCE ${ABORT} "This might be an internal error???"
	    gotoHell ${ABORT}
	    ;;
    esac
}



#FUNCBEG###############################################################
#NAME:
#  cutCancelSessionPM
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Handles shutdown of PMs.
#
#  The current version controls the container instances and it's contents.
#  Here a PM will be managed with it's running entities, which could be 
#  handled as nested execution stack. Therefore containment hierarchies of 
#  PMs, and nested VMs - e.g. Xen and QEMU - will be handled.
#
#  This version is solely based on SW features provided by the OS, future versions
#  will utilize in an seamless escalation scenario HW equipment with external sitches
#  for power-supply and controlled hardware-reset by remote enforcement.
#
#EXAMPLE:
#
#PARAMETERS:
#
# Control enforcement scope and behaviour 
#  FORCE
#    Forces the execution of method, even though some thing might hang.
#
#  STACK
#    When provided the execution stack on current instance will be worked 
#    top-down, thus providing a proper and (almost?) reliable shutdown.
#
# Special methods, e.g. OS dependent
#  INIT:<target-init-state>
#    Will be mapped to unix init command, depends on specific UNIX variant. 
#
# Common methods
#  REBOOT
#    Performs a soft reboot.
#
#  RESET
#    Performs a hard reboot, which is currently an immediate command on 
#    current instance, therefore all VMs will be killed after a short 
#    timeout.
#
#  SUSPEND
#    Suspends both.
#
#  SUSPEND2D
#    Suspends to disk.
#
#  SUSPEND2R
#    Suspends to RAM.
#
#  POWEROFF
#    Switches the power off immediately.
#
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function cutCancelSessionPM () {
  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "${FUNCNAME}:$*"
  local OPMODE=$1;shift
  local ACTION=$1;shift

  function chkCtysVhost () {
      if [ $1 != 0 ];then
	  printERR $LINENO $BASH_SOURCE ${ABORT} "ctys-vhost ${CTRL_VERBOSE:+ -d $CTRL_VERBOSE} exit with error:$ret"
 	  gotoHell ${1}
      fi
  }


  #Killing server alone is senseless, so client else both is applicable.
  local _CSB=BOTH;

  local _behaviour=;
  local _i=;

  case ${OPMODE} in
      CHECKPARAM)
          #
          #Just check syntax drafts, the expansion of labels etc. could just be
          #expanded on target machine.
          #

          if [ -n "$CTRL_MODE_ARGS" ];then
              A=`echo ${CTRL_MODE_ARGS}|sed 's/,/ /g'`
              printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "PM($A)"

              #guarantee unambiguity
              local _unambig=0;
              local _unambigCSB=0;
              local _unambigCMD=0;
              for i in $A;do
		  KEY=`echo ${i%%:*}|tr '[:lower:]' '[:upper:]'`
		  ARG=${i#*:}
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "KEY=${KEY}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "ARG=<${ARG}>"
                  #handle keywords
                  if [ -n "${ARG}" \
		      -o -z "${ARG}" -a "${KEY}" == "CLIENT" \
		      -o -z "${ARG}" -a "${KEY}" == "SERVER" \
		      -o -z "${ARG}" -a "${KEY}" == "BOTH" \
                      -o -z "${ARG}" -a "${KEY}" == "S3" \
                      -o -z "${ARG}" -a "${KEY}" == "S4" \
		      -o -z "${ARG}" -a "${KEY}" == "S5" \
                      -o -z "${ARG}" -a "${KEY}" == "RESET" \
                      -o -z "${ARG}" -a "${KEY}" == "REBOOT" \
                      -o -z "${ARG}" -a "${KEY}" == "PAUSE" \
                      -o -z "${ARG}" -a "${KEY}" == "SUSPEND" \
 		      -o -z "${ARG}" -a "${KEY}" == "FORCE" \
		      -o -z "${ARG}" -a "${KEY}" == "STACK" \
		      -o -z "${ARG}" -a "${KEY}" == "SELF" \
		      -o -z "${ARG}" -a "${KEY}" == "ALL" \
		      -o -z "${ARG}" -a "${KEY}" == "NOCACHE" \
		      -o -z "${ARG}" -a "${KEY}" == "NOPOLL" \
                      ];then
		      case $KEY in


                     ##################################################
                     # Common control enforcement scope and behaviour #
                     ##################################################
			  FORCE)
                              local _force=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:FORCE"
			      ;;

			  STACK)
                              local _stack=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:STACK (DEFAULT)"
			      ;;

			  SELF)
                              local _self=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:SELF"
			      ;;

                     ##################
                     # Common methods #  
                     ##################
			  REBOOT)
                              local _reboot=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:REBOOT"
			      ;;
			  RESET)
                              local _reset=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:RESET"
			      ;;
			  PAUSE|S3)
                              local _pause=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:PAUSE-S3"
			      ;;
			  SUSPEND|S4)
                              local _suspend=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:SUSPEND-S4"
			      ;;
			  POWEROFF|S5)
                              local _powoff=1;
                              local _powoffdelay="${ARG}";
			      let _unambigCMD+=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:POWEROFF-S5 DELAY=${_powoffdelay}"
			      ;;

			  INIT)
                              local _init=1;
                              local _initstate="${ARG}";
			      let _unambigCMD+=1;
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:INIT=${_initstate}"
			      ;;


                     #####################
                     # <machine-address> #
                     #####################
			  NOCACHE)
			      local _cache=0;
			      printWNG $LINENO $BASH_SOURCE 0 "NOCACHE not yet implemented"
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "NOCACHE"
			      ;;
			  NOPOLL)
			      local _poll=0;
			      printWNG $LINENO $BASH_SOURCE 0 "NOPOLL not yet implemented"
			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "NOPOLL"
			      ;;



			  LABEL|L)#just for LIST of long-runner shutdown
                              local _label="${ARG}";
 			      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "RANGE:LABEL=${_label}"
			      let _unambig+=1;
			      ;;

			  BASEPATH|BASE|B|TCP|T|MAC|M|UUID|U|FILENAME|FNAME|F|ID|I|PATHNAME|PNAME|P)
			      ABORT=1;
			      printERR $LINENO $BASH_SOURCE ${ABORT} "Not applicable for PM:\"${KEY}\""
			      printERR $LINENO $BASH_SOURCE ${ABORT} "Execution scope is <execution-target>"
 			      gotoHell ${ABORT}
			      ;;

			  *)
			      ABORT=1;
			      printERR $LINENO $BASH_SOURCE ${ABORT} "Unknown sub-opt for PM:\"${KEY}\""
 			      gotoHell ${ABORT}
			      ;;
		      esac
                  else
		      ABORT=1;
		      printERR $LINENO $BASH_SOURCE ${ABORT} "Erroneous KEY:<${KEY}>"
 		      printERR $LINENO $BASH_SOURCE ${ABORT} "  Required syntax :<KEY>:<ARG>";
 		      printERR $LINENO $BASH_SOURCE ${ABORT} "  Given systax    :<${KEY}>:<${ARG}>";
 		      gotoHell ${ABORT}               
		  fi
	      done
          fi

#           if((_unambig!=1));then
# 	      ABORT=1;
# 	      printERR $LINENO $BASH_SOURCE ${ABORT} "Exactly one of the following sub-opts is required:"
# 	      printERR $LINENO $BASH_SOURCE ${ABORT} " (label|l)-(fname|f)-(pname|p)-(tcp|t)-(mac|m)-(uuid|u)"
#  	      gotoHell ${ABORT}
#           fi

          if [ -z "$_reboot" -a -z "$_init" -a -z "$_powoff" ];then
	      ABORT=1;
	      printERR $LINENO $BASH_SOURCE ${ABORT} "Missing: REBOOT|INIT|POWEROFF"
 	      gotoHell ${ABORT}
          fi

          if [ -n "$_force" -a -n "$_stack" ];then
	      ABORT=1;
	      printERR $LINENO $BASH_SOURCE ${ABORT} "Only one allowed: FORCE|STACK(default)"
 	      gotoHell ${ABORT}
          fi

          if((_reboot+_init+_powoff>1));then
	      ABORT=1;
	      printERR $LINENO $BASH_SOURCE ${ABORT} "Only one allowed: REBOOT|INIT|POWEROFF"
 	      gotoHell ${ABORT}
          fi
	  ;;


      ACTION)
	  if [ -n "${R_TEXT}" ];then
	      echo "${R_TEXT}"
	  fi
	  if [ -z "${CTRL_EXECLOCAL}" ];then
	      assembleExeccall
	  else
              #
              #Doing local semantical correctness evaluation now.
              #
              if [ -n "$CTRL_MODE_ARGS" ];then
		  A=`echo ${CTRL_MODE_ARGS}|sed 's/,/ /g'`
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "WMW($A)"

                  #guarantee unambiguity of EXOR: (label|l)  (fname|f)  (pname|p)
		  local _unambig=0;
		  for i in $A;do
		      KEY=`echo ${i}|awk -F':' '{print $1}'|tr '[:lower:]' '[:upper:]'`
		      ARG=`echo ${i}|awk -F':' '{print $2}'`

		      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "KEY=${KEY}";
		      printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "ARG=${ARG}";
                      #handle keywords
                      if [ -n "${ARG}" \
			  -o -z "${ARG}" -a "${KEY}" == "CLIENT" \
			  -o -z "${ARG}" -a "${KEY}" == "SERVER" \
			  -o -z "${ARG}" -a "${KEY}" == "BOTH" \
			  -o -z "${ARG}" -a "${KEY}" == "S3" \
			  -o -z "${ARG}" -a "${KEY}" == "S4" \
			  -o -z "${ARG}" -a "${KEY}" == "S5" \
			  -o -z "${ARG}" -a "${KEY}" == "RESET" \
			  -o -z "${ARG}" -a "${KEY}" == "REBOOT" \
			  -o -z "${ARG}" -a "${KEY}" == "PAUSE" \
			  -o -z "${ARG}" -a "${KEY}" == "SUSPEND" \
 			  -o -z "${ARG}" -a "${KEY}" == "FORCE" \
			  -o -z "${ARG}" -a "${KEY}" == "STACK" \
			  -o -z "${ARG}" -a "${KEY}" == "SELF" \
			  -o -z "${ARG}" -a "${KEY}" == "ALL" \
			  -o -z "${ARG}" -a "${KEY}" == "NOCACHE" \
			  -o -z "${ARG}" -a "${KEY}" == "NOPOLL" \
			  ];then
			  case $KEY in

                           #########
			      FORCE)
				  local _force=1;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:FORCE"
				  ;;

			      STACK)
				  local _stack=1;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:STACK (DEFAULT)"
				  ;;

			      SELF)
				  local _self=1;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:SELF"
				  ;;


                           #########
			      INIT)
				  _behaviour=INIT;
				  local _init=1;
				  local _initstate="${ARG}";
				  [ -n "${_initstate}" ]&&_behaviour="${_behaviour}:${_initstate}";
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:${_behaviour}"
				  ;;

                           #########
			      REBOOT)
				  _behaviour=REBOOT;
				  local _reboot=1;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:REBOOT"
				  ;;
			      RESET)
				  _behaviour=RESET;
				  local _reset=1;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:RESET"
				  ;;
			      PAUSE|S3)
				  _behaviour=PAUSE;
				  local _suspend=1;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:PAUSE-S3"
				  ;;
			      SUSPEND|S4)
				  _behaviour=SUSPEND;
				  local _suspend=1;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:SUSPEND-S4"
				  ;;
			      POWEROFF|S5)
				  _behaviour=POWEROFF;
				  local _powoff=1;
				  local _powoffdelay="${ARG}";
				  [ -n "${ARG}" ]&&_behaviour="$_behaviour:${ARG}";
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "MODE:POWEROFF-S5 DELAY=${_powoffdelay}"
				  ;;


                           #####################
                           # <machine-address> #
                           #####################
			      NOCACHE)
				  local _cache=0;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "NOCACHE"
				  ;;
			      NOPOLL)
				  local _poll=0;
				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "NOPOLL"
				  ;;


			      LABEL|L)
                                  local _label="${ARG}";
 				  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "RANGE:LABEL=${_label}"
				  ;;


			      *)
				  ABORT=1;
				  printERR $LINENO $BASH_SOURCE ${ABORT} "Unexpected sub-opts for PM:${KEY}"
 				  gotoHell ${ABORT}
				  ;;
			  esac
		      fi
		  done


		  printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "CombineParamaters"
#                   local _dbg1=${CTRL_VERBOSE:+ -d $CTRL_VERBOSE}
#                   local _chainedFilter="${_base} ${_pname} ${_uuid} ${_label} ${_fname} ${_mac} ${_tcp}" 
#                   _myIP=`${MYCALLPATH}/ctys-vhost ${CTRL_VERBOSE:+ -d $CTRL_VERBOSE} $_dbg1 -Y MACMAP -o TCP -p ${DBPATHLST} "${_chainedFilter}"`
# 		  chkCtysVhost $?

		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "----------------------"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "- Cancel sessions:"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "-  _force     = ${_force}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "----------------------"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "-  _reboot    = ${_reboot}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "-  _reset     = ${_reset}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "-  _suspend   = ${_suspend}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "-  _init      = ${_init} - ${_initstate}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "-  _powoff    = ${_powoff} - ${_powoffdelay}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "----------------------"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "-  _behaviour = ${_behaviour}"
		  printVerboseDebug ${DBG_LVL_UID} $LINENO $BASH_SOURCE "----------------------"




              ###########################
               #    So, ... let's go!    #
              ###########################

		stackerCancelPM "${_behaviour}" "${_force}" "${_self}"; 
	      fi
	  fi
	  ;;
  esac

}


