summaryrefslogtreecommitdiffstats
path: root/lib/plugins/stonith/external/libvirt
diff options
context:
space:
mode:
Diffstat (limited to 'lib/plugins/stonith/external/libvirt')
-rw-r--r--lib/plugins/stonith/external/libvirt298
1 files changed, 298 insertions, 0 deletions
diff --git a/lib/plugins/stonith/external/libvirt b/lib/plugins/stonith/external/libvirt
new file mode 100644
index 0000000..494b048
--- /dev/null
+++ b/lib/plugins/stonith/external/libvirt
@@ -0,0 +1,298 @@
+#!/bin/sh
+#
+# External STONITH module for a libvirt managed hypervisor (kvm/Xen).
+# Uses libvirt as a STONITH device to control guest.
+#
+# Copyright (c) 2010 Holger Teutsch <holger.teutsch@web.de>
+#
+# 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.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+# start a domain
+libvirt_start() {
+ out=$($VIRSH -c $hypervisor_uri start $domain_id 2>&1)
+ if [ $? -eq 0 ]
+ then
+ ha_log.sh notice "Domain $domain_id was started"
+ return 0
+ fi
+
+ $VIRSH -c $hypervisor_uri dominfo $domain_id 2>&1 |
+ egrep -q '^State:.*(running|idle)|already active'
+ if [ $? -eq 0 ]
+ then
+ ha_log.sh notice "Domain $domain_id is already active"
+ return 0
+ fi
+
+ ha_log.sh err "Failed to start domain $domain_id"
+ ha_log.sh err "$out"
+ return 1
+}
+# reboot a domain
+# return
+# 0: success
+# 1: error
+libvirt_reboot() {
+ local rc out
+ out=$($VIRSH -c $hypervisor_uri reboot $domain_id 2>&1)
+ rc=$?
+ if [ $rc -eq 0 ]
+ then
+ ha_log.sh notice "Domain $domain_id was rebooted"
+ return 0
+ fi
+ ha_log.sh err "Failed to reboot domain $domain_id (exit code: $rc)"
+ ha_log.sh err "$out"
+ return 1
+}
+
+# stop a domain
+# return
+# 0: success
+# 1: error
+# 2: was already stopped
+libvirt_stop() {
+ out=$($VIRSH -c $hypervisor_uri destroy $domain_id 2>&1)
+ if [ $? -eq 0 ]
+ then
+ ha_log.sh notice "Domain $domain_id was stopped"
+ return 0
+ fi
+
+ $VIRSH -c $hypervisor_uri dominfo $domain_id 2>&1 |
+ egrep -q '^State:.*shut off|not found|not running'
+ if [ $? -eq 0 ]
+ then
+ ha_log.sh notice "Domain $domain_id is already stopped"
+ return 2
+ fi
+
+ ha_log.sh err "Failed to stop domain $domain_id"
+ ha_log.sh err "$out"
+ return 1
+}
+
+# get status of stonith device (*NOT* of the domain).
+# If we can retrieve some info from the hypervisor
+# the stonith device is OK.
+libvirt_status() {
+ out=$($VIRSH -c $hypervisor_uri version 2>&1)
+ if [ $? -eq 0 ]
+ then
+ return 0
+ fi
+
+ ha_log.sh err "Failed to get status for $hypervisor_uri"
+ ha_log.sh err "$out"
+ return 1
+}
+
+# check config and set variables
+# does not return on error
+libvirt_check_config() {
+ VIRSH=`which virsh 2>/dev/null`
+
+ if [ ! -x "$VIRSH" ]
+ then
+ ha_log.sh err "virsh not installed"
+ exit 1
+ fi
+
+ if [ -z "$hostlist" -o -z "$hypervisor_uri" ]
+ then
+ ha_log.sh err "hostlist or hypervisor_uri missing; check configuration"
+ exit 1
+ fi
+
+ case "$reset_method" in
+ power_cycle|reboot) : ;;
+ *)
+ ha_log.sh err "unrecognized reset_method: $reset_method"
+ exit 1
+ ;;
+ esac
+}
+
+# set variable domain_id for the host specified as arg
+libvirt_set_domain_id ()
+{
+ for h in $hostlist
+ do
+ case $h in
+ $1:*)
+ domain_id=`expr $h : '.*:\(.*\)'`
+ return
+ ;;
+
+ $1)
+ domain_id=$1
+ return
+ esac
+ done
+
+ ha_log.sh err "Should never happen: Called for host $1 but $1 is not in $hostlist."
+ exit 1
+}
+
+libvirt_info() {
+cat << LVIRTXML
+<parameters>
+<parameter name="hostlist" unique="1" required="1">
+<content type="string" />
+<shortdesc lang="en">
+List of hostname[:domain_id]..
+</shortdesc>
+<longdesc lang="en">
+List of controlled hosts: hostname[:domain_id]..
+The optional domain_id defaults to the hostname.
+</longdesc>
+</parameter>
+
+<parameter name="hypervisor_uri" required="1">
+<content type="string" />
+<shortdesc lang="en">
+Hypervisor URI
+</shortdesc>
+<longdesc lang="en">
+URI for connection to the hypervisor.
+driver[+transport]://[username@][hostlist][:port]/[path][?extraparameters]
+e.g.
+qemu+ssh://my_kvm_server.mydomain.my/system (uses ssh for root)
+xen://my_kvm_server.mydomain.my/ (uses TLS for client)
+
+virsh must be installed (e.g. libvir-client package) and access control must
+be configured for your selected URI.
+</longdesc>
+</parameter>
+
+<parameter name="reset_method" required="0">
+<content type="string" default="power_cycle"/>
+<shortdesc lang="en">
+How to reset a guest.
+</shortdesc>
+<longdesc lang="en">
+A guest reset may be done by a sequence of off and on commands
+(power_cycle) or by the reboot command. Which method works
+depend on the hypervisor and guest configuration management.
+</longdesc>
+</parameter>
+</parameters>
+LVIRTXML
+exit 0
+}
+
+#############
+# Main code #
+#############
+
+# don't fool yourself when testing with stonith(8)
+# and transport ssh
+unset SSH_AUTH_SOCK
+
+# support , as a separator as well
+hostlist=`echo $hostlist| sed -e 's/,/ /g'`
+
+reset_method=${reset_method:-"power_cycle"}
+
+case $1 in
+ gethosts)
+ hostnames=`echo $hostlist|sed -e 's/:[^ ]*//g'`
+ for h in $hostnames
+ do
+ echo $h
+ done
+ exit 0
+ ;;
+
+ on)
+ libvirt_check_config
+ libvirt_set_domain_id $2
+
+ libvirt_start
+ exit $?
+ ;;
+
+ off)
+ libvirt_check_config
+ libvirt_set_domain_id $2
+
+ libvirt_stop
+ [ $? = 1 ] && exit 1
+ exit 0
+ ;;
+
+ reset)
+ libvirt_check_config
+ libvirt_set_domain_id $2
+
+ if [ "$reset_method" = "power_cycle" ]; then
+ libvirt_stop
+ [ $? = 1 ] && exit 1
+ sleep 2
+ libvirt_start
+ else
+ libvirt_reboot
+ fi
+ exit $?
+ ;;
+
+ status)
+ libvirt_check_config
+ libvirt_status
+ exit $?
+ ;;
+
+ getconfignames)
+ echo "hostlist hypervisor_uri reboot_method"
+ exit 0
+ ;;
+
+ getinfo-devid)
+ echo "libvirt STONITH device"
+ exit 0
+ ;;
+
+ getinfo-devname)
+ echo "libvirt STONITH external device"
+ exit 0
+ ;;
+
+ getinfo-devdescr)
+ echo "libvirt-based host reset for Xen/KVM guest domain through hypervisor"
+ exit 0
+ ;;
+
+ getinfo-devurl)
+ echo "http://libvirt.org/uri.html http://linux-ha.org/wiki"
+ exit 0
+ ;;
+
+ getinfo-xml)
+ libvirt_info
+ echo 0;
+ ;;
+
+ *)
+ exit 1
+ ;;
+esac
+
+# vi:et:ts=4:sw=4