forked from pool/virtualbox
06c8f73ab1
- Merge host kmp and guest kmp into a single kmp. The existence of two different kernel module packages is believed to be the reason that it is possible for a new kernel not to include the necessary kernel modules (boo#1142955). Files "virtualbox-host-kmp-files" and "virtualbox-guest-kmp-files" are deleted. File "virtualbox-kmp-files" is added. Files "virtualbox-host-preamble" and virtualbox-guest-preamble" are deleted. File "virtualbox-kmp-preamble" is added. File "fix_conflict_between_host_and_guest.patch" is added. - Script vboxdrv.sh, which is called from the systemd service file, incorrectly called a routine that does not exist when the kernel modules were not available. This call is changed to /sbin/vboxconfig that will build the modules if the requisite packages are available. If that is not true, the systemctl status vboxdrv will list the command needed to load the missing packages. This change address part of boo#1142995. OBS-URL: https://build.opensuse.org/request/show/719647 OBS-URL: https://build.opensuse.org/package/show/Virtualization/virtualbox?expand=0&rev=498
388 lines
13 KiB
Bash
388 lines
13 KiB
Bash
#! /bin/sh
|
|
# Oracle VM VirtualBox
|
|
# Linux kernel module init script
|
|
|
|
#
|
|
# Copyright (C) 2006-2015 Oracle Corporation
|
|
#
|
|
# 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: 345 20 80
|
|
# description: VirtualBox Linux kernel module
|
|
#
|
|
### BEGIN INIT INFO
|
|
# Provides: vboxdrv
|
|
# Required-Start: $syslog $remote_fs
|
|
# Required-Stop: $syslog $remote_fs
|
|
# Default-Start: 2 3 5
|
|
# Default-Stop: 0 1 6
|
|
# Short-Description: VirtualBox Linux module
|
|
# Description: VirtualBox Linux kernel module
|
|
### END INIT INFO
|
|
|
|
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
|
|
DEVICE=/dev/vboxdrv
|
|
LOG="/var/log/vbox-install.log"
|
|
MODPROBE=/sbin/modprobe
|
|
SCRIPTNAME=vboxdrv.sh
|
|
INSTALL_DIR=/usr/lib/virtualbox
|
|
|
|
# The below is GNU-specific. See VBox.sh for the longer Solaris/OS X version.
|
|
TARGET=`readlink -e -- "${0}"` || exit 1
|
|
SCRIPT_DIR="${TARGET%/[!/]*}"
|
|
|
|
if $MODPROBE -c | grep -q '^allow_unsupported_modules *0'; then
|
|
MODPROBE="$MODPROBE --allow-unsupported-modules"
|
|
fi
|
|
|
|
[ -f /etc/vbox/vbox.cfg ] && . /etc/vbox/vbox.cfg
|
|
export BUILD_TYPE
|
|
export USERNAME
|
|
export USER=$USERNAME
|
|
|
|
VIRTUALBOX="${INSTALL_DIR}/VirtualBox"
|
|
VBOXMANAGE="${INSTALL_DIR}/VBoxManage"
|
|
BUILDINTMP="${MODULE_SRC}/build_in_tmp"
|
|
if test -u "${VBOXMANAGE}"; then
|
|
GROUP=root
|
|
DEVICE_MODE=0600
|
|
else
|
|
GROUP=vboxusers
|
|
DEVICE_MODE=0660
|
|
fi
|
|
|
|
[ -r /etc/default/virtualbox ] && . /etc/default/virtualbox
|
|
|
|
begin_msg()
|
|
{
|
|
test -n "${2}" && echo "${SCRIPTNAME}: ${1}."
|
|
logger -t "${SCRIPTNAME}" "${1}."
|
|
}
|
|
|
|
succ_msg()
|
|
{
|
|
logger -t "${SCRIPTNAME}" "${1}."
|
|
}
|
|
|
|
fail_msg()
|
|
{
|
|
echo "${SCRIPTNAME}: failed: ${1}." >&2
|
|
logger -t "${SCRIPTNAME}" "failed: ${1}."
|
|
}
|
|
|
|
failure()
|
|
{
|
|
fail_msg "$1"
|
|
exit 1
|
|
}
|
|
|
|
running()
|
|
{
|
|
lsmod | grep -q "$1[^_-]"
|
|
}
|
|
|
|
## Output the vboxdrv part of our udev rule. This is redirected to the right file.
|
|
udev_write_vboxdrv() {
|
|
VBOXDRV_GRP="$1"
|
|
VBOXDRV_MODE="$2"
|
|
|
|
echo "KERNEL==\"vboxdrv\", NAME=\"vboxdrv\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\""
|
|
echo "KERNEL==\"vboxdrvu\", NAME=\"vboxdrvu\", OWNER=\"root\", GROUP=\"root\", MODE=\"0666\""
|
|
echo "KERNEL==\"vboxnetctl\", NAME=\"vboxnetctl\", OWNER=\"root\", GROUP=\"$VBOXDRV_GRP\", MODE=\"$VBOXDRV_MODE\""
|
|
}
|
|
|
|
## Output the USB part of our udev rule. This is redirected to the right file.
|
|
udev_write_usb() {
|
|
INSTALLATION_DIR="$1"
|
|
USB_GROUP="$2"
|
|
|
|
echo "SUBSYSTEM==\"usb_device\", ACTION==\"add\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh \$major \$minor \$attr{bDeviceClass}${USB_GROUP}\""
|
|
echo "SUBSYSTEM==\"usb\", ACTION==\"add\", ENV{DEVTYPE}==\"usb_device\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh \$major \$minor \$attr{bDeviceClass}${USB_GROUP}\""
|
|
echo "SUBSYSTEM==\"usb_device\", ACTION==\"remove\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh --remove \$major \$minor\""
|
|
echo "SUBSYSTEM==\"usb\", ACTION==\"remove\", ENV{DEVTYPE}==\"usb_device\", RUN+=\"$INSTALLATION_DIR/VBoxCreateUSBNode.sh --remove \$major \$minor\""
|
|
}
|
|
|
|
## Generate our udev rule file. This takes a change in udev rule syntax in
|
|
## version 55 into account. It only creates rules for USB for udev versions
|
|
## recent enough to support USB device nodes.
|
|
generate_udev_rule() {
|
|
VBOXDRV_GRP="$1" # The group owning the vboxdrv device
|
|
VBOXDRV_MODE="$2" # The access mode for the vboxdrv device
|
|
INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
|
|
USB_GROUP="$4" # The group that has permission to access USB devices
|
|
NO_INSTALL="$5" # Set this to "1" to remove but not re-install rules
|
|
|
|
# Extra space!
|
|
case "$USB_GROUP" in ?*) USB_GROUP=" $USB_GROUP" ;; esac
|
|
case "$NO_INSTALL" in "1") return ;; esac
|
|
udev_write_vboxdrv "$VBOXDRV_GRP" "$VBOXDRV_MODE"
|
|
udev_write_usb "$INSTALLATION_DIR" "$USB_GROUP"
|
|
}
|
|
|
|
## Install udev rule (disable with INSTALL_NO_UDEV=1 in
|
|
## /etc/default/virtualbox).
|
|
install_udev() {
|
|
VBOXDRV_GRP="$1" # The group owning the vboxdrv device
|
|
VBOXDRV_MODE="$2" # The access mode for the vboxdrv device
|
|
INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
|
|
USB_GROUP="$4" # The group that has permission to access USB devices
|
|
NO_INSTALL="$5" # Set this to "1" to remove but not re-install rules
|
|
|
|
if test -d /etc/udev/rules.d; then
|
|
generate_udev_rule "$VBOXDRV_GRP" "$VBOXDRV_MODE" "$INSTALLATION_DIR" \
|
|
"$USB_GROUP" "$NO_INSTALL"
|
|
fi
|
|
# Remove old udev description file
|
|
rm -f /etc/udev/rules.d/10-vboxdrv.rules 2> /dev/null
|
|
}
|
|
|
|
## Create a usb device node for a given sysfs path to a USB device.
|
|
install_create_usb_node_for_sysfs() {
|
|
path="$1" # sysfs path for the device
|
|
usb_createnode="$2" # Path to the USB device node creation script
|
|
usb_group="$3" # The group to give ownership of the node to
|
|
if test -r "${path}/dev"; then
|
|
dev="`cat "${path}/dev" 2> /dev/null`"
|
|
major="`expr "$dev" : '\(.*\):' 2> /dev/null`"
|
|
minor="`expr "$dev" : '.*:\(.*\)' 2> /dev/null`"
|
|
class="`cat ${path}/bDeviceClass 2> /dev/null`"
|
|
sh "${usb_createnode}" "$major" "$minor" "$class" \
|
|
"${usb_group}" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
udev_rule_file=/etc/udev/rules.d/60-vboxdrv.rules
|
|
sysfs_usb_devices="/sys/bus/usb/devices/*"
|
|
|
|
## Install udev rules and create device nodes for usb access
|
|
setup_usb() {
|
|
VBOXDRV_GRP="$1" # The group that should own /dev/vboxdrv
|
|
VBOXDRV_MODE="$2" # The mode to be used for /dev/vboxdrv
|
|
INSTALLATION_DIR="$3" # The directory VirtualBox is installed in
|
|
USB_GROUP="$4" # The group that should own the /dev/vboxusb device
|
|
# nodes unless INSTALL_NO_GROUP=1 in
|
|
# /etc/default/virtualbox. Optional.
|
|
usb_createnode="$INSTALLATION_DIR/VBoxCreateUSBNode.sh"
|
|
# install udev rule (disable with INSTALL_NO_UDEV=1 in
|
|
# /etc/default/virtualbox)
|
|
if [ "$INSTALL_NO_GROUP" != "1" ]; then
|
|
usb_group=$USB_GROUP
|
|
vboxdrv_group=$VBOXDRV_GRP
|
|
else
|
|
usb_group=root
|
|
vboxdrv_group=root
|
|
fi
|
|
install_udev "${vboxdrv_group}" "$VBOXDRV_MODE" \
|
|
"$INSTALLATION_DIR" "${usb_group}" \
|
|
"$INSTALL_NO_UDEV" > ${udev_rule_file}
|
|
# Build our device tree
|
|
for i in ${sysfs_usb_devices}; do # This line intentionally without quotes.
|
|
install_create_usb_node_for_sysfs "$i" "${usb_createnode}" \
|
|
"${usb_group}"
|
|
done
|
|
}
|
|
|
|
cleanup_usb()
|
|
{
|
|
# Remove udev description file
|
|
rm -f /etc/udev/rules.d/60-vboxdrv.rules
|
|
rm -f /etc/udev/rules.d/10-vboxdrv.rules
|
|
|
|
# Remove our USB device tree
|
|
rm -rf /dev/vboxusb
|
|
}
|
|
|
|
start_drv()
|
|
{
|
|
begin_msg "Starting VirtualBox services" console
|
|
if [ -d /proc/xen ]; then
|
|
failure "Running VirtualBox in a Xen environment is not supported"
|
|
fi
|
|
if ! running vboxdrv; then
|
|
if ! rm -f $DEVICE; then
|
|
failure "Cannot remove $DEVICE"
|
|
fi
|
|
if ! $MODPROBE vboxdrv > /dev/null 2>&1; then
|
|
/sbin/vboxconfig
|
|
if ! $MODPROBE vboxdrv > /dev/null 2>&1; then
|
|
failure "modprobe vboxdrv failed. Please use 'dmesg' to find out why"
|
|
fi
|
|
fi
|
|
sleep .2
|
|
fi
|
|
# ensure the character special exists
|
|
if [ ! -c $DEVICE ]; then
|
|
MAJOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/devices`
|
|
if [ ! -z "$MAJOR" ]; then
|
|
MINOR=0
|
|
else
|
|
MINOR=`sed -n 's;\([0-9]\+\) vboxdrv$;\1;p' /proc/extra`
|
|
if [ ! -z "$MINOR" ]; then
|
|
MAJOR=10
|
|
fi
|
|
fi
|
|
if [ -z "$MAJOR" ]; then
|
|
rmmod vboxdrv 2>/dev/null
|
|
failure "Cannot locate the VirtualBox device"
|
|
fi
|
|
if ! mknod -m 0660 $DEVICE c $MAJOR $MINOR 2>/dev/null; then
|
|
rmmod vboxdrv 2>/dev/null
|
|
failure "Cannot create device $DEVICE with major $MAJOR and minor $MINOR"
|
|
fi
|
|
fi
|
|
# ensure permissions
|
|
if ! $MODPROBE vboxnetflt > /dev/null 2>&1; then
|
|
failure "modprobe vboxnetflt failed. Please use 'dmesg' to find out why"
|
|
fi
|
|
if ! $MODPROBE vboxnetadp > /dev/null 2>&1; then
|
|
failure "modprobe vboxnetadp failed. Please use 'dmesg' to find out why"
|
|
fi
|
|
if ! $MODPROBE vboxpci > /dev/null 2>&1; then
|
|
failure "modprobe vboxpci failed. Please use 'dmesg' to find out why"
|
|
fi
|
|
# Create the /dev/vboxusb directory if the host supports that method
|
|
# of USB access. The USB code checks for the existance of that path.
|
|
if grep -q usb_device /proc/devices; then
|
|
mkdir -p -m 0750 /dev/vboxusb 2>/dev/null
|
|
chown root:vboxusers /dev/vboxusb 2>/dev/null
|
|
fi
|
|
succ_msg "VirtualBox services started"
|
|
}
|
|
|
|
stop_drv()
|
|
{
|
|
begin_msg "Stopping VirtualBox services" console
|
|
|
|
if running vboxpci; then
|
|
if ! rmmod vboxpci 2>/dev/null; then
|
|
failure "Cannot unload module vboxpci"
|
|
fi
|
|
fi
|
|
if running vboxnetadp; then
|
|
if ! rmmod vboxnetadp 2>/dev/null; then
|
|
failure "Cannot unload module vboxnetadp"
|
|
fi
|
|
fi
|
|
if running vboxdrv; then
|
|
if running vboxnetflt; then
|
|
if ! rmmod vboxnetflt 2>/dev/null; then
|
|
failure "Cannot unload module vboxnetflt"
|
|
fi
|
|
fi
|
|
if ! rmmod vboxdrv 2>/dev/null; then
|
|
failure "Cannot unload module vboxdrv"
|
|
fi
|
|
if ! rm -f $DEVICE; then
|
|
failure "Cannot unlink $DEVICE"
|
|
fi
|
|
fi
|
|
succ_msg "VirtualBox services stopped"
|
|
}
|
|
|
|
cleanup_vb()
|
|
{
|
|
for i in /lib/modules/*; do
|
|
# We could just do "rm -f", but we only want to try deleting folders if
|
|
# we are sure they were ours, i.e. they had our modules in beforehand.
|
|
if test -e "${i}/extra/vboxdrv.ko" \
|
|
|| test -e "${i}/extra/vboxnetadp.ko" \
|
|
|| test -e "${i}/extra/vboxnetflt.ko" \
|
|
|| test -e "${i}/extra/vboxpci.ko"; then
|
|
rm -f "${i}/extra/vboxdrv.ko" "${i}/extra/vboxnetadp.ko" \
|
|
"${i}/extra/vboxnetflt.ko" "${i}/extra/vboxpci.ko"
|
|
# Remove the kernel version folder if it was empty except for us.
|
|
test "`echo ${i}/extra/* ${i}/extra/.?* ${i}/* ${i}/.?*`" \
|
|
= "${i}/extra/* ${i}/extra/.. ${i}/extra ${i}/.." &&
|
|
rmdir "${i}/extra" "${i}" # We used to leave empty folders.
|
|
version=`expr "${i}" : "/lib/modules/\(.*\)"`
|
|
depmod -a "${version}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# setup_script
|
|
setup_vb()
|
|
{
|
|
# Try to build the host kernel modules in case prepackaging has failed
|
|
/sbin/vboxconfig
|
|
}
|
|
|
|
dmnstatus()
|
|
{
|
|
if running vboxdrv; then
|
|
str="vboxdrv"
|
|
if running vboxnetflt; then
|
|
str="$str, vboxnetflt"
|
|
if running vboxnetadp; then
|
|
str="$str, vboxnetadp"
|
|
fi
|
|
fi
|
|
if running vboxpci; then
|
|
str="$str, vboxpci"
|
|
fi
|
|
echo "VirtualBox kernel modules ($str) are loaded."
|
|
for i in $SHUTDOWN_USERS; do
|
|
# don't create the ipcd directory with wrong permissions!
|
|
if [ -d /tmp/.vbox-$i-ipc ]; then
|
|
export VBOX_IPC_SOCKETID="$i"
|
|
VMS=`$VBOXMANAGE --nologo list runningvms | sed -e 's/^".*".*{\(.*\)}/\1/' 2>/dev/null`
|
|
if [ -n "$VMS" ]; then
|
|
echo "The following VMs are currently running:"
|
|
for v in $VMS; do
|
|
echo " $v"
|
|
done
|
|
fi
|
|
fi
|
|
done
|
|
else
|
|
echo "VirtualBox kernel module is not loaded."
|
|
fi
|
|
}
|
|
|
|
case "$1" in
|
|
start)
|
|
start_drv
|
|
;;
|
|
stop)
|
|
stop_drv
|
|
;;
|
|
restart)
|
|
"$0" stop && "$0" start
|
|
;;
|
|
setup)
|
|
# Create udev rule and USB device nodes.
|
|
## todo Wouldn't it make more sense to install the rule to /lib/udev? This
|
|
## is not a user-created configuration file after all.
|
|
## todo Do we need a udev rule to create /dev/vboxdrv[u] at all? We have
|
|
## working fall-back code here anyway, and the "right" code is more complex
|
|
## than the fall-back. Unnecessary duplication?
|
|
stop_drv && cleanup_vb
|
|
setup_usb "$GROUP" "$DEVICE_MODE" "$INSTALL_DIR"
|
|
setup_vb && start_drv
|
|
;;
|
|
cleanup)
|
|
stop_drv && cleanup_vb
|
|
cleanup_usb
|
|
;;
|
|
force-reload)
|
|
"$0" stop
|
|
"$0" start
|
|
;;
|
|
status)
|
|
dmnstatus
|
|
;;
|
|
*)
|
|
echo "Usage: $0 {start|stop|stop_vms|restart|force-reload|status}"
|
|
exit 1
|
|
esac
|
|
|
|
exit 0
|
|
|