#!/usr/bin/env bash # # Copyright 1998-2008 VMware, Inc. All rights reserved. # # This script manages the services needed to run VMware software. # # Basic support for IRIX style chkconfig ### # chkconfig: 235 19 08 # description: Manages the services needed to run VMware software ### # Basic support for the Linux Standard Base Specification 1.3 # Used by insserv and other LSB compliant tools. ### BEGIN INIT INFO # Provides: VMware # Required-Start: $network $syslog # Required-Stop: # Default-Start: 2 3 5 # Default-Stop: 0 6 # Short-Description: Manages the services needed to run VMware software # Description: Manages the services needed to run VMware software ### END INIT INFO ETCDIR=/etc/vmware VMIS_MAJOR_VERSION=1 . $ETCDIR/bootstrap libdir="$LIBDIR"/vmware . "$libdir"/scripts/util.sh load_settings "$libdir" || exit 1 VNETLIB_LOG=/var/log/vnetlib PRODUCT_NAME="VMware Player" COMPONENT_NAME="vmware-player-app" # This comment is a hack to prevent RedHat distributions from outputing # "Starting " when running this startup script. # We just need to write the word daemon followed by a space # This defines echo_success() and echo_failure() on RedHat if [ -r "$INITSCRIPTDIR"'/functions' ]; then . "$INITSCRIPTDIR"'/functions' fi # This defines $rc_done and $rc_failed on S.u.S.E. if [ -f /etc/rc.config ]; then # Don't include the entire file: there could be conflicts rc_done=`(. /etc/rc.config; echo "$rc_done")` rc_failed=`(. /etc/rc.config; echo "$rc_failed")` else # Make sure the ESC byte is literal: Ash does not support echo -e rc_done=' done' rc_failed='failed' fi subsys=vmware driver=vmmon vnet=vmnet vmblock=vmblock vmci=vmci vsock=vsock vmciNode=vmci vsockNode=vsock # SHM settings shmmaxPath=/proc/sys/kernel/shmmax shmmaxMinValue=268435456 # 256MB # # Are we running in a VM? # vmwareInVM() { "$BINDIR"/checkvm >/dev/null 2>&1 } # # Report a positive number if there are any VMs running. # May not be the actual vmmon reference count. # vmmonUseCount() { local count # Beware of module dependencies here. An exact match is important count=`/sbin/lsmod | awk 'BEGIN {n = 0} {if ($1 == "'"$driver"'") n = $3} END {print n}'` # If CONFIG_MODULE_UNLOAD is not set in the kernel, lsmod prints '-' instead of the # reference count, so ask vmrun, or if we don't have vmrun, look for running vmx processes if [ x${count} = "x-" ] then type vmrun > /dev/null 2>&1 if [ $? -eq 0 ] then count=`vmrun list | awk 'BEGIN {n=0} /^Total running VMs:/ {n = $4} END {print n}'` else count=`ps -afe | grep "/bin/vmware-vmx" | grep -v grep | wc -l` fi fi echo $count } # Is a given module loaded? isLoaded() { local module="$1" /sbin/lsmod | awk 'BEGIN {n = "no";} {if ($1 == "'"$module"'") n = "yes";} END {print n;}' } # Build a Linux kernel integer version kernelVersionInteger() { echo $(((($1 * 256) + $2) * 256 + $3)) } # Get the running kernel integer version getVersionInteger() { local version_uts local v1 local v2 local v3 version_uts=`uname -r` # There is no double quote around the back-quoted expression on purpose # There is no double quote around $version_uts on purpose set -- `IFS='.'; echo $version_uts` v1="$1" v2="$2" v3="$3" # There is no double quote around the back-quoted expression on purpose # There is no double quote around $v3 on purpose set -- `IFS='-ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'; echo $v3` v3="$1" kernelVersionInteger "$v1" "$v2" "$v3" } vmwareLoadModule() { /sbin/insmod -s -f "/lib/modules/`uname -r`/misc/$1.ko" || exit 1 return 0 } vmwareUnloadModule() { if [ "`isLoaded "$1"`" = 'yes' ]; then /sbin/rmmod "$1" || exit 1 fi return 0 } # Start the virtual machine monitor kernel service vmwareStartVmmon() { vmwareLoadModule $driver } # Stop the virtual machine monitor kernel service vmwareStopVmmon() { vmwareUnloadModule $driver } # Start the virtual ethernet kernel service vmwareStartVmnet() { vmwareLoadModule $vnet "$BINDIR"/vmware-networks --start >> $VNETLIB_LOG 2>&1 } # Stop the virtual ethernet kernel service vmwareStopVmnet() { "$BINDIR"/vmware-networks --stop >> $VNETLIB_LOG 2>&1 vmwareUnloadModule $vnet } # Start the virtual machine USB Arbitrator service vmwareStartUSBArbitrator() { # The executable checks for already running instances, so it # is safe to just run it. "$BINDIR"/vmware-usbarbitrator } # Stop the virtual machine USB Arbitrator service vmwareStopUSBArbitrator() { # Find the running process # grep instead of pgrep... Turns out to be more reliable. pgrep # would return extranneous results. pid=`pgrep -f "$BINDIR"/vmware-usbarbitrator` # If it is not running if [ $? -eq 0 ]; then # PID was found, stop it. kill $pid return 0 else # No process found. return 0 fi } # Returns 0 if networking is enabled, otherwise 1 vmwareIsNetworkingEnabled() { [ "$vmdb_NETWORKING" = 'yes' ] return } # Start the virtual machine communication interface kernel service vmwareStartVmci() { # only load vmci if it's not already loaded if [ "`isLoaded "$vmci"`" = 'no' ]; then vmwareLoadModule "$vmci" fi vmware_rm_stale_node "$vmciNode" if [ ! -e "/dev/$vmciNode" ]; then local minor=`cat /proc/misc | grep $vmciNode | awk '{print $1}'` mknod --mode=666 "/dev/$vmciNode" c 10 "$minor" else chmod 666 "/dev/$vmciNode" fi return 0 } # Make sure the system has enough shared memory available to cover shmmaxMinValue. # To handle overflow/wrapping, check that shmmax is greater than 1 since any overflow # will make shmmax look negative. At least until shmmax or shmmaxMinValue wrap around # again. vmwareCheckSharedMemory() { if [ -f "$shmmaxPath" ]; then shmmax=`cat $shmmaxPath` # Account for numbers that are too large that they wrap around and alias # to a smaller number or they are outright set to -1. If "1 < XXXX" fails # then the XXX value is # out of bounds. The only acceptable combo is that # both values satisfy that condition, else report that the max value the # system supports may not satisfy this programs requirements. if (( $shmmax < 1 )) || (( $shmmaxMinValue < 1 )) \ || (( $shmmax < $shmmaxMinValue )) ; then echo "$shmmaxMinValue" > "$shmmaxPath" echo "" echo "Setting the max shared memory the system will allow to $shmmaxMinValue." echo "" fi fi return 0 } # Stop the virtual machine communication interface kernel service vmwareStopVmci() { # only unload vmci if it's already loaded if [ "`isLoaded "$vmci"`" = 'yes' ]; then vmwareUnloadModule "$vmci" fi rm -f "/dev/$vmciNode" } isVmciNeeded() { if [ "$vmdb_VMCI_CONFED" = 'yes' ]; then echo yes else echo no fi } # starts after vmci is loaded vmwareStartVsock() { # only load vsock if it's not already loaded if [ "`isLoaded "$vsock"`" = 'no' ]; then vmwareLoadModule "$vsock" fi vmware_rm_stale_node "$vsockNode" # Give udev 5 seconds to create our node vmware_delay_for_node "/dev/$vsockNode" 5 if [ ! -e "/dev/$vsockNode" ]; then local minor=`cat /proc/misc | grep $vsockNode | awk '{print $1}'` mknod --mode=666 "/dev/$vsockNode" c 10 "$minor" else chmod 666 "/dev/$vsockNode" fi return 0 } # unloads before vmci vmwareStopVsock() { # only unload vsock if it's already loaded if [ "`isLoaded "$vsock"`" = 'yes' ]; then vmwareUnloadModule "$vsock" fi rm -f /dev/vsock } isVsockNeeded() { if [ "$vmdb_VSOCK_CONFED" = 'yes' ]; then echo yes else echo no fi } vmwareService() { case "$1" in start) if vmwareInVM; then # Refuse to start services in a VM: they are useless exit 1 fi echo 'Starting VMware services:' exitcode='0' vmware_exec 'VMware USB Arbitrator' vmwareStartUSBArbitrator exitcode=$(($exitcode + $?)) vmware_exec 'Virtual machine monitor' vmwareStartVmmon exitcode=$(($exitcode + $?)) if [ "`isVmciNeeded`" = 'yes' ]; then vmware_exec 'Virtual machine communication interface' vmwareStartVmci exitcode=$(($exitcode + $?)) fi # vsock needs vmci started first if [ "`isVsockNeeded`" = 'yes' ]; then vmware_exec 'VM communication interface socket family' vmwareStartVsock # a vsock failure to load shouldn't cause the init to fail completely. fi if [ "`is_vmblock_needed`" = 'yes' ] ; then vmware_exec 'Blocking file system' vmware_start_vmblock exitcode=$(($exitcode + $?)) fi # Try to load parport_pc. /sbin/modprobe parport_pc >/dev/null 2>&1 if vmwareIsNetworkingEnabled; then vmware_exec 'Virtual ethernet' vmwareStartVmnet exitcode=$(($exitcode + $?)) fi if [ "$exitcode" -gt 0 ]; then exit 1 fi [ -d /var/lock/subsys ] || mkdir -p /var/lock/subsys touch /var/lock/subsys/"$subsys" vmware_exec "Shared Memory Available" vmwareCheckSharedMemory ;; stop) echo 'Stopping VMware services:' exitcode='0' # If the 'K' version of this script is running, the system is # stoping services not because the user is running vmware-config.pl # or running the initscript directly but because the user wants to # shutdown. Suspend all VMs. if [ -x "$BINDIR"/vmrun ] ; then for i in `pidof vmware-vmx` ; do "$BINDIR"/vmrun suspend `ps -p $i -f | \ sed -ne '/vmware/s/.* \(\/.*\.vmx\)/\1/p'` 2> /dev/null done fi vmware_exec 'VMware USB Arbitrator' vmwareStopUSBArbitrator exitcode=$(($exitcode + $?)) if [ "`vmmonUseCount`" -gt 0 ]; then echo 'At least one instance of '"$PRODUCT_NAME"' is still running.' 1>&2 echo 'Please stop all running instances of '"$PRODUCT_NAME"' first.' 1>&2 echo " " >&2 # Since we stopped authdlauncer to prevent new connections before disabling # any vmxs, need to restart it here to restore the environment back to # what it was before this init script ran. vmware_exec 'VMware Authentication Daemon' vmware_start_authdlauncher # The unconfigurator handle this exit code differently exit 2 fi # vmci is used by vsock so the module can't unload until vsock does. if [ "`isVsockNeeded`" = 'yes' ]; then vmware_exec 'VM communication interface socket family' vmwareStopVsock exitcode=$(($exitcode + $?)) fi if [ "`isVmciNeeded`" = 'yes' ]; then vmware_exec 'Virtual machine communication interface' vmwareStopVmci exitcode=$(($exitcode + $?)) fi vmware_exec 'Virtual machine monitor' vmwareStopVmmon exitcode=$(($exitcode + $?)) if [ "`is_vmblock_needed`" = 'yes' ] ; then vmware_exec 'Blocking file system' vmware_stop_vmblock exitcode=$(($exitcode + $?)) fi # Try to unload parport_pc. Failure is allowed as it does not # exist on kernels 2.0, and some other process could be using # it. /sbin/modprobe -r parport_pc >/dev/null 2>&1 if vmwareIsNetworkingEnabled; then vmwareStopVmnet fi # The vmware and vmware-tray processes don't terminate automatically # when the other services are shutdown. They persist after calling # 'init.d/vmware stop' and will happily keep going through an init # start command, continuing to minimally function, blissfully ignorant. # Time for a buzzkill. for i in `pidof vmware vmware-tray` ; do vmware_synchrone_kill $i "INT" done if [ "$exitcode" -gt 0 ]; then exit 1 fi rm -f /var/lock/subsys/"$subsys" ;; status) if [ "`vmmonUseCount`" -gt 0 ]; then echo 'At least one instance of '"$PRODUCT_NAME"' is still running.' echo if [ "$2" = "vmcount" ]; then exit 2 fi fi if [ "$2" = "vmcount" ]; then exit 0 fi exitcode='0' echo -n "Module $driver " [ "`isLoaded "$driver"`" = 'yes' ] && echo loaded || echo "not loaded" if vmwareIsNetworkingEnabled; then echo -n "Module $vnet " [ "`isLoaded "$vnet"`" = 'yes' ] && echo loaded || echo "not loaded" fi if [ "$exitcode" -gt 0 ]; then exit 1 fi ;; restart) "$SCRIPTNAME" stop && "$SCRIPTNAME" start ;; # Called to make sure script is in a runnable state. validate) exit 100 ;; stoppable) [ "`vmmonUseCount`" -lt 1 ] exit ;; *) echo "Usage: "$BASENAME" {start|stop|status|restart|stoppable}" exit 1 esac } SCRIPTNAME="$0" BASENAME=`basename "$SCRIPTNAME"` # Check permissions if [ "`id -ur`" != '0' ]; then echo 'Error: you must be root.' echo exit 1 fi vmwareService "$1" exit 0