Call the rdns script with 3 users
[ganneffutils.git] / kvm-shell
index 7348af4..278b151 100644 (file)
--- a/kvm-shell
+++ b/kvm-shell
 #    GNU General Public License for more details.
 #
 # INSTALL:
 #    GNU General Public License for more details.
 #
 # INSTALL:
-# 1) create these entries for your users in /etc/sudoers (use visudo) :
+# 1) create these entries for your users in /etc/sudoers (use visudo)
+#    (in Debian its even better to use /etc/sudoers.d/kvm-shell, run
+#    visudo -f /etc/sudoers.d/kvm-shell):
 #    User_Alias   KVMUSERS = vuser1,vuser2
 #    Cmnd_Alias   KVM      = /usr/bin/virsh
 #    KVMUSERS     ALL      = NOPASSWD: KVM
 #    User_Alias   KVMUSERS = vuser1,vuser2
 #    Cmnd_Alias   KVM      = /usr/bin/virsh
 #    KVMUSERS     ALL      = NOPASSWD: KVM
-# 2) Create /usr/local/etc/kvm-shell-users (see config variable below) :
+# 2) Create /etc/kvm-shell/users (or whatever name you set USERSFILE
+#    to below):
 #    Format:
 #    Format:
-#      <username> <vm1, vm2, ....>
+#      <username> <vm1 vm2 ...>
 #    Example:
 #      vuser1 vm1
 #      vuser2 vm1 vm2 vm3
 #    Example:
 #      vuser1 vm1
 #      vuser2 vm1 vm2 vm3
@@ -34,96 +37,256 @@ VERSION="2.0"
 PROGRAM="kvm-shell"
 
 # configuration
 PROGRAM="kvm-shell"
 
 # configuration
-CURRENTUSER=${USER:-""}
-if [-z ${CURRENTUSER} ]; then
-    echo "Unknown user"
-    exit 1
-fi
 USERSFILE=/etc/kvm-shell/users
 USERSFILE=/etc/kvm-shell/users
+# What do we run for sudo?
 SUDO=/usr/bin/sudo
 SUDO=/usr/bin/sudo
+# Where is virsh
 VIRSH=/usr/bin/virsh
 VIRSH=/usr/bin/virsh
-MYEXIT=0
-
-function select_vm {
-# PARAMETERS: none
-# DESCRIPTION: extract the vms which the current user is allowed to control and display them in a little menu
-    AVAILABLEVMS=$(egrep "^$CURRENTUSER " $USERSFILE | sed -e "s/$CURRENTUSER\(.*\)/\1/g")
-    MENUITEMS=""
-    COUNTER=0
-    NEWAVAILABLEVMS=""
-    for i in $AVAILABLEVMS; do
-           set +e
-        $SUDO $VIRSH domstate $i 2>/dev/null
-           foo=$?
-           set -e
-        if [ "$foo" = "0" ]; then
-            NEWAVAILABLEVMS="${NEWAVAILABLEVMS} ${i}"
-            COUNTER=$((COUNTER+1))
-            STATE=`$SUDO $VIRSH domstate $i|grep -v "^$" | sed -e "s/ /_/g"`
-            MENUITEMS="$MENUITEMS $i $STATE"
+# After how many seconds without input do we exit the dialogbox?
+TIMEOUTSECS=120
+# A tempdir. Whatever is in the environment before has precedence.
+TMPDIR=${TMPDIR:-"/tmp"}
+# Set to no if you do not want people to edit DNS information
+DO_RDNS="yes"
+# Where are the rdns files stored?
+# Files in that directory should be named after the VM they are for.
+# Inside kvm-shell they will just end up in an editor, whatever function
+# and format is required by the tool actually doing the rdns setup is up
+# to whatever, kvm-shell doesn't care
+# The files don't even need to be writable by the user, readable is enough.
+# (New version is edited in a tempfile, then given to RDNSSCRIPT)
+# Obviously RDNSSCRIPT should be able to replace them with the new version.
+RDNS=/etc/kvm-shell/rdns
+# A script to do whatever with the dns function after the editbox
+# is done. It gets two arguments:
+# 1 - the original file
+# 2 - the new edit from the user
+# 3 - the calling username (can be used for logging. Nice for sudo users)
+RDNSSCRIPT="${SUDO} /usr/local/bin/dodns"
+
+########################################################################
+# Helper functions                                                     #
+########################################################################
+# Simple function to cleanup whenever we exit.
+# This goes through all variable names in TEMPFILES and deletes the files
+# that those variables point to.
+function cleanup() {
+    ERRVAL=$?
+    trap - ERR EXIT TERM HUP INT QUIT
+
+    for TEMPFILE in ${TEMPFILES}; do
+        DELF=${!TEMPFILE:-""}
+        if [ -n "${DELF}" ] && [ -f "${DELF}" ]; then
+            rm -f "${DELF}"
         fi
     done
         fi
     done
-    AVAILABLEVMS=$NEWAVAILABLEVMS
-    selectedvm=`dialog --stdout --title "User $CURRENTUSER - please select your VM to manage" --menu "Available VMs:" 15 55 $COUNTER $MENUITEMS`
-    ret=$?
-    case $ret in
-           0)
-            while [ $MYEXIT -ne 2 ];
-            do
-                select_action
-            done
-            MYEXIT=0
-            ;;
-           1)
-            MYEXIT=1;;
-           255)
-            MYEXIT=1;;
-    esac
+    exit $ERRVAL
 }
 }
+# Define TEMPFILES so we are always sure it is there
+TEMPFILES=""
 
 
+########################################################################
+########################################################################
 
 
+########################################################################
+# Main functions come here                                             #
+########################################################################
 
 
-function select_action {
-# PARAMETERS: none
-# DESCRIPTION: display actions and execute them on the selected vm
-# REQUIRES: $selectedvm filled with a valid vm
-# actions displayed in menu:
-#   - dominfo
-#   - start
-#   - shutdown
-#   - reboot
-#   - destroy
-### TODO: Check if $selectedvm is really a valid vm (should be ok, but still ...)
-    STATE=`$SUDO $VIRSH domstate $selectedvm|grep -v "^$" | sed -e "s/ /_/g"`
-    selectedaction=`dialog --stdout --title "User $CURRENTUSER - please select action for VM $selectedvm" --menu "Available actions for VM $selectedvm ($STATE):" 15 55 5  "dominfo" "" "console" "" "start" "" "shutdown" "" "reboot" "" "destroy" ""`
+# Function to handle reverse DNS setup. Basically uses dialogs editbox
+# to let user edit a file, then hands that over to RDNSSCRIPT.
+# Arguments: VM name
+function revdns() {
+    local VM=${1:-""}
+    if [ -z ${VM} ]; then
+        # No VM, byebye
+        return
+    fi
+    local dnsfile="${RDNS}/${VM}"
+    if [ -f "${dnsfile}" ]; then
+        # edit it, put output into a tempfile for processing
+        dnsedit=$(mktemp -p "${TMPDIR}" kvmshell.XXXXXXXX)
+        TEMPFILES="${TEMPFILES} dnsedit"
+        set +e
+        dialog --backtitle "KVM Shell ${VERSION}" \
+            --title "User ${USER} - Edit reverse DNS for VM ${VM}" \
+            --cancel-label "Cancel, don't save" --ok-label "Apply" \
+            --timeout ${TIMEOUTSECS} \
+            --editbox ${dnsfile} 22 78 2>${dnsedit}
+        ret=$?
+        set -e
+        case ${ret} in
+            0)
+                # Clean exit, means we have something to do
+                echo "Applying changes, please be patient..."
+                ${RDNSSCRIPT} "${dnsfile}" "${dnsedit}" "${USER}"
+                ;;
+            *)
+                # Anything else means we send em to the shredder...
+                echo "Break, not changing RDNS for ${VM}"
+                ;;
+        esac
+        rm -f "${dnsedit}"
+    fi
+}
+
+# Just split out a little helptext
+function helpbox() {
+    set +e
+    dialog --stdout --backtitle "KVM Shell ${VERSION}" \
+        --title "User ${USER} - Help" \
+        --msgbox "                         KVM Shell ${VERSION}
+
+This is the KVM Shell Version ${VERSION}, written by Joerg Jaspert,
+based on an initial version from Michael Kress.
+
+KVM Shell allows you to manage your domains daily operations
+such as using its serial console, starting or stopping it.
+
+You may also, if configured, change the reverse DNS for the
+IP addresses associated with your VM.
+
+Simply select the VM you want to manage and then follow the
+menu options given to you.
+
+[This text could be extended. Want to write it?]
+" 20 70
+    set -e
+    return 0
+
+}
+
+########################################################################
+
+# main_menu: Find the VMs for the current user and display a menu to
+#            select from
+# No arguments
+function main_menu {
+    local AVAILABLEVMS=$(egrep "^${USER} " "${USERSFILE}")
+    # Only end up with the VMs, not the username too
+    AVAILABLEVMS=${AVAILABLEVMS#* }
+    local MENUITEMS=""
+    local COUNTER=0
+    for vm in ${AVAILABLEVMS}; do
+        set +e
+        local STATE=$(${SUDO} ${VIRSH} domstate $vm 2>/dev/null)
+        local ret=$?
+        set -e
+        # if virsh got us nothing we replace it with "unknown"
+        STATE=${STATE:-"unknown"}
+        # dialog is picky-picky-annoying, so we want to ensure there isnt a space anywhere in STATE
+        STATE=${STATE// /-}
+        if [ "${ret}" = 0 ]; then
+            COUNTER=$(( COUNTER+1 ))
+            MENUITEMS="${MENUITEMS} ${vm} ${STATE}"
+        fi
+    done
+    dialogout=$(mktemp -p "${TMPDIR}" kvmshell.XXXXXXXX)
+    TEMPFILES="${TEMPFILES} dialogout"
+    set +e
+    dialog --backtitle "KVM Shell ${VERSION}" \
+        --title "User ${USER} - Select VM to manage" \
+        --cancel-label "Exit" --ok-label "Select VM" \
+        --help-button --timeout ${TIMEOUTSECS} \
+        --menu 'Available VMs:' 15 55 ${COUNTER} ${MENUITEMS} 2>${dialogout}
     ret=$?
     ret=$?
-    clear
+    set -e
+    local selvm=$(cat "${dialogout}")
+    rm -f "${dialogout}"
     case $ret in
     case $ret in
-           0)
-            #echo "$SUDO $VIRSH $selectedaction $selectedvm"
-            case $selectedaction in
-                       dominfo|console|start|shutdown|reboot|destroy)
-                           set +e
-                    $SUDO $VIRSH $selectedaction $selectedvm
-                           set -e
-                    ;;
-            esac
-            sleep 1
-            read -p "[Hit Return]" x
+        0)
+            # Clean exit, means selected a VM, lets call its action menu
+            select_action ${selvm}
             ;;
             ;;
-           1)
-            MYEXIT=2
+        2)
+            # Hoowah, help? Go away.
+            helpbox
             ;;
             ;;
-           255)
-            MYEXIT=2
+        *)
+            # Anything else means we send em to the shredder...
+            exit
             ;;
     esac
 }
 
             ;;
     esac
 }
 
+# Deal with a VM directly, do whatever (console, dominfo, ...)
+# Takes on argument, the VM name
+function select_action {
+    local selvm=${1:-""}
+    if [ -z "${selvm}" ]; then
+        return 2
+    fi
+    set +e
+    STATE=$(${SUDO} ${VIRSH} domstate ${selvm} 2>/dev/null)
+    ret=$?
+    set -e
+    if [ ${ret} -ne 0 ]; then
+        dialog --sleep 5 --title "User ${USER} - unknown VM Selected" --infobox "\nHeyho, you selected an unknown VM" 5 40
+        return
+    fi
+    while :; do
+        dialogout=$(mktemp -p "${TMPDIR}" kvmshell.XXXXXXXX)
+        TEMPFILES="${TEMPFILES} dialogout"
+        set +e
+        dialog --backtitle "KVM Shell ${VERSION}" \
+            --title "User ${USER} - please select action for VM ${selvm} (${STATE})" \
+            --cancel-label "Main Menu" --ok-label "Select Action" \
+            --help-button --timeout ${TIMEOUTSECS} \
+            --menu "Available actions for VM ${selvm} ($STATE):" 15 65 10 \
+            "dominfo"  "Information about your VM" \
+            "console"  "Serial console access" \
+            "start"    "Boot a stopped VM" \
+            "shutdown" "Stop a running VM" \
+            "reboot"   "Reboot a running VM" \
+            "destroy"  "Kill a VM (as if power cable pulled)" \
+            "rdns"     "Edit reverse DNS of IPs for the VM" \
+            "mainmenu" "Back to main menu" 2>${dialogout}
+        ret=$?
+        set -e
+        local selact=$(cat "${dialogout}")
+        rm -f "${dialogout}"
+        clear
+        case ${ret} in
+            0)
+                case ${selact} in
+                    console)
+                        echo "Remember, you can leave the console with Strg+]"
+                        echo "Also, you may need to hit Enter once to see anything"
+                        echo ""
+                        ${SUDO} ${VIRSH} ${selact} ${selvm}
+                        ;;
+                    dominfo|start|shutdown|reboot|destroy)
+                        set +e
+                        ${SUDO} ${VIRSH} ${selact} ${selvm}
+                        set -e
+                        ;;
+                    rdns)
+                        if [ "${DO_RDNS}" = "yes" ]; then
+                            revdns ${selvm}
+                        else
+                            echo "Sorry, admin disabled this function. Maybe you should poke them with a stick?"
+                            sleep 2
+                        fi
+                        ;;
+                    mainmenu)
+                        return
+                        ;;
+                esac
+                read -p "[Hit Return]" x
+                ;;
+            2)
+                helpbox
+                ;;
+               *)
+                return
+                ;;
+        esac
+    done
+}
+
+trap cleanup EXIT TERM HUP INT QUIT
 
 
-# main loop
-while [ $MYEXIT -ne 1 ]; do
-    select_vm
+while :; do
+    main_menu
 done
 
 exit 0
 done
 
 exit 0