Created
January 22, 2017 07:46
-
-
Save murank/5e1cb151a30c45bfc88b285781afea32 to your computer and use it in GitHub Desktop.
A trivial script to managee VMs on VirtualBox
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A trivial script to managee VMs on VirtualBox | |
test "$debug" == "y" && set -x | |
error() { | |
echo "$*" >&2 | |
} | |
usage() { | |
error "Usage: $0 list" | |
error " up [--gui] <vm>" | |
error " down <vm>" | |
error " suspend <vm>" | |
error " sandbox [list|begin|rollback|commit] <vm>" | |
} | |
check_vm_exists() { | |
local vm="$1" | |
if [ -z "$vm" ]; then | |
error "Target vm is not specified." | |
error | |
usage | |
return 1 | |
fi | |
if ! VBoxManage list vms | grep "\"$vm\"" > /dev/null; then | |
error "No such vm: $vm" | |
return 2 | |
fi | |
return 0 | |
} | |
execute() { | |
if ! "$@"; then | |
error "Fail to execute command: $@" | |
return 1 | |
fi | |
return 0 | |
} | |
wait_state() { | |
local vm="$1" | |
local expected="$2" | |
local timeout=60 | |
for i in `seq 0 $timeout`; do | |
execute VBoxManage showvminfo "$vm" --machinereadable | grep "VMState=\"$expected\"" > /dev/null && break | |
echo -n . | |
if [ $i -ge $timeout ]; then | |
echo "timeout" | |
return 1 | |
fi | |
sleep 1 | |
done | |
echo done | |
return 0 | |
} | |
action_list() { | |
VBoxManage list vms | sed -e 's/[^"]*"\([^"]*\)"[^"]*/\1/' | sort | |
} | |
action_up() { | |
case $1 in | |
"--gui") local type=gui; local vm="$2" ;; | |
*) local type=headless; local vm="$1" ;; | |
esac | |
check_vm_exists "$vm" || return 1 | |
execute VBoxManage startvm --type $type "$vm" || return 2 | |
} | |
action_down() { | |
local vm="$1" | |
check_vm_exists "$vm" || return 1 | |
echo -n "Shutting down $vm" | |
execute VBoxManage controlvm "$vm" acpipowerbutton || return 2 | |
wait_state "$vm" poweroff | |
} | |
action_suspend() { | |
local vm="$1" | |
check_vm_exists "$vm" || return 1 | |
echo "Suspending $vm..." | |
execute VBoxManage controlvm "$vm" savestate || return 2 | |
} | |
sandbox_prefix=Sandbox | |
action_sandbox_list() { | |
local vm="$1" | |
VBoxManage snapshot "$vm" list --machinereadable | awk "BEGIN { cnt=0 } /^SnapshotName[^=]*=\"$sandbox_prefix-/ { match(\$0, /\"[^\"]*\"/); print substr(\$0, RSTART+1, RLENGTH-2); cnt++ } END { if(cnt==0) {print \"$vm has not begun sandbox\"} }" | |
} | |
find_latest_sandbox_no() { | |
local vm="$1" | |
VBoxManage snapshot "$vm" list --machinereadable | awk "BEGIN { max_no=0; prefix_len=length(\"$sandbox_prefix \") } /^SnapshotName[^=]*=\"$sandbox_prefix-/ { match(\$0, /\"[^\"]*\"/); no=substr(\$0, RSTART+1+prefix_len, RLENGTH-2-prefix_len); if(no>max_no){max_no=no} } END { print max_no }" | |
} | |
action_sandbox_begin() { | |
local vm="$1" | |
local next_no=$(expr $(find_latest_sandbox_no "$vm") + 1) | |
echo "Taking snapshot..." | |
execute VBoxManage snapshot "$vm" take "$sandbox_prefix-$next_no" | |
} | |
action_sandbox_commit() { | |
local vm="$1" | |
local latest=$(find_latest_sandbox_no "$vm") | |
if [ $latest -eq 0 ]; then | |
error "$vm has not begun sandbox" | |
return 1 | |
fi | |
echo "Committing changes..." | |
execute VBoxManage snapshot "$vm" delete "$sandbox_prefix-$latest" | |
} | |
action_sandbox_rollback() { | |
local vm="$1" | |
local latest=$(find_latest_sandbox_no "$vm") | |
if [ $latest -eq 0 ]; then | |
error "$vm has not begun sandbox" | |
return 1 | |
fi | |
if VBoxManage showvminfo "$vm" --machinereadable | grep 'VMState="running"' > /dev/null; then | |
local type=$(VBoxManage showvminfo "$vm" --details | awk '/^Session type:/ { print $3 }') | |
execute VBoxManage controlvm "$vm" savestate || return 2 | |
fi | |
echo "Rolling back changes..." | |
execute VBoxManage snapshot "$vm" restore "$sandbox_prefix-$latest" && \ | |
execute VBoxManage snapshot "$vm" delete "$sandbox_prefix-$latest" || return 2 | |
if [ -n "$type" ]; then | |
execute VBoxManage startvm --type $type "$vm" | |
fi | |
} | |
action_sandbox() { | |
local vm="$2" | |
check_vm_exists "$vm" || return 1 | |
local prefix=Sandbox | |
case $1 in | |
"list") action_sandbox_list "$vm" ;; | |
"begin") action_sandbox_begin "$vm" ;; | |
"rollback") action_sandbox_rollback "$vm" ;; | |
"commit") action_sandbox_commit "$vm" ;; | |
*) | |
error "Unknown command: sandbox $1" | |
error | |
usage | |
return 1 | |
;; | |
esac | |
} | |
case $1 in | |
"list") action_list ;; | |
"up") action_up "$2" "$3" ;; | |
"down") action_down "$2" ;; | |
"suspend") action_suspend "$2" ;; | |
"sandbox") action_sandbox "$2" "$3" ;; | |
"") usage;; | |
*) echo "Unknown command: $1" >&2; echo >&2; usage ;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment