You are on page 1of 8

#!

/bin/bash
########################################################################
##########################
# vbctl.sh
# VirtualBox Control
# This script scans and shows information on all virtual machines installed on the current host
# allows to perform basic tasks (start, pause, stop, etc)
# Designed particularly for headless machines
#
# Version 1.0 - May 2, 2011
# Version 1.1 - July 2011 - Enable VRDE activation, improve presentation.
# Version 1.2 - August 2011 - Fix machine listing when having sharedfolders.
# Version 1.3 - August 2011 - Using UUID instead of name for all functions.
# Correctly handle machine names with spaces
# Code cleaning and ANSI colors on menus.
# Animation while reading machines status.
# New option to change VRDE port.
# Removal of temporary les on exit.
#
# Developed on Oracle Virtual Box 4.0.4 on linux
# Only tested on Linux
#
# Original versions (1.0 .. 1.2) by Carlos Acosta Alamo
# http://oracleexamples.wordpress.com
# Oracle DBA
#
# Version 1.3 by Joao Figueiredo
# http://www.enide.net
#
# Licensed under Creative Commons Attribution 3.0 Unported (CC BY 3.0)
# http://creativecommons.org/licenses/by/3.0/
# http://creativecommons.org/licenses/by/3.0/legalcode
#
########################################################################
###########################

## Virtualbox suggested VRDE ports


MIN_VRDE_PORT=5000
MAX_VRDE_PORT=5100

## ANSI foreground colors


NORMAL="\033[0m"

DARKRED="\033[31m"
RED="\033[31;1m"

DARKGREEN="\033[32m"
GREEN="\033[32;1m"

DARKYELLOW="\033[33m"
YELLOW="\033[33;1m"

DARKBLUE="\033[34m"
BLUE="\033[34;1m"

DARKPURPLE="\033[35m"
PURPLE="\033[35;1m"

DARKCYAN="\033[36m"
CYAN="\033[36;1m"

WHITE="\033[37;1m"
UNDERLINEWHITE="\033[37;4m"

## wheel animation
WHEEL_INDEX=1
WHEEL_CHARS[0]="-"
WHEEL_CHARS[1]="\\"
WHEEL_CHARS[2]="|"
WHEEL_CHARS[3]="/"
function animate_wheel()
{
# remove old char
echo -e "\b\b\c"

# print char
echo -e "${WHEEL_CHARS[$WHEEL_INDEX]} \c"

# increment index
WHEEL_INDEX=`expr $WHEEL_INDEX + 1`
if [ $WHEEL_INDEX -ge 4 ]; then WHEEL_INDEX=0;
}

#$1 nbr of spaces


function print_spaces()
{
SAVEIFS=$IFS
IFS="-"
if [ $1 -le 0 ]; then
return;

SPACES=$(seq -s " " $1 | sed 's/[0-9]//g')
echo -e -n ${SPACES}

IFS=$SAVEIFS
}

# $1 extra string for header


function print_header()
{
FREE_SPACE=59 # 80 - 19 for "VirtualBox Console " - 2 for []
REQUIRED_SPCS=`expr ${FREE_SPACE} - ${#1} + 1`

clear
echo -e "${WHITE}VirtualBox Console${NORMAL} \c"
print_spaces ${REQUIRED_SPCS}
echo -e "[$1]"
echo "--------------------------------------------------------------------------------"
echo ""
}

function refresh_vmdetails ()
{
print_header "scanning for virtual machines"
echo -e "Please wait - \c"
VMDETAILS=.vbox_vmdetails
TEMPFILE=.vbox_temp
TEMPFILE2=.vbox_temp2

# JP: IFS is the eld separator in BASH, default is space, so I'm redenig it to \n
# JP: so it's possible to iterate VM names with spaces in the for loop
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")

VM_GETINFO="Name:|Guest OS:|Memory size:|Number of CPUs:|State:|VRDE:|Hardware


UUID:"
index=1
rm -f $VMDETAILS >/dev/null 2>&1

# JP: redened the awk eld separator to \" to get the VM names with spaces
for i in `VBoxManage list vms|awk -F\" '{print $2}'` ; do
animate_wheel

VBoxManage showvminfo "$i"|egrep "$VM_GETINFO">$TEMPFILE2


head -7 $TEMPFILE2 >$TEMPFILE
while read vmdetail; do
echo -n "myvm$index) "$vmdetail >>$VMDETAILS
echo "" >>$VMDETAILS
done<$TEMPFILE
index=$(($index+1));
done

# JP: restore IFS state otherwise all echos print a lot of spaces
IFS=$SAVEIFS
}

function list_vm_details ()
{
print_header "virtual machine information"
grep $1 $VMDETAILS|sed -e "s/"$1"/ /"
}

function select_vm ()
{
response_valid=1
while [ $response_valid -gt 0 ];do
print_header "select id from the list or exit with CTRL-C"
for VMID in `grep "Name:" $VMDETAILS|awk '{print $1}'`
do
VMID=$VMID" "
VMNAME=`grep $VMID $VMDETAILS|sed -e 's/myvm//'|grep "Name:"`
VRDE=`grep $VMID $VMDETAILS|sed -e "s/${VMID}//g"|grep "VRDE:"|sed -e 's/, Multi.*//' -e
's/(//'`
VMSTATE=`grep $VMID $VMDETAILS|sed -e "s/${VMID}//g"|grep "State:"|sed 's/(since.*//'`"
"$VRDE

# JP: print in colors


case $VMSTATE in
##*"powered off"*) echo -e $DARKRED $VMNAME ${NORMAL};echo -e " "$VRDE ;;
##*"aborted"*) echo -e $RED $VMNAME ${NORMAL};echo -e " "$VRDE ;;
##*"running"*) echo -e $DARKGREEN $VMNAME ${NORMAL};echo -e " "$VRDE ;;
##*"paused"*) echo -e $YELLOW $VMNAME ${NORMAL};echo -e " "$VRDE ;;
##*) echo -e $NORMAL $VMNAME; echo -e " "$VMSTATE ;;
*"powered off"*) echo -e $DARKRED $VMNAME ${NORMAL}- $VRDE ;;
*"aborted"*) echo -e $RED $VMNAME ${NORMAL}- $VRDE ;;
*"running"*) echo -e $DARKGREEN $VMNAME ${NORMAL}- $VRDE ;;
*"paused"*) echo -e $YELLOW $VMNAME ${NORMAL}- $VRDE ;;
*) echo -e $NORMAL $VMNAME - $VMSTATE ;;
esac
done # for

No_VMs=`VBoxManage list vms|wc -l`

echo ""
echo -n "Select a VM Id: ";read SELECTED_VM
if echo $SELECTED_VM | grep "^[0-9]*$">/dev/null
then
if [ $SELECTED_VM -gt 0 -a $SELECTED_VM -le $No_VMs ];then
response_valid=0

done #while

SELECTED_VM=myvm$SELECTED_VM")"
SELECTED_VM_NAME=`grep $SELECTED_VM $VMDETAILS|grep "Name:"|awk -F\: '{print $2}'`
SELECTED_VM_UUID=`grep $SELECTED_VM $VMDETAILS|grep "Hardware UUID:"|awk -F\: '{print
$2}'`
#SELECTED_VM_STATUS=`grep $SELECTED_VM $VMDETAILS|grep "State:"|awk '{print $3}'`

list_vm_details $SELECTED_VM

echo "-------------------------------------------------------------------------------"
}

function STARTUP_VM ()
{
if grep $SELECTED_VM $VMDETAILS|grep "VRDE:"|grep "enabled" >/dev/null
then
echo "Starting up"
else
read -s -n 1 -p "Warning, VRDE is not enabled, enable it? (Y/[N])" SETVRDE
if [ $SETVRDE == "Y" ] || [ $SETVRDE == "y" ]
then
response_valid=1
while [ $response_valid = 1 ];do
echo
read -p "Enter port number (between $MIN_VRDE_PORT and $MAX_VRDE_PORT): "
PORTNUMBER
if [ $PORTNUMBER -ge $MIN_VRDE_PORT -a $PORTNUMBER -le $MAX_VRDE_PORT ]
>/dev/null 2>&1;then
VBoxManage modifyvm $SELECTED_VM_UUID --vrde on
VBoxManage modifyvm $SELECTED_VM_UUID --vrdeport $PORTNUMBER
response_valid=0
else
echo "Invalid port number, please choose between $MIN_VRDE_PORT and
$MAX_VRDE_PORT"

done

VBoxManage startvm $SELECTED_VM_UUID --type headless


}

function change_vrde_port ()
{
response_valid=1
while [ $response_valid = 1 ];do
echo ""
read -p "Enter port number (between $MIN_VRDE_PORT and $MAX_VRDE_PORT, 0 to return): "
PORTNUMBER
if [ $PORTNUMBER -eq 0 ]; then
return;
elif [ $PORTNUMBER -ge $MIN_VRDE_PORT -a $PORTNUMBER -le $MAX_VRDE_PORT ] >/dev/null
2>&1;then
VBoxManage modifyvm $SELECTED_VM_UUID --vrde on
VBoxManage modifyvm $SELECTED_VM_UUID --vrdeport $PORTNUMBER
response_valid=0
else
echo "Invalid port number, please try again"

done
}

control_vm()
{
response_valid=1
while [ $response_valid -gt 0 ];do
echo "Available Options"
echo ""
echo -e " 1) ${GREEN}STARTUP${NORMAL} (starts headless from Powered off or Saved)"
echo -e " 2) ${DARKYELLOW}Pause${NORMAL}"
echo -e " 3) ${DARKGREEN}Resume${NORMAL} (starts from paused)"
echo -e " 4) Reset"
echo -e " 5) ${RED}Power Off${NORMAL}"
echo -e " 6) Save state"
echo -e " 7) ${DARKRED}ACPI power button${NORMAL}"
echo -e " 8) ${PURPLE}Change VRDE port${NORMAL}"
echo -e ""
echo -e " 9) Select another machine"
echo -e ""
echo -n "Option: " ;read VM_ACTION

if echo $VM_ACTION | grep "^[0-9]*$">/dev/null


then
if [ $VM_ACTION -gt 0 -a $VM_ACTION -le 9 ];then
response_valid=0


done #while

case $VM_ACTION in
1 ) STARTUP_VM
echo -n "Press enter to continue..."; read dummy
;;
2 ) VBoxManage controlvm $SELECTED_VM_UUID pause
echo -n "Press enter to continue..."; read dummy
;;
3 ) VBoxManage controlvm $SELECTED_VM_UUID resume
echo -n "Press enter to continue..."; read dummy
;;
4 ) VBoxManage controlvm $SELECTED_VM_UUID reset
echo -n "Press enter to continue..."; read dummy
;;
5 ) VBoxManage controlvm $SELECTED_VM_UUID poweroff
echo -n "Press enter to continue..."; read dummy
;;
6 ) VBoxManage controlvm $SELECTED_VM_UUID savestate
echo -n "Press enter to continue..."; read dummy
;;
7 ) VBoxManage controlvm $SELECTED_VM_UUID acpipowerbutton
echo -n "Press enter to continue..."; read dummy
;;
8 ) change_vrde_port
;;
9 ) ;;
esac
}

function cleanup_before_exit()
{
echo -e "\nSee you soon...";
rm -f ${VMDETAILS} ${TEMPFILE} ${TEMPFILE2}
}

####
#### MAIN
####

#set -x

trap "cleanup_before_exit;exit" SIGINT SIGTERM


clear
while [ 1 = 1 ];do
refresh_vmdetails
select_vm
#read -s -n 1 -p "Press a key to continue.."
control_vm
done