Preparing Virtual Machine for Virsh Shutdown

One of the a bit tricky things with libvirt is to make guest OS support shutdown command directly, i.e. when you call virsh shutdown ${machine_name} the virtual machine shuts down gracefully and without any delay. 

Libvirt sends the an ACPI (see acpi.info for details)event to virtual machine when shutdown command is issued. Although delivering of ACPI events can be disabled in libvirt configuration, often the problem is that default settings of the most operating systems ignores the events or requires user interaction during their processing. That is undesired behavior for headless automated virtual machines -- below is how to configure some of the currently used operating systems to correctly shutdown when they receive the proper ACPI event. 

note: I intend to update this article when I get experience with any other operating system setup. Feel free to send me yous hands-on as comments.



  1. install acpid : apt-get install acpid
  2. start it : service acpid start
  3. Add it to default run level:  update-rc.d acpid enable
  4. disable confirmation dialogs by editing /etc/acpi/events/powerbtn
    1. add # to comment line: #action=/etc/acpi/powerbtn.sh
    2. add a new line: action=/sbin/poweroff

Windows Server

  1. change policies
    1. open the Group Policy Editor: gpedit.msc
    2. allow shutdown when an administrator is not logged in
      1. navigate to Local Computer Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Local Policies -> Security Options
      2. find option: “Shutdown: Allow system to be shut down without having to log on” and set it to “Enabled”
    3. disable the “Shutdown Event Tracker” (the dialog that will be presented to the user when a shutdown is requested)
      1. navigate to Local Computer Policy -> Computer Configuration -> Administrative Templates -> System
      2. find option “Display Shutdown Event Tracker” and set it to “Disabled”
  2. set power button to shutdown
    1. open Control Panel
    2. select Power Options
    3. left pane select “Change what the power buttons do” and set it to “shutdown”
  3. disable monitor sleep
    1. open Control Panel
    2. select Power Options, select "Change power-saving settings"
    3. select “High performance”
    4. click on “Change plan settings” and disable monitor sleep by setting "Turn off display" option to 'Never"


Getting IP Address of a Virtual Machine

When assigning IP addresses to a virtual machine, aka domain, you have two options -- either to assign a fixed IP to the machine or use DHCP for providing an IP address from a predefined range.

In environment in which you need to dynamically create groups of cooperating virtual machines the approach with fixed IP address is not feasible as it uses the network address range inefficiently and/or requires careful IP address management. 

We needed the DHCP way. The problem is how to get the IP address for a virtual machine when all you have is only the machine's name.

There are two ways how to find out most of the information about a virtual machine, including its IP address:
  • with a help from inside -- guest OS needs to have installed kind of hypervisor-specific software, so called guest agent, mediating communication of the host with the guest
  • from outside -- gathering the desired information relies on standard tools of host OS and network connectivity

Virtualbox - Guest Additions

The IP address of the virtual machine can by retrieved from the machine properties with a single command vboxmanage guestproperty enumerate ${machine_name}. The information about guest network is available in guest properties only when the guest has installed Guest Additions, which limits the list of guest operating systems to Linux, Windows and Solaris.

To extract just the IP in bash or similar UNIX shell run:
vboxmanage guestproperty enumerate ${machine_name} | grep IP | cut -d " " -f 4 | cut -d "," -f 1

Libvirt - QEMU Guest Agent

Also QEMU has Guest Agent, supporting Linux and Windows guests, that can be use to get machine's IP address

No Guest Tools, Just Linux

Second approach relies some basic knowledge about the virtual machine and the network interface it is connected to. Basically you need to know machine's MAC address and name of the NIC. For bridged networking the NIC is likely to be named br0.

Let's suppose the host OS is Linux. Similar approach should work on other operating systems but the tools will differ. 

For the translation if MAC address to IP address I rely on arp-scan.  It scans the whole network or given range if IP addresses and provides the MAC-to-IP mapping. To scan a whole network you can run arp-scan --interface ${bridge_name} -l , for larger networks you should provide IP address range to reduce time and memory footprint:
arp-scan --interface ${brige_name} ${low_ip_limit}-${high_ip_limit} .

So the complete bash script for getting virtual machine's IP address could look like this (for libvirt and br0 NIC):



mac_address=`virsh dumpxml ${vm_name} | grep "mac address" | cut -d "'" -f 2`

arp_scan_record=`arp-scan --interface ${bridge_name} -l | grep $mac_address`

ip_address=`echo -n ${arp_scan_record} | cut -d " " -f 1`

echo -n "${ip_address}"