#!/bin/sh
#
# AIP-Linux - Version: 1.1 -  2009.05.27 10:30 H.E - heartbeat 2.1.3
# External STONITH module using IPMI.
# This modules uses uses the ipmitool program available from 
# http://ipmitool.sf.net/ for actual communication with the 
# managed device. 
#
# Copyright (c) 2007 Martin Bene <martin.bene@icomedias.com>
# 
# This program is free software; you can redistribute it and/or modify
# it under the terms of version 2 of the GNU General Public License as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it would be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# Further, this software is distributed without any warranty that it is
# free of the rightful claim of any third person regarding infringement
# or the like.  Any license provided herein, whether implied or
# otherwise, applies only to this software file.  Patent licenses, if
# any, provided herein do not apply to combinations of this program with
# other software, or any other product whatsoever.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write the Free Software Foundation,
# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
#

IPMIENV='ha.env'

USER=`id -un 2> /dev/null`
LHOST=`uname -n`
OPTION=$@
LOGDATE=`date +%Y%m%d-%H:%M:%S`
SERVICEDIR=/var/opt/aip_ha/lock
SERVICEFILE=ipmi.service
AIP_HA_LOG=/var/opt/aip_ha/log/ipmi.log
MSGFILE=/var/opt/aip_ha/message/ipmi_$$.msg

printf "%s P:%5s U:%s %7s +++++ %s ++++++++++++++++++++++++++++\n" ${LOGDATE} $$ ${USER} "${OPTION}" $0 >> ${AIP_HA_LOG}


if [ -f /etc/ha.d/ipmi.cfg ]; then
  if [ -z "${ipaddr}" -o -z "${userid}" -o -z "${passwd}" ]; then
   . /etc/ha.d/ipmi.cfg
   IPMIENV='ipmi.cfg'
   
  fi
else
  writelog - "exit:${STATE} ERROR: /etc/ha.d/ipmi.cfg environment file MISSING" >> ${AIP_HA_LOG}
fi


RESET="power reset"
POWEROFF="power off"
POWERON="power on"
STATUS="power status"
IPMITOOL=`which ipmitool 2>/dev/null`

writelog()
{
 printf "%s P:%5s U:%s %7s [%s] %s %s \n" ${LOGDATE} $$ ${USER} ${OPTION} $1 "$2" >> ${AIP_HA_LOG}
 #printf "PID:%5s [%s] %s \n" $$ $1 "$2"
}

writemsg()
{
 printf "%s P:%5s U:%s %7s [%s] ...... write message \n" ${LOGDATE} $$ ${USER} ${OPTION} $1  >> ${AIP_HA_LOG}
 printf "%s - %s P:%5s U:%s %7s [%s] %s \n" ${LHOST} ${LOGDATE} $$ ${USER} ${OPTION} $1 "$2"  >> ${MSGFILE}
}

endlog()
{
 printf "%s P:%5s U:%s %7s ---- exit: %s ------------------------------------------ \n" \
 ${LOGDATE} $$ ${USER} "${OPTION}" $1 $2 >> ${AIP_HA_LOG}
}

write_service()
{
 if [ ! -d ${SERVICEDIR} ]; then
   mkdir ${SERVICEDIR}; chown ubis:ubis ${SERVICEDIR}
 fi
 touch ${SERVICEDIR}/${SERVICEFILE}
 writelog $1 "exit:${STATE} UBIS Servicemode for IPMI activated"
}


function have_ipmi() {
	test -x "${IPMITOOL}"
}

function do_ipmi() {
	have_ipmi || {
		echo "ipmitool not installed"
		return 1
	}
	if [ -z "${ipaddr}" -o -z "${userid}" -o -z "${passwd}" ]; then
		echo "ipaddr, userid or password missing; check configuration"
		return 1
	fi

        if [ "${LHOST}" ==  "${hostname}" ]; then
          writelog - "cmd: ${IPMITOOL} ${1}"
	  ${IPMITOOL} ${1} || {
		echo "error executing ipmi command"
		return 1
                }
        else
          writelog - "cmd: ${IPMITOOL} -I lan -H ${ipaddr} -U ${userid} -P xxxxx ${1}"
	  ${IPMITOOL} -I lan -H ${ipaddr} -U ${userid} -P ${passwd} ${1} || {
		echo "error executing ipmi command"
		return 1
	        }
        fi
}


list_local_fail()
{
cl_status hbstatus >/dev/null 2>&1
if [ $? = 0 ]; then
  STATE=0
  LOC_RESURCES=`crm_resource -Ql | tr '*' ' ' | grep ipmi`
  LOC_HOST_ID=`crmadmin -N | grep $HOSTNAME | cut -d "(" -f2 | tr -d ")"`
  for LOC_RES in ${LOC_RESURCES}
  do
    FEHLCNT=`cibadmin -Q | grep fail-c | grep ${LOC_HOST_ID} | grep ${LOC_RES} | awk ' BEGIN{ FS="value=" } {print $2}' | tr -d '"/>' | cut -d " " -f1`
    if [ -z ${FEHLCNT} ]; then
      FEHLCNT=0
      writelog $1 "exit:${STATE} IPMI ${LOC_RES} heartbeat local fail-count:>${FEHLCNT}<"
    else
      writelog $1 "exit:${STATE} IPMI ${LOC_RES} heartbeat local fail-count:>${FEHLCNT}<"
    fi
  done
fi
}

cleanup_resource()
{
cl_status hbstatus >/dev/null 2>&1
if [ $? = 0 ]; then
  STATE=0
  LOC_RESURCES=`crm_resource -Ql | tr '*' ' ' | grep ipmi`
  LOC_HOST_ID=`crmadmin -N | grep $HOSTNAME | cut -d "(" -f2 | tr -d ")"`
  for LOC_RES in ${LOC_RESURCES}
  do
    crm_resource -C -r ${LOC_RES} -H ${HOSTNAME} && STATE=0
    writelog $1 "exit:${STATE} IPMI heartbeat clean up resource >${LOC_RES}<"
    writelog $1 "       -> crm_resource -C -r ${LOC_RES} -H ${HOSTNAME} "
  done
  else
    STATE=0
    writelog $1 "exit:${STATE} IPMI heartbeat is not running"
fi
}


reset_local_fail()
{
cl_status hbstatus >/dev/null 2>&1
if [ $? = 0 ]; then
  STATE=0
  LOC_RESURCES=`crm_resource -Ql | tr '*' ' ' | grep ipmi`
  LOC_HOST_ID=`crmadmin -N | grep $HOSTNAME | cut -d "(" -f2 | tr -d ")"`
  for LOC_RES in ${LOC_RESURCES}
  do
    FEHL=`cibadmin -Q | grep fail-c | grep ${LOC_HOST_ID} | grep ${LOC_RES} | wc -l`
    if [ "${FEHL}" -gt 0 ]; then
      STATE=1
      FEHLCNT=`cibadmin -Q | grep fail-c | grep ${LOC_HOST_ID} | grep ${LOC_RES} | awk ' BEGIN{ FS="value=" } {print $2}' | tr -d '"/>' | cut -d " " -f1`
      crm_failcount -r ${LOC_RES} -U ${HOSTNAME} -D && STATE=0
      writelog $1 "exit:${STATE} IPMI heartbeat local resource >${LOC_RES}< fail-count:>${FEHLCNT}< - reset"
    else
      writelog $1 "exit:${STATE} IPMI heartbeat local resource >${LOC_RES}< fail-count:>${FEHL} no reset"
    fi
  done
else
  STATE=0
  writelog $1 "exit:${STATE} IPMI heartbeat is not running"
fi
}


# Rewrite the hostname to accept "," as a delimeter for hostnames too.
hostname=`echo ${hostname} | tr ',' ' '`

case ${1} in
gethosts)
	for h in ${hostname} ; do
		echo ${h}
	done
        endlog 0
	exit 0
	;;
on)
	res=1
	for h in ${hostname}; do
		if [ "${h}" != "${2}" ]; then
			continue
		fi
                writelog U "IP:${ipaddr} USER:${userid} IPMIHOST:${hostname} ENV:${IPMIENV} CMD:${POWERON}"
		do_ipmi "${POWERON}"
		res=$?
	done
        endlog ${res}
	exit ${res}
	;;
off)
        if [ -f ${SERVICEDIR}/${SERVICEFILE} ]; then
           writelog S "exit:${STATE} Servicemode for IPMI is activ - do nothing" 
        else
          res=0
          writelog R "IP:${ipaddr} USER:${userid} ENV:${IPMIENV} CMD:${RESET}"
	  for h in ${hostname}; do
		  if [ "${h}" != "${2}" ]; then
                    writelog R "IPMIHOST:${h} != >${2}<"
		    continue
		  fi
                  writelog D "IP:${ipaddr} USER:${userid} IPMIHOST:${hostname} ENV:${IPMIENV} CMD:${POWEROFF}"
                  sync
                  sleep 5
		  do_ipmi "${POWEROFF}"
		  res=$?
	  done
          endlog ${res}
	  exit ${res}
        fi
	;;
reset)
        if [ -f ${SERVICEDIR}/${SERVICEFILE} ]; then
           writelog S "exit:${STATE} Servicemode for IPMI is activ - do nothing" 
        else
	  res=0
          writelog R "IP:${ipaddr} USER:${userid} ENV:${IPMIENV} CMD:${RESET}"
	  for h in ${hostname}; do
		  if [ "${h}" != "${2}" ]; then
                    writelog R "IPMIHOST:${h} != >${2}<"
		    continue
		  fi
                  writelog R "IP:${ipaddr} USER:${userid} IPMIHOST:${hostname} ENV:${IPMIENV} CMD:${RESET}"
                  sync
                  sleep 5
		  do_ipmi "${RESET}"
		  res=$?
	  done
          endlog ${res}
	exit $res
        fi
	;;
status)
        writelog S "IP:${ipaddr} USER:${userid} IPMIHOST:${hostname} ENV:${IPMIENV} CMD:${STATUS}"
	do_ipmi "${STATUS}"
        EXITSTATE=$?
        list_local_fail S
        endlog ${EXITSTATE}
	exit ${EXITSTATE}
	;;

resetc)
        reset_local_fail R
        endlog 0
	exit 0
        ;;
cleanup)
        cleanup_resource C
        endlog 0
	exit 0
        ;;

service)
        write_service S
        endlog 0
	exit 0
        ;;

service-off)
        if [ -f ${SERVICEDIR}/${SERVICEFILE} ]; then
          rm ${SERVICEDIR}/${SERVICEFILE}
          writelog O "exit:- Servicemode for IPMI removed"
        fi
        endlog 0
	exit 0
        ;;

getconfignames)
	for i in hostname ipaddr userid passwd; do
		echo $i
	done
	exit 0
	;;
getinfo-devid)
	echo "IPMI STONITH device"
        endlog 0
	exit 0
	;;
getinfo-devname)
	echo "IPMI STONITH external device"
        endlog 0
	exit 0
	;;
getinfo-devdescr)
	echo "IPMI-based host reset"
        endlog 0
	exit 0
	;;
getinfo-devurl)
	echo "http://ipmitool.sf.net/"
        endlog 0
	exit 0
	;;
getinfo-xml)
	cat << IPMIXML
<parameters>
<parameter name="hostname" unique="1">
<content type="string" />
<shortdesc lang="en">
Hostname
</shortdesc>
<longdesc lang="en">
The name of the host to be managed by this STONITH device
</longdesc>
</parameter>

<parameter name="ipaddr" unique="1">
<content type="string" />
<shortdesc lang="en">
IP Address
</shortdesc>
<longdesc lang="en">
The IP address of the STONITH device
</longdesc>
</parameter>

<parameter name="userid" unique="1">
<content type="string" />
<shortdesc lang="en">
Login
</shortdesc>
<longdesc lang="en">
The username used for logging in to the STONITH device
</longdesc>
</parameter>

<parameter name="passwd" unique="1">
<content type="string" />
<shortdesc lang="en">
Password
</shortdesc>
<longdesc lang="en">
The password used for logging in to the STONITH device
</longdesc>
</parameter>
</parameters>
IPMIXML
        endlog 0
	exit 0
	;;
*)
        OPTION='!!!!'
        writelog X "exit:1 fehlende Uebergabe"
        echo "usage: $0 {on|off|reset|status|resetc|cleanup|service|service-off|getconfignames|getinfo-devid|getinfo-devname|getinfo-devdescr|getinfo-devurl|getinfo-xml}"
        endlog 1
	exit 1
	;;
esac
