#!/bin/sh
#
# 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.
#

# Initialization -- fix locale settings so we can parse output from
# binaries if we need it
LANG=C
LC_ALL=C

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

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

# Wrapper function for ipmitool that sets the correct host IP address,
# username, and password, and invokes ipmitool with any arguments
# passed in
run_ipmitool() {
	have_ipmi || {
		ha_log.sh err "ipmitool not installed"
		return 1
	}
	if [ -z "${ipaddr}" -o -z "${userid}" -o -z "${passwd}" ]; then
		ha_log.sh err "ipaddr, userid or passwd missing; check configuration"
		return 1
	fi

	if [ -z "${interface}" ]; then
		# default to "lan" interface
		interface="lan"
	fi

	action="$*"

	${IPMITOOL} -I ${interface} -H ${ipaddr} -U "${userid}" -P "${passwd}" ${action} 2>&1
}

# Yet another convenience wrapper that invokes run_ipmitool, captures
# its output, logs the output, returns either 0 (on success) or 1 (on
# any error)
do_ipmi() {
	if outp=`run_ipmitool $*`; then
		ha_log.sh debug "ipmitool output: `echo $outp`"
		return 0
	else
		ha_log.sh err "error executing ipmitool: `echo $outp`"
		return 1
	fi
}

# Check if the managed node is powered on. To do so, issue the "power
# status" command. Should return either "Chassis Power is on" or
# "Chassis Power is off".
ipmi_is_power_on() {
	local outp
	outp=`run_ipmitool ${STATUS}`
	case "${outp}" in
	    *on)
		return 0
		;;
	    *off)
		return 1
		;;
	esac
}


# Rewrite the hostname to accept "," as a delimeter for hostnames too.

case ${1} in
gethosts)
	echo $hostname
	exit 0
	;;
on)
	do_ipmi "${POWERON}"
	exit
	;;
off)
	do_ipmi "${POWEROFF}"
	exit
	;;
reset)
	if ipmi_is_power_on; then
		do_ipmi "${RESET}"
	else
		do_ipmi "${POWERON}"
	fi
	exit
	;;
status)
	# "status" reflects the status of the stonith _device_, not
	# the managed node. Hence, only check if we can contact the
	# IPMI device with "power status" command, don't pay attention
	# to whether the node is in fact powered on or off.
	do_ipmi "${STATUS}"
	exit $?
	;;
getconfignames)
	for i in hostname ipaddr userid passwd interface; do
		echo $i
	done
	exit 0
	;;
getinfo-devid)
	echo "IPMI STONITH device"
	exit 0
	;;
getinfo-devname)
	echo "IPMI STONITH external device"
	exit 0
	;;
getinfo-devdescr)
	echo "ipmitool based power management. Apparently, the power off"
	echo "method of ipmitool is intercepted by ACPI which then makes"
	echo "a regular shutdown. If case of a split brain on a two-node"
	echo "it may happen that no node survives. For two-node clusters"
	echo "use only the reset method."
	exit 0
	;;
getinfo-devurl)
	echo "http://ipmitool.sf.net/"
	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>

<parameter name="interface" unique="1">
<content type="string" default="lan"/>
<shortdesc lang="en">
IPMI interface
</shortdesc>
<longdesc lang="en">
IPMI interface to use, such as "lan" or "lanplus".
</longdesc>
</parameter>

</parameters>
IPMIXML
	exit 0
	;;
*)
	exit 1
	;;
esac
