diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain index 7dd66de21..baf565a1f 100644 --- a/heartbeat/VirtualDomain +++ b/heartbeat/VirtualDomain @@ -1,212 +1,267 @@ #!/bin/sh # # Support: linux-ha@lists.linux-ha.org # License: GNU General Public License (GPL) # # Resource Agent for domains managed by the libvirt API. # Requires a running libvirt daemon (libvirtd), except when running # in a Xen Domain-0 and specifying xen:/// as the hypervisor URL. # # usage: $0 {start|stop|status|monitor|meta-data} # # TODO: when properly supported by libvirt, this RA should include # support for domain live migration and implement the # migrate-to and migrate-from operations. # ####################################################################### # Initialization: . ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs LC_ALL="C" LANG="C" # Defaults : ${OCF_RESKEY_force_stop=0} ####################################################################### usage() { echo "usage: $0 {start|stop|status|monitor|meta-data|validate-all}" } meta_data() { cat < 1.0 Resource agent for a virtual domain (a.k.a. domU, virtual machine, virtual environment etc., depending on context) managed by libvirtd. Manages virtual domains Absolute path to the libvirt configuration file, for this virtual domain. virtual domain configuration file Hypervisor URI to connect to. See the libvirt documentation for details on supported URI formats. The default is system dependent. Hypervisor URI Forcefully shut down ("destroy") the domain on stop. Enable this only if your virtual domain (or your virtualization backend) does not support graceful shutdown. Force shutdown on stop + + + +To additionally monitor services within the virtual domain, add this +parameter with a list of scripts to monitor. + +Note: when monitor scripts are used, the start operation will complete +only when all monitor scripts have completed successfully. Be sure to +set the timeout of your start operation to accommodate this delay. + +space-separated list of monitor scripts + + + - + EOF } +# Set options to be passed to virsh: +# +# if OCF_RESKEY_hypervisor is set, add the --connect option. +# Otherwise, omit it so virsh connects to libvirt's +# system-dependent default hypervisor. +if [ -n "$OCF_RESKEY_hypervisor" ]; then + VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor}" +fi +VIRSH_OPTIONS="${VIRSH_OPTIONS} --quiet" + VirtualDomain_Define() { - DOMAIN_NAME="$(virsh ${VIRSH_OPTIONS} define ${OCF_RESKEY_config} | sed -e 's/Domain \(.*\) defined from .*$/\1/')" \ - || return $OCF_ERR_GENERIC + # Note: passing in the domain name from outside the script is + # intended for testing and debugging purposes only. Don't do this + # in production, instead let the script figure out the domain name + # from the config file. You have been warned. + if [ -z "$DOMAIN_NAME" ]; then + DOMAIN_NAME="$(virsh ${VIRSH_OPTIONS} define ${OCF_RESKEY_config} | sed -e 's/Domain \(.*\) defined from .*$/\1/')" \ + || return $OCF_ERR_GENERIC + else + ocf_log warn "Domain name ${DOMAIN_NAME} already defined, overriding configuration file ${OCF_RESKEY_config}. You should do this for testing only." + fi } VirtualDomain_Status() { rc=$OCF_ERR_GENERIC status="`virsh $VIRSH_OPTIONS domstate $DOMAIN_NAME`" case $status in "shut off") rc=$OCF_NOT_RUNNING ;; running|paused|blocked) rc=$OCF_SUCCESS ;; esac ocf_log debug "Virtual domain $DOMAIN_NAME is currently $status." return $rc } VirtualDomain_Start() { if VirtualDomain_Status ${DOMAIN_NAME}; then ocf_log info "Virtual domain $DOMAIN_NAME already running." return $OCF_SUCCESS fi virsh $VIRSH_OPTIONS start ${DOMAIN_NAME} rc=$? if [ $rc -ne 0 ]; then ocf_log error "Failed to start virtual domain ${DOMAIN_NAME}." return $OCF_ERR_GENERIC fi while sleep 1; do - VirtualDomain_Status && return $OCF_SUCCESS + VirtualDomain_Monitor && return $OCF_SUCCESS done } VirtualDomain_Stop() { if VirtualDomain_Status ${DOMAIN_NAME}; then case $OCF_RESKEY_force_stop in [Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) op="destroy" ;; *) op="shutdown" ;; esac virsh $VIRSH_OPTIONS $op ${DOMAIN_NAME} while sleep 1; do VirtualDomain_Status if [ $? -eq $OCF_NOT_RUNNING ]; then return $OCF_SUCCESS fi done else ocf_log info "Domain $DOMAIN_NAME already stopped." return $OCF_SUCCESS fi } +VirtualDomain_Monitor() { + # First, check the domain status. If that returns anything other + # than $OCF_SUCCESS, something is definitely wrong. + VirtualDomain_Status ${DOMAIN_NAME} + rc=$? + if [ ${rc} -eq ${OCF_SUCCESS} ]; then + # OK, the generic status check turned out fine. Now, if we + # have monitor scripts defined, run them one after another. + for script in ${OCF_RESKEY_monitor_scripts}; do + script_output="$($script 2>&1)" + script_rc=$? + if [ ${script_rc} -ne ${OCF_SUCCESS} ]; then + # A monitor script returned a non-success exit + # code. Stop iterating over the list of scripts, log a + # warning message, and propagate $OCF_ERR_GENERIC. + ocf_log warn "Monitor command \"${script}\" for domain ${DOMAIN_NAME} returned ${script_rc} with output: ${script_output}" + rc=$OCF_ERR_GENERIC + break + else + ocf_log debug "Monitor command \"${script}\" for domain ${DOMAIN_NAME} completed successfully with output: ${script_output}" + fi + done + fi + return ${rc} +} + VirtualDomain_Validate_All() { # Required binaries: for binary in virsh sed; do check_binary $binary done if [ -z $OCF_RESKEY_config ]; then ocf_log error "Missing configuration parameter \"config\"." return $OCF_ERR_CONFIGURED fi # check if we can read the config file (otherwise we're unable to # deduce $DOMAIN_NAME from it, see below) if [ ! -r $OCF_RESKEY_config ]; then ocf_log error "Configuration file $OCF_RESKEY_config does not exist or is not readable." return $OCF_ERR_CONFIGURED fi } if [ $# -ne 1 ]; then usage exit $OCF_ERR_ARGS fi case $1 in meta-data) meta_data exit $OCF_SUCCESS ;; usage) usage exit $OCF_SUCCESS ;; esac # Everything except usage and meta-data must pass the validate test VirtualDomain_Validate_All || exit $? -# Set options to be passed to virsh: -# -# if OCF_RESKEY_hypervisor is set, add the --connect option. -# Otherwise, omit it so virsh connects to libvirt's -# system-dependent default hypervisor. -if [ -n "$OCF_RESKEY_hypervisor" ]; then - VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor}" -fi -VIRSH_OPTIONS="${VIRSH_OPTIONS} --quiet" - # Define the domain on startup, and re-define (harmlessly) # on every invocation. This also sets DOMAIN_NAME. If this fails, # bail out. VirtualDomain_Define || exit $? case $1 in - start) VirtualDomain_Start - ;; - stop) VirtualDomain_Stop - ;; - monitor|status) VirtualDomain_Status ${DOMAIN_NAME} - ;; - validate-all) - ;; - *) usage - exit $OCF_ERR_UNIMPLEMENTED - ;; + start) + VirtualDomain_Start + ;; + stop) + VirtualDomain_Stop + ;; + status) + VirtualDomain_Status + ;; + monitor) + VirtualDomain_Monitor + ;; + validate-all) + ;; + *) + usage + exit $OCF_ERR_UNIMPLEMENTED + ;; esac exit $?