======================
== fabulous.systems ==
======================
Welcome to the world of fabulous.systems

Using qemu-guest-agent as interface between VMs and Proxmox host systems

#modern-stuff #sysops #linux #proxmox

Since virtual machines created with KVM/QEMU are not simple containers but quite isolated from the host’s environment, exchanging data and information between the host and the VMs can be a bit tricky. Therefore, QEMU offers a companion service called qemu-guest-agent for Linux guests. qemu-guest-agent acts as an interface between the VMs and the host system.

Some features like passing ACPI information for a clean guest shutdown are pretty well-known. However, did you know that you can even send commands to your VMs directly from your Proxmox host system?

Proxmox Virtual Environment uses KVM/QEMU as virtualization technology. Since calling the qemu-guest-agent interface is not very intuitive by itself, Proxmox provides the qm guest command which acts like a bridge between the host system and the VMs.

Using the qm guest command requires qemu-guest-agent to be installed inside your Linux guests. Since the guest agent is pretty essential in case you want to be able to do properly shut down the VMs without performing virtual powercuts or being able to create consistent backups, you want to install it on all of your Linux guests anyways.

In order to use the following commands, you need to get the VMID of your virtual machines. You can get them either from the Proxmox dashboard or by running the qm list command on your host system.

Reset user passwords (including the root user)

I basically learned about qm by accident. Usually, I tend to lock all local user accounts in order to make (virtual) console access impossible. Especially on VMs, this might not even be exactly helpful regarding security, but this is some sort of personal preference. Due to a configuration error on my end, I locked myself out of a VM running on my Proxmox host, so I was not able to SSH into it anymore.

The obvious solution would be to shut down the VM, boot a rescue environment or live distribution, mount the disk and fix the configuration there. I knew the VM was performing some maintenance tasks in the background which do not like sudden interruptions, so I needed some sort of backdoor.

This is where qm guest passwd comes in handy. As the command suggests, it can be used to set user passwords in your VM, even if there’s no direct access to it anymore.

As an example, the following command resets the password for the user root on VMID 100:

qm guest passwd 100 root

After invoking this command, qm will interactively tell you how to set a new user password for the account in question. If the user was previously locked with passwd -l, the user will be automatically unlocked.

Run arbitrary commands in your VM

As you might have noticed, we have full access to the guest operating system using the QEMU Guest Agent (or QGA for short). Therefore, we can pass any command to the guest. Side note: This is a friendly reminder that you really want to care about the security of your host system.

The command we are looking for is qm guest exec (again using VMID 100 as an example):

qm guest exec 100 -- ping google.com -c 3

qm exec will pass the command to the VM, execute it and wait for the command to finish or break with an exit code. Afterwards, it will return the exit code as well as the contents of stdout and stderr in JSON format. Please be aware that all commands are executed with root privileges.

Long-running tasks can be sent to the background using the --synchronous=0 parameter. You can check the state of the process by using the qm guest exec-status $yourVMID $PID command.

Get additional VM information and perform low-level tasks

Next, let’s take a look at qm guest cmd. Now, we are not executing commands within the guest operating system itself. Instead, with cmd we call various QGA commands on a lower level. Those commands are more focused on maintenance and less on interaction with the guest operating system.

In order to use this feature, use the following command:

qm guest cmd $yourVMID $Command

I compiled a list of valid commands below. Just like the qm guest exec command, the output will be JSON formatted.

Command                Description
fsfreeze-freezeSend the fsfreeze-freeze command to the guest, locks the file system on the guest machine
fsfreeze-statusQuery fsfreeze-status, returns ‘frozen’ or ‘thawed’
fsfreeze-thawThawing a frozen filesystem returns control to the guest operating system
fstrimIssue the TRIM command to the VM’s block device(s). The VM has to be configured with the discard option or running with SSD emulation enabeld and the guest’s filesystem needs to be TRIM aware. Note: Since running a full fstrim takes quite a while, it’s not uncommon that the command seemingly fails with ‘qmp command ‘guest-fstrim’ failed – got timeout’. Check the guest’s message log for ‘guest-fstrim called’.
get-fsinfoReturns all mounted filesystems
get-host-nameReturns the hostname of the guest system
get-memory-block-infoDisplays memory information
get-memory-blocksDisplays memory information
get-osinfoDisplays various OS information like the distribution, kernel version and architecture
get-timeGet the system time of the guest OS
get-timezoneGet the timezone set in the guest OS
get-usersGet all users currently logged into the guest OS
get-vcpusGet information about the assigned virtual CPUs
infoReturn a list of available commands that can be issued through QGA
network-get-interfacesReturn a list of configured network interfaces along with traffic statistics
pingCheck if the VM is up and qemu-guest-agent is running. If this command times out, the VM is either offline or qemu-guest-agent is not working properly. Note: This is not a ‘traditional’ ping over a network connection. Instead, the host is trying to communicate with the VM over QGA.
shutdownSend the ACPI shutdown command to the VM
suspend-diskSend the suspend-to-disk command to the VM
suspend-hybridSend the suspend-hybrid (faster suspend-to-disk?) to the VM
suspend-ramSend the suspend-to-ram command to the VM

Conclusion

The QEMU Guest Agent provides an extensive interface for communication between the host system and the VMs.

You can either send any arbitray command to the guest systems or use QGA to get some details about the VMs themselves. It is also possible to go a bit more low-level, so you can shutdown your VMs or let the host system take control over the file system by essentially freezing it.

This is especially helpful if you want to use Proxmox’ built-in snapshots. However, if you use the backup and snapshot functions from the Proxmox GUI, freezing and thawing is handled automatically.

Currently, only a subset of the QGA protocol is abstracted by the qm command. Since calling the other commands supported by QGA is a little bit more complicated, I’ll cover this in a seperate article.

Do you have any comments or suggestions regarding this article? Please drop an e-mail to feedback@fabulous.systems!