Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F7609313
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/heartbeat/VirtualDomain b/heartbeat/VirtualDomain
index baf565a1f..d4ac6cba8 100644
--- a/heartbeat/VirtualDomain
+++ b/heartbeat/VirtualDomain
@@ -1,267 +1,319 @@
#!/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.
+# Requires a running libvirt daemon (libvirtd).
#
-# 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.
+# usage: $0 {start|stop|status|monitor|migrate_to|migrate_from|meta-data|validate-all}
#
#######################################################################
# Initialization:
. ${OCF_ROOT}/resource.d/heartbeat/.ocf-shellfuncs
LC_ALL="C"
LANG="C"
# Defaults
-: ${OCF_RESKEY_force_stop=0}
-#######################################################################
+OCF_RESKEY_force_stop_default=0
+OCF_RESKEY_hypervisor_default="$(virsh --quiet uri)"
+: ${OCF_RESKEY_force_stop=${OCF_RESKEY_force_stop_default}}
+: ${OCF_RESKEY_hypervisor=${OCF_RESKEY_hypervisor_default}}
+#######################################################################
usage() {
- echo "usage: $0 {start|stop|status|monitor|meta-data|validate-all}"
+ echo "usage: $0 {start|stop|status|monitor|migrate_to|migrate_from|meta-data|validate-all}"
}
meta_data() {
cat <<EOF
<?xml version="1.0"?>
<!DOCTYPE resource-agent SYSTEM "ra-api-1.dtd">
<resource-agent name="VirtualDomain">
<version>1.0</version>
<longdesc lang="en">
Resource agent for a virtual domain (a.k.a. domU, virtual machine,
virtual environment etc., depending on context) managed by libvirtd.
</longdesc>
<shortdesc lang="en">Manages virtual domains</shortdesc>
<parameters>
<parameter name="config" unique="1" required="1">
<longdesc lang="en">
Absolute path to the libvirt configuration file,
for this virtual domain.
</longdesc>
-<shortdesc lang="en">virtual domain configuration file</shortdesc>
+<shortdesc lang="en">Virtual domain configuration file</shortdesc>
<content type="string" default="" />
</parameter>
-<parameter name="hypervisor" unique="0" required="0">
+<parameter name="hypervisor" unique="1" required="0">
<longdesc lang="en">
Hypervisor URI to connect to. See the libvirt documentation for
details on supported URI formats. The default is system dependent.
</longdesc>
<shortdesc lang="en">Hypervisor URI</shortdesc>
-<content type="string"/>
+<content type="string" default="${OCF_RESKEY_hypervisor_default}"/>
</parameter>
-<parameter name="force_stop" unique="0" required="0">
+<parameter name="force_stop" unique="1" required="0">
<longdesc lang="en">
Forcefully shut down ("destroy") the domain on stop. Enable this only if
your virtual domain (or your virtualization backend) does not support
graceful shutdown.
</longdesc>
<shortdesc lang="en">Force shutdown on stop</shortdesc>
-<content type="boolean" default="0" />
+<content type="boolean" default="${OCF_RESKEY_force_stop_default}" />
+</parameter>
+
+<parameter name="migration_transport" unique="1" required="0">
+<longdesc lang="en">
+Transport used to connect to the remote hypervisor while
+migrating. Please refer to the libvirt documentation for details on
+transports available. If this parameter is omitted, the resource will
+use libvirt's default transport to connect to the remote hypervisor.
+</longdesc>
+<shortdesc lang="en">Remote hypervisor transport</shortdesc>
+<content type="string" default="" />
</parameter>
<parameter name="monitor_scripts" unique="0" required="0">
<longdesc lang="en">
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.
+Note: when monitor scripts are used, the start and migrate_from operations
+will complete only when all monitor scripts have completed successfully.
+Be sure to set the timeout of these operations to accommodate this delay.
</longdesc>
<shortdesc lang="en">space-separated list of monitor scripts</shortdesc>
<content type="string" default="" />
</parameter>
</parameters>
<actions>
<action name="start" timeout="90" />
<action name="stop" timeout="90" />
<action name="status" depth="0" timeout="30" interval="10" />
<action name="monitor" depth="0" timeout="30" interval="10" />
+<action name="migrate_from" timeout="60" />
+<action name="migrate_to" timeout="120" />
<action name="meta-data" timeout="5" />
<action name="validate-all" timeout="5" />
</actions>
</resource-agent>
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"
+VIRSH_OPTIONS="--connect=${OCF_RESKEY_hypervisor} --quiet"
VirtualDomain_Define() {
# 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")
+ "shut off"|"no state")
+ # shut off: domain is defined, but not started
+ # no state: domain is migrating (migration target only)
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_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_Migrate_To() {
+ local target_node
+ local remoteuri
+ local transport_suffix
+
+ target_node="$OCF_RESKEY_CRM_meta_migrate_target"
+
+ if VirtualDomain_Status ${DOMAIN_NAME}; then
+ # Find out the remote hypervisor to connect to. That is, turn
+ # something like "qemu://foo:9999/system" into
+ # "qemu+tcp://bar:9999/system"
+ if [ -n "${OCF_RESKEY_migration_transport}" ]; then
+ transport_suffix="+${OCF_RESKEY_migration_transport}"
+ fi
+ # Scared of that sed expression? So am I. :-)
+ remoteuri=$(echo ${OCF_RESKEY_hypervisor} | sed -e "s/\(.*\):\/\/[^\/\:]*\(:\?[0-9]*\)\/\(.*\)/\1${transport_suffix}:\/\/${target_node}\2\/\3/")
+
+ # OK, we know where to connect to. Now do the actual migration.
+ ocf_log info "$DOMAIN_NAME: Starting live migration to ${remoteuri}"
+ virsh ${VIRSH_OPTIONS} migrate --live $DOMAIN_NAME ${remoteuri}
+ rc=$?
+ if [ $rc -ne 0 ]; then
+ ocf_log err "$DOMAIN_NAME: live migration to ${remoteuri} failed: $rc"
+ return $OCF_ERR_GENERIC
+ else
+ ocf_log info "$DOMAIN_NAME: live migration to ${remoteuri} succeeded."
+ return $OCF_SUCCESS
+ fi
+ else
+ ocf_log err "$DOMAIN_NAME: migrate_to: Not active locally!"
+ return $OCF_ERR_GENERIC
+ fi
+}
+
+VirtualDomain_Migrate_From() {
+ while sleep 1; do
+ VirtualDomain_Monitor && return $OCF_SUCCESS
+ done
+}
+
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 $?
# 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
;;
+ migrate_to)
+ VirtualDomain_Migrate_To
+ ;;
+ migrate_from)
+ VirtualDomain_Migrate_From
+ ;;
status)
VirtualDomain_Status
;;
monitor)
VirtualDomain_Monitor
;;
validate-all)
;;
*)
usage
exit $OCF_ERR_UNIMPLEMENTED
;;
esac
exit $?
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Oct 16, 12:04 AM (7 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2530630
Default Alt Text
(11 KB)
Attached To
Mode
rR Resource Agents
Attached
Detach File
Event Timeline
Log In to Comment