Hi there,
don't know if something like this is already out there (hint ?),
wrote my own little script :
#!/bin/sh
TIMEOUT=60
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
while [ "$COUNT" -lt "$TIMEOUT" ]
do
ps --pid $PID
# echo pid $?
if [ "$?" -eq "1" ]
then
return 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo kvmshutdown \: Timeout happend. Destroying VM $1
virsh destroy $1
return 1
}
# Here is the start of the main "program" :-)
virsh list|grep running|tr -s \ |cut -f3 -d\ > /tmp/runvm.lst
while read vm
do
echo $vm is running
kvmshutdown $vm
if [ "$?" -eq "0" ]
then
echo VM $vm normally shutdown
else
echo VM $vm destroyed !
fi
done < /tmp/runvm.lst
If you can improve the script : do it :-)
greetings
joern
Well, I guess I'm going to mix your script with a middle step: a shutdown through ssh.
ACPI isn't working right with Windows, and it wouldn't guarantee a close of all software running. The XEN aproach doesn't help when you REALLY WANT to shutdown all ou restart all, so Suspend or Save Snapshot is not the answer to me.
So, I collaborate here my ssh shutdown (just use Cygwin with openssh installed, and .ssh/authorized_keys):
ssh windows_server 'shutdown /m WIN2003TS /s /t 60 /d p:0:0 /c "[SDEV Manut - SDEV]"'
Then I would wait a min for the shutdown, try again with a /f to force closing of all apps, then wait another min and finally destroy it.
Thank you very much for the script. It didn't work for me the way I wanted, and hence modified it a bit.
The challenges were
1. "virsh shutdown" didn't work for me well. So, I used SSH instead, as also was mentioned by Anonymous above.
2. The while loop, reading /tmp/runvm.lst was not taking multiple virtual machines correctly - it used to only shutdown one machine and exit. I couldn't figure out the problem, so I replaced it with a for loop.
3. Enabled logging also.
The updated code is available at http://exain.wordpress.com/2009/05/22/auto-shutdown-kvm-virtual-machines...
Thank you
Vivek Kapoor
http://exain.com
hi Joern i have extended ur script ... since under KVM Windows vm's do not accept acpi-power-switch.
So I had to make a start-stop-script that saves and restores the vm.
And we need one start-stop-script per vm. I only done some initial testing.
Would be great if u or someone else could test all cases in the script.
cheers saman.behnam@opensoft24.com
###############################################################
#!/bin/sh
# U need per VM a separate start-stop-script!
VM_NAME="win0" # Name of ur guest VM
VM_XML_FILE="/etc/libvirt/qemu/"$VM_NAME".xml" # XML config file of ur guest VM.
TIMEOUT=300
VM_SAVE_DIR="/kvm/tmp/vm_save_dir" # Directory for storing the guest VM save data..
DEVNULL="/dev/null"
#ACTION="shutdown"
ACTION="save" # ACTION takes one argument, either "save" or "shutdown". In the "save" case it will save the VM and restore it while stopping or starting. In the "shtudown" case it will sutdown then VM and start it while stopping or starting.
vmshutdown () {
PID=$(ps ax|grep $VM_NAME|grep kvm|cut -c 1-6)
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "1" ]; then
echo "VM "$VM_NAME" is not running!!! Exiting."
exit 1
fi
COUNT=0
echo "kvmshutdown \: Shutting down "$VM_NAME" with pid $PID"
virsh shutdown "$VM_NAME" && exit 0
while [ "$COUNT" -lt "$TIMEOUT" ]; do
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "1" ]; then
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "kvmshutdown \: Timeout happend. Destroying VM "$VM_NAME""
virsh destroy "$VM_NAME" && exit 1
}
vmstart () {
PID=$(ps ax|grep $VM_NAME|grep kvm|cut -c 1-6)
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "0" ]; then
echo "VM "$VM_NAME" is allready running!!! Exiting."
exit 1
fi
virsh start "$VM_XML_FILE" && exit 0
exit 1
}
vmsave () {
PID=$(ps ax|grep $VM_NAME|grep kvm|cut -c 1-6)
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "1" ]; then
echo "VM "$VM_NAME" is not running!!! Exiting."
exit 1
fi
COUNT=0
echo "vmsave \: Saving VM "$VM_NAME""
if [ ! -d "$VM_SAVE_DIR" ]; then
echo "creating "$VM_SAVE_DIR""
mkdir -p "$VM_SAVE_DIR"
fi
virsh save "$VM_NAME" "$VM_SAVE_DIR/$VM_NAME.kvm.save" && exit 0
while [ "$COUNT" -lt "$TIMEOUT" ]; do
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "1" ]; then
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "vmsave \: Timeout happend. Destroying VM "$VM_NAME""
virsh destroy "$VM_NAME"
exit 1
}
vmrestore () {
PID=$(ps ax|grep $VM_NAME|grep kvm|cut -c 1-6)
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "0" ]; then
echo "VM "$VM_NAME" is allready running!!! Exiting."
exit 1
fi
if ! ls "$VM_SAVE_DIR"/"$VM_NAME".kvm.save > /dev/null 2>&1 ; then
echo "Restore file "$VM_NAME".kvm.save in "$VM_SAVE_DIR" not found! Starting VM!!!"
vmstart
exit 1
fi
cd "$VM_SAVE_DIR"
echo "vmrestore \: Restoring VM "$VM_NAME""
virsh restore "$VM_SAVE_DIR"/"$VM_NAME".kvm.save && rm -f "$VM_SAVE_DIR"/"$VM_NAME".kvm.save
exit 0
}
# Here is the start of the main "program" :-)
case "$1" in
start)
case "$ACTION" in
save)
vmrestore
;;
shutdown)
vmstart
;;
esac
;;
stop)
case "$ACTION" in
save)
vmsave
;;
shutdown)
vmshutdown
;;
esac
;;
*)
N="$0"
echo "Usage: "$N" {start|stop}" >&2
exit 1
;;
esac
exit 0
###############################################################
#!/bin/sh
# U need per VM a separate start-stop-script!
VM_NAME="lenny0" # Name of ur guest VM
TIMEOUT=300
VM_SAVE_DIR="/kvm/tmp/vm_save_dir" # Directory for storing the guest VM save data..
DEVNULL="/dev/null"
#ACTION="shutdown"
ACTION="save" # ACTION takes one argument, either "save" or "shutdown". In the "save" case it will save the VM and restore it while stopping or starting. In the "shtudown" case it will sutdown then VM and start it while stopping or starting.
vmshutdown () {
if ! virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is not running!!! Exiting."
exit 1
fi
PID=$(ps ax|grep $VM_NAME|grep kvm|cut -c 1-6)
COUNT=0
echo "kvmshutdown \: Shutting down "$VM_NAME" with pid $PID"
virsh shutdown "$VM_NAME" && exit 0
while [ "$COUNT" -lt "$TIMEOUT" ]; do
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "1" ]; then
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "kvmshutdown \: Timeout happend. Destroying VM "$VM_NAME""
virsh destroy "$VM_NAME" && exit 1
}
vmstart () {
if virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is allready running!!! Exiting."
exit 1
fi
virsh start "$VM_NAME" && exit 0
exit 1
}
vmsave () {
if ! virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is not running!!! Exiting."
exit 1
fi
PID=$(ps ax|grep $VM_NAME|grep kvm|cut -c 1-6)
COUNT=0
echo "vmsave \: Saving VM "$VM_NAME""
if [ ! -d "$VM_SAVE_DIR" ]; then
echo "creating "$VM_SAVE_DIR""
mkdir -p "$VM_SAVE_DIR"
fi
virsh save "$VM_NAME" "$VM_SAVE_DIR/$VM_NAME.kvm.save" && exit 0
while [ "$COUNT" -lt "$TIMEOUT" ]; do
ps --pid $PID > "$DEVNULL" 2>&1
if [ "$?" -eq "1" ]; then
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "vmsave \: Timeout happend. Destroying VM "$VM_NAME""
virsh destroy "$VM_NAME"
exit 1
}
vmrestore () {
if virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is allready running!!! Exiting."
exit 1
fi
if ! ls "$VM_SAVE_DIR"/"$VM_NAME".kvm.save > /dev/null 2>&1 ; then
echo "Restore file "$VM_NAME".kvm.save in "$VM_SAVE_DIR" not found! Starting VM!!!"
vmstart
exit 1
fi
cd "$VM_SAVE_DIR"
echo "vmrestore \: Restoring VM "$VM_NAME""
virsh restore "$VM_SAVE_DIR"/"$VM_NAME".kvm.save && rm -f "$VM_SAVE_DIR"/"$VM_NAME".kvm.save
exit 0
}
# Here is the start of the main "program" :-)
case "$1" in
start)
case "$ACTION" in
save)
vmrestore
;;
shutdown)
vmstart
;;
esac
;;
stop)
case "$ACTION" in
save)
vmsave
;;
shutdown)
vmshutdown
;;
esac
;;
*)
N="$0"
echo "Usage: "$N" {start|stop}" >&2
exit 1
;;
esac
exit 0
Hi Joern
Hi there
I've done agian some modification to ur script, as I had the time now to check and the script. The TIMEOUT condition that u handle in ur script would never happen because ur script will wait till the process of stopping / saving the VM finishes. Thus if a VM hangs it will wait endless. Another funny thing is if I hade a VI editor open editing a "VM. xml"file the scirpt will see two pids (PID=$(ps ax|grep $1|grep kvm|cut -c 1-6). Its better to relay on the "virsh" command when checking VM state. Thus I wrote yet another "stop script running vms using virsh" Please check also here!
########################################################
#!/bin/sh
### BEGIN INIT INFO
# Provides: kvm-win0-rcs
# Required-Start: $kvm $libvirtd
# Required-Stop: $kvm $libvirtd
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starting/Saving, Stopping/Restoring kvm-win0-rcs KVM guest.
# Description: Starting/Saving, Stopping/Restoring KVM guest "win0".
# kvm-win0-rcs KVM guest.
### END INIT INFO#
# Please copy the init scripts of the KVM VM's in to "/etc/init.d" and then run! "for i in `cd /etc/init.d && ls kvm-*` ; do update-rc.d $i defaults 21 19 ; done"
# U need per VM a separate start-stop-script!
VM_NAME="win0" # Name of ur guest VM
TIMEOUT=300
VM_SAVE_DIR="/kvm/tmp/vm_save_dir" # Directory for storing the guest VM save data..
DEVNULL="/dev/null"
#ACTION="shutdown"
ACTION="save" # ACTION takes one argument, either "save" or "shutdown". In the "save" case it will save the VM and restore it while stopping or starting. In the "shtudown" case it will sutdown then VM and s
tart it while stopping or starting.
vmshutdown () {
if ! virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is not running!!! Exiting."
exit 1
fi
COUNT=0
echo "kvmshutdown \: Shutting down "$VM_NAME" with pid $PID"
virsh shutdown "$VM_NAME" &
while [ "$COUNT" -lt "$TIMEOUT" ]; do
if ! virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "kvmshutdown \: Timeout happend. Destroying VM "$VM_NAME""
virsh destroy "$VM_NAME" && exit 1
}
vmstart () {
if virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is allready running!!! Exiting."
exit 1
fi
virsh start "$VM_NAME" && exit 0
exit 1
}
vmsave () {
if ! virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is not running!!! Exiting."
exit 1
fi
COUNT=0
echo "vmsave \: Saving VM "$VM_NAME""
if [ ! -d "$VM_SAVE_DIR" ]; then
echo "creating "$VM_SAVE_DIR""
mkdir -p "$VM_SAVE_DIR"
fi
virsh save "$VM_NAME" "$VM_SAVE_DIR/$VM_NAME.kvm.save" &
while [ "$COUNT" -lt "$TIMEOUT" ]; do
if ! virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "vmsave \: Timeout happend. Destroying VM "$VM_NAME""
virsh destroy "$VM_NAME"
exit 1
}
vmrestore () {
if virsh list|grep running|grep -v grep|grep "$VM_NAME" > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is allready running!!! Exiting."
exit 1
fi
if ! ls "$VM_SAVE_DIR"/"$VM_NAME".kvm.save > /dev/null 2>&1 ; then
echo "Restore file "$VM_NAME".kvm.save in "$VM_SAVE_DIR" not found! Starting VM!!!"
vmstart
exit 1
fi
cd "$VM_SAVE_DIR"
echo "vmrestore \: Restoring VM "$VM_NAME""
virsh restore "$VM_SAVE_DIR"/"$VM_NAME".kvm.save && rm -f "$VM_SAVE_DIR"/"$VM_NAME".kvm.save
exit 0
}
# Here is the start of the main "program" :-)
case "$1" in
start)
case "$ACTION" in
save)
vmrestore
;;
shutdown)
vmstart
;;
esac
;;
stop)
case "$ACTION" in
save)
vmsave
;;
shutdown)
vmshutdown
;;
esac
;;
*)
N="$0"
echo "Usage: "$N" {start|stop}" >&2
exit 1
;;
esac
exit 0
########################################################
Please tell also if there is an official script for gracefully stopping / starting KVM VM's.
greets
saman
I have added the line
unset LANG # Ensure english user interface for text tools
to ensure it also works for non english locales.
Jarl
Hi Samman.
I have tried your script, excelent work. However the script does not wait for libvirtd to start, it seems like the line # Required-Start: $kvm $libvirtd only ensures that kvm is started.
I have cleaned up the script to have identical indentation for the init script comments:
### BEGIN INIT INFO
# Provides: kvm-rcs-YOUR_VM_NAME
# Required-Start: $kvm $libvirtd
# Required-Stop: $kvm $libvirtd
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starting/Saving, Stopping/Restoring kvm-rcs-
# Description: Starting/Saving, Stopping/Restoring KVM guest.
### END INIT INFO#
This seem to have helped.
I have also made some other improvements, but somehow I don't feel this is the right place for developing a script together... Please let me know if you are interested.
Jarl
I should have used the pre tag in stead of code tag. Here it goes.
hi Jarl
hi there,
sorry for beeing away for so long. now i've updated the rc kvm scripts.
changes that i have made were:
- the script is now fully virsh libvirt and only virsh cli statements are used for vm management. so it's easy to adopt them to xen for example ...
- every domain has its own script and all the domain-scripts are invoked from one script called "kvm-domains" (similar to xen :) )
- i have implemented it now under centos but it should work in general also under debian and derivatives.
- i will also post how to make a centos kvm host wait for the domains to shutdown before shutting down itself.
here is the "kvm-domains" script:
###########################################################################################################
#!/bin/sh
### BEGIN INIT INFO
# Provides: kvm-domains
# Default-Start: 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop kvm domains!
# Description: Start/Stop kvm domains!
# kvm-domains.
### END INIT INFO#
# the following is chkconfig init header for Redhat/Suse ...
#
# kvm-domains: Start/Stop kvm domains!
# chkconfig: 345 99 01
# description: Start/Stop kvm domains!
#
START_WAIT=3 # Time to wait between starting of the domains
STOP_WAIT=2 # Time to wait between shutdown of the domains
DEVNULL="/dev/null"
LIBVIRT="/etc/init.d/libvirtd"
KVM_RCS_DIR="/etc/init.d" # Directory where the startup scripts of the domains are located.
TIMEOUT=600 # Time to wait untill the KVM kernel modules are loaded and the libvirt daemon ist started
# and if of them fails within this time then we cancel the startup of the KVM domains.
start_kvm_libvirtd () {
COUNT=0
KVMINITFAIL=0
while [ "$COUNT" -lt "$TIMEOUT" ]; do
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 || ! pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 ; then
if [ $(grep -c vmx /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-intel > "$DEVNULL" 2>&1
fi
if [ $(grep -c svm /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-amd > "$DEVNULL" 2>&1
fi
modprobe ksm > "$DEVNULL" 2>&1 # This is CentOS specific I think!
fi
! pgrep ^libvirtd$ > "$DEVNULL" 2>&1 && "$LIBVIRT" start > "$DEVNULL" 2>&1
fi
if lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 && pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
COUNT="$TIMEOUT"
KVMINITFAIL=1
fi
sleep 5
COUNT=$(($COUNT+5))
done
if [ "$KVMINITFAIL" -eq 0 ] ; then
echo "!!!!!!!!!! Timeout happend inititalizing KVM. Exiting !!!!!!!!!" && exit 1
fi
}
# Here comes the main program!
case "$1" in
start)
start_kvm_libvirtd
COUNTER=0
COUNT=2 # How many times should we try to bring up the KVM domains. I experienced a bug in libvritd,
# and had to start saved domains twice to get them up!!!!! You can leave this at default!
DOMCOUNTER=0
while [ "$COUNTER" -lt "$COUNT" ] ; do
cd "$KVM_RCS_DIR"
for i in `ls kvm*rcs` ; do
"$KVM_RCS_DIR"/"$i" start
DOMCOUNTER=$(($DOMCOUNTER+1))
sleep "$START_WAIT"
done
if [ `virsh list|grep running|wc -l` -eq $DOMCOUNTER ] ; then
echo "All KVM domains started sucessfully" && exit 0
fi
COUNTER=$(($COUNTER+1))
done
echo "One or more KVM domains failed starting!!!" && exit 1
;;
stop)
start_kvm_libvirtd
cd "$KVM_RCS_DIR"
for i in `ls kvm*rcs` ; do
"$KVM_RCS_DIR"/"$i" stop
sleep "$STOP_WAIT"
done
while virsh list|grep running|grep -v grep ; do
sleep 5
done
exit 0
;;
status)
virsh list
;;
*)
echo $"Usage: "$0" {start|stop|status}"
exit 1
esac
exit 0
###########################################################################################################
Here is an example domain script
###########################################################################################################
#!/bin/sh
# Start/Stop script for KVM-QEMU domains. This scipt is invoked by the "kvm-domains" script!
VM_NAME="win0" # Name of your KVM domain. Check also the "virsh list" command.
TIMEOUT=300 # Time to wait while shutting down or saving! When gracefull shutdown or saving of the domain hangs we will kill the domain after 5 minutes.
VM_SAVE_DIR="/kvm/tmp/vm_save_dir" # Directory for storing the domain save data..
DEVNULL="/dev/null"
#ACTION="shutdown"
ACTION="save" # ACTION takes one argument, either "save" or "shutdown". In the "save" case it will save the domain when stopping and restore it when starting. In the "shtudown" case it will shutdown the domain when stopping and start it when starting.
vmshutdown () {
if ! virsh dominfo $VM_NAME|grep State|grep "running"|grep -v grep > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is not running!!! Exiting" && exit 1
fi
virsh shutdown "$VM_NAME" && echo "Shutting down "$VM_NAME"!"
COUNT=0
while [ "$COUNT" -lt "$TIMEOUT" ]; do
if ! virsh dominfo $VM_NAME|grep State|grep "running"|grep -v grep > "$DEVNULL" 2>&1; then
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "!!!!!!!!!! Coult not shutdown. Timeout happend. Destroying VM "$VM_NAME" !!!!!!!!!"
echo "!!!!!!!!!! Please check why we could not shutdown !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
virsh destroy "$VM_NAME" &
exit 1
}
vmstart () {
if virsh dominfo $VM_NAME|grep State|grep "running"|grep -v grep > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is allready running!!! Exiting" && exit 1
fi
virsh start "$VM_NAME"&
exit 0
}
vmsave () {
if ! virsh dominfo $VM_NAME|grep State|grep "running"|grep -v grep > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is not running!!! Exiting" && exit 1
fi
if [ ! -d "$VM_SAVE_DIR" ]; then
echo "creating "$VM_SAVE_DIR""
mkdir -p "$VM_SAVE_DIR"
fi
virsh save "$VM_NAME" "$VM_SAVE_DIR/$VM_NAME.kvm.save" &
echo "Saving VM "$VM_NAME""
COUNT=0
while [ "$COUNT" -lt "$TIMEOUT" ]; do
if ! virsh dominfo $VM_NAME|grep State|grep "running"|grep -v grep > "$DEVNULL" 2>&1; then
echo "Last saved at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.save.log
exit 0
fi
sleep 5
COUNT=$(($COUNT+5))
done
echo "!!!!!!!!!! Coult not save. Timeout happend. Destroying VM "$VM_NAME" !!!!!!!!!"
echo "!!!!!!!!!! Please check why we could not save !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
virsh destroy "$VM_NAME" &
exit 1
}
vmrestore () {
if virsh dominfo $VM_NAME|grep State|grep "running"|grep -v grep > "$DEVNULL" 2>&1; then
echo "VM "$VM_NAME" is allready running!!! Exiting" && exit 1
fi
if ! ls "$VM_SAVE_DIR"/"$VM_NAME".kvm.save > "$DEVNULL" 2>&1 ; then
echo "Restore file "$VM_NAME".kvm.save in "$VM_SAVE_DIR" not found! Starting VM!!!"
vmstart &
exit 1
fi
echo "Restoring VM "$VM_NAME"" && cd "$VM_SAVE_DIR"
virsh restore "$VM_SAVE_DIR"/"$VM_NAME".kvm.save && \
rm -f "$VM_SAVE_DIR"/"$VM_NAME".kvm.save && \
echo "Last restored at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.restore.log
exit 0
}
# Here is the start of the main "program" :-)
case "$1" in
start)
case "$ACTION" in
save)
vmrestore
;;
shutdown)
vmstart
;;
esac
;;
stop)
case "$ACTION" in
save)
vmsave
;;
shutdown)
vmshutdown
;;
esac
;;
*)
N="$0"
echo "Usage: "$N" {start|stop}" >&2
exit 1
;;
esac
exit 0
###########################################################################################################
to make a centos kvm host wait for the domains to shutdown before shutting down itself, i had to edit my "/etc/inittab"
(under debian this was working without to edit "/etc/inittab")
so my centos inittab looks like this now :
###########################################################################################################
#
# inittab This file describes how the INIT process should set up
# the system in a certain run-level.
#
# Author: Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
# Modified for RHS Linux by Marc Ewing and Donnie Barnes
#
# Default runlevel. The runlevels used by RHS are:
# 0 - halt (Do NOT set initdefault to this)
# 1 - Single user mode
# 2 - Multiuser, without NFS (The same as 3, if you do not have networking)
# 3 - Full multiuser mode
# 4 - unused
# 5 - X11
# 6 - reboot (Do NOT set initdefault to this)
#
id:3:initdefault:
# System initialization.
si::sysinit:/etc/rc.d/rc.sysinit
17:0:wait:/etc/init.d/kvm-domains stop
l0:0:wait:/etc/rc.d/rc 0
18:1:wait:/etc/init.d/kvm-domains stop
l1:1:wait:/etc/rc.d/rc 1
19:6:wait:/etc/init.d/kvm-domains stop
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
20:6:wait:/etc/init.d/kvm-domains stop
l6:6:wait:/etc/rc.d/rc 6
# Trap CTRL-ALT-DELETE
ca::ctrlaltdel:/sbin/shutdown -t3 -r now
# When our UPS tells us power has failed, assume we have a few minutes
# of power left. Schedule a shutdown for 2 minutes from now.
# This does, of course, assume you have powerd installed and your
# UPS connected and working correctly.
pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
# If power was restored before the shutdown kicked in, cancel it.
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"
# Run gettys in standard runlevels
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6
# Run xdm in runlevel 5
x:5:respawn:/etc/X11/prefdm -nodaemon
###########################################################################################################
tip: when u invoke the virt-manager on a centos host via ssh and x-forwarding then use absolute paths :)
cheers
Saman
system is Centos 5.4
These scripts are all seem to be based around a serial shutdown process which can have a maximum delay of 90 seconds per VM on the system. So if you have a large number of misbehaving VMs it can delay shutdown for a LONG time. That delay is way too long and unnecessary.
The two scripts below, while minimal, have a maximum total timeout of 90 seconds (or whatever you set) and run in parallel on all the VMs, resulting in a quick and efficient shutdown process. Despite the children all writing to the log file, in production this hasn't been an issue.
To install, copy the scripts to /etc/init.d and uou can enable them at shutdown with these two commands:
ln -s ../init.d/shutdown_vms /etc/rc6.d/K18shutdown_vms
ln -s ../init.d/shutdown_vms /etc/rc0.d/K18shutdown_vms
> cat /etc/init.d/shutdown_vms
#!/bin/bash
LISTFILE=/root/runvm.lst
LOGFILE=/var/log/kvmshutdown.log
GREP=/bin/grep
CUT=/usr/bin/cut
VIRSH=/usr/bin/virsh
TR=/usr/bin/tr
CAT=/bin/cat
# 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
( /etc/init.d/shutdown_vms.child "$vm" )&
done
for job in `jobs -p`
do
wait $job
done
> cat /etc/init.d/shutdown_vms.child
#!/bin/bash
TIMEOUT=90
LOGFILE=/var/log/kvmshutdown.log
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 > /dev/null
if [ "$?" -eq "1" ]
then
return 0
else
sleep 1
COUNT=$(($COUNT+1))
fi
done
echo kvmshutdown \: Timeout happened. Destroying VM $1
$VIRSH destroy $1
return 1
}
# The program begins here
if [ "$#" -ne "1" ]
then
echo ERROR: Wrong number of arguments!
exit 1
fi
VMN=$1
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
I could not get Robert's script to work on Lucid. Somehow virsh does not return the running domains anymore because of libvirt already shutting down.
I could get the solution found here to work on Lucid https://bugs.launchpad.net/ubuntu/+source/libvirt/+bug/350936
hi there,
Running Ubuntu Lucid 10.04-3 amd64 as a KVM host I ended up in writing
start/stop script running VMs! OK here we go again :-)
I never had to patch my system. It just runs out of the box!
> cat /usr/local/bin/kvm-domains.bin
###################################################################################
root@node1:~# cat /usr/local/bin/kvm-domains
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: kvm-domains
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop kvm domains!
# Description: Start/Stop kvm domains!
### END INIT INFO#
#
# Saman.Behnam@opensoft24.de 13.09.2011
# GPL system-V Start/Stop script for KVM VM's.
# Its developed and tested under Ubuntu Lucid 10.04-3 amd64 but should also work with
# Debian and derevatives.
#
# - Installation: please copy the scripts "kvm-domians.bin" and "kvm-domians"
# in to "/usr/local/bin" directory, cd to "/usr/local/bin" and run "./kvm-domians install"
#
# - Usage: we start the VM's with "service kvm-domians start" and shutdown the VM's
# with "service kvm-domians stop". However after installation this should be done
# automatically.
# After installation the is a file "/usr/local/bin/kvm-domains.txt".
# Please check that file beacuse here we can set the time that the script waits for a
# KVM guest. After that time if the VM does not appear or shutdown then we kill it!
# We can not wait endless if we are running a UPS host shutdown.
# Also the order the VM's are started/stopped e.g. start
# DNS/DHCP VM before others ...
# This script is also capable of save/restore VM's instead of shutdown/start them.
# This is good for VM's that are not willing to stop or taking unpredictable huge
# time e.g. Windows VM's to shutdown :-) .
#
# - Uninstallation: cd to "/usr/local/bin" and run "./kvm-domians uninstall"
#
# Timeout trying to start libvirt
LBVIRT_TIMEOUT=60
DEVNULL="/dev/null"
VM_FILE="kvm-domains.txt"
KVM_DOMAINS_BIN="kvm-domains.bin"
VIRSH="/usr/bin/virsh"
SCRIPTNAME="kvm-domains"
BIN_DIR="/usr/local/bin"
#drbd_degraded_node () {
# if [ -x "/sbin/drbdadm" ] ; then
# drbdadm primary all
# fi
#}
log_print_message () {
echo "$@"
logger -t "$SCRIPTNAME" "$@"
}
install_kvm_domains () {
if [ -x $BIN_DIR/$KVM_DOMAINS_BIN ] ; then
update-rc.d -f libvirt-bin remove
\cp -a $BIN_DIR/$SCRIPTNAME /etc/init.d
update-rc.d $SCRIPTNAME defaults
rm -f /etc/rc*.d/K*$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc0.d/K00$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc1.d/K00$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc6.d/K00$SCRIPTNAME
if cat /etc/init/libvirt-bin.conf | sed 's/^[ \t]*//g' | grep -v "#" | grep -q "stop on runlevel" ; then
log_print_message "I have to modify \"/etc/init/libvirt-bin.conf\"!"
log_print_message "Backing up \"/etc/init/libvirt-bin.conf\" to \"/etc/init/libvirt-bin.conf.origin\"!"
\cp -a /etc/init/libvirt-bin.conf /etc/init/libvirt-bin.conf.origin
sed -i 's/stop on runlevel/#stop on runlevel/g' /etc/init/libvirt-bin.conf
fi
if [ ! -s $BIN_DIR/$VM_FILE ] ; then
echo "# Add here the VM entrys in the following manner:" > $BIN_DIR/$VM_FILE
echo "# name of the VM (VM_NAME) save or shutdown VM (save/shutdown) Time waiting between VM shutdown (STOP_WAIT) Time waiting between VM start (START_WAIT)" >> $BIN_DIR/$VM_FILE
echo "#vm0 shutdown 45 20" >> $BIN_DIR/$VM_FILE
fi
else
log_print_message "Could not find \"$BIN_DIR/$KVM_DOMAINS_BIN\"! Exiting."
return 1
fi
}
uninstall_kvm_domains () {
update-rc.d libvirt-bin defaults
update-rc.d -f $SCRIPTNAME remove
cat /etc/init/libvirt-bin.conf | grep -q "#stop on runlevel" && sed -i 's/#stop on runlevel/stop on runlevel/g' /etc/init/libvirt-bin.conf
return 0
}
start_kvm_libvirtd () {
COUNT=0
while [ "$COUNT" -lt "$LBVIRT_TIMEOUT" ]; do
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 || ! pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 ; then
if [ $(grep -c vmx /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-intel > "$DEVNULL" 2>&1
fi
if [ $(grep -c svm /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-amd > "$DEVNULL" 2>&1
fi
fi
! pgrep ^libvirtd$ > "$DEVNULL" 2>&1 && libvirt-bin start > "$DEVNULL" 2>&1
fi
if lsmod|grep ^kvm_ > "$DEVNULL" 2>&1 && pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
COUNT="$LBVIRT_TIMEOUT"
KVMINITFAIL=0
else
KVMINITFAIL=1
fi
sleep 1
COUNT=$(($COUNT+1))
done
if [ "$KVMINITFAIL" -eq 1 ] ; then
log_print_message "Timeout happend inititalizing KVM. Exiting!"
echo "Timeout happend inititalizing KVM. Exiting!"|mail -s "Timeout happend inititalizing KVM. Exiting!" root && exit 1
fi
}
# Here comes the main program!
case "$1" in
start)
#drbd_degraded_node
start_kvm_libvirtd
for VM_NAME in $(cat $BIN_DIR/$VM_FILE|grep -v "^#"|awk '{ print $1 }') ; do
$BIN_DIR/$KVM_DOMAINS_BIN start $VM_NAME
sleep 1
done
;;
stop)
start_kvm_libvirtd
for VM_NAME in $(cat $BIN_DIR/$VM_FILE|grep -v "^#"|awk '{ print $1 }') ; do
$BIN_DIR/$KVM_DOMAINS_BIN stop $VM_NAME
sleep 1
done
for VM_NAME in $($VIRSH list |grep -v "^$"|awk 'NR > 2 {print $2}'); do
$BIN_DIR/$KVM_DOMAINS_BIN stop $VM_NAME
sleep 1
done
;;
install)
install_kvm_domains || exit 1
;;
uninstall)
uninstall_kvm_domains || exit 1
;;
*)
echo $"Usage: "$0" {start|stop}"
exit 1
esac
exit 0
###################################################################################
root@node1:~# cat /usr/local/bin/kvm-domains.bin
###################################################################################
#!/bin/sh
# Saman.Behnam@opensoft24.de 13.09.2011
# GPL Start/Stop script for KVM VM's. This script is invoked by the "kvm-domains" script!
# It is not recommended and not written to use it manually however when invoked manually
# e.g. "kvm-domains.bin start vm0" or "kvm-domains.bin stop vm0" ... it should work.
# All actions are logged to syslog.
# Its developed and tested under Ubuntu Lucid 10.04-3 amd64 but should also work with
# Debian and derevatives.
# For installation and usage please see "kvm-domains"
VM_SAVE_DIR="/kvm/kvmsave" # Directory for storing the domain save data..
DEVNULL="/dev/null"
VM_FILE="/usr/local/bin/kvm-domains.txt"
STOP_WAIT_PREDEF="120" # predfined value for $STOP_WAIT
START_WAIT_PREDEF="60"
ACTION_PREFDEF="shutdown" # predfined value for $ACTION
VM_NAME="$2"
COMMAND="$1"
VIRSH="/usr/bin/virsh"
SCRIPTNAME="kvm-domains.bin"
BIN_DIR="/usr/local/bin"
log_print_message () {
echo "$@"
logger -t "$SCRIPTNAME" "$@"
}
vmstart () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
log_print_message "VM "$VM_NAME" is allready running. Exiting!"
exit 1
fi
$VIRSH start $VM_NAME &
log_print_message "Starting $VM_NAME!"
COUNTER=0
while [ "$COUNTER" -lt "$START_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
echo "VM $VM_NAME started successfully."
sleep $(($START_WAIT-$COUNTER))
exit 0
fi
done
log_print_message "Failed starting VM $VM_NAME! Exiting."
exit 1
}
vmrestore () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
log_print_message "VM "$VM_NAME" is allready running. Exiting!"
exit 1
elif [ ! -r ""$VM_SAVE_DIR"/"$VM_NAME".kvm.save" ] ; then
log_print_message "Restore file $VM_NAME.kvm.save in \"$VM_SAVE_DIR\" not found! Exiting."
exit 1
fi
$VIRSH restore "$VM_SAVE_DIR"/"$VM_NAME".kvm.save &
log_print_message "Restoring VM $VM_NAME!"
COUNTER=0
while [ "$COUNTER" -lt "$START_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
log_print_message "VM $VM_NAME restored successfully."
rm -f "$VM_SAVE_DIR"/"$VM_NAME".kvm.save
echo "Last restored at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.restore.log
sleep $(($START_WAIT-$COUNTER))
exit 0
fi
done
log_print_message "Failed restoring VM $VM_NAME! Exiting"
exit 1
}
vmshutdown () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
log_print_message "$VM_NAME is shut off! Exiting."
exit 1
fi
$VIRSH shutdown "$VM_NAME" &
log_print_message "Shutting down $VM_NAME!"
COUNTER=0
while [ "$COUNTER" -lt "$STOP_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
log_print_message "VM $VM_NAME shut down successfully."
exit 0
fi
done
log_print_message "Failed shutdown VM $VM_NAME. Timed out! Destroying."
$VIRSH destroy $VM_NAME
exit 1
}
vmsave () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
log_print_message "VM $VM_NAME is not running. Exiting!"
exit 1
fi
if [ ! -d "$VM_SAVE_DIR" ]; then
log_print_message "creating "$VM_SAVE_DIR""
mkdir -p "$VM_SAVE_DIR"
fi
$VIRSH save "$VM_NAME" "$VM_SAVE_DIR/$VM_NAME.kvm.save" &
log_print_message "Saving VM "$VM_NAME""
COUNTER=0
while [ "$COUNTER" -lt "$STOP_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
echo "Last saved at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.save.log
log_print_message "VM $VM_NAME saved successfully."
exit 0
fi
done
echo "Could not save VM $VM_NAME. Timed out. Destroying `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.save.log
log_print_message "Failed saving VM $VM_NAME. Timed out. Destroying!"
$VIRSH destroy $VM_NAME
exit 1
}
# Here is the start of the main "program" :-)
if ! $VIRSH dominfo $VM_NAME > "$DEVNULL" 2>&1 ; then
log_print_message "No such VM $VM_NAME!"
log_print_message "Please check entry in \""$BIN_DIR/$VM_FILE"\"!"
log_print_message "Please check if VM $VM_NAME is defined in libvirt!"
log_print_message "Exiting."
exit 1
fi
if grep -q "^$VM_NAME" $BIN_DIR/$VM_FILE ; then
STOP_WAIT=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $3 }')
if echo $STOP_WAIT|egrep -q "^[0-9]+$" ; then
if [ ! $STOP_WAIT -ge 0 ] ; then
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message "STOP_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $STOP_WAIT for STOP_WAIT!"
fi
elif [ -z $STOP_WAIT ] ; then
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message "No STOP_WAIT entry found in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $STOP_WAIT for STOP_WAIT!"
else
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message "Please check your $BIN_DIR/$VM_FILE"
log_print_message "START_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
fi
START_WAIT=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $4 }')
if echo $START_WAIT|egrep -q "^[0-9]+$" ; then
if [ ! $START_WAIT -ge 0 ] ; then
START_WAIT=$START_WAIT_PREDEF
log_print_message "START_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
fi
elif [ -z $STOP_WAIT ] ; then
START_WAIT=$START_WAIT_PREDEF
log_print_message "No START_WAIT entry found in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
else
START_WAIT=$START_WAIT_PREDEF
log_print_message "Please check your $BIN_DIR/$VM_FILE!"
log_print_message "START_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
fi
ACTION=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $2 }')
if [ -z "$ACTION" ] ; then
ACTION=$ACTION_PREFDEF
log_print_message "No ACTION entry found in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $ACTION for ACTION!"
elif [ "$ACTION" != shutdown -a "$ACTION" != save ] ; then
ACTION=$ACTION_PREFDEF
log_print_message "Please check your $BIN_DIR/$VM_FILE!"
log_print_message "ACTION must be either \"save\" or \"shutdown\" in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $ACTION for ACTION!"
fi
else
STOP_WAIT=$STOP_WAIT_PREDEF
ACTION=$ACTION_PREFDEF
log_print_message "No such VM $VM_NAME entry in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $STOP_WAIT for STOP_WAIT!"
log_print_message "Using predefined value of $ACTION for ACTION!"
fi
case "$COMMAND" in
start)
case "$ACTION" in
save)
vmrestore
;;
shutdown)
vmstart
;;
esac
;;
stop)
case "$ACTION" in
save)
vmsave
;;
shutdown)
vmshutdown
;;
esac
;;
*)
N="$0"
echo "Usage: "$N" {start|stop}" >&2
exit 1
esac
exit 0
###################################################################################
have fun
Deshalb koennen Pinguine nicht fliegen. Was nicht fliegt, kann nicht abstuerzen!
hi there,
Running Ubuntu Lucid 10.04-3 amd64 as a KVM host I ended up in writing
start/stop script running VMs! OK here we go again :-)
I never had to patch my system. It just runs out of the box!
> cat /usr/local/bin/kvm-domains.bin
###################################################################################
root@node1:~# cat /usr/local/bin/kvm-domains
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: kvm-domains
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop kvm domains!
# Description: Start/Stop kvm domains!
### END INIT INFO#
#
# Saman.Behnam@opensoft24.de 13.09.2011
# GPL system-V Start/Stop script for KVM VM's.
# Its developed and tested under Ubuntu Lucid 10.04-3 amd64 but should also work with
# Debian and derevatives.
#
# - Installation: please copy the scripts "kvm-domians.bin" and "kvm-domians"
# in to "/usr/local/bin" directory, cd to "/usr/local/bin" and run "./kvm-domians install"
#
# - Usage: we start the VM's with "service kvm-domians start" and shutdown the VM's
# with "service kvm-domians stop". However after installation this should be done
# automatically.
# After installation the is a file "/usr/local/bin/kvm-domains.txt".
# Please check that file beacuse here we can set the time that the script waits for a
# KVM guest. After that time if the VM does not appear or shutdown then we kill it!
# We can not wait endless if we are running a UPS host shutdown.
# Also the order the VM's are started/stopped e.g. start
# DNS/DHCP VM before others ...
# This script is also capable of save/restore VM's instead of shutdown/start them.
# This is good for VM's that are not willing to stop or taking unpredictable huge
# time e.g. Windows VM's to shutdown :-) .
#
# - Uninstallation: cd to "/usr/local/bin" and run "./kvm-domians uninstall"
#
# Timeout trying to start libvirt
LBVIRT_TIMEOUT=60
DEVNULL="/dev/null"
VM_FILE="kvm-domains.txt"
KVM_DOMAINS_BIN="kvm-domains.bin"
VIRSH="/usr/bin/virsh"
SCRIPTNAME="kvm-domains"
BIN_DIR="/usr/local/bin"
#drbd_degraded_node () {
# if [ -x "/sbin/drbdadm" ] ; then
# drbdadm primary all
# fi
#}
log_print_message () {
echo "$@"
logger -t "$SCRIPTNAME" "$@"
}
install_kvm_domains () {
if [ -x $BIN_DIR/$KVM_DOMAINS_BIN ] ; then
update-rc.d -f libvirt-bin remove
\cp -a $BIN_DIR/$SCRIPTNAME /etc/init.d
update-rc.d $SCRIPTNAME defaults
rm -f /etc/rc*.d/K*$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc0.d/K00$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc1.d/K00$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc6.d/K00$SCRIPTNAME
if cat /etc/init/libvirt-bin.conf | sed 's/^[ \t]*//g' | grep -v "#" | grep -q "stop on runlevel" ; then
log_print_message "I have to modify \"/etc/init/libvirt-bin.conf\"!"
log_print_message "Backing up \"/etc/init/libvirt-bin.conf\" to \"/etc/init/libvirt-bin.conf.origin\"!"
\cp -a /etc/init/libvirt-bin.conf /etc/init/libvirt-bin.conf.origin
sed -i 's/stop on runlevel/#stop on runlevel/g' /etc/init/libvirt-bin.conf
fi
if [ ! -s $BIN_DIR/$VM_FILE ] ; then
echo "# Add here the VM entrys in the following manner:" > $BIN_DIR/$VM_FILE
echo "# name of the VM (VM_NAME) save or shutdown VM (save/shutdown) Time waiting between VM shutdown (STOP_WAIT) Time waiting between VM start (START_WAIT)" >> $BIN_DIR/$VM_FILE
echo "#vm0 shutdown 45 20" >> $BIN_DIR/$VM_FILE
fi
else
log_print_message "Could not find \"$BIN_DIR/$KVM_DOMAINS_BIN\"! Exiting."
return 1
fi
}
uninstall_kvm_domains () {
update-rc.d libvirt-bin defaults
update-rc.d -f $SCRIPTNAME remove
cat /etc/init/libvirt-bin.conf | grep -q "#stop on runlevel" && sed -i 's/#stop on runlevel/stop on runlevel/g' /etc/init/libvirt-bin.conf
return 0
}
start_kvm_libvirtd () {
COUNT=0
while [ "$COUNT" -lt "$LBVIRT_TIMEOUT" ]; do
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 || ! pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 ; then
if [ $(grep -c vmx /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-intel > "$DEVNULL" 2>&1
fi
if [ $(grep -c svm /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-amd > "$DEVNULL" 2>&1
fi
fi
! pgrep ^libvirtd$ > "$DEVNULL" 2>&1 && libvirt-bin start > "$DEVNULL" 2>&1
fi
if lsmod|grep ^kvm_ > "$DEVNULL" 2>&1 && pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
COUNT="$LBVIRT_TIMEOUT"
KVMINITFAIL=0
else
KVMINITFAIL=1
fi
sleep 1
COUNT=$(($COUNT+1))
done
if [ "$KVMINITFAIL" -eq 1 ] ; then
log_print_message "Timeout happend inititalizing KVM. Exiting!"
echo "Timeout happend inititalizing KVM. Exiting!"|mail -s "Timeout happend inititalizing KVM. Exiting!" root && exit 1
fi
}
# Here comes the main program!
case "$1" in
start)
#drbd_degraded_node
start_kvm_libvirtd
for VM_NAME in $(cat $BIN_DIR/$VM_FILE|grep -v "^#"|awk '{ print $1 }') ; do
$BIN_DIR/$KVM_DOMAINS_BIN start $VM_NAME
sleep 1
done
;;
stop)
start_kvm_libvirtd
for VM_NAME in $(cat $BIN_DIR/$VM_FILE|grep -v "^#"|awk '{ print $1 }') ; do
$BIN_DIR/$KVM_DOMAINS_BIN stop $VM_NAME
sleep 1
done
for VM_NAME in $($VIRSH list |grep -v "^$"|awk 'NR > 2 {print $2}'); do
$BIN_DIR/$KVM_DOMAINS_BIN stop $VM_NAME
sleep 1
done
;;
install)
install_kvm_domains || exit 1
;;
uninstall)
uninstall_kvm_domains || exit 1
;;
*)
echo $"Usage: "$0" {start|stop}"
exit 1
esac
exit 0
###################################################################################
root@node1:~# cat /usr/local/bin/kvm-domains
###################################################################################
#!/bin/sh
# Saman.Behnam@opensoft24.de 13.09.2011
# GPL Start/Stop script for KVM VM's. This script is invoked by the "kvm-domains" script!
# It is not recommended and not written to use it manually however when invoked manually
# e.g. "kvm-domains.bin start vm0" or "kvm-domains.bin stop vm0" ... it should work.
# All actions are logged to syslog.
# Its developed and tested under Ubuntu Lucid 10.04-3 amd64 but should also work with
# Debian and derevatives.
# For installation and usage please see "kvm-domains"
VM_SAVE_DIR="/kvm/kvmsave" # Directory for storing the domain save data..
DEVNULL="/dev/null"
VM_FILE="/usr/local/bin/kvm-domains.txt"
STOP_WAIT_PREDEF="120" # predfined value for $STOP_WAIT
START_WAIT_PREDEF="60"
ACTION_PREFDEF="shutdown" # predfined value for $ACTION
VM_NAME="$2"
COMMAND="$1"
VIRSH="/usr/bin/virsh"
SCRIPTNAME="kvm-domains.bin"
BIN_DIR="/usr/local/bin"
log_print_message () {
echo "$@"
logger -t "$SCRIPTNAME" "$@"
}
vmstart () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
log_print_message "VM "$VM_NAME" is allready running. Exiting!"
exit 1
fi
$VIRSH start $VM_NAME &
log_print_message "Starting $VM_NAME!"
COUNTER=0
while [ "$COUNTER" -lt "$START_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
echo "VM $VM_NAME started successfully."
sleep $(($START_WAIT-$COUNTER))
exit 0
fi
done
log_print_message "Failed starting VM $VM_NAME! Exiting."
exit 1
}
vmrestore () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
log_print_message "VM "$VM_NAME" is allready running. Exiting!"
exit 1
elif [ ! -r ""$VM_SAVE_DIR"/"$VM_NAME".kvm.save" ] ; then
log_print_message "Restore file $VM_NAME.kvm.save in \"$VM_SAVE_DIR\" not found! Exiting."
exit 1
fi
$VIRSH restore "$VM_SAVE_DIR"/"$VM_NAME".kvm.save &
log_print_message "Restoring VM $VM_NAME!"
COUNTER=0
while [ "$COUNTER" -lt "$START_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
log_print_message "VM $VM_NAME restored successfully."
rm -f "$VM_SAVE_DIR"/"$VM_NAME".kvm.save
echo "Last restored at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.restore.log
sleep $(($START_WAIT-$COUNTER))
exit 0
fi
done
log_print_message "Failed restoring VM $VM_NAME! Exiting"
exit 1
}
vmshutdown () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
log_print_message "$VM_NAME is shut off! Exiting."
exit 1
fi
$VIRSH shutdown "$VM_NAME" &
log_print_message "Shutting down $VM_NAME!"
COUNTER=0
while [ "$COUNTER" -lt "$STOP_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
log_print_message "VM $VM_NAME shut down successfully."
exit 0
fi
done
log_print_message "Failed shutdown VM $VM_NAME. Timed out! Destroying."
$VIRSH destroy $VM_NAME
exit 1
}
vmsave () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
log_print_message "VM $VM_NAME is not running. Exiting!"
exit 1
fi
if [ ! -d "$VM_SAVE_DIR" ]; then
log_print_message "creating "$VM_SAVE_DIR""
mkdir -p "$VM_SAVE_DIR"
fi
$VIRSH save "$VM_NAME" "$VM_SAVE_DIR/$VM_NAME.kvm.save" &
log_print_message "Saving VM "$VM_NAME""
COUNTER=0
while [ "$COUNTER" -lt "$STOP_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
echo "Last saved at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.save.log
log_print_message "VM $VM_NAME saved successfully."
exit 0
fi
done
echo "Could not save VM $VM_NAME. Timed out. Destroying `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.save.log
log_print_message "Failed saving VM $VM_NAME. Timed out. Destroying!"
$VIRSH destroy $VM_NAME
exit 1
}
# Here is the start of the main "program" :-)
if ! $VIRSH dominfo $VM_NAME > "$DEVNULL" 2>&1 ; then
log_print_message "No such VM $VM_NAME!"
log_print_message "Please check entry in \""$BIN_DIR/$VM_FILE"\"!"
log_print_message "Please check if VM $VM_NAME is defined in libvirt!"
log_print_message "Exiting."
exit 1
fi
if grep -q "^$VM_NAME" $BIN_DIR/$VM_FILE ; then
STOP_WAIT=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $3 }')
if echo $STOP_WAIT|egrep -q "^[0-9]+$" ; then
if [ ! $STOP_WAIT -ge 0 ] ; then
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message "STOP_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $STOP_WAIT for STOP_WAIT!"
fi
elif [ -z $STOP_WAIT ] ; then
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message "No STOP_WAIT entry found in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $STOP_WAIT for STOP_WAIT!"
else
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message "Please check your $BIN_DIR/$VM_FILE"
log_print_message "START_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
fi
START_WAIT=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $4 }')
if echo $START_WAIT|egrep -q "^[0-9]+$" ; then
if [ ! $START_WAIT -ge 0 ] ; then
START_WAIT=$START_WAIT_PREDEF
log_print_message "START_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
fi
elif [ -z $STOP_WAIT ] ; then
START_WAIT=$START_WAIT_PREDEF
log_print_message "No START_WAIT entry found in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
else
START_WAIT=$START_WAIT_PREDEF
log_print_message "Please check your $BIN_DIR/$VM_FILE!"
log_print_message "START_WAIT must be an integer greater 0 in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $START_WAIT for START_WAIT!"
fi
ACTION=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $2 }')
if [ -z "$ACTION" ] ; then
ACTION=$ACTION_PREFDEF
log_print_message "No ACTION entry found in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $ACTION for ACTION!"
elif [ "$ACTION" != shutdown -a "$ACTION" != save ] ; then
ACTION=$ACTION_PREFDEF
log_print_message "Please check your $BIN_DIR/$VM_FILE!"
log_print_message "ACTION must be either \"save\" or \"shutdown\" in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $ACTION for ACTION!"
fi
else
STOP_WAIT=$STOP_WAIT_PREDEF
ACTION=$ACTION_PREFDEF
log_print_message "No such VM $VM_NAME entry in $BIN_DIR/$VM_FILE!"
log_print_message "Using predefined value of $STOP_WAIT for STOP_WAIT!"
log_print_message "Using predefined value of $ACTION for ACTION!"
fi
case "$COMMAND" in
start)
case "$ACTION" in
save)
vmrestore
;;
shutdown)
vmstart
;;
esac
;;
stop)
case "$ACTION" in
save)
vmsave
;;
shutdown)
vmshutdown
;;
esac
;;
*)
N="$0"
echo "Usage: "$N" {start|stop}" >&2
exit 1
esac
exit 0
###################################################################################
have fun
Deshalb koennen Pinguine nicht fliegen. Was nicht fliegt, kann nicht abstuerzen!
On Lucid 10.04-3 Apparmor was running in enforcing mode controlling "libvirt-bin"
In lack of time and also because of my host runs KVM and only KVM, I did not test it instead I disabled it.
service apparmor stop; update-rc.d -f apparmor remove
hello
please delete this post, the scripts are bugy!
check the last one at 13.09.2011 and the first on at 14.09.2011
thanks
cat kvm-domains
#!/bin/sh
#
### BEGIN INIT INFO
# Provides: kvm-domains
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/Stop kvm domains!
# Description: Start/Stop kvm domains!
### END INIT INFO#
#
# Saman.Behnam@opensoft24.de 13.09.2011
# GPL system-V Start/Stop script for KVM VM's.
# Its developed and tested under Ubuntu Lucid 10.04-3 amd64 but should also work with
# Debian and derivatives with Upstart system.
#
# - Installation: please copy the scripts "kvm-domians.bin" and "kvm-domians"
# in to "/usr/local/bin" directory, cd to "/usr/local/bin" and run "./kvm-domians install"
#
# - Usage: we start the VM's with "service kvm-domians start" and shutdown the VM's
# with "service kvm-domians stop". However after installation this should be done
# automatically.
# After installation the is a file "/usr/local/bin/kvm-domains.txt".
# Please check that file beacuse here we must list the VM's that we want to be autostarted
# with host start up. Here we can set the time that the script waits for a
# KVM guest. After that time if the VM does not appear or shutdown then we kill it!
# We can not wait endless if we are running a UPS host shutdown.
# Also the order the VM's are started/stopped e.g. start
# DNS/DHCP VM before others ...
# This script is also capable of save/restore VM's instead of shutdown/start them.
# This is good for VM's that are not willing to stop or taking unpredictable huge
# time e.g. Windows VM's to shutdown :-) .
# VM's that we want to be autostarted with host start up must be listed in "/usr/local/bin/kvm-domains.txt"
#
# - Uninstallation: cd to "/usr/local/bin" and run "./kvm-domians uninstall"
# Timeout trying to start libvirt
LBVIRT_TIMEOUT=60
DEVNULL="/dev/null"
VM_FILE="kvm-domains.txt"
KVM_DOMAINS_BIN="kvm-domains.bin"
VIRSH="/usr/bin/virsh"
SCRIPTNAME="kvm-domains"
BIN_DIR="/usr/local/bin"
#drbd_degraded_node () {
# if [ -x "/sbin/drbdadm" ] ; then
# drbdadm primary all
# fi
#}
log_print_message () {
echo "$@"
logger -t "$SCRIPTNAME" "$@"
}
install_kvm_domains () {
if [ -x $BIN_DIR/$KVM_DOMAINS_BIN ] ; then
update-rc.d -f libvirt-bin remove
\cp -a $BIN_DIR/$SCRIPTNAME /etc/init.d
update-rc.d $SCRIPTNAME defaults
rm -f /etc/rc*.d/K*$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc0.d/K00$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc1.d/K00$SCRIPTNAME
ln -s /etc/init.d/$SCRIPTNAME /etc/rc6.d/K00$SCRIPTNAME
if cat /etc/init/libvirt-bin.conf | sed 's/^[ \t]*//g' | grep -v "#" | grep -q "stop on runlevel" ; then
log_print_message 'I have to modify "/etc/init/libvirt-bin.conf"!'
log_print_message 'Backing up "/etc/init/libvirt-bin.conf" to "/etc/init/libvirt-bin.conf.origin"!'
\cp -a /etc/init/libvirt-bin.conf /etc/init/libvirt-bin.conf.origin
sed -i 's/stop on runlevel/#stop on runlevel/g' /etc/init/libvirt-bin.conf
fi
if [ ! -s $BIN_DIR/$VM_FILE ] ; then
echo "# Add here the VM entrys in the following manner:" > $BIN_DIR/$VM_FILE
echo "# name of the VM (VM_NAME) save or shutdown VM (save/shutdown) Time waiting between VM shutdown (STOP_WAIT) Time waiting between VM start (START_WAIT)" >> $BIN_DIR/$VM_FILE
echo "#vm0 shutdown 45 20" >> $BIN_DIR/$VM_FILE
fi
else
log_print_message 'Could not find "'$BIN_DIR'/'$KVM_DOMAINS_BIN'"! Exiting.'
return 1
fi
}
uninstall_kvm_domains () {
update-rc.d libvirt-bin defaults
update-rc.d -f $SCRIPTNAME remove
cat /etc/init/libvirt-bin.conf | grep -q "#stop on runlevel" && sed -i 's/#stop on runlevel/stop on runlevel/g' /etc/init/libvirt-bin.conf
return 0
}
start_kvm_libvirtd () {
COUNT=0
while [ "$COUNT" -lt "$LBVIRT_TIMEOUT" ]; do
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 || ! pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
if ! lsmod|grep ^kvm_|grep -v grep > "$DEVNULL" 2>&1 ; then
if [ $(grep -c vmx /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-intel > "$DEVNULL" 2>&1
fi
if [ $(grep -c svm /proc/cpuinfo) -ne 0 ]; then
modprobe kvm-amd > "$DEVNULL" 2>&1
fi
fi
! pgrep ^libvirtd$ > "$DEVNULL" 2>&1 && libvirt-bin start > "$DEVNULL" 2>&1
fi
if lsmod|grep ^kvm_ > "$DEVNULL" 2>&1 && pgrep ^libvirtd > "$DEVNULL" 2>&1 ; then
COUNT="$LBVIRT_TIMEOUT"
KVMINITFAIL=0
else
KVMINITFAIL=1
fi
sleep 1
COUNT=$(($COUNT+1))
done
if [ "$KVMINITFAIL" -eq 1 ] ; then
log_print_message 'Timeout happend inititalizing KVM. Exiting!'
echo "Timeout happend inititalizing KVM. Exiting!"|mail -s "Timeout happend inititalizing KVM. Exiting!" root && exit 1
fi
}
# Here comes the main program!
case "$1" in
start)
#drbd_degraded_node
start_kvm_libvirtd
for VM_NAME in $(cat $BIN_DIR/$VM_FILE|grep -v "^#"|awk '{ print $1 }') ; do
$BIN_DIR/$KVM_DOMAINS_BIN start $VM_NAME
sleep 1
done
;;
stop)
start_kvm_libvirtd
for VM_NAME in $(cat $BIN_DIR/$VM_FILE|grep -v "^#"|awk '{ print $1 }') ; do
$BIN_DIR/$KVM_DOMAINS_BIN stop $VM_NAME
sleep 1
done
for VM_NAME in $($VIRSH list |grep -v "^$"|awk 'NR > 2 {print $2}'); do
$BIN_DIR/$KVM_DOMAINS_BIN stop $VM_NAME
sleep 1
done
;;
install)
install_kvm_domains || exit 1
;;
uninstall)
uninstall_kvm_domains || exit 1
;;
*)
echo $"Usage: "$0" {start|stop}"
exit 1
esac
exit 0
##################################################################
cat kvm-domains.bin
#!/bin/sh
# Saman.Behnam@opensoft24.de 13.09.2011
# GPL Start/Stop script for KVM VM's. This script is invoked by the "kvm-domains" script!
# It is not recommended and not written to use it manually however when invoked manually
# e.g. "kvm-domains.bin start vm0" or "kvm-domains.bin stop vm0" ... it should work.
# All actions are logged to syslog.
# Its developed and tested under Ubuntu Lucid 10.04-3 amd64 but should also work with
# Debian and derevatives.
# For installation and usage please see "kvm-domains"
VM_SAVE_DIR="/kvm/kvmsave" # Directory for storing the domain save data..
DEVNULL="/dev/null"
VM_FILE="kvm-domains.txt"
STOP_WAIT_PREDEF="120" # predfined value for $STOP_WAIT
START_WAIT_PREDEF="60"
ACTION_PREFDEF="shutdown" # predfined value for $ACTION
VM_NAME="$2"
COMMAND="$1"
VIRSH="/usr/bin/virsh"
SCRIPTNAME="kvm-domains.bin"
BIN_DIR="/usr/local/bin"
log_print_message () {
echo "$@"
logger -t "$SCRIPTNAME" "$@"
}
vmstart () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
log_print_message 'VM '$VM_NAME' is allready running. Exiting!'
exit 1
fi
$VIRSH start $VM_NAME &
log_print_message 'Starting '$VM_NAME'!'
COUNTER=0
while [ "$COUNTER" -lt "$START_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
log_print_message 'VM '$VM_NAME' started successfully.'
sleep $(($START_WAIT-$COUNTER))
exit 0
fi
done
log_print_message 'Failed starting VM '$VM_NAME'! Exiting.'
exit 1
}
vmrestore () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
log_print_message 'VM '$VM_NAME' is allready running. Exiting!'
exit 1
elif [ ! -r ""$VM_SAVE_DIR"/"$VM_NAME".kvm.save" ] ; then
log_print_message 'Restore file '$VM_NAME'.kvm.save in "'$VM_SAVE_DIR'" not found! Exiting.'
exit 1
fi
$VIRSH restore "$VM_SAVE_DIR"/"$VM_NAME".kvm.save &
log_print_message 'Restoring VM '$VM_NAME'!'
COUNTER=0
while [ "$COUNTER" -lt "$START_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "running$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
log_print_message 'VM '$VM_NAME' restored successfully.'
rm -f "$VM_SAVE_DIR"/"$VM_NAME".kvm.save
echo "Last restored at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.restore.log
sleep $(($START_WAIT-$COUNTER))
exit 0
fi
done
log_print_message 'Failed restoring VM '$VM_NAME'! Exiting'
exit 1
}
vmshutdown () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
log_print_message ''$VM_NAME' is shut off! Exiting.'
exit 1
fi
$VIRSH shutdown "$VM_NAME" &
log_print_message 'Shutting down '$VM_NAME'!'
COUNTER=0
while [ "$COUNTER" -lt "$STOP_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
log_print_message 'VM '$VM_NAME' shut down successfully.'
exit 0
fi
done
log_print_message 'Failed shutdown VM '$VM_NAME'. Timed out! Destroying.'
$VIRSH destroy $VM_NAME
exit 1
}
vmsave () {
if $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
log_print_message 'VM '$VM_NAME' is not running. Exiting!'
exit 1
fi
if [ ! -d "$VM_SAVE_DIR" ]; then
log_print_message 'creating '$VM_SAVE_DIR''
mkdir -p "$VM_SAVE_DIR"
fi
$VIRSH save "$VM_NAME" "$VM_SAVE_DIR/$VM_NAME.kvm.save" &
log_print_message 'Saving VM '$VM_NAME''
COUNTER=0
while [ "$COUNTER" -lt "$STOP_WAIT" ]; do
if ! $VIRSH dominfo $VM_NAME|grep "^State:"|grep -q "shut off$" ; then
sleep 1
COUNTER=$(($COUNTER+1))
else
echo "Last saved at `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.save.log
log_print_message 'VM '$VM_NAME' saved successfully.'
exit 0
fi
done
echo "Failed saving VM $VM_NAME. Timed out. Destroying `date`" > "$VM_SAVE_DIR"/"$VM_NAME".kvm.save.log
log_print_message 'Failed saving VM '$VM_NAME'. Timed out. Destroying!'
$VIRSH destroy $VM_NAME
exit 1
}
# Here is the start of the main "program" :-)
if ! $VIRSH dominfo $VM_NAME > "$DEVNULL" 2>&1 ; then
log_print_message 'No such VM '$VM_NAME'!'
log_print_message 'Please check entry in "'$BIN_DIR'/'$VM_FILE'"!'
log_print_message 'Please check if VM '$VM_NAME' is defined in libvirt!'
log_print_message 'Exiting.'
exit 1
fi
if grep -q "^$VM_NAME" $BIN_DIR/$VM_FILE ; then
STOP_WAIT=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $3 }')
if echo $STOP_WAIT|egrep -q "^[0-9]+$" ; then
if [ ! $STOP_WAIT -ge 0 ] ; then
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message 'STOP_WAIT must be an integer greater 0 in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$STOP_WAIT' for STOP_WAIT!'
fi
elif [ -z $STOP_WAIT ] ; then
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message 'No STOP_WAIT entry found in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$STOP_WAIT' for STOP_WAIT!'
else
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message 'Please check your '$BIN_DIR'/'$VM_FILE''
log_print_message 'START_WAIT must be an integer greater 0 in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$START_WAIT' for START_WAIT!'
fi
START_WAIT=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $4 }')
if echo $START_WAIT|egrep -q "^[0-9]+$" ; then
if [ ! $START_WAIT -ge 0 ] ; then
START_WAIT=$START_WAIT_PREDEF
log_print_message 'START_WAIT must be an integer greater 0 in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$START_WAIT' for START_WAIT!'
fi
elif [ -z $STOP_WAIT ] ; then
START_WAIT=$START_WAIT_PREDEF
log_print_message 'No START_WAIT entry found in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$START_WAIT' for START_WAIT!'
else
START_WAIT=$START_WAIT_PREDEF
log_print_message 'Please check your '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'START_WAIT must be an integer greater 0 in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$START_WAIT' for START_WAIT!'
fi
ACTION=$(grep $VM_NAME $BIN_DIR/$VM_FILE|awk '{ print $2 }')
if [ -z "$ACTION" ] ; then
ACTION=$ACTION_PREFDEF
log_print_message 'No ACTION entry found in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$ACTION' for ACTION!'
elif [ "$ACTION" != shutdown -a "$ACTION" != save ] ; then
ACTION=$ACTION_PREFDEF
log_print_message 'Please check your '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'ACTION must be either "save" or "shutdown" in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$ACTION' for ACTION!'
fi
else
ACTION=$ACTION_PREFDEF
START_WAIT=$START_WAIT_PREDEF
STOP_WAIT=$STOP_WAIT_PREDEF
log_print_message 'No such VM '$VM_NAME' entry in '$BIN_DIR'/'$VM_FILE'!'
log_print_message 'Using predefined value of '$ACTION' for ACTION!'
log_print_message 'Using predefined value of '$START_WAIT' for START_WAIT!'
log_print_message 'Using predefined value of '$STOP_WAIT' for STOP_WAIT!'
fi
case "$COMMAND" in
start)
case "$ACTION" in
save)
vmrestore
;;
shutdown)
vmstart
;;
esac
;;
stop)
case "$ACTION" in
save)
vmsave
;;
shutdown)
vmshutdown
;;
esac
;;
*)
N="$0"
echo "Usage: "$N" {start|stop}" >&2
exit 1
esac
exit 0
###########################################################
have fun!
Post new comment