Skip to content

Making sure virtual machine guests shut down properly on a Debian host

I just installed libvirt and installed a vritual machine with virt-install. I also used virsh to configure it to autostart on machine start. This way, it integrates quite nicely with the host operating system.

However, I found out that libvirt provides no way to properly shut the machines down when the host goes down. It is completely beyond me that they didn’t implement this. When you shut down libvirtd, the guests just die…

Googling yielded almost nothing, except a bug report from 17 Mar 2009 with a request for this. The report still wasn’t handled, but the guy said that he wrote a crude script to do it. I mailed him to ask for it, and here it is:

#! /bin/sh
### BEGIN INIT INFO
# Provides:          kvm_domains
# Required-Start:    $remote_fs
# Required-Stop:     $remote_fs
# Default-Start:     
# Default-Stop:      0 6
# Short-Description: Shutdown kvm domains
# Description:       Shutdown kvm domains on reboot/poweroff.
#                    Forcefully kill instances that still run after a
#                    given timeout.
### END INIT INFO
 
# Author: Michael Biebl <biebl@teco.edu>
#
 
# Do NOT "set -e"
 
# PATH should only include /usr/* if it runs after the mountnfs.sh script
PATH=/sbin:/usr/sbin:/bin:/usr/bin
DESC="KVM domains"
VIRSH=/usr/bin/virsh
SCRIPTNAME=/etc/init.d/kvm_domains
TIMEOUT=60
 
# Exit if the package is not installed
[ -x "$VIRSH" ] || exit 0
 
# Define LSB log_* functions.
# Depend on lsb-base (>= 3.0-6) to ensure that this file is present.
. /lib/lsb/init-functions
 
#
# Function that stops the daemon/service
#
do_stop()
{
	domains=$($VIRSH -q list | awk '/running/ {print $2}')
	if [ -z "$domains" ] ; then
		log_progress_msg "none"
		return 0
	fi
	for d in $domains ; do
		$VIRSH -q shutdown $d > /dev/null
		log_progress_msg $d
	done
 
	i=0
	while [ $i -lt $TIMEOUT ] ; do
		if $VIRSH -q list | grep -q running ; then
			i=$(($i+1))
			log_progress_msg "."
			sleep 1
		else
			return 0
		fi
	done
	# forcefully kill the remaining kvm instances
	killall -9 kvm
	return 1 
}
 
 
case "$1" in
  start)
	;;
  stop)
	log_begin_msg "Stopping $DESC:"
	do_stop
	case "$?" in
		0) log_end_msg 0 ;;
		1) log_end_msg 1 ;;
	esac
	;;
  restart|force-reload)
	;;
  *)
	#echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
	echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
	exit 3
	;;
esac
 
:

It depends on text output by virsh, so it’s not the most robust, but it works.

Run this to put in it in the proper runlevels (the 10 on my system makes sure it executes before kvm and libvirt):

update-rc.d kvm_domains stop 10 0 6 .

    No Comments ( Add comment / trackback )