#!/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)
#
########################################################################

_myPKGNAME_XEN_SESSION="${BASH_SOURCE}"
_myPKGVERS_XEN_SESSION="01.01.001a00"
hookInfoAdd $_myPKGNAME_XEN_SESSION $_myPKGVERS_XEN_SESSION
_myPKGBASE_XEN_SESSION="`dirname ${_myPKGNAME_XEN_SESSION}`"

_XEN_SESSION="${_myPKGNAME_XEN_SESSION}"

_VNC_CLIENT_MODE=;


#FUNCBEG###############################################################
#NAME:
#  fetchXenDomID4Label
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Onyl applicable on execution target
#
#EXAMPLE:
#
#PARAMETERS:
#  $1: LABEL
#
#OUTPUT:
#  RETURN:
#  VALUES:
#    <DomU-ID>
#
#FUNCEND###############################################################
function fetchXenDomID4Label () {
    local _x=`callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} domid $1`
    local _ret=$?
    echo ${_x//[^0-9]/}
    return $_ret
}


#FUNCBEG###############################################################
#NAME:
#  noClientServerSplitSupportedMessageXEN
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#
#OUTPUT:
#  RETURN:
#  VALUES:
#
#FUNCEND###############################################################
function noClientServerSplitSupportedMessageXEN () {
    printWNG $LINENO $BASH_SOURCE ${ABORT} "INFO:This message Should not occur."
}


#FUNCBEG###############################################################
#NAME:
#  expandSessionIDXEN
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function expandSessionIDXEN () {
  echo $1
}



#FUNCBEG###############################################################
#NAME:
#  getClientTPXEN
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
# GENERIC-IF-DESCRIPTION:
#  Gives the termination points port number, to which a client could be 
#  attachhed. This port is forseen to be used in port-forwarding e.g.
#  by OpenSSH.
#
#  The port is the local port number, which in general has to be mapped 
#  on remote site, when already in use. Therefore the application has
#  to provide a port-number-independent client access protocol in order 
#  to be used by connection forwarding. In any other case display 
#  forwarding has to be choosen.
#
#  Some applications support only one port for access by multiple 
#  sessions, dispatching and bundling the communications channels
#  by their own protocol. 
#
#  While others require for each channel a seperate litenning port.
#
#  So it is up to the specific package to support a function returning 
#  the required port number which could be used to attach an forwarded 
#  port. 
#  
#  The applications client has to support a remapped port number.
#
#EXAMPLE:
#
#PARAMETERS:
#  $1: <label>
#       The <label> to which the client will be attached.
#
#  $2: <pname>
#      The pname of the configuration file, this is required for 
#      VNC-sessions, and given to avoid scanning for labels
#
#OUTPUT:
#  RETURN:
#    0: If OK
#    1: else
#
#  VALUES:
#    <TP-port>
#      The TP port, to which a client could be attached.
#
#FUNCEND###############################################################
function getClientTPXEN () {
    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "$FUNCNAME:\$@=$@"
    local _port=;

    _port=`listMySessionsXEN S MACHINE|awk -F';' -v l="${_label}" '$1~l{print $7;}'`
    if [ -z "${_port}" ];then
	_port="NO-CPORT"
    fi
    local _ret=$_port;  
    printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "$FUNCNAME port number=$_ret from ID=_port"
    echo ${_ret}
}



#FUNCBEG###############################################################
#NAME:
#  startSessionXEN
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
# $1: label
#     For legacy reasons of inherited code, in case of Xen, Xen itself
#     requires UNIQUE(scope=node+) DomainName=LABEL to be preconfigured
#     in config file(pname), so must not differ!!!
#
# $2: ID/pname
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function startSessionXEN () {
  local _label=$1
  local _pname=$2
  local _console=${3:-VNC}
  printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "${FUNCNAME}:LABEL=$_label"
  printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "${FUNCNAME}:PNAME=$_pname"
  printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "${FUNCNAME}:CONSOLE=$_console"

  #should not happen, anyhow, once again, check it
  if [ -z "${_label}" ];then
      ABORT=1
      printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Missing LABEL"
      gotoHell ${ABORT}
  fi

  #should not happen, anyhow, once again, check it
  if [ -z "${_pname}" ];then
      ABORT=1
      printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Missing PNAME"
      gotoHell ${ABORT}
  fi


  case ${XEN_MAGIC} in
      XEN_303) #verified to work
	  ;;
      XEN_3x)
	  printWNG $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:This version is not yet tested, but any version \"3.x\" might work."
	  printWNG $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:  XEN_VERSTRING = ${XEN_VERSTRING}"
	  printWNG $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:  XEN_MAGIC     = ${XEN_MAGIC}"
	  ;;
      *)
	  printWNG $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:This version is not yet tested, you cannot really expect it to work properly."
	  printWNG $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:  XEN_VERSTRING = ${XEN_VERSTRING}"
	  printWNG $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:  XEN_MAGIC     = ${XEN_MAGIC}"
	  ;;
  esac


  #set appropriate DomU call
  if [ "${CTRL_ASYNC}" == 1 ];then
      CALLER="${XENCALL} ${XM} create \"${_pname}\""
  else
      case $_console in
	  CLI)
	      CALLER="${XENCALL} ${XM} create -c \"${_pname}\""
	      ;;
	  *)
	      CALLER="${XENCALL} ${XM} create \"${_pname}\""
	      ;;
      esac

  fi

  #check for backgound execution when locally called, without ssh.
  if [ "${CTRL_ASYNC}" == 1 ];then
      if [ "${CTRL_CLIENTLOCATION}" ==  "-L ConnectionForwarding" \
          -o "${CTRL_CLIENTLOCATION}" ==  "-L LocalOnly" \
 	  ];then
	  CALLER="${CALLER} &"
      fi
  fi

  #bring up the DomU now
  printVerboseDebug ${DBG_LVL_UIE} $LINENO $BASH_SOURCE "ENABLE DomU:${CALLER}"
  printVerboseDebug ${DBG_LVL_UIE} $LINENO $BASH_SOURCE "TERM=${TERM}"

  [ -z "${CTRL_NOEXEC}" ]&&eval ${CALLER} 

  if [ "$_console" == "CLI" ];then
      return
  fi

  #anyhow, let's do it in any case - for now
  if [ "${CTRL_ASYNC}" == 1 ];then
      sleep ${XEN_CONSOLE_DOMU_INIT_WAIT}
  fi


  #if no client required
  if [ "${CTRL_CLIENTLOCATION}" ==  "-L ServerOnly" ];then
      return
  fi


  #now check for console
  #assuming that combination check for options has been validated!
  local _args1=;
  _args1="${_args1} ${CTRL_VERBOSE:+ -d $CTRL_VERBOSE} "
  _args1="${_args1} ${CTRL_ASYNC:+ -b $CTRL_ASYNC} "
  _args1="${_args1} ${CTRL_GEOMETRY:+ -g $CTRL_GEOMETRY} "
  _args1="${_args1} ${CTRL_XTOOLKITOPTS} "
  local _args=;
  case $_console in
      GTERM)
	  _args=" -t X11 -a create=l:${_label},cmd:gnome-terminal,dh"
	  _args="${_args},c:\\\"${XENCALL// /%}%${XM}%console%`fetchXenDomID4Label ${_label}`\\\" ${_args1}"
	  ;;
      XTERM)
	  _args=" -t X11 -a create=l:${_label},cmd:xterm,sh"
	  _args="${_args},c:${XENCALL// /%}%${XM}%console%`fetchXenDomID4Label ${_label}` ${_args1}"
	  ;;
      VNC)
	  MYVNCPORT=`${MYCALLPATH}/ctys -t xen -a list=label,cport|awk -F';' -v l=${_label} '$1==l{print $2;}'`
	  printVerboseDebug ${DBG_LVL_UIE} $LINENO $BASH_SOURCE "MYVNCPORT=${MYVNCPORT}"
	  _args=" -t VNC -a create=l:${_label},v:${MYVNCPORT},connect  ${_args1}"
	  ;;
      *)
	  ABORT=1
	  printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Unexpected CONSOLE:${_console}"
	  gotoHell ${ABORT}
	  ;;
  esac

  CALLER="${MYCALLPATH}/ctys ${_args}"

  printVerboseDebug ${DBG_LVL_UIE} $LINENO $BASH_SOURCE "Attach CONSOLE:${CALLER}"
  [ -z "${CTRL_NOEXEC}" ]&&eval ${CALLER} 
}



#FUNCBEG###############################################################
#NAME:
#  connectSessionXEN
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  This function is the plugins local connection wrapper.
#  The basic decisions from where the connection is established and 
#  to which peer it has to be connected is done before calling this.
#  But some knowledge of the connection itself is still required here.
#
#  So "the wrapper is in close relation to the controller", it is his  
#  masters not so stupid paladin.
#
#EXAMPLE:
#
#PARAMETERS:
#  $1: <console-type> could be
#      CLI|X11|VNC
#
#  $2: <session-label>
#      This will be used for the title of the client window.
#
#  $3: <session-id>
#      This is the absolute pathname to the vmx-file.
#
#  $4: <actual-access-id>
#      This will be used for actual connection, when direct acces to
#      a ip port is provided. 
#
#
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function connectSessionXEN () {
  local _contype=${1}
  local _label=${2}
  local _id=${3}
  local _actaccessID=${4}

  printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "$FUNCNAME ${_contype} ${_label} ${_id} ${_actaccessID}"

  if [ -z "${_id}" -o -z "${_label}" ];then
      ABORT=1
      printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:At least one parameter required:<session-id> or <session-label>"
      gotoHell ${ABORT}
  fi


  local _args=;
  local _args1=;
  _args1="${_args1} ${CTRL_VERBOSE:+ -d $CTRL_VERBOSE} "
  _args1="${_args1} ${CTRL_ASYNC:+ -b $CTRL_ASYNC} "
  _args1="${_args1} ${CTRL_GEOMETRY:+ -g $CTRL_GEOMETRY} "
  _args1="${_args1} ${CTRL_ALLOWAMBIGIOUS+ -A $CTRL_ALLOWAMBIGIOUS} "
  _args1="${_args1} ${CTRL_XTOOLKITOPTS} "


  #
  #local native access: same as DisplayForwarding or LocalOnly
  #
  case $_contype in
      CLI)
	  ${XENCALL} ${XM} console `fetchXenDomID4Label ${_label}`
	  ;;
      GTERM)
	  _args="${_args} -t X11 -a create=l:${_label},cmd:gnome-terminal,dh"
 	  _args="${_args},c:${XENCALL// /%}%${XM}%console%`fetchXenDomID4Label ${_label}`"
          _args="${MYCALLPATH}/ctys ${_args} ${_args1} "
	  printVerboseDebug ${DBG_LVL_UIE} $LINENO $BASH_SOURCE "_args=${_args}"
	  ${_args}
	  ;;
      XTERM)
	  _args="${_args} -t X11 -a create=l:${_label},cmd:xterm,sh,c:${XENCALL// /%}%${XM}%console%`fetchXenDomID4Label ${_label}`"
          _args="${MYCALLPATH}/ctys ${_args} ${_args1} "
	  printVerboseDebug ${DBG_LVL_UIE} $LINENO $BASH_SOURCE "_args=${_args}"
	  ${_args}
	  ;;
      VNC)
	  if [ -n "${_actaccessID}" ];then
#timeout>>!20
#	      _args=" -t VNC -a create=l:${_label},v:${_actaccessID},connect ${_args}"
#	      _args=" -t VNC -a create=l:${_label},v:${_actaccessID},connect ${_args}"
#              _args="${MYCALLPATH}/ctys ${_args} ${_args1} "
#	      ${_args}
 	      connectSessionXENVNC "${_actaccessID}" "${_label}" 
	  else
	      ABORT=1
	      printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Missing _actaccessID:${_actaccessID}"
	      gotoHell ${ABORT}
	  fi
	  ;;
      *)
	  ABORT=1
	  printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Unknown CONSOLE:${_contype}"
	  gotoHell ${ABORT}
	  ;;
  esac
}




#FUNCBEG###############################################################
#NAME:
#  vmMgrXEN
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#  Encapsulates the vmrun command with unified calls.
#
#EXAMPLE:
#
#PARAMETERS:
# $1:                 $2       $3                        
#---------------------------------------------------------------------
# REBOOT              <label> <id-pname>                 => virsh  reboot
# RESET               <label> <id-pname>                 => virsh  reboot
# PAUSE               <label> <id-pname>                 => virsh  suspend
# SUSPEND             <label> <id-pname>  <statefile>    => virsh  save 
# POWEROFF            <label> <id-pname>  <timeout>      => virsh  shutdown+destroy
#
# RESUME              <label> <id-pname>  [<statefile>]  => virsh  reboot
#
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function vmMgrXEN () {
    printVerboseDebug ${DBG_LVL_UIE} $LINENO $BASH_SOURCE "${FUNCNAME} $*"
    local _cmd=$1;shift
    local _label=$1;shift
    local _id=$1;shift
    local _arg=$1;shift

    if [ -z "${_cmd}" ];then
	ABORT=1
	printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Missing CMD"
	gotoHell ${ABORT}
    fi
    if [ -z "${_label}" ];then
	ABORT=1
	printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Missing LABEL"
	gotoHell ${ABORT}
    fi
    if [ -z "${_id}" ];then
	ABORT=1
	printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Missing ID"
	gotoHell ${ABORT}
    fi



    case $_cmd in
        #CREATE######################
	RESUME)
            if [ -z "${CTRL_NOEXEC}" ];then
		if [ -n "${_arg}" ];then
		    callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} "restore" "${_arg}"
		else
		    callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} "resume" "$_label"
		fi
	    fi
	    ;;


        #CANCEL######################
	SUSPEND)
            if [ -z "${CTRL_NOEXEC}" ];then
		callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} "save" "$_label" "${_arg}"
	    fi
	    ;;

	PAUSE)
            if [ -z "${CTRL_NOEXEC}" ];then
		callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} "suspend" "$_label"
	    fi
	    ;;

	REBOOT|RESET)
            if [ -z "${CTRL_NOEXEC}" ];then
		callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} "reboot" "$_label"
	    fi
	    ;;
	POWEROFF)
            if [ -z "${CTRL_NOEXEC}" ];then
		callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} "shutdown" "$_label"
		sleep ${_arg:-1}
		callErrOutWrapper $LINENO $BASH_SOURCE  ${VIRSHCALL} ${VIRSH} "destroy" "$_label"

	    fi

            ;;
    esac
}




#FUNCBEG###############################################################
#NAME:
#  connectSessionXENVNC
#
#TYPE:
#  bash-function
#
#DESCRIPTION:
#
#EXAMPLE:
#
#PARAMETERS:
#  $1: <display-id>|<display-port>
#      This is calculated from the port, and is the offset to that.
#      The base-value is normally 5900 for RealVNC+TIghtVNC.
#      TightVNC might allow the selection of another port.
#
#  $2: <session-label>
#      This will be used for the title of the client window.
#
#OUTPUT:
#  RETURN:
#
#  VALUES:
#
#FUNCEND###############################################################
function connectSessionXENVNC () {
  local _id=${1}
  local _label=${2}
  printVerboseDebug ${DBG_LVL_MAINT} $LINENO $BASH_SOURCE "$FUNCNAME ${_id} ${_label}"


  #even though this condition might be impossible now, let it beeeee ...
  if [ -z "${_label}" -a -z "${_id}" ];then
    ABORT=1
    printERR $LINENO $BASH_SOURCE ${ABORT} "${FUNCNAME}:Fetch of peer entry failed:_id=${_id} - _label=${_label}"
    gotoHell ${ABORT}
  fi

  printVerboseDebug ${DBG_LVL_OVERKILL} $LINENO $BASH_SOURCE "OK:_id=${_id} - _label=${_label}"
  #
  #Now shows name+id in title, id could not be set for server as default.
  local _vieweropt="-name ${_label}:${_id} ${VNCVIEWER_OPT} ${CTRL_GEOMETRY:+ -geometry=$CTRL_GEOMETRY} "

  #old version with server-default label in title
  #  local _vieweropt="${VNCVIEWER_OPT} ${CTRL_GEOMETRY:+ -geometry=$CTRL_GEOMETRY} "
  local CALLER="${VNCVIEWER} ${CTRL_VERBOSE:+ -d $CTRL_VERBOSE} ${_vieweropt} :${_id}"
  printVerboseDebug ${DBG_LVL_OVERKILL} $LINENO $BASH_SOURCE "${CALLER}"
  export CTRL_ASYNC;
  [ -z "${CTRL_NOEXEC}" ]&&eval ${CALLER}
}




