-3

When I start a qemu (Windows Server 2003) virtual machine with

-qmp tcp:127.0.0.1:4444,server,nowait

I can make it shutdown with the following script

#!/bin/bash
telnet 127.0.0.1 4444 <<JSON 
{ "execute": "qmp_capabilities" } 
{ "execute": "system_powerdown" } 

JSON

But there are two problems:

  1. the script exits with $? = 1 and says "Connection closed by foreign host". Can I make it exit in a clean way?

  2. The shutdown process happens asynchronously. So, the script returns at once, not waiting for the vm to finish the shutdown. How do I know when it's done (without grepping ps for qemu or something like this)?

The background is I want to host a Windows Server 2003 installation inside a VM on a linux host and I want to use an UPS. In case of a blackout, I want to shutdown the VM and then the host – and of course, the host should start the shutdown not until the VM is done.

  • 2
    Why aren't you running your VMs with libvirt? It takes care of this for you. – Michael Hampton Dec 27 '13 at 09:44
  • 1
    I want to keep the overhead as small as possible. Libvirt is an abstraction layer that I actually don't need – starting the VM via shell script is just fine. It's just this one case (that hopefully never will happen) where this would be a benefit, so I'm looking for a solution without it. – Tobias Leupold Dec 27 '13 at 09:49
  • 2
    I think you're making the overhead TOO small. libvirt is pretty lightweight already, and not to mention it makes doing everything else with your VMs much easier. – Michael Hampton Dec 27 '13 at 09:50
  • Well, everthing else works just fine ;-) – Tobias Leupold Dec 27 '13 at 09:51
  • 2
    If you're doing stuff like the above, then everything else is probably a complete mess that only barely works, and will break if you look at it the wrong way. You **really** should be using libvirt. – Michael Hampton Dec 27 '13 at 09:52
  • Honestly, I do nothing else but starting the VM with "qemu-kvm -monitor stdio -qmp tcp:127.0.0.1:4444,server,nowait -smp 2 -m 2G -net nic,model=virtio -net tap,ifname=tap0,script=no,downscript=no -drive file=system.qcow2,if=virtio -usbdevice tablet". The networking infrastructure setup is done via the host system (Gentoo). It does work without a problem. What benefit would libvirt bring? Anyway, I'll have a look at it. – Tobias Leupold Dec 27 '13 at 09:56

2 Answers2

2

It is possible using expect. An event called "SHUTDOWN" will be emitted when the vm is finished. So, the following script starts the shutdown and waits for it to complete:

#!/usr/bin/expect

set timeout -1

spawn telnet 127.0.0.1 4444

expect "QMP"
send "{ 'execute': 'qmp_capabilities' }\n"

expect "return"
send "{ 'execute': 'system_powerdown' }\n"

expect "SHUTDOWN"

As I got already downvotes for my question and especially considering the following statement

If you're doing stuff like the above, then everything else is probably a complete mess that only barely works, and will break if you look at it the wrong way.

I have to say another thing. I really don't see why doing something like this is "probably a complete mess", especially the vm itself. When launching it via libvirt, the very same thing is done compared to a shell script doing the job. Why should it "barely work"?! Additionally, QMP has been designed and made available through something like telnet to make it possible to do "something like this" in this way, isn't it?

And isn't libvirt nothing but a wrapper to the interfaces of several virtualization solutions so one can handle multiple vm installations run by different hypervisors in the same manner? So why should I use it when I only run one vm in one hypervisor?

Probably I'm completely wrong here, but at least, this is how one can shutdown a qemu virtual machine using a (bash) script and know when it's done in a decent way without having to use libvirt.

1

Came across this looking to shut down a VM with out libvirtd. As to why, libvirtd would not start due to a failed swap device. I wanted to cleanly shut down the vm's and couldn't use libvirt to save to disk. With the above I came up with

in /var/lib/libvirt/qemu

for sock in $(find | grep monitor); do printf "{ 'execute': 'qmp_capabilities' }\n{ 'execute': 'system_powerdown' }\n" | socat - UNIX-CONNECT:$sock; done

This is for UBUNTU. So overall yes I usually would use libvirt, but I knew it was an interface to some other command to shut down. Knowing what libvirt was actually doing let me cleanly shut down the vm's.