Virtualbox Windows graceful shutdown of guests on host shutdown

19

5

I am trying to find a solution to gracefully shutdown any guest VMs running under VirtualBox Windows when the host computer is shut down or restarted.

It seems that the safest option would be to trigger the "save state" command when the host starts shutting down, but it is not clear whether the host will wait long enough for the VMs to finish saving state and power off.

Does anyone have a robust solution for this (seemingly basic) issue?

Matt Jenkins

Posted 2015-08-19T12:24:04.553

Reputation: 291

Install the guest additions? Does that not provide the functionality required? – Canadian Luke – 2015-08-19T23:31:25.420

@CanadianLuke It does not. :) – Matt Jenkins – 2015-11-06T11:09:33.907

Answers

6

I had a similar problem and solved it by running VirtualBox as a service:

http://vboxvmservice.sourceforge.net/

With VBoxVMService you can chose how you want the machine to shutdown (Save state, power off) and startup. Since it's running as a service, Windows will automatically wait for it to shutdown, during the system shutdown process.

Bill Westrup

Posted 2015-08-19T12:24:04.553

Reputation: 193

The setting up process is not so automatic on Windows 10. I have to refer to the trouble shooting to see what's wrong. However, after configured correctely, this software does exactly what I need. Thank you for you great work. – iuradz – 2017-05-09T06:25:11.187

4

Sorry I'm late to the party. There is an exact answer to this, though it requires some commandline-foo. See this thread post for more information: https://forums.virtualbox.org/viewtopic.php?f=6&t=53684#p285540

The command you are looking for is:

"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" setextradata "VM NAME" GUI/DefaultCloseAction Shutdown

This is what I use on multiple VMs, close the window and it starts a safe shutdown automatically. Shutdown Windows, and in its attempt to close everything, it will wait for these processes to complete.

Kris Bahnsen

Posted 2015-08-19T12:24:04.553

Reputation: 149

Thanks! Since OP was looking for save state, the answer is SaveState instead of Shutdown. – wbkang – 2020-02-17T22:15:28.763

3

Unfortunately that doesn't seem to be possible for VMs started via VirtualBox GUI. Even though the GUI might catch the host shutdown event and react, the VirtualBox service gets terminated: https://forums.virtualbox.org/viewtopic.php?p=278668#p278668

If you don't need a graphical console, VBoxHeadlessTray or VBoxVMService might be the way to go. Both support automatic save and resume on Windows host shutdown and restart.

VirtualBox 5.0 introduces a "detachable UI" start mode. This mode starts a headless VM with a separate UI process. Graphical performance suffers though and 3D acceleration isn't supported yet. But maybe this can be combined with VBoxHeadlessTray in the future (VBoxHeadlessTray doesn't support 5.0 yet.) Links to VBoxHeadlessTray GitHub repository and to the corresponding GitHub pull request for adding VirtualBox 5 support.

Edit: VBoxVmService also doesn't support the new detachable mode as of version 5.0. Only headless so far. I added a feature request for that.

Leo B

Posted 2015-08-19T12:24:04.553

Reputation: 31

As I am not allowed to port more than two links per post, here are the links to VBoxHeadlessTray and to the corresponding GitHub pull request for adding VirtualBox 5 support.

– Leo B – 2015-10-31T10:00:55.393

I do not experience the issues outlined in the thread. See my answer on this topic. I can run Windows host shutdown and walk away. Shutdown blocks until all of my VMs are closed, and I've changed the default action to do a clean shutdown or a save state. – Kris Bahnsen – 2018-04-04T16:59:29.483

2

I have 3 batch scripts which I use instead of the startmenu power buttons.

do_shutdown.bat (shutdown pc with a 10 sec waiting period, not to give the vm's 10 sec time to savestate, but to allow me to cancel the shutdown within 10 seconds. The countdown starts after the vm's have been shut down)

"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Server" savestate
"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Minimal" savestate
shutdown /s /t 10

do_reboot.bat (reboots immediately after the vm's got shut down)

"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Server" savestate
"C:\VirtualBox\VBoxManage.exe" controlvm "Ubuntu Minimal" savestate
shutdown /r /t 0

do_cancel.bat (allows me to cancel the pc-shutdown within the 10 second waiting period. It then restarts the vm's again, since they got shut down with the do_shutdown.bat)

shutdown /a
C:\VirtualBox\VBoxManage.exe startvm "Ubuntu Minimal" --type headless
C:\VirtualBox\VBoxManage.exe startvm "Ubuntu Server" --type headless

Instead of savestate you can also use one of the following

poweroff        - pulls the plug
                  (probably not a good idea...)

acpipowerbutton - presses the power off button for a clean shutdown
                  ("The system is going down for power off NOW!" to all consoles)

acpisleepbutton - tells the os to go to sleep
                  (probably just as bad as poweroff)

Daniel F

Posted 2015-08-19T12:24:04.553

Reputation: 751

1Thanks, this is interesting. Unfortunately, there are other non-manual shutdown/reboot scenarios that I need to handle as well. For example, restarts scheduled by Windows Update, or low battery power off/shutdown events. – Matt Jenkins – 2015-11-06T11:08:56.217

1

Oh, ok. There's also the Group Policy Editor with the "Scripts (Startup/Shutdown)" section http://lifehacker.com/use-group-policy-editor-to-run-scripts-when-shutting-do-980849001 I'm using that one for a very short command on shutdown (one curl call), so I don't know how it behaves on scripts that take a while to complete.

– Daniel F – 2015-11-06T13:07:53.090

1

I had a similar question and found this page. I don't want to run VirtualBox as a service, because I have a lot of VMs for testing, and usually pick different ones to run in the VirtualBox UI. When I shutdown my computer, it is annoying to manually save the state of each VM. Using scripts to save all running VMs seems to be a practical solution in this case. To make the answer of Daniel F more general, I wrote these scripts that automatically save the state of all running VMs without naming them explicitly.

saveRunningVMs.bat for Windows:

set VBoxManageEXE="%ProgramFiles%\Oracle\VirtualBox\VBoxManage.exe"
set ListRunningVMS=%VboxManageEXE% list runningvms
for /f tokens^=2^,4^ delims^=^" %%p in ('%ListRunningVMS%') do %VBoxManageEXE% controlvm %%p savestate

echo all vms saved, you can shutdown now.

rem shutdown /s /t 10

saveRunningVMs.sh for Linux:

#!/bin/bash
vboxmanage list runningvms | while read line; do
  #echo "VBoxManage controlvm $uuid savestate;"
  echo $line
  if [[ $line =~ \{(.*)\} ]]
  then
    vboxmanage controlvm ${BASH_REMATCH[1]} savestate
  fi
done

Karl Wolfram

Posted 2015-08-19T12:24:04.553

Reputation: 11

0

I created a python script that would suspend all the running VirtualBox VMs, and then set the system up to run the script on logout as a scheduled task.

I don't know how reliable this method is exactly. As others have noted there are limits to how long the system will wait for a Winlogon 7002 task to complete. But I personally haven't had any problem with it giving usable save states even with multiple running VMs across 4+ GB of overall VM RAM.

Here are the steps to set it up:

  1. Download and install Python 2.7.x from python.org
  2. Create the python script file somewhere on your system using Notepad or any other plain text editor (see below)
  3. Open Task Scheduler
  4. Choose Action -> Create a Basic Task... and use the wizard to create a task with the following settings
    • A name of your choice
    • Start the task when a specific event is logged
    • Log: System
    • Source: Winlogon
    • Event ID: 7002
    • Start a Program
    • Next to Program/Script, enter the full path to your python.exe, for instance c:\Python27\python.exe
    • Next to Add arguments, enter the full path where you put the python script file, for instance I put mine in a subfolder of my documents folder, so this is C:\Users\rakslice\Documents\vboxsuspend\vboxsuspend.py
    • Choose Finish.

Now VirtualBox VMs should be suspended on logout/restart/shutdown.

The python script to do the shutdown is below:

# A script to suspend all running VirtualBox VMs

import os

import subprocess

import sys


class VM(object):
    def __init__(self, name, uuid):
        self.name = name
        self.uuid = uuid

    def __repr__(self):
        return "VM(%r,%r)" % (self.name, self.uuid)


class VBoxRunner(object):
    def __init__(self):
        program_files = os.environ["ProgramW6432"]
        vbox_dir = os.path.join(program_files, "Oracle", "VirtualBox")
        self.vboxmanage_filename = os.path.join(vbox_dir, "VBoxManage.exe")

    def vbox_run(self, *args):
        subprocess.check_call([self.vboxmanage_filename] + list(args))

    def vbox_run_output(self, *args):
        return subprocess.check_output([self.vboxmanage_filename] + list(args))

    def list(self, running=True):
        if running:
            list_cmd = "runningvms"
        else:
            list_cmd = "vms"

        return [self.parse_vm_list_entry(x) for x in self.vbox_run_output("list", list_cmd).strip().split("\n")]

    def suspend_all(self):
        success = True
        stopped_some_vms = False
        vms = self.list(running=True)
        for vm in vms:
            if vm is None:
                continue
            # noinspection PyBroadException
            try:
                self.suspend_vm(vm)
            except:
                success = False
            else:
                stopped_some_vms = True
        if not stopped_some_vms:
            self.message("No running vms")
        return success

    @staticmethod
    def parse_vm_list_entry(x):
        """:type x: str"""
        if not x.startswith('"'):
            return None
        end_pos = x.find('"', 1)
        if end_pos == -1:
            return None
        name = x[1:end_pos]
        assert x[end_pos + 1: end_pos + 3] == " {"
        assert x.endswith("}")
        uuid = x[end_pos + 2:]

        return VM(name, uuid)

    @staticmethod
    def message(msg):
        print >>sys.stderr, msg

    def suspend_vm(self, vm):
        assert isinstance(vm, VM)
        self.vbox_run("controlvm", vm.uuid, "savestate")


def main():
    vr = VBoxRunner()
    success = vr.suspend_all()
    if not success:
        sys.exit(1)


if __name__ == "__main__":
    main()

rakslice

Posted 2015-08-19T12:24:04.553

Reputation: 2 276

1Others' suggestion of using a batch script you can run manually that does the savestates and then does the shut down is great if that fits your use case. But what I really want this for is Windows Update automatic reboots, after a VM I've been working with has been hard powered off overnight by Windows Update restarts for the past two days in a row... – rakslice – 2018-06-04T03:59:44.947