Auto shutdown KVM Virtual Machines on system shutdown

Update August 2010: It does not always work as expected. Though this method works well if the server is Ubuntu 8.04 or Ubuntu 9.04, but the shutdown script never get called in Debian Squeeze. Maybe a better init script would be required for newer versions.

Update February 2011: You should have a look at Sergey‘s comment below, where he mentions why it doesn’t work in Debian Squeeze. Thanks Sergey!


I have been  using KVM for virtualization for quite some time now, probably more than a year. Though the initial use was on the servers which were rarely shutdown, now I’ve started using it in my home envir0nment where frequent restarts or shutdowns are there. The challenge that I faced was to automatically shutdown the KVM virtual machines when the system was shutdown or restarted.

Thanks to Joern at linux-kvm.com, I was able to setup a script which does an auto shutdown of the Linux (basically any VM which has ssh available) machines. I am using it on Ubuntu 9.04 (Jaunty Jackalope) 64 Bit Desktop edition.

Steps

  1. Add the host file entries
  2. Make sure you are able to do ssh without entering any password from root into the VMs
  3. Put the script into the /etc/init.d directory.
  4. Test the script before rebooting the system
  5. Reboot the system to check if it worked

The Host File Entries

The VM should  have a static IP, and not through DHCP. The VM name should be added into the /etc/hosts file. If you have a VM named Crayon with IP Address 172.16.0.5, then add the entry in the host file like the following

172.16.0.5            Crayon

This is important as I’m doing it through ssh, so I need to ssh into the domain by its name.

Doing ssh into the VMs through root without password

This is out of the scope of this document. You can look at the “Passwordless ssh” post by Adam Monsen on linuxconfig.org

Just make sure, through the root login you are able to ssh into your VM without entering the password. Try it a few times.  You may need to set the root password through sudo passwd on your Ubuntu machine.

The Script

I have modified the script provided by Joern. I used ssh instead of “virsh shutdown domain” because “virsh shutdown” didn’t work at all for the Ubuntu 8.04 Server VM that I had, and for Ubuntu 9.04 Desktop VM it opened up the dialog where it asks what to do (Shutdown/Suspend/Restart etc.). It didn’t suit me well, thus I used the ssh method

Put the following script into /etc/init.d/shutdownvm

#!/bin/bash

# Original Author :
#    Joern http://www.linux-kvm.com/content/stop-script-running-vms-using-virsh
#
# Modified by : Vivek Kapoor http://exain.com
# Date: 22 May 2009

# Parameters you can modify :: START

TIMEOUT=90
LISTFILE=/root/runvm.lst
LOGFILE=/var/log/kvmshutdown.log
# Parameters you can modify :: STOP

PS=/bin/ps
SSH=/usr/bin/ssh
GREP=/bin/grep
CUT=/usr/bin/cut
VIRSH=/usr/bin/virsh
TR=/usr/bin/tr
CAT=/bin/cat
DATE=/bin/date

# Function to shutdown the virtual machine
kvmshutdown () {
COUNT=0
PID=$($PS ax|$GREP $1|$GREP kvm|$CUT -c 1-6)

echo kvmshutdown \: Shutting down $1 with pid $PID

#$VIRSH shutdown $1
$($SSH root@$1 halt)

while [ "$COUNT" -lt "$TIMEOUT" ]
do
 $PS --pid $PID
 if [ "$?" -eq "1" ]
 then
 return 0
 else
 sleep 5
 COUNT=$(($COUNT+5))
 fi
done

echo kvmshutdown \: Timeout happened. Destroying VM $1

$VIRSH destroy $1

return 1

}

# The program begins here

$VIRSH list 2>/dev/null|$GREP running|$TR -s \ |$CUT -f3 -d\  > $LISTFILE

VMN=`$CAT $LISTFILE`

for vm in $VMN
do
 echo "$vm" is running
 kvmshutdown "$vm"
 if [ "$?" -eq "0" ]
 then
 echo VM "$vm" normally shutdown
 echo `$DATE +%Y-%m-%d\ %H:%M:%S` VM $vm normally shutdown >> $LOGFILE
 else
 echo VM "$vm" destroyed !
 echo `$DATE +%Y-%m-%d\ %H:%M:%S` VM $vm destroyed >> $LOGFILE
 fi;
done

Now for some more activities so that it initializes on halt and reboot

  1. chmod 755 /etc/init.d/shutdownvm
  2. cd /etc/rc0.d
    ln -s ../init.d/shutdownvm K18shutdownvm
  3. cd /etc/rc6.d
    ln -s ../init.d/shutdownvm K18shutdownvm

I am using K18 as the kvm is having K20 value, and the above script should execute before kvm.

The beauty of the script by Joern is, it keeps on checking if the process has shutdown. So it will not wait for the complete Timeout value – in case the machine is shutdown earlier, it will proceed further. This I found to be great.

Testing the scripts

You may want to comment out “virsh destroy $1” in the script while you are testing it.

Using root, run the script /etc/init.d/shutdownvm

Keep on doing it as long as you don’t get the desired results. You probably would need to start your VMs a number of times to test it completely.

Reboot the system

Once you are satisfied that it is working as per your requirements, reboot the system. Prior to that you may want to uncomment the “virsh destroy $1” line in the script. While the system is rebooting, quickly try to shift to terminal 7 by pressing ALT+7. You should see the virtual machines being shutdown from there. If it doesn’t work successfully, you may need to do some more testing – probably the ssh connections are not getting established correctly as it is asking for password.

17 thoughts on “Auto shutdown KVM Virtual Machines on system shutdown

  1. “I used ssh instead of “virsh shutdown domain” because “virsh shutdown” didn’t work at all for the Ubuntu 8.04 Server VM that I had”

    well, I think it’s because you don’t have acpid in all servers. to virsh shutdown works correctly you NEED acpid and in your vm XML.

  2. Yes, absolutely correct. I figured it out much later, in fact this year only, and felt so dumb to create an inefficient (and not so elegant) way of doing something which can be done in a much better way.

    I guess I’ll be doing it when I upgrade my workstation to Ubuntu 10.04, in a couple months. And then add a note in the post on the same.

  3. I would like to shutdown many different virtualized OS, Win7 + CentOS any so on.
    This script assumes that all VMs are Linux based.
    I see there is command like “virsh shutdown DOMAIN” and it works like POWER BUTTON. Maybe this is not bad idea?

  4. @Tom – yes, you can go ahead with virsh shutdown DOMAIN. It didn’t work for me earlier because I hadn’t installed acpi on my Ubuntu box, and that’s why this whole passwordless login etc. stuff. virsh shutdown domain works just fine.

  5. Automatically shutdown KVM Virtual Machines « Hardcore Linux

    • haha!
      I’ve renamed it to “aashutdownvm” but it seems it doesn’t work either 😉 it’s not called at shutdown.
      http://toomeek.waw.pl/blog/?p=916
      I’ve backup powered server, however I want to test it anyway to secure shutdown procedure..

      I have running Debian Sqeeze amd64 as hypervisor, should I put there:
      CONCURRENCY=none
      and something else?
      Right now it has:

      # /etc/default/rcS
      #
      # Default settings for the scripts in /etc/rcS.d/
      #
      # For information about these variables see the rcS(5) manual page.
      #
      # This file belongs to the “initscripts” package.

      TMPTIME=0
      SULOGIN=no
      DELAYLOGIN=no
      UTC=yes
      VERBOSE=no
      FSCKFIX=no
      RAMRUN=no
      RAMLOCK=no

  6. In Ubuntu 10.04 there is just another and a much shorter solution possible. Add

    pre-stop script
    for RUNNING_VM in `virsh list | grep -E \(laufend\|running\) | awk -F” ” ‘{ print $2 }’`
    do
    echo shutting down ${RUNNING_VM} on `date` >> /var/log/libvirt/qemu/shutdown_vms.log
    virsh shutdown ${RUNNING_VM}
    done
    # Waiting 30 s to shutdown VMs …
    sleep 30
    end script

    in /etc/init/libvirt-bin.conf .
    And everything is done by the upstart mechanism.

    Regards, Udo

  7. Fun with KVM on Squeeze | inutility.net

  8. Hi, I’m coming from another distro.
    It needs some time but upstart seems to be a nice thing – I have to learn it.
    I’m a little confused by the ticks and think that awk is a little powerful for just cutting out
    a field, so I use the following and it seems to work.
    pre-stop script
    for RUNNING_VM in $(virsh list | grep -E \(laufend\|running\) | cut -d ‘ ‘ -f 3)
    do
    echo shutting down ${RUNNING_VM} on $(date) >> /var/log/libvirt/qemu/shutdown_vms.log
    virsh shutdown ${RUNNING_VM}
    done
    # Waiting 30 s to shutdown VMs …
    sleep 30
    end script

    The loop is tested the rest not : -)

Leave a comment