3
# Copyright (C) 1997-2003 Sistina Software, Inc. All rights reserved.
4
# Copyright (C) 2004-2011 Red Hat, Inc. All rights reserved.
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
PATH=/bin:/sbin:/usr/bin:/usr/sbin
25
. $(dirname $0)/ocf-shellfuncs || exit 1
28
# Virtual Machine start/stop script (requires the virsh command)
31
# Indeterminate state: xend/libvirtd is down.
32
export OCF_APP_ERR_INDETERMINATE=150
38
<resource-agent version="rgmanager 2.0" name="vm">
39
<version>1.0</version>
42
Defines a Virtual Machine
45
Defines a Virtual Machine
49
<parameter name="name" primary="1">
51
This is the name of the virtual machine.
56
<content type="string"/>
59
<parameter name="domain" reconfig="1">
61
Failover domains define lists of cluster members
62
to try in the event that the host of the virtual machine
66
Cluster failover Domain
68
<content type="string"/>
71
<parameter name="autostart" reconfig="1">
73
If set to yes, this resource group will automatically be started
74
after the cluster forms a quorum. If set to no, this virtual
75
machine will start in the 'disabled' state after the cluster
79
Automatic start after quorum formation
81
<content type="boolean" default="1"/>
84
<parameter name="exclusive" reconfig="1">
86
If set, this resource group will only relocate to
87
nodes which have no other resource groups running in the
88
event of a failure. If no empty nodes are available,
89
this resource group will not be restarted after a failure.
90
Additionally, resource groups will not automatically
91
relocate to the node running this resource group. This
92
option can be overridden by manual start and/or relocate
96
Exclusive resource group
98
<content type="boolean" default="0"/>
101
<parameter name="recovery" reconfig="1">
103
This currently has three possible options: "restart" tries
104
to restart this virtual machine locally before
105
attempting to relocate (default); "relocate" does not bother
106
trying to restart the VM locally; "disable" disables
109
<shortdesc lang="en">
110
Failure recovery policy
112
<content type="string"/>
115
<parameter name="migration_mapping" reconfig="1">
117
Mapping of the hostname of a target cluster member to a different hostname
119
<shortdesc lang="en">
120
memberhost:targethost,memberhost:targethost ..
122
<content type="string"/>
125
<parameter name="use_virsh">
127
Force use of virsh instead of xm on Xen machines.
129
<shortdesc lang="en">
130
If set to 1, vm.sh will use the virsh command to manage
131
virtual machines instead of xm. This is required when
132
using non-Xen virtual machines (e.g. qemu / KVM).
134
<content type="integer" default=""/>
137
<parameter name="xmlfile">
139
Full path to libvirt XML file describing the domain.
141
<shortdesc lang="en">
142
Full path to libvirt XML file describing the domain.
144
<content type="string"/>
147
<parameter name="migrate">
149
Migration type (live or pause, default = live).
151
<shortdesc lang="en">
152
Migration type (live or pause, default = live).
154
<content type="string" default="live"/>
157
<parameter name="path">
159
Path specification vm.sh will search for the specified
160
VM configuration file. /path1:/path2:...
162
<shortdesc lang="en">
163
Path to virtual machine configuration files.
165
<content type="string"/>
168
<parameter name="snapshot">
170
Path to the snapshot directory where the virtual machine
171
image will be stored.
173
<shortdesc lang="en">
174
Path to the snapshot directory where the virtual machine
175
image will be stored.
177
<content type="string" default=""/>
180
<parameter name="depend">
182
Service dependency; will not start without the specified
185
<shortdesc lang="en">
186
Top-level service this depends on, in service:name format.
188
<content type="string"/>
191
<parameter name="depend_mode">
193
Service dependency mode.
194
hard - This service is stopped/started if its dependency
196
soft - This service only depends on the other service for
197
initial startip. If the other service stops, this
198
service is not stopped.
200
<shortdesc lang="en">
201
Service dependency mode (soft or hard).
203
<content type="string" default="hard"/>
206
<parameter name="max_restarts" reconfig="1">
208
Maximum restarts for this service.
210
<shortdesc lang="en">
211
Maximum restarts for this service.
213
<content type="string" default="0"/>
216
<parameter name="restart_expire_time" reconfig="1">
218
Restart expiration time. A restart is forgotten
219
after this time. When combined with the max_restarts
220
option, this lets administrators specify a threshold
221
for when to fail over services. If max_restarts
222
is exceeded in this given expiration time, the service
223
is relocated instead of restarted again.
225
<shortdesc lang="en">
226
Restart expiration time; amount of time before a restart
229
<content type="string" default="0"/>
232
<parameter name="status_program" reconfig="1">
234
Ordinarily, only the presence/health of a virtual machine
235
is checked. If specified, the status_program value is
236
executed during a depth 10 check. The intent of this
237
program is to ascertain the status of critical services
238
within a virtual machine.
240
<shortdesc lang="en">
241
Additional status check program
243
<content type="string" default=""/>
246
<parameter name="hypervisor">
247
<shortdesc lang="en">
251
Specify hypervisor tricks to use. Default = auto.
252
Other supported options are xen and qemu.
254
<content type="string" default="auto" />
257
<parameter name="hypervisor_uri">
259
Hypervisor URI. Generally, this is keyed off of the
260
hypervisor and does not need to be set.
262
<shortdesc lang="en">
263
Hypervisor URI (normally automatic).
265
<content type="string" default="auto" />
268
<parameter name="migration_uri">
270
Migration URI. Generally, this is keyed off of the
271
hypervisor and does not need to be set.
273
<shortdesc lang="en">
274
Migration URI (normally automatic).
276
<content type="string" default="auto" />
282
<action name="start" timeout="300"/>
283
<action name="stop" timeout="120"/>
285
<action name="status" timeout="10" interval="30"/>
286
<action name="monitor" timeout="10" interval="30"/>
288
<!-- depth 10 calls the status_program -->
289
<action name="status" depth="10" timeout="20" interval="60"/>
290
<action name="monitor" depth="10" timeout="20" interval="60"/>
292
<!-- reconfigure - reconfigure with new OCF parameters.
293
NOT OCF COMPATIBLE AT ALL -->
294
<action name="reconfig" timeout="10"/>
296
<action name="migrate" timeout="10m"/>
298
<action name="meta-data" timeout="5"/>
299
<action name="validate-all" timeout="5"/>
303
<special tag="rgmanager">
304
<!-- Destroy_on_delete / init_on_add are currently only
305
supported for migratory resources (no children
306
and the 'migrate' action; see above. Do not try this
307
with normal services -->
308
<attributes maxinstances="1" destroy_on_delete="0" init_on_add="0"/>
315
build_virsh_cmdline()
320
if [ -n "$OCF_RESKEY_hypervisor_uri" ]; then
321
cmdline="$cmdline -c $OCF_RESKEY_hypervisor_uri"
324
cmdline="$cmdline $operation $OCF_RESKEY_name"
330
# this is only used on startup
335
# Virtual domains should never restart themselves when
336
# controlled externally; the external monitoring app
339
declare cmdline="on_shutdown=\"destroy\" on_reboot=\"destroy\" on_crash=\"destroy\""
341
if [ -n "$OCF_RESKEY_path" ]; then
342
operation="$operation --path=\"$OCF_RESKEY_path\""
345
if [ -n "$OCF_RESKEY_name" ]; then
346
cmdline="$operation $OCF_RESKEY_name $cmdline"
355
# Use /dev/null for the configuration file, if xmdefconfig
360
echo -n "Virtual machine $OCF_RESKEY_name is "
361
do_status && return 0
363
cmdline="`build_xm_cmdline create`"
365
ocf_log debug "xm $cmdline"
374
declare -i default_timeout=60
377
if [ -n "$OCF_RESKEY_RGMANAGER_meta_timeout" ]; then
378
tout=$OCF_RESKEY_RGMANAGER_meta_timeout
379
elif [ -n "$OCF_RESKEY_CRM_meta_timeout" ]; then
380
tout=$OCF_RESKEY_CRM_meta_timeout
383
if [ $tout -eq 0 ]; then
384
echo $default_timeout
387
if [ $tout -lt 0 ]; then
388
echo $default_timeout
398
# Start a virtual machine given the parameters from
404
declare snapshotimage
406
echo -n "Virtual machine $OCF_RESKEY_name is "
407
do_status && return 0
409
snapshotimage="$OCF_RESKEY_snapshot/$OCF_RESKEY_name"
411
if [ -n "$OCF_RESKEY_snapshot" -a -f "$snapshotimage" ]; then
412
eval virsh restore $snapshotimage
413
if [ $? -eq 0 ]; then
420
if [ -n "$OCF_RESKEY_xmlfile" -a -f "$OCF_RESKEY_xmlfile" ]; then
421
# TODO: try to use build_virsh_cmdline for the hypervisor_uri
422
cmdline="virsh create $OCF_RESKEY_xmlfile"
424
cmdline="virsh $(build_virsh_cmdline start)"
427
ocf_log debug "$cmdline"
436
declare -i timeout=60
441
echo "CMD: xm $op $OCF_RESKEY_name"
442
xm $op $OCF_RESKEY_name
445
while [ $timeout -gt 0 ]; do
448
do_status&>/dev/null || return 0
449
while read dom state; do
451
# State is "stopped". Kill it.
453
if [ "$dom" != "$OCF_RESKEY_name" ]; then
456
if [ "$state" != "---s-" ]; then
459
xm destroy $OCF_RESKEY_name
460
done < <(xm list | awk '{print $1, $5}')
469
# Stop a VM. Try to shut it down. Wait a bit, and if it
470
# doesn't shut down, destroy it.
474
declare -i timeout=$(get_timeout)
479
[ $? -eq 0 ] || return 0
481
if [ -n "$OCF_RESKEY_snapshot" ]; then
482
virsh save $OCF_RESKEY_name "$OCF_RESKEY_snapshot/$OCF_RESKEY_name"
486
echo virsh $op $OCF_RESKEY_name ...
487
virsh $op $OCF_RESKEY_name
489
timeout=$(get_timeout)
490
while [ $timeout -gt 0 ]; do
494
[ $? -eq 0 ] || return 0
496
if [ "$state" = "paused" ]; then
497
virsh destroy $OCF_RESKEY_name
508
if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
522
domstate=$(do_status)
524
ocf_log debug "Virtual machine $OCF_RESKEY_name is $domstate"
525
if [ $rv -eq $OCF_APP_ERR_INDETERMINATE ]; then
526
ocf_log crit "xend/libvirtd is dead; cannot stop $OCF_RESKEY_name"
530
if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
541
# Reconfigure a running VM.
551
service xend status &> /dev/null
552
if [ $? -ne 0 ]; then
555
return $OCF_APP_ERR_INDETERMINATE
558
xm list $OCF_RESKEY_name &> /dev/null
559
if [ $? -eq 0 ]; then
563
xm list migrating-$OCF_RESKEY_name &> /dev/null
564
if [ $? -eq 0 ]; then
577
if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
578
service xend status &> /dev/null
579
if [ $? -ne 0 ]; then
581
return $OCF_APP_ERR_INDETERMINATE
586
# libvirtd is required when using virsh even though
587
# not specifically when also using Xen. This is because
588
# libvirtd is required for migration.
590
pid=$(pidof libvirtd)
591
if [ -z "$pid" ]; then
593
return $OCF_APP_ERR_INDETERMINATE
596
state=$(virsh domstate $OCF_RESKEY_name)
600
if [ "$state" = "running" ] || [ "$state" = "paused" ] || [ "$state" = "no state" ] ||
601
[ "$state" = "idle" ]; then
605
if [ "$state" = "shut off" ]; then
606
return $OCF_NOT_RUNNING
609
return $OCF_ERR_GENERIC
614
# Simple status check: Find the VM in the list of running
619
if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
630
# virsh "path" attribute support
636
if [ -f "$path/$OCF_RESKEY_name" ]; then
637
echo $path/$OCF_RESKEY_name
639
elif [ -f "$path/$OCF_RESKEY_name.xml" ]; then
640
echo $path/$OCF_RESKEY_name.xml
656
while [ -n "$input" ]; do
657
value=${input/$delim*/}
658
if [ -n "$value" ]; then
660
if [ $? -eq 2 ]; then
664
inp=${input/$value$delim/}
665
if [ "$input" = "$inp" ]; then
675
declare config_file=$(parse_input ":" "$OCF_RESKEY_path" check_config_file)
677
if [ -n "$config_file" ]; then
678
export OCF_RESKEY_xmlfile=$config_file
686
choose_management_tool()
691
# Don't override user value for use_virsh if one is given
693
if [ -n "$OCF_RESKEY_use_virsh" ]; then
697
which xmllint &> /dev/null
698
if [ $? -ne 0 ]; then
699
ocf_log warning "Could not find xmllint; assuming virsh mode"
700
export OCF_RESKEY_use_virsh=1
701
unset OCF_RESKEY_path
705
xmllint $OCF_RESKEY_xmlfile &> /dev/null
708
if [ $is_xml -eq 0 ]; then
709
ocf_log debug "$OCF_RESKEY_xmlfile is XML; using virsh"
710
export OCF_RESKEY_use_virsh=1
711
unset OCF_RESKEY_path
713
ocf_log debug "$OCF_RESKEY_xmlfile is not XML; using xm"
714
export OCF_RESKEY_use_virsh=0
715
unset OCF_RESKEY_xmlfile
725
if [ "$(id -u)" != "0" ]; then
726
ocf_log err "Cannot control VMs. as non-root user."
731
# If someone selects a hypervisor, honor it.
732
# Otherwise, ask virsh what the hypervisor is.
734
if [ -z "$OCF_RESKEY_hypervisor" ] ||
735
[ "$OCF_RESKEY_hypervisor" = "auto" ]; then
736
export OCF_RESKEY_hypervisor="`virsh version | grep \"Running hypervisor:\" | awk '{print $3}' | tr A-Z a-z`"
737
if [ -z "$OCF_RESKEY_hypervisor" ]; then
738
ocf_log err "Could not determine Hypervisor"
741
echo Hypervisor: $OCF_RESKEY_hypervisor
745
# Xen hypervisor only for when use_virsh = 0.
747
if [ "$OCF_RESKEY_use_virsh" = "0" ]; then
748
if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then
749
ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh"
753
if [ -n "$OCF_RESKEY_xmlfile" ]; then
754
ocf_log err "Cannot use xmlfile if use_virsh is set to 0"
760
# Virsh path support.
762
if [ -n "$OCF_RESKEY_path" ] &&
763
[ "$OCF_RESKEY_path" != "/etc/xen" ]; then
764
if [ -n "$OCF_RESKEY_xmlfile" ]; then
765
ocf_log warning "Using $OCF_RESKEY_xmlfile instead of searching $OCF_RESKEY_path"
768
if [ $? -ne 0 ]; then
769
ocf_log warning "Could not find $OCF_RESKEY_name or $OCF_RESKEY_name.xml in search path $OCF_RESKEY_path"
770
unset OCF_RESKEY_xmlfile
772
ocf_log debug "Using $OCF_RESKEY_xmlfile"
774
choose_management_tool
777
export OCF_RESKEY_use_virsh=1
781
if [ "$OCF_RESKEY_use_virsh" = "0" ]; then
783
echo "Management tool: xm"
784
which xm &> /dev/null
785
if [ $? -ne 0 ]; then
786
ocf_log err "Cannot find 'xm'; is it installed?"
787
return $OCF_ERR_INSTALLED
790
if [ "$OCF_RESKEY_hypervisor" != "xen" ]; then
791
ocf_log err "Cannot use $OCF_RESKEY_hypervisor hypervisor without using virsh"
795
echo "Management tool: virsh"
796
which virsh &> /dev/null
797
if [ $? -ne 0 ]; then
798
ocf_log err "Cannot find 'virsh'; is it installed?"
799
return $OCF_ERR_INSTALLED
804
# Set the hypervisor URI
806
if [ -z "$OCF_RESKEY_hypervisor_uri" -o "$OCF_RESKEY_hypervisor_uri" = "auto" ] &&
807
[ "$OCF_RESKEY_use_virsh" = "1" ]; then
809
# Virsh makes it easier to do this. Really.
810
if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
811
OCF_RESKEY_hypervisor_uri="qemu:///system"
814
# I just need to believe in it more.
815
if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
816
OCF_RESKEY_hypervisor_uri="xen:///"
819
echo Hypervisor URI: $OCF_RESKEY_hypervisor_uri
823
# Set the migration URI
825
if [ -z "$OCF_RESKEY_migration_uri" -o "$OCF_RESKEY_migration_uri" = "auto" ] &&
826
[ "$OCF_RESKEY_use_virsh" = "1" ]; then
828
# Virsh makes it easier to do this. Really.
829
if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
830
export OCF_RESKEY_migration_uri="qemu+ssh://%s/system"
833
# I just need to believe in it more.
834
if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
835
export OCF_RESKEY_migration_uri="xenmigr://%s/"
838
[ -n "$OCF_RESKEY_migration_uri" ] && echo Migration URI format: $(printf $OCF_RESKEY_migration_uri target_host)
841
if [ -z "$OCF_RESKEY_name" ]; then
842
echo No domain name specified
846
if [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
847
export migrateuriopt="tcp:%s"
850
#virsh list --all | awk '{print $2}' | grep -q "^$OCF_RESKEY_name\$"
861
# Xen and qemu have different migration mechanisms
863
if [ "$OCF_RESKEY_hypervisor" = "xen" ]; then
864
cmd="virsh migrate $migrate_opt $OCF_RESKEY_name $OCF_RESKEY_hypervisor_uri $(printf $OCF_RESKEY_migration_uri $target)"
867
err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
869
elif [ "$OCF_RESKEY_hypervisor" = "qemu" ]; then
870
cmd="virsh migrate $migrate_opt $OCF_RESKEY_name $(printf $OCF_RESKEY_migration_uri $target) $(printf $migrateuriopt $target)"
873
err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
877
if [ $rv -ne 0 ]; then
878
ocf_log err "Migrate $OCF_RESKEY_name to $target failed:"
881
if [ "$err" != "${err/does not exist/}" ]; then
882
return $OCF_ERR_CONFIGURED
884
if [ "$err" != "${err/Domain not found/}" ]; then
885
return $OCF_ERR_CONFIGURED
888
return $OCF_ERR_GENERIC
901
declare errstr rv migrate_opt cmd
905
if [ "$OCF_RESKEY_migrate" = "live" ]; then
909
# migrate() function sets target using migration_mapping;
910
# no need to do it here anymore
911
cmd="xm migrate $migrate_opt $OCF_RESKEY_name $target"
914
err=$($cmd 2>&1 | head -1; exit ${PIPESTATUS[0]})
917
if [ $rv -ne 0 ]; then
918
ocf_log err "Migrate $OCF_RESKEY_name to $target failed:"
921
if [ "$err" != "${err/does not exist/}" ]; then
922
return $OCF_NOT_RUNNING
924
if [ "$err" != "${err/Connection refused/}" ]; then
925
return $OCF_ERR_CONFIGURED
928
return $OCF_ERR_GENERIC
940
declare rv migrate_opt
942
if [ "$OCF_RESKEY_migrate" = "live" ]; then
946
# Patch from Marcelo Azevedo to migrate over private
947
# LANs instead of public LANs
948
if [ -n "$OCF_RESKEY_migration_mapping" ] ; then
949
target=${OCF_RESKEY_migration_mapping#*$target:} target=${target%%,*}
952
if [ "$OCF_RESKEY_use_virsh" = "1" ]; then
953
virsh_migrate $target
966
declare -i timeout_remaining=$(get_timeout)
967
declare -i start_time
970
declare -i sleep_time
972
if [ -z "$OCF_RESKEY_status_program" ]; then
976
while [ $timeout_remaining -gt 0 ]; do
977
start_time=$(date +%s)
978
bash -c "$OCF_RESKEY_status_program"
979
if [ $? -eq 0 ]; then
983
delta=$(((end_time - start_time)))
984
sleep_time=$(((5 - delta)))
986
((timeout_remaining -= $delta))
987
if [ $sleep_time -gt 0 ]; then
989
((timeout_remaining -= $sleep_time))
993
ocf_log err "Start of $OCF_RESOURCE_INSTANCE has failed"
994
ocf_log err "Timeout exceeded while waiting for \"$OCF_RESKEY_status_program\""
1005
validate_all || exit $OCF_ERR_ARGS
1008
if [ $rv -ne 0 ]; then
1016
validate_all || exit $OCF_ERR_ARGS
1017
do_stop shutdown destroy
1021
validate_all || exit $OCF_ERR_ARGS
1029
validate_all || exit $OCF_ERR_ARGS
1030
echo -n "Virtual machine $OCF_RESKEY_name is "
1033
if [ $rv -ne 0 ]; then
1036
[ -z "$OCF_RESKEY_status_program" ] && exit 0
1037
[ -z "$OCF_CHECK_LEVEL" ] && exit 0
1038
[ $OCF_CHECK_LEVEL -lt 10 ] && exit 0
1040
bash -c "$OCF_RESKEY_status_program" &> /dev/null
1044
validate_all || exit $OCF_ERR_ARGS
1045
migrate $2 # Send VM to this node
1047
if [ $rv -eq $OCF_ERR_GENERIC ]; then
1048
# Catch-all: If migration failed with
1049
# an unhandled error, do a status check
1050
# to see if the VM is really dead.
1052
# If the VM is still in good health, return
1053
# a value to rgmanager to indicate the
1054
# non-critical error
1056
# OCF states that codes 150-199 are reserved
1057
# for application use, so we'll use 150
1059
do_status > /dev/null
1060
if [ $? -eq 0 ]; then
1070
validate_all || exit $OCF_ERR_ARGS
1071
echo "$0 RECONFIGURING $OCF_RESKEY_memory"
1084
echo "usage: $0 {start|stop|restart|status|reload|reconfig|meta-data|validate-all}"