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 <t...@solitudo.net>
#!/bin/sh
#
# This script automatically saves running VMs
# managed by libvirtd on stop and restores VMs on start
#
# (C) 2008 Tuomas Jormola <t...@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
# 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

Reply via email to