git.lirion.de

Of git, get, and gud

aboutsummaryrefslogtreecommitdiffstats
path: root/usr/local/bin/kvmhelper
diff options
context:
space:
mode:
authorH. P. <harald.p.@xmart.de> 2018-07-10 10:30:24 +0200
committerH. P. <harald.p.@xmart.de> 2018-07-10 10:30:24 +0200
commit819374205af3ae702a22d1dc6d0542d25ace05bd (patch)
treebd88dc1d01c9c03a51d52b4d802d18cbd6cf28d9 /usr/local/bin/kvmhelper
downloadkvm-helper-819374205af3ae702a22d1dc6d0542d25ace05bd.tar.bz2
Initial commit, ported from systemd-units.git
Diffstat (limited to 'usr/local/bin/kvmhelper')
-rwxr-xr-xusr/local/bin/kvmhelper215
1 files changed, 215 insertions, 0 deletions
diff --git a/usr/local/bin/kvmhelper b/usr/local/bin/kvmhelper
new file mode 100755
index 0000000..e24e6f5
--- /dev/null
+++ b/usr/local/bin/kvmhelper
@@ -0,0 +1,215 @@
+#!/bin/env bash
+
+# Script starts or stops KVM machines or networks in your environment through virsh.
+# I.e. your environment must be set up already so you
+# - either are able to administer the system's KVM environment (qemu:///system), or
+# - have your environment variables set up so you aim at the right KVM environment
+#
+# Future versions may explicitly ask for the QEMU URI variable and default to qemu:///system, but for
+# now we take this for granted that virsh works right for you without specific connection parameters.
+#
+# The maximum time in seconds to wait for the net-* commands to be successful:
+KHNTWAIT=10
+# The maximum time in seconds to wait for the machine commands to be successful:
+KHVMWAIT=60
+# The interval in seconds a network should be polled for status change when executing a start/shutdown -
+# while it is called *NT*, this will also be used for starting a VM:
+KHNTIVAL="5"
+# The interval in seconds a VM should be polled for status change when executing a shutdown:
+KHVMIVAL="10"
+
+##### SCRIPT FROM HERE #####
+
+
+export SHUDDUP=0
+prsopt=$(getopt -n "$0" -o q -- "$@")
+eval "set -- $prsopt"
+while [ "$#" -gt 0 ];do
+ case "$1" in
+ (-q) SHUDDUP=1;shift;;
+ (--) shift;break;;
+ (*) exit 1;;
+ esac
+done
+
+RETVAL=0
+KHCMD="$1"
+shift
+KHTARGS=( "$@" )
+declare -x INFOCMD STARTCMD STOPCMD ACTGREP ACTYES ACTNO KILLCMD QWAIT QSTATE
+export QLISTNPARMS=( "--name" "--all" )
+
+command -V virsh >/dev/null||exit 255
+command -V tput >/dev/null||exit 255
+
+kh_help() {
+ [ "$SHUDDUP" -eq 1 ]&&return
+ echo -n "USAGE: $(basename "$0") vm-start|vm-stop|net-start|net-stop"
+ echo " VMNAME|NETNAME [VMNAME|NETNAME ...]"
+}
+
+case "$KHCMD" in
+ "net-start"|"net-stop"|"vm-start"|"vm-stop")
+ [ "${#KHTARGS[@]}" -eq 0 ]&&echo "Please specify a target."&&kh_help&&exit 127
+ ;;
+ "")
+ echo "Please specify a command."
+ kh_help
+ exit 127
+ ;;
+ *)
+ echo "$KHCMD is not a valid command." >&2
+ kh_help
+ exit 127
+ ;;
+esac
+
+kh_status() {
+ # Function should be called with exit status of stop/start command or
+ # "start name"/"stop name" for the initial message.
+ case "$1" in
+ "start")
+ [ "$SHUDDUP" -eq 0 ]&&echo -ne "$(tput cub 666)[....] Starting $2...\\033[s\\033[K"||:
+ ;;
+ "stop")
+ [ "$SHUDDUP" -eq 0 ]&&echo -ne "$(tput cub 666)[....] Shutting down $2...\\033[s\\033[K"||:
+ ;;
+ 255)
+ [ "$SHUDDUP" -eq 0 ]&&echo -ne "$(tput cub 666)[$(tput setaf 3)WARN$(tput sgr0)]"
+ [ "$SHUDDUP" -eq 0 ]&&echo -e "\\033[u\\033[K successfully force-killed. ($(tput setaf 3)warn$(tput sgr0))"||:
+ ;;
+ 0)
+ [ "$SHUDDUP" -eq 0 ]&&echo -ne "$(tput cub 666)[$(tput setaf 2) OK $(tput sgr0)]"
+ [ "$SHUDDUP" -eq 0 ]&&echo -e "\\033[u\\033[K done."||:
+ ;;
+ 10)
+ [ "$SHUDDUP" -eq 0 ]&&echo -ne "$(tput cub 666)[$(tput setaf 7)DONE$(tput sgr0)]"
+ [ "$SHUDDUP" -eq 0 ]&&echo -e "\\033[u\\033[K already done."||:
+ ;;
+ *)
+ [ "$SHUDDUP" -eq 0 ]&&echo -ne "$(tput cub 666)[$(tput setaf 1)FAIL$(tput sgr0)]"
+ [ "$SHUDDUP" -eq 0 ]&&echo -e "\\033[u\\033[K $(tput setaf 1)failed$(tput sgr0)."||:
+ ;;
+ esac
+}
+kh_qstate() {
+ case "$ACTGREP" in
+ "") QSTATE="$(virsh "$INFOCMD" "$2" 2>/dev/null)";;
+ *) QSTATE="$(virsh "$INFOCMD" "$2" 2>&1|grep "$ACTGREP"|awk '{print $NF}')";;
+ esac
+ case "$1" in
+ "start")
+ [ "$QSTATE" == "$ACTYES" ]&&return 0||return 1
+ ;;
+ "stop")
+ [ "$QSTATE" == "$ACTNO" ]&&return 0||return 1
+ ;;
+ esac
+}
+kh_exec() {
+ # Function expects exactly two arguments: command and KVM net name to be started/stopped.
+ # RC:
+ # 1 if no argument passed or arguments invalid
+ # 2 if start is unsuccessful or times out.
+ FN="kh_exec"
+ [ -z "$1" ]&&echo "Critical exception in $FN(): no argument passed!" >&2&&exit 1
+ [ -z "$2" ]&&echo "Critical exception in $FN(): no network name passed!" >&2&&exit 1
+ if ! virsh "$LISTCMD" "${QLISTNPARMS[@]}"|grep "$2" >/dev/null;then
+ echo "Critical exception in $FN(): Network/VM $2 unknown!" >&2&&exit 2
+ fi
+ case "$1" in
+ "start") kh_status start "$2";;
+ "stop") kh_status stop "$2";;
+ esac
+ case "$1" in
+ "start")
+ kh_qstate start "$2"&&kh_status 10 "$2"&&return 0
+ ;;
+ "stop")
+ kh_qstate stop "$2"&&kh_status 10 "$2"&&return 0
+ ;;
+ esac
+ TOELAPSE="0"
+ while [ "$TOELAPSE" -lt "$QWAIT" ];do
+ case "$1" in
+ "start") virsh "$STARTCMD" "$2" >/dev/null 2>&1;;
+ "stop") virsh "$STOPCMD" "$2" >/dev/null 2>&1;;
+ esac
+ TOELAPSE=$((TOELAPSE+QIVAL))
+ sleep "$QIVAL"
+ [ "$SHUDDUP" -eq 0 ]&&echo -n "."
+ case "$1" in
+ "start")kh_qstate start "$2"&&break;;
+ "stop")kh_qstate stop "$2"&&break;;
+ esac
+ done
+ case "$1" in
+ "start")
+ if kh_qstate start "$2";then
+ kh_status 0
+ else
+ kh_status 1;RETVAL=20
+ fi
+ ;;
+ "stop")
+ if kh_qstate stop "$2";then
+ kh_status 0
+ else
+ virsh "$KILLCMD" "$2" >/dev/null 2>&1
+ if kh_qstate stop "$2";then
+ kh_status 255;RETVAL=255
+ else
+ kh_status 1;RETVAL=20
+ fi
+ fi
+ ;;
+ esac
+}
+kh_filter() {
+ # Function expects exactly two arguments: command and KVM net name to be started/stopped.
+ # This works as a pre-filter for knstart and knstop
+ # RC:
+ # 1 if no argument, no network name passed, or wrong syntax
+ # 2 if network/VM does not exist
+ # 3 if network/VM cannot be started
+ # 4 if network/VM state is not determinable
+ FN="kh_filter"
+ [ -z "$1" ]&&echo "Critical exception in $FN(): no argument passed!" >&2&&exit 1
+ [ -z "$2" ]&&echo "Critical exception in $FN(): no action specified!" >&2&&exit 1
+ [ -z "$3" ]&&echo "Critical exception in $FN(): no network/VM name passed!" >&2&&exit 1
+ case "$1" in
+ "net")
+ INFOCMD="net-info"; STARTCMD="net-start"
+ STOPCMD="net-destroy"; ACTGREP="^Active:"
+ ACTYES="yes"; ACTNO="no"
+ KILLCMD="$STOPCMD"; LISTCMD="net-list"
+ QWAIT="$KHNTWAIT"; QIVAL="$KHNTIVAL"
+ ;;
+ "vm")
+ INFOCMD="domstate"; STARTCMD="start"
+ STOPCMD="shutdown"; #ACTGREP="^State:"
+ ACTYES="running"; ACTNO="shut off"
+ KILLCMD="destroy"; LISTCMD="list"
+ QWAIT="$KHVMWAIT" QIVAL="$KHVMIVAL"
+ [ "$2" == "start" ]&&QIVAL="$KHNTIVAL"
+ ;;
+ esac
+ case "$2" in
+ "start") kh_exec start "$3";;
+ "stop") kh_exec stop "$3";;
+ *) echo "Invalid action $2 to $FN()!" >&2&&exit 1;;
+ esac
+}
+
+[ ${#KHTARGS} -eq 0 ]&&echo "No VM/network specified, aborting." >&2&&exit 127
+for i in "${KHTARGS[@]}";do
+ case "$KHCMD" in
+ "net-stop") kh_filter net stop "$i"||RETVAL="$((RETVAL+1))";;
+ "net-start") kh_filter net start "$i"||RETVAL="$((RETVAL+1))";;
+ "vm-stop") kh_filter vm stop "$i"||RETVAL="$((RETVAL+1))";;
+ "vm-start") kh_filter vm start "$i"||RETVAL="$((RETVAL+1))";;
+ esac
+
+done
+
+exit "$RETVAL"