diff options
Diffstat (limited to '')
-rw-r--r-- | lib/plugins/stonith/external/xen0 | 253 | ||||
-rwxr-xr-x | lib/plugins/stonith/external/xen0-ha-dom0-stonith-helper | 72 | ||||
-rwxr-xr-x | lib/plugins/stonith/external/xen0-ha.in | 96 |
3 files changed, 421 insertions, 0 deletions
diff --git a/lib/plugins/stonith/external/xen0 b/lib/plugins/stonith/external/xen0 new file mode 100644 index 0000000..ef1ee40 --- /dev/null +++ b/lib/plugins/stonith/external/xen0 @@ -0,0 +1,253 @@ +#!/bin/sh +# +# External STONITH module for Xen Dom0 through ssh. +# +# Description: Uses Xen Dom0 Domain as a STONITH device +# to control DomUs. +# +# +# Author: Serge Dubrouski (sergeyfd@gmail.com) +# Inspired by Lars Marowsky-Bree's external/ssh agent. +# +# Copyright 2007 Serge Dubrouski <sergeyfd@gmail.com> +# License: GNU General Public License (GPL) +# + +STOP_COMMAND="xm destroy" +START_COMMAND="xm create" +DUMP_COMMAND="xm dump-core" +DEFAULT_XEN_DIR="/etc/xen" +SSH_COMMAND="/usr/bin/ssh -q -x -n" + +# Rewrite the hostlist to accept "," as a delimeter for hostnames too. +hostlist=`echo $hostlist | tr ',' ' '` + +CheckIfDead() { + for j in 1 2 3 4 5 + do + if ! ping -w1 -c1 "$1" >/dev/null 2>&1 + then + return 0 + fi + sleep 1 + done + + return 1 +} + +CheckHostList() { + if [ "x" = "x$hostlist" ] + then + ha_log.sh err "hostlist isn't set" + exit 1 + fi +} + +CheckDom0() { + if [ "x" = "x$dom0" ] + then + ha_log.sh err "dom0 isn't set" + exit 1 + fi +} + +RunCommand() { + CheckHostList + CheckDom0 + + for h in $hostlist + do + CIFS=$IFS + IFS=: + read node cfg << -! +$h +-! + IFS=$CIFS + + if [ "x" = "x$node" ] + then + ha_log.sh err "Syntax error in host list" + exit 1 + fi + + if [ "x" = "x$cfg" ] + then + cfg="${DEFAULT_XEN_DIR}/${node}.cfg" + fi + + if [ "$node" != "$1" ] + then + continue + fi + + case $2 in + stop) + kill_node=`$SSH_COMMAND $dom0 "grep ^[[:space:]]*name $cfg" | cut -f 2 -d '=' | sed -e 's,",,g'` + if [ "x" = "x$kill_node" ] + then + ha_log.sh err "Couldn't find a node name to stop" + exit 1 + fi + + if [ "x$run_dump" != "x" ] + then + #Need to run core dump + if [ "x$dump_dir" != "x" ] + then + #Dump with the specified core file + TIMESTAMP=`date +%Y-%m%d-%H%M.%S` + DOMAINNAME=`printf "%s" $kill_node` + COREFILE=$dump_dir/$TIMESTAMP-$DOMAINNAME.core + $SSH_COMMAND $dom0 "(mkdir -p $dump_dir; $DUMP_COMMAND $kill_node $COREFILE) >/dev/null 2>&1" + else + $SSH_COMMAND $dom0 "$DUMP_COMMAND $kill_node >/dev/null 2>&1" + fi + fi + $SSH_COMMAND $dom0 "(sleep 2; $STOP_COMMAND $kill_node) >/dev/null 2>&1 &" + break;; + start) + $SSH_COMMAND $dom0 "(sleep 2; $START_COMMAND $cfg) >/dev/null 2>&1 &" + break;; + esac + exit 0 + done +} + + +# Main code + +case $1 in +gethosts) + CheckHostList + + for h in $hostlist ; do + CIFS=$IFS + IFS=: + read node cfg << -! +$h +-! + IFS=$CIFS + + echo $node + done + exit 0 + ;; +on) + RunCommand $2 start + exit $? + ;; +off) + if RunCommand $2 stop + then + if CheckIfDead $2 + then + exit 0 + fi + fi + + exit 1 + ;; +reset) + RunCommand $2 stop + + if CheckIfDead $2 + then + RunCommand $2 start + exit 0 + fi + + exit 1 + ;; +status) + CheckHostList + + for h in $hostlist + do + CIFS=$IFS + IFS=: + read node cfg << -! +$h +-! + IFS=$CIFS + + echo $node + if ping -w1 -c1 "$node" 2>&1 | grep "unknown host" + then + exit 1 + fi + done + exit 0 + ;; +getconfignames) + echo "hostlist dom0" + exit 0 + ;; +getinfo-devid) + echo "xen0 STONITH device" + exit 0 + ;; +getinfo-devname) + echo "xen0 STONITH external device" + exit 0 + ;; +getinfo-devdescr) + echo "ssh-based host reset for Xen DomU trough Dom0" + echo "Fine for testing, but not really suitable for production!" + exit 0 + ;; +getinfo-devurl) + echo "http://openssh.org http://www.xensource.com/ http://linux-ha.org/wiki" + exit 0 + ;; +getinfo-xml) + cat << SSHXML +<parameters> +<parameter name="hostlist" unique="1" required="1"> +<content type="string" /> +<shortdesc lang="en"> +Hostlist +</shortdesc> +<longdesc lang="en"> +The list of controlled nodes in a format node[:config_file]. +For example: "node1:/opt/xen/node1.cfg node2" +If config file isn't set it defaults to /etc/xen/{node_name}.cfg +</longdesc> +</parameter> +<parameter name="dom0" unique="1" required="1"> +<content type="string" /> +<shortdesc lang="en"> +Dom0 +</shortdesc> +<longdesc lang="en"> +Name of the Dom0 Xen node. Root user shall be able to ssh to that node. +</longdesc> +</parameter> +<parameter name="run_dump" unique="0" required="0"> +<content type="string" /> +<shortdesc lang="en"> +Run dump-core +</shortdesc> +<longdesc lang="en"> +If set plugin will call "xm dump-core" before killing DomU +</longdesc> +</parameter> +<parameter name="dump_dir" unique="1" required="0"> +<content type="string" /> +<shortdesc lang="en"> +Run dump-core with the specified directory +</shortdesc> +<longdesc lang="en"> +This parameter can indicate the dump destination. +Should be set as a full path format, ex.) "/var/log/dump" +The above example would dump the core, like; +/var/log/dump/2009-0316-1403.37-domU.core +</longdesc> +</parameter> +</parameters> +SSHXML + exit 0 + ;; +*) + exit 1 + ;; +esac diff --git a/lib/plugins/stonith/external/xen0-ha-dom0-stonith-helper b/lib/plugins/stonith/external/xen0-ha-dom0-stonith-helper new file mode 100755 index 0000000..b313f8b --- /dev/null +++ b/lib/plugins/stonith/external/xen0-ha-dom0-stonith-helper @@ -0,0 +1,72 @@ +#!/bin/bash +# Author: Lars Marowsky-Bree +# +# Copyright 2008 Lars Marowsky-Bree +# License: GNU General Public License (GPL) + +# This is not an external/stonith plugin by itself, but instead a helper +# script which gets installed in Dom0. + +# TODO: +# - Error handling +# - How to handle if the DomU resource doesn't exist? +# - Does this truly work with split-brain? +# - Is the handling of non-existent resources adequate? +# ... +# Basically: more testing. This is proof-of-concept and works, but deserves +# validation. + +CMD="$1" +DOMU="$2" +TIMEOUT="$3" + +# Make sure the timeout is an integer: +if [ "0$TIMEOUT" -eq 0 ]; then + TIMEOUT=300 +fi + +SetTargetRole() { + local new_role="$1" + crm_resource -r $DOMU --meta -p target_role -v $new_role + + local timeout="$TIMEOUT" + + # We only need to wait for "stopped". + if [ "$new_role" != "stopped" ]; then + return 0 + fi + + while [ $timeout -gt 0 ]; do + local rc + crm_resource -W -r $DOMU 2>&1 | grep -q "is NOT running" + rc=$? + if [ $rc -eq 0 ]; then + return 0 + fi + timeout=$[timeout-1]; + sleep 1 + done + return 1 +} + + +case $CMD in +on) SetTargetRole started + exit $? + ;; +off) SetTargetRole stopped + exit $? + ;; +reset) SetTargetRole stopped || exit 1 + SetTargetRole started + exit $? + ;; +status) exit 0 + ;; +*) ha_log.sh err "Called with unknown command: $CMD" + exit 1 + ;; +esac + +exit 1 + diff --git a/lib/plugins/stonith/external/xen0-ha.in b/lib/plugins/stonith/external/xen0-ha.in new file mode 100755 index 0000000..cb42cbc --- /dev/null +++ b/lib/plugins/stonith/external/xen0-ha.in @@ -0,0 +1,96 @@ +#!/bin/bash +# +# This STONITH script integrates a cluster running within DomUs +# with the CRM/Pacemaker cluster running in Dom0. +# +# Author: Lars Marowsky-Bree +# Copyright: 2008 Lars Marowsky-Bree +# License: GNU General Public License (GPL) +# + +SSH_COMMAND="@SSH@ -q -x -n" +HVM_HELPER="@stonith_plugindir@/xen0-ha-dom0-stonith-helper" + +# Rewrite the hostlist to accept "," as a delimeter for hostnames too. +hostlist=`echo $hostlist | tr ',' ' '` + +# Runs a command on the host, waiting for it to return +RunHVMCommand() { + $SSH_COMMAND $dom0_cluster_ip "$HVM_HELPER $1 $2 $stop_timeout" +} + +# Main code +case $1 in +gethosts) + echo $hostlist + exit 0 + ;; +on|off|reset|status) + RunHVMCommand $1 $2 + exit $? + ;; +getconfignames) + echo "hostlist dom0_cluster_ip timeout" + exit 0 + ;; +getinfo-devid) + echo "xen0-ha DomU/Dom0 device" + exit 0 + ;; +getinfo-devname) + echo "xen0-ha DomU/Dom0 external device" + exit 0 + ;; +getinfo-devdescr) + echo "Allows STONITH to control DomUs managed by a CRM/Pacemaker Dom0." + echo "Requires Xen + CRM/Pacemaker at both layers." + echo "Proof-of-concept code!" + exit 0 + ;; +getinfo-devurl) + echo "http://linux-ha.org/wiki/DomUClusters" + exit 0 + ;; +getinfo-xml) + cat << SSHXML +<parameters> +<parameter name="hostlist" unique="1" required="1"> +<content type="string" /> +<shortdesc lang="en"> +Hostlist +</shortdesc> +<longdesc lang="en"> +The list of controlled DomUs, separated by whitespace. +These must be configured as Xen RA resources with a name with a matching +id. +For example: "xen-1 xen-2 xen-3" +</longdesc> +</parameter> +<parameter name="dom0_cluster_ip" unique="1" required="1"> +<content type="string" /> +<shortdesc lang="en"> +Dom0 cluster ip +</shortdesc> +<longdesc lang="en"> +The cluster IP address associated with Dom0. +Root user must be able to ssh to that node. +</longdesc> +</parameter> +<parameter name="stop_timeout"> +<content type="integer" /> +<shortdesc lang="en"> +Stop timeout +</shortdesc> +<longdesc lang="en"> +The timeout, in seconds, for which to wait for Dom0 to report that the +DomU has been stopped, before aborting with a failure. +</longdesc> +</parameter> +</parameters> +SSHXML + exit 0 + ;; +*) + exit 1 + ;; +esac |