#! /bin/sh
# Sun VirtualBox
# Linux kernel module init script

#
# Copyright (C) 2006-2009 Sun Microsystems, Inc.
#
# This file is part of VirtualBox Open Source Edition (OSE), as
# available from http://www.virtualbox.org. This file is free software;
# you can redistribute it and/or modify it under the terms of the GNU
# General Public License (GPL) as published by the Free Software
# Foundation, in version 2 as it comes in the "COPYING" file of the
# VirtualBox OSE distribution. VirtualBox OSE is distributed in the
# hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
#

# chkconfig: 35 30 70
# description: VirtualBox Linux kernel module
#
### BEGIN INIT INFO
# Provides:       vboxdrv virtualbox
# Required-Start: $remote_fs $network
# Required-Stop:  $remote_fs
# Default-Start:  2 3 4 5
# Default-Stop:   0 1 6
# Short-Description: VirtualBox Linux kernel module
### END INIT INFO

source /lib/lsb/init-functions

test -d /usr/share/doc/virtualbox -a -x /usr/bin/VBoxHeadless || exit 0

# Include virtualbox defaults if available
test -r /etc/default/virtualbox && source /etc/default/virtualbox

# set list of all active users if asked to do so
if test $SHUTDOWN_USERS = "all" {
	setvar SHUTDOWN_USERS = """"
	for i in /tmp/.vbox-*-ipc {
		setvar SHUTDOWN_USERS = ""$SHUTDOWN_USERS $(echo $i|cut -d'-' -f2)""
	}
}

if test $LOAD_VBOXDRV_MODULE != 1 {
	log_success_msg "virtualbox disabled; edit /etc/default/virtualbox"
	exit 0
}

proc running {
    lsmod | grep -q "$1[^_-]"
}

proc start {
	log_begin_msg "Loading VirtualBox kernel modules..."
	
	if ! running vboxdrv {
		if ! modprobe vboxdrv > /dev/null 2>&1 {
			if ! find /lib/modules/$(uname -r) -name "vboxdrv\.*" 2>/dev/null|grep -q vboxdrv {
				log_failure_msg "No suitable module for running kernel found"
			} else {
				log_failure_msg "modprobe vboxdrv failed. Please use 'dmesg' to find out why"
			}
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxdrv"
		}
	}
	
	if ! running vboxnetflt {
		if ! modprobe vboxnetflt > /dev/null 2>&1 {
			if ! find /lib/modules/$(uname -r) -name "vboxnetflt\.*" 2>/dev/null|grep -q vboxnetflt {
				log_failure_msg "No suitable vboxnetflt module for running kernel found"
			} else {
				log_failure_msg "modprobe vboxnetflt failed. Please use 'dmesg' to find out why"
			}
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxnetflt"
		}
	}
	
	if ! running vboxnetadp {
		if ! modprobe vboxnetadp > /dev/null 2>&1 {
			if ! find /lib/modules/$(uname -r) -name "vboxnetadp\.*" 2>/dev/null|grep -q vboxnetadp {
				log_failure_msg "No suitable vboxnetadp module for running kernel found"
			} else {
				log_failure_msg "modprobe vboxnetadp failed. Please use 'dmesg' to find out why"
			}
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxnetadp"
		}
	}
	
	if ! running vboxpci {
		if ! modprobe vboxpci > /dev/null 2>&1 {
			if ! find /lib/modules/$(uname -r) -name "vboxpci\.*" 2>/dev/null|grep -q vboxpci {
				log_failure_msg "No suitable vboxpci module for running kernel found"
			} else {
				log_failure_msg "modprobe vboxpci failed. Please use 'dmesg' to find out why"
			}
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxpci"
		}
	}
	
	log_end_msg 0
}

proc stop {
	log_begin_msg "Unloading VirtualBox kernel modules..."
	
	if running vboxnetadp {
		if ! rmmod vboxnetadp 2>/dev/null {
			log_failure_msg "Cannot unload module vboxnetadp"
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxnetadp"
		}
	}
	
	if running vboxnetflt {
		if ! rmmod vboxnetflt 2>/dev/null {
			log_failure_msg "Cannot unload module vboxnetflt"
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxnetflt"
		}
	}
	
	if running vboxpci {
		if ! rmmod vboxpci 2>/dev/null {
			log_failure_msg "Cannot unload module vboxpci"
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxpci"
		}
	}
	
	if running vboxdrv {
		if ! rmmod vboxdrv 2>/dev/null {
			log_failure_msg "Cannot unload module vboxdrv"
			log_end_msg 1
			return 1
		} else {
			log_progress_msg "vboxdrv"
		}
	}
	
	log_end_msg 0
}

# enter the following variables in /etc/default/virtualbox:
#   SHUTDOWN_USERS="foo bar"  
#     check for running VMs of user foo and user bar
#   SHUTDOWN=poweroff
#   SHUTDOWN=acpibutton
#   SHUTDOWN=savestate
#     select one of these shutdown methods for running VMs
proc stop_vms {
	if ! pidof VBoxSVC > /dev/null {
		return 0
	}
	
	setvar wait = '0'
	
	for i in $SHUTDOWN_USERS {
		if test -d /tmp/.vbox-$i-ipc {
			export VBOX_IPC_SOCKETID="$i"
			setvar VMS = $(VBoxManage --nologo list runningvms )
			if test $? -eq 0 -a -n $VMS {
				setvar VMS = $(echo $VMS | sed -e 's/^".*".*{\(.*\)}/\1/)
				if test $SHUTDOWN = "poweroff" {
					log_action_msg "Powering off remaining VMs from user $i"
					for v in $VMS {
						VBoxManage --nologo controlvm $v poweroff
						setvar wait = '10'
					}
				} elif test $SHUTDOWN = "acpibutton" {
					log_action_msg "Sending ACPI power button event to remaining VMs from user $i"
					for v in $VMS {
						VBoxManage --nologo controlvm $v acpipowerbutton
						setvar wait = '30'
					}
				} elif test $SHUTDOWN = "savestate" {
					log_action_msg "Saving state of remaining VMs from user $i"
					for v in $VMS {
						VBoxManage --nologo controlvm $v savestate
						setvar wait = '30'
					}
				}
			}
		}
	}
	
	# wait for some seconds when doing ACPI shutdown
	if test $wait -ne 0 {
		log_action_begin_msg "Waiting for $wait seconds for VM shutdown"
		sleep $wait
		log_action_end_msg 0
	}
	return 0
}

proc dmnstatus {
	if running vboxdrv && running vboxnetflt && running vboxnetadp && running vboxpci {
		echo "VirtualBox kernel modules are loaded."
		
		for i in $SHUTDOWN_USERS {
			if test -d /tmp/.vbox-$i-ipc {
				export VBOX_IPC_SOCKETID="$i"
				setvar VMS = $(VBoxManage --nologo list runningvms )
				if test $? -eq 0 -a -n $VMS {
					setvar VMS = $(echo $VMS | sed -e 's/^".*".*{\(.*\)}/\1/)
					echo "The following VMs are currently running:"
					for v in $VMS {
						echo "  $v"
					}
				}
			}
		}
		return 0
	} else {
		echo "VirtualBox kernel module is not loaded."
		return 3
	}
}

case (1) {
start {
	start
	}
stop {
	stop_vms && stop
	}
stop_vms {
	stop_vms
	}
restart|force-reload {
	stop_vms && stop && start
	}
status {
	dmnstatus
	}
* {
	echo "Usage: $0 {start|stop|stop_vms|restart|force-reload|status}"
	exit 1
}
}