I have updated the synaccess stonith script, to support multiple synaccess devices and multiple power outlets with the
same name. This allows redundant power circuits to drive redundant power supplies in the cluster nodes. Because the
devices can now be chained together this should also simplify configuring large clusters.
This version also works around a couple of issues that have been discovered with the synaccess devices. More details
can be found in the appropriate sections (search for sleep) of the script.
Syntactically this version should be a drop in replacement for the previous version. The only difference is the ability
to specify more than one synaccess device in the ip list delimited by spaces or commas. This now matches the behavior of
some of the other stonith plug-ins.
The diff was quite large, so I again both attached and pasted the whole script
below.
#!/bin/bash
#
# External STONITH module for synaccess.
#
# Copyright (c) 2008 Gresham Enterprise Storage
# Jeremy Linton <[EMAIL PROTECTED]>
#
# 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.
#
#
#
# The original version only controlled a single synaccess device
# this version adds the ability to combine multiple devices to control larger
# clusters, or alternatively to have multiple synaccess devices on different
power
# circuits for redundant power supplies.
#
# This script requires a few things:
# net-snmp
# SYNACCESS-MIB.txt
# the hostnames that are controlled are placed in the "power outlet" "name"
field.
# The Synaccess device must have SNMP turned on
# The script must have the IP/Hostname of the synaccess device passed in via
"synaccessip"
#
# finally, if you are using multiple synaccess devices on different power
circuits plugged
# into redundant power ports, you can specify multiple IPs for the synaccessip
variable.
# Outlets with the same name on diffrent synaccess devices will be turned
on/off/reset in parallel.
# in order to use this script you must have installed the MIB that came with
the synaccess device
# in /usr/share/snmp/mibs/SYNACCESS-MIB.txt or similar. From then on the
net-snmp utilities
# are aware of the proper names.
# if you are having problems detecting the proper power status make sure the
mib power status reads:
#outletStatus OBJECT-TYPE
#SYNTAX INTEGER {
#off(0),
#on(1),
#off(2),
#on(257),
#off(256)
#}
# Check the synaccess specific mib with
# snmpwalk -c public -m SYNACCESS-MIB -v 1 x.x.x.x synAcc
# default to 5 seconds of sleep time after all the outlets have been turned off
# before we turn them back on
reset_delay=${reset_delay:-"5"}
# drop "public" in if the community isn't set
community=${community:-"public"}
# rewrite the ip list to accept , or space as a delimiter
synaccessip=`echo $synaccessip | tr ',' ' '`
# commands used to get/set snmp object id (oid) values
SNMP_GETCOMMAND="/usr/bin/snmpget -c $community -m SYNACCESS-MIB -v 1"
SNMP_SETCOMMAND="/usr/bin/snmpset -c $community -m SYNACCESS-MIB -v 1"
# pass the IP and then the name
get_snmp_value()
{
device_ip=$1
oid=$2
echo `$SNMP_GETCOMMAND $device_ip $oid 2>&1|cut -d: -f4`
}
# the port name given in the web interface must match the switched port number
# this discovers all the hostnames set as the outlet name
discover_hostlist()
{
synaccessdeviceip=$1
portcount=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::powerOutletNum.0`
for ((i=1; $i <= ${portcount:-"0"};i++)); do
portname=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::outletName.$i`
if [[ "$portname" && "$portname" != "Undefined" ]]; then
# only save unique host names
if [[ !("$hostlist" =~ "$portname ") ]]; then
hostlist="$hostlist$portname "
fi
fi
done
}
# this looks up the port number based on the passed hostname, using the power
outlet name
get_port_for_host()
{
synaccessdeviceip=$1
hostlookup=$2
portcount=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::powerOutletNum.0`
if [[ -z "$portcount" ]]; then
# device isn't responding
return 0
else
ret_code=2 #default to not finding any matching hosts on this device
for ((i=1; $i <= $portcount ;i++)); do
portname=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::outletName.$i`
if [[ "$portname" == "$hostlookup" ]]; then
echo "$i "
ret_code=1
fi
# the error handling leaves a possible race, if the device dies
while we are
# scanning the ports, we just assume the outlet isn't found, if
this happens
# and there is more than one synaccess device its possible we only
set the state
# for one power rail.
done
# if ret_code=2 everything was responding but we didn't find the
# named port assume it doesn't exist. It could be a configuration error,
# but we can't tell.
return $ret_code
fi
}
# this sends a ON/OFF/RESET action to the given hostname
do_port_action()
{
synaccessdeviceip=$1
controlledhost=$2
newportstate=$3
portnum=`get_port_for_host $synaccessdeviceip $controlledhost`
portret=$?
if [[ "$portret" == "1" ]]; then
for curport in $portnum ; do
out=`$SNMP_SETCOMMAND $synaccessdeviceip
"SYNACCESS-MIB::outletAction.$curport" = $newportstate`
# this sleep is here, because commands fired in rapid succession
don't always take affect, the
# snmp values get updated, but the device fails to internally
trigger on the change
sleep 1
#TODO check to see if port was successfuly set
done
fi
return $portret
}
# this takes the list of synaccess devices, and calls do_port_action for each
one
# this makes sure that if there are multiple synaccess devices with a
particular host plugged
# in all the outlets are set, this allows multiple circuit configurations
set_all_ports()
{
host_to_update=$1
new_port_state=$2
failed_to_set_all=0
set_atleast_one=0
for deviceip in $synaccessip ; do
do_port_action $deviceip $host_to_update $new_port_state
port_set_ok=$?
case $port_set_ok in
0)
# if any of the syanaccess devices fail, then assume
# that the whole operation failed, this is because we can never
# know if that device may still be providing power on a
redunant circuit to the
# machine
failed_to_set_all=1
;;
1)
set_atleast_one=1
;;
2)
# this device doesn't have a port configured with the given
hostname, ignore it
;;
esac
done
if [[ "$set_atleast_one" == "0" ]]; then
# none of the synaccess devices had a port with the given name
# fail the operation
failed_to_set_all=1
fi
return $failed_to_set_all
}
# Handle script commands
case $1 in
gethosts)
for deviceip in $synaccessip ; do
discover_hostlist $deviceip
done
for h in $hostlist ; do
echo $h
done
exit 0
;;
on)
set_all_ports $2 1
exit $?
;;
off)
set_all_ports $2 2
exit $?
;;
reset)
# The synaccess devices have a nice "reboot" function which
# turns the power off and after a configured length turns
# it back on. The only problem is that its really a power toggle
function.
# If the power is off, then it turns it on, and then back off
# So, before we use that function, we make sure that the power is
turned on
# (which in general it should be)
# BTW: the setting for the port delay is in the telnet menu, and not in
the
# web interface.
#set_all_ports $2 1
#set_all_ports $2 3
#
# For now the reboot seems to have to many side effects to be truly
useful
# instead lets just manually set it off/on
#
set_all_ports $2 2 # turn it off
# wait a few seconds for the power supplies to drain (some have pretty
long holdup times)
sleep $reset_delay
set_all_ports $2 1 # turn it on
exit $?
;;
status)
# if any of the given devices fail to responed then assume failure
for deviceip in $synaccessip ; do
portcount=`get_snmp_value $deviceip SYNACCESS-MIB::powerOutletNum.0`
if [[ -z $portcount ]]; then
exit 1
fi
done
exit 0
;;
getconfignames)
echo "synaccessip community"
exit 0
;;
getinfo-devid)
echo "synaccess"
exit 0
;;
getinfo-devname)
for deviceip in $synaccessip ; do
synModel=`get_snmp_value $deviceip SYNACCESS-MIB::systemModel.0`
synName=`get_snmp_value $deviceip SYNACCESS-MIB::systemName.0`
echo "Synaccess netBooter $synModel $synName"
done
exit 0
;;
getinfo-devdescr)
echo "synaccess netbooter STONITH device"
exit 0
;;
getinfo-devurl)
echo "http://www.synaccess-net.com"
exit 0
;;
getinfo-xml)
# Parameters (hostname, synaccess IP, synaccess port)
cat << SAXML
<parameters>
<parameter name="synaccessip" unique="1" required="1">
<content type="string" />
<shortdesc lang="en">SynaccessIp</shortdesc>
<longdesc lang="en">The IPs of the synaccess devices controlling the
hosts</longdesc>
</parameter>
<parameter name="community" unique="1" required="0">
<content type="string" />
<shortdesc lang="en">Community</shortdesc>
<longdesc lang="en">The SNMP Community string</longdesc>
</parameter>
</parameters>
SAXML
exit 0
;;
*)
exit 1
;;
esac
#!/bin/bash
#
# External STONITH module for synaccess.
#
# Copyright (c) 2008 Gresham Enterprise Storage
# Jeremy Linton <[EMAIL PROTECTED]>
#
# 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.
#
#
#
# The original version only controlled a single synaccess device
# this version adds the ability to combine multiple devices to control larger
# clusters, or alternatively to have multiple synaccess devices on different
power
# circuits for redundant power supplies.
#
# This script requires a few things:
# net-snmp
# SYNACCESS-MIB.txt
# the hostnames that are controlled are placed in the "power outlet" "name"
field.
# The Synaccess device must have SNMP turned on
# The script must have the IP/Hostname of the synaccess device passed in via
"synaccessip"
#
# finally, if you are using multiple synaccess devices on different power
circuits plugged
# into redundant power ports, you can specify multiple IPs for the synaccessip
variable.
# Outlets with the same name on diffrent synaccess devices will be turned
on/off/reset in parallel.
# in order to use this script you must have installed the MIB that came with
the synaccess device
# in /usr/share/snmp/mibs/SYNACCESS-MIB.txt or similar. From then on the
net-snmp utilities
# are aware of the proper names.
# if you are having problems detecting the proper power status make sure the
mib power status reads:
#outletStatus OBJECT-TYPE
#SYNTAX INTEGER {
#off(0),
#on(1),
#off(2),
#on(257),
#off(256)
#}
# Check the synaccess specific mib with
# snmpwalk -c public -m SYNACCESS-MIB -v 1 x.x.x.x synAcc
# default to 5 seconds of sleep time after all the outlets have been turned off
# before we turn them back on
reset_delay=${reset_delay:-"5"}
# drop "public" in if the community isn't set
community=${community:-"public"}
# rewrite the ip list to accept , or space as a delimiter
synaccessip=`echo $synaccessip | tr ',' ' '`
# commands used to get/set snmp object id (oid) values
SNMP_GETCOMMAND="/usr/bin/snmpget -c $community -m SYNACCESS-MIB -v 1"
SNMP_SETCOMMAND="/usr/bin/snmpset -c $community -m SYNACCESS-MIB -v 1"
# pass the IP and then the name
get_snmp_value()
{
device_ip=$1
oid=$2
echo `$SNMP_GETCOMMAND $device_ip $oid 2>&1|cut -d: -f4`
}
# the port name given in the web interface must match the switched port number
# this discovers all the hostnames set as the outlet name
discover_hostlist()
{
synaccessdeviceip=$1
portcount=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::powerOutletNum.0`
for ((i=1; $i <= ${portcount:-"0"};i++)); do
portname=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::outletName.$i`
if [[ "$portname" && "$portname" != "Undefined" ]]; then
# only save unique host names
if [[ !("$hostlist" =~ "$portname ") ]]; then
hostlist="$hostlist$portname "
fi
fi
done
}
# this looks up the port number based on the passed hostname, using the power
outlet name
get_port_for_host()
{
synaccessdeviceip=$1
hostlookup=$2
portcount=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::powerOutletNum.0`
if [[ -z "$portcount" ]]; then
# device isn't responding
return 0
else
ret_code=2 #default to not finding any matching hosts on this device
for ((i=1; $i <= $portcount ;i++)); do
portname=`get_snmp_value $synaccessdeviceip
SYNACCESS-MIB::outletName.$i`
if [[ "$portname" == "$hostlookup" ]]; then
echo "$i "
ret_code=1
fi
# the error handling leaves a possible race, if the device dies
while we are
# scanning the ports, we just assume the outlet isn't found, if
this happens
# and there is more than one synaccess device its possible we only
set the state
# for one power rail.
done
# if ret_code=2 everything was responding but we didn't find the
# named port assume it doesn't exist. It could be a configuration error,
# but we can't tell.
return $ret_code
fi
}
# this sends a ON/OFF/RESET action to the given hostname
do_port_action()
{
synaccessdeviceip=$1
controlledhost=$2
newportstate=$3
portnum=`get_port_for_host $synaccessdeviceip $controlledhost`
portret=$?
if [[ "$portret" == "1" ]]; then
for curport in $portnum ; do
out=`$SNMP_SETCOMMAND $synaccessdeviceip
"SYNACCESS-MIB::outletAction.$curport" = $newportstate`
# this sleep is here, because commands fired in rapid succession
don't always take affect, the
# snmp values get updated, but the device fails to internally
trigger on the change
sleep 1
#TODO check to see if port was successfuly set
done
fi
return $portret
}
# this takes the list of synaccess devices, and calls do_port_action for each
one
# this makes sure that if there are multiple synaccess devices with a
particular host plugged
# in all the outlets are set, this allows multiple circuit configurations
set_all_ports()
{
host_to_update=$1
new_port_state=$2
failed_to_set_all=0
set_atleast_one=0
for deviceip in $synaccessip ; do
do_port_action $deviceip $host_to_update $new_port_state
port_set_ok=$?
case $port_set_ok in
0)
# if any of the syanaccess devices fail, then assume
# that the whole operation failed, this is because we can never
# know if that device may still be providing power on a
redunant circuit to the
# machine
failed_to_set_all=1
;;
1)
set_atleast_one=1
;;
2)
# this device doesn't have a port configured with the given
hostname, ignore it
;;
esac
done
if [[ "$set_atleast_one" == "0" ]]; then
# none of the synaccess devices had a port with the given name
# fail the operation
failed_to_set_all=1
fi
return $failed_to_set_all
}
# Handle script commands
case $1 in
gethosts)
for deviceip in $synaccessip ; do
discover_hostlist $deviceip
done
for h in $hostlist ; do
echo $h
done
exit 0
;;
on)
set_all_ports $2 1
exit $?
;;
off)
set_all_ports $2 2
exit $?
;;
reset)
# The synaccess devices have a nice "reboot" function which
# turns the power off and after a configured length turns
# it back on. The only problem is that its really a power toggle
function.
# If the power is off, then it turns it on, and then back off
# So, before we use that function, we make sure that the power is
turned on
# (which in general it should be)
# BTW: the setting for the port delay is in the telnet menu, and not in
the
# web interface.
#set_all_ports $2 1
#set_all_ports $2 3
#
# For now the reboot seems to have to many side effects to be truly
useful
# instead lets just manually set it off/on
#
set_all_ports $2 2 # turn it off
# wait a few seconds for the power supplies to drain (some have pretty
long holdup times)
sleep $reset_delay
set_all_ports $2 1 # turn it on
exit $?
;;
status)
# if any of the given devices fail to responed then assume failure
for deviceip in $synaccessip ; do
portcount=`get_snmp_value $deviceip SYNACCESS-MIB::powerOutletNum.0`
if [[ -z $portcount ]]; then
exit 1
fi
done
exit 0
;;
getconfignames)
echo "synaccessip community"
exit 0
;;
getinfo-devid)
echo "synaccess"
exit 0
;;
getinfo-devname)
for deviceip in $synaccessip ; do
synModel=`get_snmp_value $deviceip SYNACCESS-MIB::systemModel.0`
synName=`get_snmp_value $deviceip SYNACCESS-MIB::systemName.0`
echo "Synaccess netBooter $synModel $synName"
done
exit 0
;;
getinfo-devdescr)
echo "synaccess netbooter STONITH device"
exit 0
;;
getinfo-devurl)
echo "http://www.synaccess-net.com"
exit 0
;;
getinfo-xml)
# Parameters (hostname, synaccess IP, synaccess port)
cat << SAXML
<parameters>
<parameter name="synaccessip" unique="1" required="1">
<content type="string" />
<shortdesc lang="en">SynaccessIp</shortdesc>
<longdesc lang="en">The IPs of the synaccess devices controlling the
hosts</longdesc>
</parameter>
<parameter name="community" unique="1" required="0">
<content type="string" />
<shortdesc lang="en">Community</shortdesc>
<longdesc lang="en">The SNMP Community string</longdesc>
</parameter>
</parameters>
SAXML
exit 0
;;
*)
exit 1
;;
esac
_______________________________________________________
Linux-HA-Dev: [email protected]
http://lists.linux-ha.org/mailman/listinfo/linux-ha-dev
Home Page: http://linux-ha.org/