Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I need to run a software system that is intended to be installed as an appliance on a dedicated machine. In order to save energy, I plan to run the system on a VirtualBox VM instead.

The host is a standard Linux box with a SysV-Init system, the guest is a heavily modified Linux and I would prefer not to have to alter it further. VirtualBox is used in the OSE version.

I have already figured out how to start the VM when the host boots (Edit: this is done, as Nikhil mentioned below, through the command VBoxManager startvm), but how can I gracefully shut down the VM? Any script running on the host would need to wait until the guest has fully shut down.

Can anyone suggest how, for example, a service file doing this would have to look?

share|improve this question
    
could you give the startup script to start virtual machine while booting –  rajcoumar Sep 26 at 7:26

9 Answers 9

up vote 23 down vote accepted
+50

Have you tried acpipowerbutton from this command set?

VBoxManage controlvm        <uuid>|<name>
                            pause|resume|reset|poweroff|savestate|
                            acpipowerbutton|acpisleepbutton|

Edit after reading the comments:

You can use acpid or other acpi utilities to make it graceful. Also, can you provide more information about how do you shutdown the machine at the moment?

Plain shutdown wouldn't wait for unfinished jobs, a time delay may be too long.

I assume you aren't using a window manager so try this tool.

Just seen this daemon. You might find it useful.

share|improve this answer
    
Thanks for your reply and welcome to unix.stackexchange.com! However, I'm afraid your answer also does not address my issue: acpipowerbutton simulates pressing the power button on a real machine, but after issuing this command on the host, the VM would, again, take some time to shut down. –  jstarek Jan 18 '12 at 19:11
2  
Sure. So you have to write a loop that checks whether the VM is still running. ACPI is exactly the same method I use in my scripts for this. vboxmanage list runningvms until your VM is gone. –  Nils Jan 18 '12 at 20:20
    
OK, while I think I'll settle for a management wrapper in practice, +50 to you for pointing to the initscript! –  jstarek Jan 24 '12 at 14:35

Looking at VirtualBox VM management documentation at http://www.virtualbox.org/manual/ch08.html

For listing the VMs, use the command VBoxManage list vms

For starting the VM, use the command VBoxManage startvm

http://www.virtualbox.org/manual/ch08.html#vboxmanage-controlvm

For controlling VM, use VBoxManage controlvm

The controlvm subcommand allows you to change the state of a virtual machine that is currently running. The following can be specified:

VBoxManage controlvm <vm> pause temporarily puts a virtual machine on hold, without changing its state for good. The VM window will be painted in gray to indicate that the VM is currently paused. (This is equivalent to selecting the "Pause" item in the "Machine" menu of the GUI.)

Use VBoxManage controlvm <vm> resume to undo a previous pause command. (This is equivalent to selecting the "Resume" item in the "Machine" menu of the GUI.)

VBoxManage controlvm <vm> reset has the same effect on a virtual machine as pressing the "Reset" button on a real computer: a cold reboot of the virtual machine, which will restart and boot the guest operating system again immediately. The state of the VM is not saved beforehand, and data may be lost. (This is equivalent to selecting the "Reset" item in the "Machine" menu of the GUI.)

VBoxManage controlvm <vm> poweroff has the same effect on a virtual machine as pulling the power cable on a real computer. Again, the state of the VM is not saved beforehand, and data may be lost. (This is equivalent to selecting the "Close" item in the "Machine" menu of the GUI or pressing the window's close button, and then selecting "Power off the machine" in the dialog.)

After this, the VM's state will be "Powered off".

share|improve this answer
    
Note that on some systems, it is vboxmanage (all lower case). –  Arcege Jan 8 '12 at 15:48
2  
Thanks for your reply, but unfortunately, this does not address my issue: I need to gracefully shut down the guest, i.e. issue a "shutdown -h now" inside the guest and have the host wait until the guest has shut down completely. None of the VBoxManage controlvm subcommands do that. –  jstarek Jan 8 '12 at 16:20
    
You can make sure that by rechecking all the vms are down in the host before host goes down. If you need to control host from inside the guest, then virtualbox.org/manual/ch08.html#vboxmanage-guestcontrol but this may not give you what you are looking for. You should write a startup script like /etc/init.d/vboxvms-service script on host system, which upon start will make all vms on and upon stop, will make all the vms go down. –  Nikhil Mulley Jan 8 '12 at 16:39
    
VBoxManage controlvm savestate is another possibilty (at least google tells me), it saves the machines status and shuts it down cleanly, but still no way to force the host to wait. –  Baarn Jan 8 '12 at 20:53

Probably a stupid question, but why don't you login to your guest and shutdown from there?

Unless you have a good reason for not installing sshd and accessing the VM really through VBox, I'd go for a script that just issues an ssh shutdown -h now. To be honest, I'd create a script for every machine that properly shuts it down and perform some checkups while at it.

Just pack an /etc/init.d/shutdown_vm script that call the other one from the host, the call will block until is ready. This process (as described) adds a linux dependency at the guest but removes the VBox dependency at the host.

Cutting to the chase: you don't need to access VBox to shutdown a machine, if you have some means of accessing it (i.e. ssh) then the OS will always have some means for that (turning it on, is different of course)

share|improve this answer
    
Two reasons: First, as stated in the original question, I did not want to alter the heavily modified guest OS if it wasn't really necessary. Secondly, and more importantly, this was intended to provide a clean way to automatically shut down all running VMs if the host was shut down. –  jstarek Mar 4 at 13:31
    
@jstarek But you don't have to modify your guest OS if you don't want to (99.99% of the time you have some means to log in, or is this an exception). And exactly that's the idea, if the host goes down, the proper script will get called when changing runtime and this just logs to the guest and shut it down from "inside", which is what vagrant does anyways... before going "brute force" that is... –  estani Mar 14 at 16:50

For a systemd based system, you could try this.

Step #1: create a service file

[Unit]
Description=VBox Virtual Machine %i Service
Requires=systemd-modules-load.service
After=systemd-modules-load.service

[Service]
User=user
Group=vboxusers
ExecStart=/usr/bin/VBoxHeadless -s %i
ExecStop=/usr/bin/VBoxManage controlvm %i savestate

[Install]
WantedBy=multi-user.target

Step #2: Enable the service file

$ sudo systemctl enable vboxvmservice@vm_name.service

References

share|improve this answer
1  
It is preferred to include an answer here and optionally provide links to more detailed information. Link targets disappear without notice, making your answer worthless. –  Anthon Jun 3 '13 at 11:53
    
Well, the problem is I cannot really copy the whole systemd file in link 1 here, or should I do this? –  Jan Rüegg Jun 3 '13 at 14:04
    
Well, unfortunately "link rot" is a huge problem in those cases... I think, for posterity, the following two lines catch the basic idea behind your Link: It's creating a service that uses VBoxHeadless -s %i to start and VBoxManage controlvm %i savestate to stop the VM. –  jstarek Jun 5 '13 at 19:03

Maybe this will help as part of the solution.

VBoxManage list runningvms | tr -s '\" {' '%{' | cut -d '%' -f3  | while read uuid; do
   VBoxManage controlvm $uuid savestate; 
done
share|improve this answer

My solution: In this shellscript 'root' is the invoker, and 'theuser' is the owner of 'thevm'

I know the vms have ended when the output of the command VBoxManage list runningvms returns an empty string.

...
start(){
    su -c "VBoxHeadless --startvm thevm" -s /bin/bash theuser &
    # maybe another vbox command
}

stop(){
    su -c "VBoxManage controlvm thevm acpipowerbutton" -s /bin/bash theuser
    # maybe another vbox command
    while [ "`su -c 'VBoxManage list runningvms' -s /bin/bash theuser`" != "" ]
    do
        echo waiting for VMs to shutdown
        sleep 3
    done
}
...
share|improve this answer

I have similar application as you, with one difference: I need to restart system and recover from snapshot.

What you are interested in is headless-mode.

I have a few of such services so I use following script:

VBox_StopRestoreStart.sh

#!/bin/bash
if [ -z "$1" ]; then
        echo "Usage: $0 VMNAME_or_UUID"
        exit 1
fi
set -x
VBoxManage controlvm  "$1" poweroff  #enforce turnoff
VBoxManage snapshot   "$1" restorecurrent   #retore state
VBoxManage showvminfo "$1" | grep State   #display state to ensure
VBoxHeadless -s       "$1"  #run in headless mode in background

how can I gracefully shut down the VM?

IF you want to turn off VM gracefully, you have two options, depending on your application:

  • Emulate "shut-down button" or "sleep button" and prepare VM to react on it (to close gracefully)
    • VBoxManage controlvm <uuid>|<VMname> acpipowerbutton
    • VBoxManage controlvm <uuid>|<VMname> acpisleepbutton
  • Save VM state in order to restore afterwards
    • VBoxManage controlvm <uuid>|<VMname> savestate

TIPS: You might find useful:

  • VBoxManage list vms - list of available vms
  • rdesktop IP-ADDR:3389 or rdesktop-vrdp IP-ADDR:3389 - when you would like a GUI (even remotely) when you run in headless mode : VBoxHeadless -s <uuid>|<VMname>
  • VBoxManage startvm - start with GUI for local debugging

Related VirtualBox manual's chapter: Chapter 7. Remote virtual machines - Step by step: creating a virtual machine on a headless server

P.S. If you are interested in full featured already implemented solutions, OpenStack seems interesting choice.

share|improve this answer

Rather than code this up yourself, consider using Vagrant, which is built to instantiate and control virtualbox instances. The documentation is excellent and I suggest that you check it out rather than attempting to roll your own.

The long and short of it is that you create a simple control file and then run vagrant up to start as many VirtualBox instances as you want. You can use vagrant ssh to log into the hosts and vagrant halt to shut the host down (without terminating). vagrant destroy will get rid of the instances.

It supports provisioning with puppet or Chef and allows you to control most of the exposed VBox configuration settings.

share|improve this answer
    
I'm a fan of vagrant, but in this case, what on earth would you want it for? The OP is running an appliance, not building up their own system, so provisioning misses the point entirely. And why go and make a custom 'box' out of the appliance, just to use vagrant, when you'd basically be going via the process of building the system with virtualbox to do that? –  mc0e Nov 24 at 17:09

How about to send the command via ssh from the host to the guest?

I am not sure if it works and if you can check the status of the machine afterwards or get something like an exit-status, but it should down clean atleast.

share|improve this answer
    
Good thought, but this would warrant that guest VM be reachable via network from the host, atleast the ssh port(22). –  Nikhil Mulley Jan 8 '12 at 17:30
    
Basically, this would work, the appliance can be reached in the entire LAN via its DNS entry. However, suppose I wrote a script that ssh'd into the appliance whenever the host goes down -- it would still have to block (pause) until the guest has shut down completely. This is precisely the point of my question: How can the script know when the guest is down, so that it can yield control flow back to SysV-Init and the host can continue to shut down? –  jstarek Jan 8 '12 at 19:35
1  
Your comment assumes that everything will work smoothly on host system and not on guest system. What if power cable is plugged out on host system? Its a different discussion. Your SysV-init on host system will wait for the service script to stop the VMs as long as service script understands the logic to get the guest VMs off in a right way (exec shutdown on remote host or just power off through vbox interface) and then yield return the success or failure status back to console or init. –  Nikhil Mulley Jan 8 '12 at 20:02
1  
Regarding: how script knows when the guest is down, try a simple check if the vm is on or off from VboxManager interface and if the guest is ssh'able. Also, put some monitoring on the host system which will perform whether the VM is available from Vboxmanager and its ssh'able on a timely basis. –  Nikhil Mulley Jan 8 '12 at 20:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.