[Pkg-libvirt-maintainers] Bug#508604: Acknowledgement (Mechanism to automatically save and restore the state of virtual machines on host shutdown/start-up)
Tuomas Jormola
tj at solitudo.net
Sat Dec 13 14:23:31 UTC 2008
Hi,
I tuned my script to be more intelligent. It now detects save/restore
conflict with Xen. Domain state file name is configurable. More robust
save and restore. Option to start QEMU/KVM virtual machines if no
restore file for the domain can be located, thus emulating libvirt
autostart feature, which must be switched off at libvirt level.
--
Tuomas Jormola <tj at solitudo.net>
-------------- next part --------------
#!/bin/sh
#
# This script automatically saves running VMs
# managed by libvirtd on stop and restores VMs on start
#
# (C) 2008 Tuomas Jormola <tj at solitudo.net>
#
### BEGIN INIT INFO
# Required-Start: $network $local_fs
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: save and restore libvirtd managed VMs
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
domain_state_file_name_pattern=%n
enabled=false
. /lib/lsb/init-functions
if test -f /etc/default/libvirt-domain-state; then
. /etc/default/libvirt-domain-state
fi
test "$enabled" = "true" || exit 0
xen_enabled=0
if test -f /etc/default/xendomains; then
. /etc/default/xendomains
if test -n "$XENDOMAINS_MIGRATE" || test "$XENDOMAINS_SAVE" = "true"; then
xen_enabled=1
fi
fi
if test $xen_enabled -eq 1; then
log_warning_msg "Automatic domain state save and restore implemented by Xen"
exit 1
fi
if test -z "$domain_state_file_directory"; then
log_failure_msg "Domain save directory not defined"
exit 1
fi
if ! test -d "$domain_state_file_directory"; then
log_failure_msg "Domain save directory not found: $domain_state_file_directory"
exit 1
fi
if test -z "$domain_state_file_name_pattern"; then
log_failure_msg "Domain state file name pattern not defined"
exit 1
fi
if echo $domain_state_file_name_pattern | grep -q '/'; then
log_failure_msg "Domain state file name pattern must not contain slashes"
exit 1
fi
if ! echo $domain_state_file_name_pattern | grep -q '%n'; then
log_failure_msg "Domain state file name pattern must contain %n"
exit 1
fi
if test -z "$libvirt_hypervisor_uri"; then
log_failure_msg "libvirt hypervisor connection URI not defined"
exit 1
fi
if test "$libvirt_hypervisor_uri" != "`virsh -q -c $libvirt_hypervisor_uri uri 2>/dev/null`"; then
log_failure_msg "Failed to connect to libvirt hypervisor $libvirt_hypervisor_uri"
exit 1
fi
run_virsh() {
virsh -q -c $libvirt_hypervisor_uri $*
}
# Print full path to domain state file for the domain.
expand_domain_state_file() {
test -n "$domain_name" || return
domain_state_file_name=`echo $domain_state_file_name_pattern | sed "s/%n/$domain_name/g" 2>/dev/null`
test -n "$domain_state_file_name" || return
echo $domain_state_file_directory/$domain_state_file_name
}
check_domain_autostart() {
virsh_output=`run_virsh dominfo $1 2>/dev/null`
ret=$?
if test $ret != 0; then
return 2
fi
echo $virsh_output | grep -q 'Autostart: disable' 2>/dev/null
}
# Restore a domain from state file if the domain is shut down
# or start QEMU/KVM domain if enabled.
restore_domain() {
case "$domain_status" in
"shut off")
domain_state_file=`expand_domain_state_file`
if test -f $domain_state_file; then
if run_virsh restore $domain_state_file >/dev/null 2>&1; then
if test "$delete_restored_domain_state_files" = "true"; then
rm -f $domain_state_file
fi
log_action_msg "$domain_name restored"
else
log_failure_msg "Failed to restore $domain_name from $domain_state_file"
fi
elif test "$start_qemu_domains_without_state_file" = "true" && test -f /etc/libvirt/qemu/$domain_name.xml; then
if run_virsh start $domain_name >/dev/null 2>&1; then
log_action_msg "$domain_name started (QEMU/KVM domain with no restore file)"
else
log_failure_msg "Failed to start QEMU/KVM domain $domain_name"
fi
else
log_warning_msg "Restore file not found for $domain_name"
fi
;;
"running") log_warning_msg "$domain_name already running"; return ;;
*) log_warning_msg "Unknown status for domain $domain_name: $domain_status"; return ;;
esac
}
# Save a domain to state file if domain is running and if libvirt
# is not starting the domain
save_domain() {
if test "$domain_status" != "running"; then
log_warning_msg "$domain_name is not running"
return
fi
check_domain_autostart $domain_name
ret=$?
case "$ret" in
0) true ;;
1) log_warning_msg "libvirtd autostart enabled for $domain_name"; return ;;
2) log_failure_msg "Failed to get autostart status for $domain_name"; return ;;
*) log_failure_msg "Unknown return code when checking autostart status for $domain_name"; return ;;
esac
domain_state_file=`expand_domain_state_file`
if run_virsh save $domain_id $domain_state_file >/dev/null 2>&1; then
log_action_msg "$domain_name saved"
else
log_failure_msg "Failed to save $domain_name as $domain_state_file"
fi
}
print_domain_status() {
log_action_msg "$domain_name: $domain_status"
}
# Generate list of all domains on the hypervisor and launch
# the callback function for each domain.
iterate_domains() {
callback=$1
run_virsh list --all 2>/dev/null | grep -v ^Connecting | \
while read domain_id domain_name domain_status; do
eval "$callback"
done
}
case "$1" in
start)
log_action_begin_msg "Restoring virtual machines"
iterate_domains restore_domain
log_action_end_msg 0
;;
stop)
log_action_begin_msg "Saving virtual machines"
iterate_domains save_domain
log_action_end_msg 0
;;
status)
log_action_begin_msg "Checking status of virtual machines"
iterate_domains print_domain_status
log_action_end_msg 0
;;
*)
N=/etc/init.d/libvirt-domain-state
echo "Usage: $N {start|stop|status}" >&2
exit 1
;;
esac
exit 0
-------------- next part --------------
# Provide support for storing virtual machine state on hypervisor host shutdown
# and restore on hypervisor host start-up. In order to support this, please
# note that you must configure each virtual machine so that the libvirt
# autostart feature is disabled. Also if you're using Xen, the built-in
# save/restore mechanism must be disabled.
# Directory where to save virtual machine state files. This directory
# needs to be created manually. Be sure that there's enough free disk
# space available! You will need at least the combied amount of physical
# memory and swap space allocated to all virtual machines plus some room
# for overhead. For instance, if you are running two virtual machines
# each configured to use 1GB of memory and 2GB of swap, you should
# reserve more than 6GB of space in the file system holding this
# directory. This setting is required.
#domain_state_file_directory=/var/lib/libvirt/domain-state-files
# File name pattern for state files where the virtual machine's state is saved.
# The pattern must contain string "%n" which is replaced with the name of each
# virtual machine. Default file name consists of just the virtual machine name,
# i.e. the pattern is "%n".
#domain_state_file_name_pattern=%n.state
# libvirt URI of the hypervisor.
# See http://libvirt.org/remote.html#Remote_URI_reference
# This setting is required.
#libvirt_hypervisor_uri=qemu:///system
# Uncommenting this setting will destroy each virtual machine state file
# after successful restore. Disabled by default, i.e. restore is performed
# but state files are left intact.
#delete_restored_domain_state_files=true
# If this setting is enabled, during the hypervisor host machine start-up the
# script will start each QEMU/KVM virtual machine that is found on the system
# for which no state file can be found. Effectively this emulates the libvirt
# auto-start feature, but in more smart manner. If state file is found, the
# virtual machine will be restored, and if not, new instance of the virtual
# machine is started. The net effect is that all QEMU/KVM machines will
# automatically be running when the hypervisor has finished booting.
#start_qemu_domains_without_state_file=true
# Uncomment this to actually enable automatic saving and restoring
# of the virtual machines.
#enabled=true
More information about the Pkg-libvirt-maintainers
mailing list