Script to gracefully power off KVM instances
authorMiguel Di Ciurcio Filho <miguel.filho@gmail.com>
Thu, 9 Dec 2010 16:00:20 +0000 (14:00 -0200)
committerMichael Hanselmann <hansmi@google.com>
Fri, 10 Dec 2010 15:13:50 +0000 (16:13 +0100)
When a node is running KVM instances and that node is rebooted or
shutdown, the gnt-noded daemon is finished and leaves the KVM instances
running. Latter on in the shutdown process, all remaining processes
receive SIGTERM as usual, meaning that the KVM instances are all
terminated, without running a proper shutdown procedure inside the
guests.

When using Xen, the xendomains script will take care of gracefully
powering down the instances, but for KVM there is nothing like that.

This patch adds an script that sends the "system_powerdown" command to
all running instances, and it could be useful for people using KVM.

This patch is a response for issue #126

Signed-off-by: Miguel Di Ciurcio Filho <miguel.filho@gmail.com>
Reviewed-by: Michael Hanselmann <hansmi@google.com>

Makefile.am
doc/examples/ganeti-kvm-poweroff.initd.in [new file with mode: 0644]

index 673e842..51d5913 100644 (file)
@@ -94,6 +94,7 @@ CLEANFILES = \
        devel/upload \
        doc/examples/bash_completion \
        doc/examples/ganeti.initd \
+       doc/examples/ganeti-kvm-poweroff.initd \
        doc/examples/ganeti.cron \
        doc/examples/gnt-config-backup \
        doc/examples/hooks/ipsec \
@@ -279,6 +280,7 @@ noinst_DATA = \
        doc/examples/bash_completion \
        doc/examples/ganeti.cron \
        doc/examples/ganeti.initd \
+       doc/examples/ganeti-kvm-poweroff.initd \
        doc/examples/gnt-config-backup \
        doc/examples/hooks/ipsec \
        $(manhtml)
@@ -356,6 +358,7 @@ EXTRA_DIST = \
        doc/conf.py \
        doc/html \
        doc/examples/ganeti.initd.in \
+       doc/examples/ganeti-kvm-poweroff.initd.in \
        doc/examples/ganeti.cron.in \
        doc/examples/gnt-config-backup.in \
        doc/examples/dumb-allocator \
diff --git a/doc/examples/ganeti-kvm-poweroff.initd.in b/doc/examples/ganeti-kvm-poweroff.initd.in
new file mode 100644 (file)
index 0000000..3449e56
--- /dev/null
@@ -0,0 +1,77 @@
+#!/bin/bash
+# ganeti kvm instance poweroff
+# based on skeleton from Debian GNU/Linux
+### BEGIN INIT INFO
+# Provides:          ganeti-kvm-poweroff
+# Required-Start:
+# Required-Stop:     drbd qemu-kvm $local_fs
+# Default-Start:
+# Default-Stop: 0 1 6
+# Short-Description: Poweroff Ganeti KVM instances
+# Description: Sends system_powerdown command to Ganeti instances, otherwise
+# they will be killed.
+### END INIT INFO
+
+shopt -s nullglob
+
+PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
+DESC="Ganeti KVM instance poweroff "
+
+. /lib/lsb/init-functions
+
+CONTROL_PATH="@LOCALSTATEDIR@/run/ganeti/kvm-hypervisor/ctrl"
+SCRIPTNAME="@SYSCONFDIR@/init.d/ganeti-kvm-poweroff"
+TIMEOUT=60
+
+do_kvm_poweroff () {
+    # shutdown VMs and remove sockets of those not running
+    for vm_monitor in $CONTROL_PATH/*.monitor; do
+        if ! echo system_powerdown | \
+            socat -U UNIX:$vm_monitor STDIO > /dev/null 2>&1; then
+            # remove disconnected socket
+            rm -f $vm_monitor
+        fi
+    done
+
+    log_action_begin_msg "Waiting VMs to poweroff"
+    waiting=true
+    remaning=$TIMEOUT
+    while $waiting && [ $remaning -ne 0 ]; do
+        if [[ -z "$(find $CONTROL_PATH -name '*.monitor')" ]]; then
+            break
+        fi
+
+        echo -n "."
+        for vm_monitor in $CONTROL_PATH/*.monitor; do
+            if ! echo | socat -U UNIX:$vm_monitor STDIO > /dev/null 2>&1; then
+                rm -rf $vm_monitor
+            fi
+        done
+
+        sleep 5
+        let remaining-=5 1
+    done
+
+    if [[ -z "$(find $CONTROL_PATH -name '*.monitor')" ]]; then
+        log_action_end_msg 0
+    else
+        log_action_end_msg 1 "some VMs did not shutdown"
+    fi
+}
+
+case "$1" in
+  start)
+    # No-op
+    ;;
+  restart|reload|force-reload)
+    echo "Error: argument '$1' not supported" >&2
+    exit 3
+    ;;
+  stop)
+    do_kvm_poweroff
+    ;;
+  *)
+    echo "Usage: $0 start|stop" >&2
+    exit 3
+    ;;
+esac