From 5d9e167affc8cd412af05e984f58fcbadf48ebf5 Mon Sep 17 00:00:00 2001
From: Miguel Di Ciurcio Filho <miguel.filho@gmail.com>
Date: Thu, 9 Dec 2010 14:00:20 -0200
Subject: [PATCH] Script to gracefully power off KVM instances

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                               |  3 +
 doc/examples/ganeti-kvm-poweroff.initd.in | 77 +++++++++++++++++++++++
 2 files changed, 80 insertions(+)
 create mode 100644 doc/examples/ganeti-kvm-poweroff.initd.in

diff --git a/Makefile.am b/Makefile.am
index 673e842a9..51d59134f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -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
index 000000000..3449e563c
--- /dev/null
+++ b/doc/examples/ganeti-kvm-poweroff.initd.in
@@ -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
-- 
GitLab