How to start a VM on boot, and shutdown on VM stop?
Solution 1:
You could set up an Init.d/Systemd script like this one:
#! /bin/sh
# /etc/init.d/vbox
#Edit these variables! VMUSER=VMAdmin VMNAME="cdb62186-7c30-4c25-a0b0-e4a32cfb0504" BASEFOLDER=/home/VMAdmin/path/to/backups/
case "$1" in
start)
echo "Starting VirtualBox VM..."
sudo -H -u $VMUSER VBoxManage startvm "$VMNAME" --type headless
;;
reset)
echo "Resetting VirtualBox VM..."
sudo -H -u $VMUSER VBoxManage controlvm "$VMNAME" reset
;;
stop)
echo "Saving state of Virtualbox VM..."
sudo -H -u $VMUSER VBoxManage controlvm "$VMNAME" savestate
;;
shutdown)
echo "Shutting down Virtualbox VM..."
sudo -H -u $VMUSER VBoxManage controlvm "$VMNAME" acpipowerbutton
;;
status)
sudo -H -u $VMUSER VBoxManage list vms -l | grep -e ^"$VMNAME": -e ^State | sed s/\ \ //g | cut -d: -f2-
;;
backup)
echo ""
sudo -H -u $VMUSER VBoxManage controlvm "$VMNAME" acpipowerbutton
echo "Waiting for VM "$VMNAME" to poweroff..."
until $(sudo -H -u $VMUSER VBoxManage showvminfo --machinereadable "$VMNAME" | grep -q ^VMState=.poweroff.)
do
sleep 1
done
FILENAME=$(date +"%Y_%m_%d-%T")
echo "Backing up Virtualbox VM to '$BASEFOLDER$FILENAME'..."
sudo -H -u $VMUSER VBoxManage clonevm "$VMNAME" --options keepallmacs --name $FILENAME --basefolder $BASEFOLDER
echo "Restarting VirtualBox VM..."
sudo -H -u $VMUSER VBoxManage startvm "$VMNAME" --type headless
echo ""
;;
*)
echo "Usage: sudo service vbox {start|stop|status|shutdown|reset|backup}"
exit 1
;; esac
exit 0
Please note that I got that script from here: https://superuser.com/questions/789653/init-d-control-script-for-virtualbox-vm
Please verify the commands within prior to installing the script, then test each functionality. You will need to place it in the /etc/init.d directory, and run chmod +x
on it to make it run. Then go through and test the functionality of it. Once satisfied, run:
sudo update-rc.d vbox defaults 99 01
This will set it to start with the system. The original post has some steps for cron jobs, as an FYI. If anyone knows of a more up to date method of doing this, please feel free to edit this post, or post another answer.
Solution 2:
I would go with a combination of cron job and usage of vboxmanage via bash scripts.
I'd have a bash script which would start up the virtual machines and fire up a cron job for checking the status of the machines.
The script should look something like:
#!/bin/bash
vboxmanage startvm "Server App VM name"
vboxmanage startvm "Windows XP VM name"
crontab ~/check_vms_and_shutdown_job.txt
Let's say we save it as start_vms_and_cronjob.sh
. Remember to chmod +x
it, so it can be actually executed.
You might wonder about the check_vms_and_shutdown_job.txt
file. It's a text file containing information about a job that should be run at certain intervals. In this example we placed it in the user's home folder and it should read:
*/5 * * * * ~/check_vms_and_shutdown.sh
This file should have a new line at the end of the line (press enter before saving ;) ) What this file does is that it describes a cron job which is run every 5 minutes and it executes a bash script.
Now what is this check_vms_and_shutdown.sh
script you might ask? Well, here's the whole point. It should say:
#!/bin/bash
if vboxmanage list runningvms | grep "Windows XP VM name"
then
echo "Windows XP still running."
else
echo "Windows XP shut down. Shutting down the rest."
vboxmanage controlvm "Server App VM name" savestate
crontab -r
shutdown -h now
fi
Now what it does, that it will check if there is the XP virtual machine running. If it's not, it will then order the server app virtual machine to save it's state. After that the cronjob will be removed and the system shut down. Remember to chmod +x
and here we also placed the file in user's home folder.
For convenience and better usage on the purpose you might also want to run the virtualboxes headless and have their usage be done through remote display.
Now add the start_vms_and_cronjob.sh
into your startup applications and you should be set.
So what we have here is:
- When the system starts, the virtual machines are started by a shell script and a new cron job (running a shell script) is created from a cron job rule txt file.
- In every 5 minutes the cron job runs the script which checks if the XP virtual machine is still running and if not it will save the other virtual machine, remove the cron job and shutdown the system.
Hope this helps you to configure just what you need.
Solution 3:
These are the steps to achieve the tasks outlined. The VM guest with the server application will be called "ServerApp", the Windows machine "WindowsXP" below. Replace these with their real names.
The method below involves creating a custom Xsession on the host machine. This has the advantage that we may strip down this session to only load applications we need for running our virtual machines (we likely won't need a full blown desktop for this). In addition, using the wait methods inbuilt to VirtualBox will not require any additional loops to be called for monitoring the VM states.
- Create a user for running the virtual machine.
- Install the guest additions to the guest
- Switch to fullscreen with Host + F while running the VM.
-
Define a custom Lubuntu session on the host:
-
Create a file in
/usr/share/xsessions
and name it e.g.WindowsVM.desktop
with following content:[Desktop Entry] Name=WindowsXP # or any other sensible name Comment=Custom Xsession running a VM Exec=/etc/X11/Xsession
Make this file executable. This session will call
~/.xsession
on login.
-
-
Create the executable session startup script named
~/.xsession
in above user's HOME:#! /bin/bash /usr/bin/lxsession -s Lubuntu LXDE & VBoxManage startvm "ServerApp" --type headless VBoxManage startvm "WindowsXP" VBoxManage guestproperty set RUNNING 1 --flags TRANSIENT VBoxManage guestproperty wait "WindowsXP" RUNNING VBoxManage controlvm "SeverApp" savestate dbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" /org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop
Choose the custom session in 4. on login.
The tricky bit is to get the guest property RUNNING (or any other name we choose) deleted from the virtual machine as it is not so transient as the specs suggest. Unfortunately it will survive a shutdown/poweroff of the virtual machine.
We therefore have to add the following command using VBoxcontrol.exe (installed with the guest additions) to the guest Windows at the end of its shutdown routine (or from a shutdown script we put there):
VBoxControl.exe guestproperty set RUNNING
This will then terminate the wait
state to proceed with saving the "ServerAPP" then poweroff the host.
An alternative to this is starting a Windows application on the guest to wait for this application to terminate before we shutdown the machines and poweroff the host. Then we'd replace the two set guestproperty
commands in the script by a line similar to this:
VBoxManage --nologo guestcontrol "WindowsXP" execute --image "C:\\full\\path\\to\\program.exe" --username <windowsuser> --password <password> --wait-exit --wait-stdout
See VirtualBox Manual for limitations, and for further details on how to set this up for a passwordless account in Windows.
Commands of script in step 5. explained:
/usr/bin/lxsession -s Lubuntu LXDE
starts a Lubuntu session (replace with any other customized Xsession if applicable)VBoxManage startvm "ServerApp --type headless"
starts the virtual machine running the server App in headless mode (i.e. no display)VBoxManage startvm "WindowsXP"
starts the virtual machine running Windows (fullscreen or any other resolution as defined on last run)VBoxManage guestproperty set "WindowsXP" RUNNING 1 --flags TRANSIENT
sets a property RUNNING for the Windows machine that can be controlled from the guest OSVBoxManage guestproperty wait "WindowsXP" RUNNING
waits for the property RUNNING to be removed from the guest WindowsVBoxManage controlvm "SeverApp" savestate
terminates the server App VM in savestatedbus-send --system --print-reply --dest="org.freedesktop.ConsoleKit" \
/org/freedesktop/ConsoleKit/Manager org.freedesktop.ConsoleKit.Manager.Stop
terminates the Lubuntu host (poweroff state) without user interaction.