3

I am running a VM using

qemu-system-x86_64 -accel kvm,thread=multi -cpu host -smp 1 -m 2048 \
-drive file=ubuntu-server1.qcow2,if=virtio -vga virtio -display none -daemonize \
-nic bridge,model=virtio-net-pci,mac=DE:AD:BE:EF:E0:00

To get the IP address I have to use:

ps -ef | grep qemu
arp | grep -i DE:AD:BE:EF:38:C4
ip neigh | grep -i DE:AD:BE:EF:38:C4

After, reading the wiki, I have installed and enabled qemu-guest-agent in the guest.

sudo apt install qemu-guest-agent
sudo systemctl start qemu-guest-agent
sudo systemctl enable qemu-guest-agent

I have run the VM using

qemu-system-x86_64 -accel kvm,thread=multi -cpu host -smp 1 -m 2048 \
-drive file=ubuntu-server1.qcow2,if=virtio -vga virtio -display none -daemonize \
-nic bridge,model=virtio-net-pci,mac=DE:AD:BE:EF:E0:00 \
-chardev socket,path=/tmp/qga.sock,server,nowait,id=qga0 \
-device virtio-serial \
-device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0

So, the socket is in /tmp/qga.sock.

Now I am not understanding how to use this socket to get the hostname and IP of the guest.

Just to be clear, I have checked How to find the IP address of a KVM Virtual Machine, that I can SSH into it? , but I am not interested to use virt-manager.

1

1 Answer 1

7

From the QEMU documentation example, socat can be used to query the guest agent's API over its socket. As everything appears to be in JSON, better have the jq tool installed too.

mdroth@illuin:~$ sudo socat unix-connect:/tmp/qga.sock readline

[...]

{"execute": "guest-info"}

[...]

The command above gives among other things the list of all possible commands that can be sent.

On my Debian system, the readline feature is disabled in socat, and man page tells to use stdio (alias -) instead. Alas, sometimes the output doesn't happen or is incomplete and I suspect socat doesn't handle optimally EOF conditions in this case. Adding a delay in the left side appears to fix this.

This becomes (as root or an adequate user):

{ echo '{"execute": "guest-info"}'; sleep 2; } | socat unix-connect:/tmp/qga.sock -| jq .

[...]
      {
        "enabled": true,
        "name": "guest-network-get-interfaces",
        "success-response": true
      },
[...]

One can now send {"execute": "guest-network-get-interfaces"} and with some filter (and some training) using jq:

# { echo '{"execute": "guest-network-get-interfaces"}'; sleep 2; } |
      socat unix-connect:/tmp/qga.sock - |
      jq -j '."return"[] | ."name", (."ip-addresses"[] | " ", ."ip-address","/",."prefix"),"\n"'
lo 127.0.0.1/8 ::1/128
ens3 192.0.2.2/24

Error handling for null values (interfaces without address) is left as an exercise.

For the hostname part, it's easier, there's a single value. The command is "guest-get-host-name":

{ echo '{"execute": "guest-get-host-name"}'; sleep 2; } | socat unix-connect:/tmp/qga.sock - | jq  -r '."return"."host-name"'
1
  • Thanks for the tip about the delay afterwards! I was having trouble (unix.stackexchange.com/questions/426652/…) where the monitor would only get one character of my command before closing with a weird reverse-rendered (tput rev-style) % sign. I thought to try a sleep before my echo which didn't help, but the sleep after does!
    – natevw
    Mar 10, 2022 at 0:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .