AW: AW: rc.d script for running multiple VirtualBox VMs from /etc/rc.conf

Tobias Oberstein tobias.oberstein at tavendo.de
Tue Apr 12 21:09:28 UTC 2011


> >> The canonical way to do what you're suggesting is to copy the script
> >> so that you have one script per process you want to start, each with
> >> a different
> >
> > I've tried that first .. but for me it gets unwieldy when you need to
> > manage i.e. a dozen VMs
> 
> I don't see how it would be "unwieldy." The rc.conf stuff would be the same,
> the only difference would be the number of rc.d scripts. What problems
> does having multiple scripts cause for you?

No, it's the number of scripts. For me, it's just more clearly arranged to edit
everything in one place (/etc/rc.conf) and with minimum edits.
And I like factoring code.

Also, I can use the rc.d script to get status for one or for all VMs at one time
or start/stop all at once.

But it's not that important. Lets call it an personal taste question.

It's just that I've read the FreeBSD manual on rc.d, which doesnt talk about
multiple instances of daemons (if I've not overlooked s.th.).

And I thought that the way the Apache rc.d script does it would be
somehow sanctioned / canonical.

> 
> >> 2) when the system shuts down, it doesnt wait for "stop" to finish
> >> graceful shutdown of VMs
> >
> > ?
> >
> > The problem is, that
> >
> > VBoxManage controlvm ${vboxvm_name} acpipowerbutton
> >
> > does exit immediately.
> >
> > It does not wait until the VM is actually powered down.
> >
> > Is there i.e. a rc.d "hook" which allows me to make the shutdown
> > process wait for some condition (at least up to say a limit of 20s)?
> 
> By "shutdown process" are you referring to system shutdown? If so, what

Yeah, "shutdown -r now".

> you probably want to do is modify your _stop method to find the pid of the
> vm and run wait_for_pids() on it. Reading through the comments in
> /etc/rc.subr may be helpful for you in this regard.

Ok. I'll look into that. Thanks.

In the meantime, I've implemented stop_cmd as synchronous (it does not
return until VM is stopped) and also restart_cmd.

I somehow works .. but there seems to be a watchdog in place: I get

"watchdog timeout 30s expired ... shutodown NOW"

Is it possible to override the 30s watchdog?

My current solution is not optimal, since it shuts down VMs sequentially
and synchronously.

Ideal would be: trigger shutdown of all VMs at once and in parallel, but then
wait until all have stopped for the final system shutdown.

Would that be possible with the wait_for_pids() you've mentioned?

Thanks again,
Tobias





-------------- next part --------------
#!/bin/sh

# PROVIDE: vboxvm
# REQUIRE: LOGIN
# KEYWORD: shutdown

. /etc/rc.subr

name="vboxvm"
rcvar=`set_rcvar`

load_rc_config $name

if [ -n "$2" ]; then
	machine="$2"
	if [ "x${vboxvm_machines}" != "x" ]; then
		eval vboxvm_name="\${vboxvm_${machine}_name:-}"
		if [ "x${vboxvm_name}" = "x" ]; then
			echo "You must define a VM name (vboxvm_${machine}_name)"
			exit 1
		fi
		eval vboxvm_user="\${vboxvm_${machine}_user:-}"
		if [ "x${vboxvm_user}" = "x" ]; then
			echo "You must define a VM execution user (vboxvm_${machine}_user)"
			exit 1
		fi
		eval vboxvm_log="\${vboxvm_${machine}_log:-${vboxvm_name}.log}"
		eval vboxvm_vncport="\${vboxvm_${machine}_vncport:-}"
		eval vboxvm_vncpassword="\${vboxvm_${machine}_vncpassword:-}"
		if [ "x${vboxvm_vncport}" = "x" -a "x${vboxvm_vncpassword}" != "x" ]; then
			echo "Warning: VNC password, but no VNC port specified for machine '${machine}' - VNC will be disabled."
		fi
	else
		echo "$0: extra argument ignored"
	fi
else
	if [ "x${vboxvm_machines}" != "x" -a "x$1" != "x" ]; then
		for machine in ${vboxvm_machines}; do
			eval _enable="\${vboxvm_${machine}_enable}"
			case "x${_enable:-${vboxvm_enable}}" in
			x|x[Nn][Oo]|x[Nn][Oo][Nn][Ee])
            echo "VBox machine '${machine}' skipped (disabled)."
				continue
				;;
			x[Yy][Ee][Ss])
				;;
			*)
				if test -z "$_enable"; then
					_var=vboxvm_enable
				else
					_var=vboxvm_"${machine}"_enable
				fi
				echo "Bad value" \
				    "'${_enable:-${vboxvm_enable}}'" \
				    "for ${_var}. " \
				    "VBox machine '${machine}' skipped."
				continue
				;;
			esac
			/usr/local/etc/rc.d/vboxvm $1 ${machine}
			retcode="$?"
			if [ "0${retcode}" -ne 0 ]; then
				failed="${machine} (${retcode}) ${failed:-}"
			else
				success="${machine} ${success:-}"
			fi
		done
		exit 0
	fi
fi

start_cmd="vboxvm_start"
stop_cmd="vboxvm_stop"
status_cmd="vboxvm_status"
extra_commands="status"

is_running()
{
    runningvms="`su -l ${vboxvm_user} -c 'exec /usr/local/bin/VBoxManage list runningvms'`"
    myvm="`echo ${runningvms} | grep -c ${vboxvm_name}`"
    if [ "${myvm}" -ne "0" ]; then
       return 1
    else
       return 0
    fi
}

wait_for_powerdown()
{
    is_running
    if [ "$?" -ne 0 ] ; then
       sleep 5
       wait_for_powerdown
    fi
}

vboxvm_start()
{
    is_running
    if [ "$?" -ne 0 ] ; then
       echo "VBox machine '${vboxvm_name}' is already running."
    else
       echo "VBox machine '${vboxvm_name}' powering up."
       if [ "x${vboxvm_vncport}" != "x" ]; then
          if [ "x${vboxvm_vncpassword}" = "x" ]; then
             vncopts="--vnc --vncport ${vboxvm_vncport}"
          else
             vncopts="--vnc --vncport ${vboxvm_vncport} --vncpass ${vboxvm_vncpassword}"
          fi
       fi
       if [ "x${vboxvm_log}" != "x" ]; then
          logopts="1>${vboxvm_log} 2>&1"
       fi
       cmd="exec /usr/local/bin/VBoxHeadless ${vncopts} -s ${vboxvm_name} ${logopts} &"
       su -l ${vboxvm_user} -c "${cmd}"
    fi
}

vboxvm_stop()
{
    is_running
    if [ "$?" -ne 0 ] ; then
       echo "VBox machine '${vboxvm_name}' powering down."
       su -l ${vboxvm_user} -c "exec /usr/local/bin/VBoxManage controlvm ${vboxvm_name} acpipowerbutton"
       wait_for_powerdown
    else
       echo "VBox machine '${vboxvm_name}' not running."
    fi
}

vboxvm_restart()
{
    is_running
    if [ "$?" -ne 0 ] ; then
       echo "VBox machine '${vboxvm_name}' powering down."
       su -l ${vboxvm_user} -c "exec /usr/local/bin/VBoxManage controlvm ${vboxvm_name} acpipowerbutton"
       wait_for_powerdown
    fi
    vboxvm_start
}

vboxvm_status()
{
    is_running
    if [ "$?" -ne 0 ] ; then
       echo "VBox machine '${vboxvm_name}' is running."
    else
       echo "VBox machine '${vboxvm_name}' is powered down."
    fi
}

run_rc_command "$1"


More information about the freebsd-emulation mailing list