# How to start a VM on boot, and shutdown on VM stop?

### Long story short...

I had to install a small server app running in a VM on one of this company's PC. Both computers are running Windows XP (with legacy softwares, so upgrading is not possible), and buying an extra PC is limited at the moment. So, I converted the host's Windows on one of them into a VM, and installed Lubuntu. Then imported the server app and everything works fine; everything is almost transparent to the user, except for the start up and shot down processes.

### The problem

I was wondering how I could start both VMs on the host's startup, then shutdown the PC when the Windows XP's VM shots down? Right now, the workers are doing this manually, but I would like to automate this process.

### Requirements

1. Lubuntu should have a user configured to log in on start up -> done!
2. The server app VM should start at logon -> unsure
3. The Windows XP VM should start at logon -> unsure
4. The server app VM should save state and be closed automatically when the Windows XP machine is terminated -> don't know
5. Lubuntu should shutdown when all VM are paused/closed. -> don't know

The system is running on Lubuntu 14.04 with VirtualBox 4.3.x.

You could set up an Init.d/Systemd script like this one:

#! /bin/sh
# /etc/init.d/vbox

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.

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.

• The cronjob is interesting. However, what if something happens and the computer powers down before the check_vms_and_shutdown.sh script is scheduled? (i.e. the employee manually shuts down the computer before it executes) Then, will it add check_vms_and_shutdown.sh again on next boot? Nov 11 '14 at 14:29

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.

1. Create a user for running the virtual machine.
2. Install the guest additions to the guest
3. Switch to fullscreen with Host + F while running the VM.
4. 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.

5. Create the executable session startup script named ~/.xsession in above user's HOME:

#! /bin/bash

/usr/bin/lxsession -s Lubuntu LXDE &
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

6. 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 OS

• VBoxManage guestproperty wait "WindowsXP" RUNNING
waits for the property RUNNING to be removed from the guest Windows

• VBoxManage controlvm "SeverApp" savestate
terminates the server App VM in savestate

• dbus-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.

• Very detailed answer! Thank you, I will start from there! But, from what I can read, it looks fine to me. I'll add the VBoxControl.exe guestproperty set RUNNING as a Windows scheduled task (on shutdown), as an admin. As for step 5, I didn't play much with LXDE, and the machine is already setup to auto-logon. Other than that, thanks! Mar 2 '15 at 18:54
• @YanickRochon: at least somebody took notice ;) I'd be happy to hear about your progress on this. Mar 2 '15 at 19:13