#!/bin/bash
# v10 - VirtualBox helper

set -e

source "/home/zwelch/src/mcf/mcsh-release/install/share/mcsh/mcsh.sh"

lib_load 'sys/tool/vbox'
lib_load "mcui"


######
# Configuration

v10_config_init() {
	script_setting_vars check_iso_name check_iso_image
}


######
# Generic Data CLI

_v10_data_list() {
	local dt=$1
	(eval cd "\$vbox_${dt}_dir" && run ls -1) \
		| eval sed -e "s,\\.\$vbox_${dt}_ext$,,"
}

_v10_data_info() {
	local dt=$1
	shift 1
	local -a datum
	datum=( $(_v10_data_list "$dt") )
	local hd
	for data in "${datum[@]}"; do
		local file sz
		file=$(vbox_data_filename "$dt" "$data")
		short=$(short_path "$file")
		sz=$(stat --printf "%s" "$file")
		sz=$(($sz / 1024 / 1024))
		printf "%-10s  %8sMB  %s\n" "$data" "$sz" "$short"
	done
}


######
# HD CLI

v10_hd() { cmd_dispatch "$@"; }
v10_hd_usage() {
	cat <<USAGE
<cmd> ...
Hard Disk Commands:
	list				Lists known Virtual Disk Images
	info				Lists image file sizes and paths
	exists <name>			Returns success if image exists
	create <name> [<sizeMB>]	Creates a disk image
	delete <name>			Deletes a disk image

HD Mounting Commands:
	partitions <name>		Shows image disk and partition info
	mounts [<name>+]		Lists mounted partitions
	mount <name> <part> <path>	Mount an image partition
	umount <name> <part>		Unmount an image partition
USAGE
}

v10_hd_exists() { vbox_hd_exists "$@"; }

v10_hd_list() { _v10_data_list hd; }
v10_hd_info() { _v10_data_info hd; }

v10_hd_create() {
	min_args 1 "$@"
	local name=$1
	local size=${2:-$vbox_hd_size}
	vbox_hd_create "$name" "$size"
}

v10_hd_delete() {
	min_args 1 "$@"
	for_each _v10_hd_delete "$@"
}
_v10_hd_delete() {
	local name=$1
	if ! v10_hd_exists "$name"; then
		info "$name: HD missing, skipped"
		return
	fi

	local result
	mcui_yesno_warn result "$name: delete HD file? "
	[ "$result" != yes ] || vbox_hd_delete "$name" true
}


######
# HD Mounting CLI

v10_hd_mounts() {
	if [ -z "${#*}" ]; then
		local -a hds
		hds=( $(v10_hd_list) )
		v10_hd_mounts "$@"
	else
		_v10_hd_mount_echo "Image Name" "Partition" "Mount Path"
		_v10_hd_mount_echo "----------" "---------" "----------"
		for_each _v10_hd_mount "$@"
	fi
}
_v10_hd_mount() {
	local -a mounts
	mounts=( $(vbox_mounttab_partitions "$1") )
	local m
	for m in "${mounts[@]}"; do
		_v10_hd_mount_echo "$1" "${m%:*}" "${m#*:}"
	done
}
_v10_hd_mount_echo() { printf "%-12s  %10s  %s\n" "$1" "$2" "$3"; }

v10_hd_partitions() { vbox_hd_image_partitions "$@"; }
v10_hd_mount() { vbox_hd_partition_mount "$@"; }
v10_hd_umount() { vbox_hd_partition_umount "$@"; }


######
# ISO CLI

v10_iso() { cmd_dispatch "$@"; }
v10_iso_usage() {
	cat<<USAGE
<cmd> ...
	list				Lists registered ISO images
	info <name>			Information about an ISO
	add <name> <file>		Add an ISO image
	delete <name>			Delete an ISO image
USAGE
}
v10_iso_list() { _v10_data_list iso; }
v10_iso_info() { _v10_data_info iso "$@"; }

v10_iso_add() { vbox_iso_add "$@"; }
v10_iso_delete() { vbox_iso_delete "$@"; }


######
# VM CLI

v10_vm() { cmd_dispatch "$@"; }
v10_vm_usage() {
	cat<<USAGE
<cmd> ...
VM Management Commands:
	list				Lists registered virtual machines
	info <name>			Shows VM information
	create <name>			Creates a VM
	delete <name>			Deletes a VM
	clone <name> <name>		Clones a VM

VM Control Commands:
	start <vm>			Starts the VM
	pause <vm>			Pauses the VM
	resume <vm>			Resumes the VM
	reset <vm>			Resets the VM
	poweroff <vm>			Powers off the VM

	headless <vm>			Run the VM headless

Command Groups:
	config ...			Configures the VM
	hd ...				Manages VM HD devices and media
	dvd ...				Manages VM DVD devices and media
	state ...			Manages VM states
	snapshot ...			Manages VM snapshots
USAGE
}

v10_vm_list() {
	vbox_manage list vms
}

v10_vm_info() {
	has_args 1 "$@"
	vbox_manage showvminfo "$1"
}

v10_vm_create() {
	has_args 1 "$@"
	local name=$1

	app_echo "vm: $name: creating new machine"
	vbox_vm_create "$name"

	app_echo "vm: $name: setting machine parameters"
	vbox_vm_modify "$name" --ioapic on
	vbox_vm_modify "$name" \
		--boot1 dvd --boot2 disk --boot3 none --boot4 none
	vbox_vm_modify "$name" --memory $vbox_mem_size --vram $vbox_vram_size

	v10_vm_config_rdp_start "$name"
	v10_vm_config_rdp_auth "$name" "host"

	vbox_sata_add "$name"
	vbox_ide_add "$name"
}

v10_vm_register() { vbox_vm_register "$1"; }
v10_vm_unregister() { vbox_vm_unregister "$1" false; }

v10_vm_delete() {
	has_args 1 "$@"
	local name=$1

	local result
	mcui_yesno_warn result "$name: delete VM files?"
	[ "$result" != yes ] || vbox_vm_unregister "$name" true
}

# VM Control CLI

v10_vm_start() { vbox_manage startvm "$1" --type headless; }
v10_vm_pause() { vbox_manage controlvm "$1" pause; }
v10_vm_resume() { vbox_manage controlvm "$1" resume; }
v10_vm_reset() { vbox_manage controlvm "$1" reset; }
v10_vm_poweroff() { vbox_manage controlvm "$1" poweroff; }

v10_vm_headless() {
	has_args 1 "$@"
	vbox_headless -s "$1"
}


######
# VM Configuration

v10_vm_config() { cmd_dispatch "$@"; }
v10_vm_config_usage() {
	cat <<USAGE
<cmd> ...
VM Config Command Groups:
	net				Configures VM network settings
	rdp				Configures VM RDP settings
USAGE
}


v10_vm_config_net() { cmd_dispatch "$@"; }
v10_vm_config_net_usage() {
	cat <<USAGE
<cmd> ...
VM Network Config Commands:
	nat <vm> <n>			Sets VM NIC<n> to NAT mode
	bridge <vm> <n> <iface>		Bridges VM NIC<n> to <iface>
	natnet <vm> <n> <netname>	Connects VM NIC<n> to NAT network
	intnet <vm> <n> <netname>	Connects VM NIC<n> to internal net
	hostonly <vm> <n> <netname>	Connects VM NIC<n> to internal net
	disconnect <vm> <n>		Disconnects NIC<n>
	remove <vm> <n>			Removes NIC<n> from the VM
USAGE
}

vbox_vm_net_modify() {
	local vm=$1
	local nic=$2
	shift 2
	vbox_vm_modify "$vm" "--nic$nic" "$@"
}
v10_vm_config_net_nat() {
	has_args 2 "$@";
	vbox_vm_net_modify "$1" "$2" nat
}
v10_vm_config_net_bridged() {
	has_args 3 "$@";
	vbox_vm_net_modify "$1" "$2" bridged --bridgeadapter$2 "$3"
}
v10_vm_config_net_natnet() {
	has_args 3 "$@";
	vbox_vm_net_modify "$1" "$2" natnetwork --net-network$2 "$3"
}
v10_vm_config_net_internal() {
	has_args 3 "$@";
	vbox_vm_net_modify "$1" "$2" intnet --intnet$2 "$3"
}
v10_vm_config_net_hostonly() {
	has_args 3 "$@";
	vbox_vm_net_modify "$1" "$2" hostonly --hostonlyadapter$2 "$3"
}
v10_vm_config_net_disconnect() {
	has_args 2 "$@";
	vbox_vm_net_modify "$1" "$2" null
}
v10_vm_config_net_remove() {
	has_args 2 "$@";
	vbox_vm_net_modify "$1" --nic$2 none
}


v10_vm_config_rdp() { cmd_dispatch "$@"; }
v10_vm_config_rdp_usage() {
	cat <<USAGE
<cmd> <vm> [...]
VM RDP Config Commands:
	start <vm>			Enable RDP for VM
	stop <vm>			Disable RDP for VM
	auth <vm> {null,host,simple}	Set authorization mechanism
USAGE
}
v10_vm_config_rdp_start() { has_args 1 "$@"; vbox_vm_config_rdp "$1" true; }
v10_vm_config_rdp_stop() { has_args 1 "$@"; vbox_vm_config_rdp "$1" false; }
v10_vm_config_rdp_auth() {
	has_args 2 "$@";
	local authtype
	case "$2" in
	null)	authtype=null ;;
	host)	authtype=external; authlib=VBoxAuth ;;
	simple)	authtype=external; authlib=VBoxAuthSimple ;;
	*)
		app_echo "RDP auth type must be 'null', 'host', or 'simple'"
		error "$2: invalid RDP auth type"
	esac
	vbox_vm_modify "$1" --vrdeauthtype "$authtype"
	[ -z "$authlib" ] || v10_manage_rdp_authlib "$2"
}


######
# VM State CLI

v10_vm_state() {
	local cmd=$1
	case "$cmd" in
	(save|adopt|discard)
		shift
		vbox_vm_state_$cmd "$@"
		;;
	(*)
		cmd_dispatch "$@"
		;;
	esac
}

v10_vm_state_usage() {
	cat <<USAGE
<cmd> <vm> ...
VM State Management:
	save <vm>			Save VM state
	adopt <vm> <file>		Adopt the VM state from file
	discard <vm>			Discard saved VM state
USAGE
}


######
# VM Snapshot CLI

v10_vm_snapshot() {
	local cmd=$1
	case "$cmd" in
	(list|info|take|delete|restore)
		shift
		vbox_vm_snapshot_$cmd "$@"
		;;
	(*)
		cmd_dispatch "$@"
		;;
	esac
}

v10_vm_snapshot_usage () {
	cat <<USAGE
<cmd> ...
VM Snapshot Commands:
	list <vm> 			Lists VM snapshots
	info <vm> <name|type>		Prints VM snapshot information
	take <vm> <type>		Takes a VM snapshot
	delete <vm> <type>		Deletes a VM snapshot
	restore <vm> <type>		Restores a VM snapshot
USAGE
}


######
# VM HD CLI

v10_vm_hd() { cmd_dispatch "$@"; }
v10_vm_hd_usage() {
	cat <<USAGE
VM Hard Disk (VDI) Commands:
	new <vm> [<name>]
	attach <vm> <hd>
USAGE
}
v10_vm_hd_new() {
	min_args 1 "$@"
	local vm=$1
	local hd=${2:-$vm}
	local sz=${3:-$vbox_hd_size}
	v10_hd_exists "$hd" || vbox_hd_create "$hd" "$sz"
	v10_vm_hd_attach "$vm" "$hd"
}

v10_vm_hd_attach() {
	min_args 1 "$@"
	local vm=$1
	local hd=${2:-$vm}
	vbox_hd_setup "$vm" "$hd"
}

######
# VM DVD CLI

v10_vm_dvd() { cmd_dispatch "$@"; }
v10_vm_dvd_usage() {
	cat <<USAGE
VM Hard Disk (VDI) Commands:
	new <vm> [<name>]
	insert <vm> <iso>
	eject <vm>
	remove <vm>
USAGE
}
v10_vm_dvd_insert() { has_args 2 "$@"; vbox_dvd_media "$@"; }
v10_vm_dvd_eject() { has_args 1 "$@"; vbox_dvd_media "$1" eject; }
v10_vm_dvd_remove() { has_args 1 "$@"; vbox_dvd_media "$1" none; }


######
# VirtualBox Configuration CLI


v10_manage() { cmd_dispatch "$@"; }
v10_manage_usage() {
	cat <<USAGE
<cmd> ...
Command Groups:
	rdp				Set the RDP options
USAGE
}
v10_manage_rdp() { cmd_dispatch "$@"; }
v10_manage_rdp_usage() {
	cat <<USAGE
<cmd> <value>
RDP Configuration Commands:
	authlib {host|simple}		Selects the vrdeauthlibrary
	extpack {vnc|oracle}		Selects the RDP extension pack
USAGE
}
v10_manage_rdp_authlib() {
	local authlib
	case "$1" in
	host)	authlib=VBoxAuth ;;
	simple) authlib=VBoxAuthSimple ;;
	*)
		app_echo "authlib must be 'host' or 'simple'"
		error "$1: invalid authlib"
		;;
	esac
	vbox_setproperty vrdeauthlibrary "$authlib"
}
v10_manage_rdp_extpack() {
	local pack
	case "$1" in
	vnc)	pack="VNC" ;;
	oracle) pack="Oracle VM VirtualBox Extension Pack" ;;
	*)
		app_echo "extpack must be 'vnc' or 'oracle'"
		error "$1: invalid extpack"
		;;
	esac
	vbox_setproperty vrdeextpack "$pack"
}


######
# Check

v10_check() {
	if [ "$*" ]; then
		cmd_dispatch "$@"
	else
		v10_check_all
	fi
}
v10_check_usage() {
	cat <<USAGE
[<cmd>]
If not command is given, runs all checks.
Check Commands:
	hd				Check the HD routines
	iso				Check the ISO routines
	vm				Check the VM routines
USAGE
}

v10_check_all() {
	run v10_check_hd
	run v10_check_iso
	run v10_check_vm
}

v10_check_hd() {
	# run HD tests
	v10_hd_create "test"
	echo yes | v10_hd_delete "test"
}
v10_check_iso() {
	# run ISO tests
	if [ -f "$check_iso_image" ]; then
		v10_iso_add "$check_iso_name" "$check_iso_image"
		echo yes | v10_iso_delete "$check_iso_name"
	else
		warn "skipping, missing ISO test image: $check_iso_image"
	fi
}
v10_check_vm() {
	# run VM tests
	v10_vm_create "test"
	v10_vm_hd_new "test"
	echo yes | v10_vm_delete "test"
	echo yes | v10_hd_delete "test"
}


######
# Main

v10_desc() { echo "VirtualBox virtual machine utility"; }

v10_usage() {
	cat <<USAGE
<cmd> [...]
Command Groups:
	manage ...			Global management commands
	hd ...				Virtual hard disk commands
	iso ...				Virtual disk image commands
	vm ...				Virtual machine commands
USAGE
}

app_run "$@"

View the Developer Guide Index

View the Reference Manual Index


Generated on Fri Jul 28 14:34:46 PDT 2017 by mcsh d14 v0.23.0.