Skip to content

qga #

QEMU Guest Agent Protocol client for V

qga is full featured QGA client for interacting with guest operating systems in QEMU-powered virtual machine from virtualisation host.

See also:

Usage

Run the virtual machine. In this example disk.qcow2 contains Debian 12 Bookworm with qemu-guest-agent package installed.

/usr/bin/qemu-system-x86_64 \
    -name testvm \
    -accel kvm \
    -cpu host \
    -smp 1 \
    -m 1024M \
    -drive file=disk.qcow2,media=disk,if=virtio \
    -chardev socket,path=/tmp/qga.sock,server=on,wait=off,id=qga0 \
    -device virtio-serial \
    -device virtserialport,chardev=qga0,name=org.qemu.guest_agent.0

Then connect to a guest agent server socket /tmp/gqa.sock:

import qga

fn main() {
  mut ga := qga.Client.new('/tmp/qga.sock')!
  agent_version := ga.info()!.version
  println('everything is fine! guest agent version is ${agent_version}')
}

Error handling

GuestAgentError contains extended error information. See the description of the structure fields.

The error can be returned either directly by the guest agent or when trying to communicating it. GuestAgentError has an explicit flag to distinguish such errors. If for some reason the guest agent could not be reached, is_unreachable will be true. The error information will be in the underlying error stored in the err field and in the error text itself.

module main

import qga

fn main() {
    mut ga := qga.Client.new('/tmp/qga.sock')!
    ga.get_devices() or {
        if err is qga.GuestAgentError {
            if err.is_unreachable {
                println('agent is unreachable')
                return
            } else {
                println('error info from guest agent: class=${err.class} desc=${err.desc}')
                return
            }
        }
    }
}

Prints this (so guest-get-devices is disabled on Debian):

error info from guest agent: class=CommandNotFound desc=Command guest-get-devices has been disabled

In addition, qga module provides a small set of specific error codes. They can be checked in this way without err smartcasting:

ga.ping() or {
  match err.code() {
    qga.err_no_connect { panic('socket connection error') }
    qga.err_timed_out { panic('timeout reached') }
    qga.err_from_agent { panic('error ocurred in guest agent') }
    else { panic(err) }
  }
}

License

LGPL-3.0-or-later

See COPYING and COPYING.LESSER for information.

Constants #

const err_no_connect = 1000

Connection to socket failed.

const err_cannot_read = 1001

Cannot read data from socket.

const err_cannot_write = 1002

Cannot write to socket.

const err_timed_out = 1003

Read or write timeout reached. This may cause if guest agent daemon is shut off in guest.

const err_from_agent = 1004

Guest agent returned an error. See details in class and desc fields of GuestAgentError.

fn Client.from_handle #

fn Client.from_handle(handle int, params ClientParams) !Client

Client.from_handle creates new Client instance connected to socket handle.

fn Client.new #

fn Client.new(addr string, params ClientParams) !Client

Client.new creates new Client instance connected to provided UNIX domain socket address.

Example

mut ga := qga.Client.new('/tmp/qga0.sock')!
ga.ping()!

fn (Client) close #

fn (mut c Client) close() !

close closes connection to stream socket.

fn (Client) exec #

fn (mut c Client) exec(path string, params GuestExecParams) !int

exec executes guest-exec command.

fn (Client) exec_status #

fn (mut c Client) exec_status(pid int) !GuestExecStatus

exec_status executes guest-exec-status command.

fn (Client) file_close #

fn (mut c Client) file_close(handle int) !

file_close executes guest-file-close command.

fn (Client) file_flush #

fn (mut c Client) file_flush(handle int) !

file_flush executes guest-file-flush command.

fn (Client) file_open #

fn (mut c Client) file_open(path string, mode string) !int

file_open executes guest-file-open command.

fn (Client) file_read #

fn (mut c Client) file_read(handle int, count int) !GuestFileRead

file_read executes guest-file-read command.

fn (Client) file_seek #

fn (mut c Client) file_seek(handle int, offset int, whence GuestAgentWhence) !GuestFileSeek

file_seek executes guest-file-seek command.

fn (Client) file_write #

fn (mut c Client) file_write(handle int, buf string, params GuestFileWriteParams) !GuestFileWrite

file_write executes guest-file-write command.

fn (Client) fsfreeze_freeze #

fn (mut c Client) fsfreeze_freeze() !int

fsfreeze_freeze executes guest-fsfreeze-freeze command.

fn (Client) fsfreeze_freeze_list #

fn (mut c Client) fsfreeze_freeze_list(mountpoints []string) !int

fsfreeze_freeze_list executes guest-fsfreeze-freeze-list command. An empty mountpoints array will freeze all filesystems.

fn (Client) fsfreeze_status #

fn (mut c Client) fsfreeze_status() !GuestFsfreezeStatus

fsfreeze_status executes guest-fsfreeze-status command.

fn (Client) fsfreeze_thaw #

fn (mut c Client) fsfreeze_thaw() !int

fsfreeze_thaw executes guest-fsfreeze-thaw command.

fn (Client) fstrim #

fn (mut c Client) fstrim(minimum u64) !GuestFilesystemTrimResponse

fstrim executes guest-fstrim command. Set minimum to zero to discard every free block.

fn (Client) get_cpustats #

fn (mut c Client) get_cpustats() ![]GuestCpuStats

get_cpustats executes guest-get-cpustats command.

fn (Client) get_devices #

fn (mut c Client) get_devices() ![]GuestDeviceInfo

get_devices executes guest-get-devices command.

fn (Client) get_disks #

fn (mut c Client) get_disks() ![]GuestDiskInfo

get_disks executes guest-get-disks command.

fn (Client) get_diskstats #

fn (mut c Client) get_diskstats() ![]GuestDiskStatsInfo

get_diskstats executes guest-get-diskstats command.

fn (Client) get_fsinfo #

fn (mut c Client) get_fsinfo() ![]GuestFilesystemInfo

get_fsinfo executes guest-get-fsinfo command.

fn (Client) get_host_name #

fn (mut c Client) get_host_name() !string

get_host_name executes guest-get-host-name command.

fn (Client) get_load #

fn (mut c Client) get_load() !GuestLoadAverage

get_load executes guest-get-load command.

fn (Client) get_memory_block_info #

fn (mut c Client) get_memory_block_info() !GuestMemoryBlockInfo

get_memory_block_info executes guest-get-memory-block-info command.

fn (Client) get_memory_blocks #

fn (mut c Client) get_memory_blocks() ![]GuestMemoryBlock

get_memory_blocks executes guest-get-memory-blocks command.

fn (Client) get_osinfo #

fn (mut c Client) get_osinfo() !GuestOSInfo

get_osinfo executes guest-get-osinfo command.

fn (Client) get_time #

fn (mut c Client) get_time() !i64

get_time executes guest-get-time command.

fn (Client) get_timezone #

fn (mut c Client) get_timezone() !GuestTimezone

get_timezone executes guest-get-timezone command.

fn (Client) get_users #

fn (mut c Client) get_users() ![]GuestUser

get_users executes guest-get-users command.

fn (Client) get_vcpus #

fn (mut c Client) get_vcpus() ![]GuestLogicalProcessor

get_vcpus executes guest-get-vcpus command.

fn (Client) info #

fn (mut c Client) info() !GuestAgentInfo

info executes guest-info command.

fn (Client) network_get_interfaces #

fn (mut c Client) network_get_interfaces() ![]GuestNetworkInterface

network_get_interfaces executes guest-network-get-interfaces command.

fn (Client) network_get_route #

fn (mut c Client) network_get_route() ![]GuestNetworkRoute

network_get_route executes guest-network-get-route command.

fn (Client) ping #

fn (mut c Client) ping() !

ping executes guest-ping command, a non-error return implies success.

fn (Client) set_memory_blocks #

fn (mut c Client) set_memory_blocks(blocks []GuestMemoryBlock) ![]GuestMemoryBlockResponse

set_memory_blocks executes guest-set-memory-blocks command.

fn (Client) set_time #

fn (mut c Client) set_time(epoch i64) !

set_time executes guest-set-time command.

fn (Client) set_user_password #

fn (mut c Client) set_user_password(username string, password string, crypted bool) !

set_user_password executes guest-set-user-password command.

fn (Client) set_vcpus #

fn (mut c Client) set_vcpus(vcpus []GuestLogicalProcessor) !int

set_vcpus executes guest-set-vcpus command.

fn (Client) shutdown #

fn (mut c Client) shutdown(mode GuestShutdownMode) !

shutdown executes guest-shutdown command.

fn (Client) ssh_add_authorized_keys #

fn (mut c Client) ssh_add_authorized_keys(username string, keys []string, reset bool) !

ssh_add_authorized_keys executes guest-ssh-add-authorized-keys command.

fn (Client) ssh_get_authorized_keys #

fn (mut c Client) ssh_get_authorized_keys() ![]string

ssh_get_authorized_keys executes guest-ssh-get-authorized-keys command.

fn (Client) ssh_remove_authorized_keys #

fn (mut c Client) ssh_remove_authorized_keys(username string, keys []string) !

ssh_remove_authorized_keys executes guest-ssh-remove-authorized-keys command.

fn (Client) suspend_disk #

fn (mut c Client) suspend_disk() !

suspend_disk executes guest-suspend-disk command.

fn (Client) suspend_hybrid #

fn (mut c Client) suspend_hybrid() !

suspend_hybrid executes guest-suspend-hybrid command.

fn (Client) suspend_ram #

fn (mut c Client) suspend_ram() !

suspend_ram executes guest-suspend-ram command.

fn (Client) sync #

fn (mut c Client) sync(id u64) !u64

sync executes the guest-sync command.

fn (Client) sync_delimited #

fn (mut c Client) sync_delimited(id u64) !u64

sync_delimited executes guest-sync-delimited command.

enum GuestCpuStatsType #

enum GuestCpuStatsType {
	linux
}

enum GuestDeviceType #

enum GuestDeviceType {
	pci
}

enum GuestDiskBusType #

enum GuestDiskBusType {
	ide
	fdc
	scsi
	virtio
	xen
	usb
	uml
	sata
	sd
	unknown
	ieee1394
	ssa
	fibre
	raid
	iscsi
	sas
	mmc
	virtual
	file_backed_virtual  @[json: 'file-backed-virtual']
	nvme
}

enum GuestFsfreezeStatus #

enum GuestFsfreezeStatus {
	thawed
	frozen
}

enum GuestIpAddressType #

enum GuestIpAddressType {
	ipv4
	ipv6
}

enum GuestMemoryBlockResponseType #

enum GuestMemoryBlockResponseType {
	success
	not_found                @[json: 'not-found']
	operation_not_supported  @[json: 'operation-not-supported']
	operation_failed         @[json: 'operation-failed']
}

enum GuestShutdownMode #

enum GuestShutdownMode {
	halt
	powerdown
	reboot
}

enum QGASeek #

enum QGASeek {
	set
	cur
	end
}

struct ClientParams #

@[params]
struct ClientParams {
	timeout          time.Duration = 5 * time.second // socket write and read timeout
	read_buffer_size int           = 4096            // read buffer size in bytes
}

struct GuestAgentCommandInfo #

struct GuestAgentCommandInfo {
pub:
	name             string
	enabled          bool
	success_response bool @[json: 'success-response']
}

struct GuestAgentError #

struct GuestAgentError {
pub:
	msg            string  // human-readable error message
	code           int     // error code (see err_* constants in this module)
	class          string  // error class provided by QEMU Guest Agent Protocol
	desc           string  // error desc provided by QEMU Guest Agent Protocol
	is_unreachable bool    // true if the error means the guest agent could not be reached
	err            ?IError // the underlying error if available
}

fn (GuestAgentError) msg #

fn (e GuestAgentError) msg() string

fn (GuestAgentError) code #

fn (e GuestAgentError) code() int

struct GuestAgentInfo #

struct GuestAgentInfo {
pub:
	version            string
	supported_commands []GuestAgentCommandInfo
}

struct GuestAgentWhence #

struct GuestAgentWhence {
pub:
	value int
	name  QGASeek
}

struct GuestCCWAddress #

struct GuestCCWAddress {
pub:
	cssid   int
	ssid    int
	subchno int
	devno   int
}

struct GuestCpuStats #

struct GuestCpuStats {
	GuestLinuxCpuStats
pub:
	type GuestCpuStatsType
}

struct GuestDeviceId #

struct GuestDeviceId {
pub:
	type      GuestDeviceType
	vendor_id int @[json: 'vendor-id']
	device_id int @[json: 'device-id']
}

struct GuestDeviceInfo #

struct GuestDeviceInfo {
	driver_name    string  @[json: 'driver-name']
	driver_data    ?string @[json: 'driver-data']
	driver_version ?string @[json: 'driver-version']
	id             ?GuestDeviceId
}

struct GuestDiskAddress #

struct GuestDiskAddress {
pub:
	pci_controller GuestPCIAddress  @[json: 'pci-controller']
	bus_type       GuestDiskBusType @[json: 'bus-type']
	bus            int
	target         int
	unit           int
	serial         ?string
	dev            ?string
	ccw_address    ?GuestCCWAddress @[json: 'ccw-address']
}

struct GuestDiskInfo #

struct GuestDiskInfo {
pub:
	name         string
	partition    bool
	dependencies ?[]string
	address      ?GuestDiskAddress
	alias        ?string
	smart        ?GuestDiskSmart
}

struct GuestDiskSmart #

struct GuestDiskSmart {
pub:
	critical_warning               int @[json: 'critical-warning']
	temperature                    int @[json: 'temperature']
	available_spare                int @[json: 'available-spare']
	available_spare_threshold      int @[json: 'available-spare-threshold']
	percentage_used                int @[json: 'percentage-used']
	data_units_read_lo             int @[json: 'data-units-read-lo']
	data_units_read_hi             int @[json: 'data-units-read-hi']
	data_units_written_lo          int @[json: 'data-units-written-lo']
	data_units_written_hi          int @[json: 'data-units-written-hi']
	host_read_commands_lo          int @[json: 'host-read-commands-lo']
	host_read_commands_hi          int @[json: 'host-read-commands-hi']
	host_write_commands_lo         int @[json: 'host-write-commands-lo']
	host_write_commands_hi         int @[json: 'host-write-commands-hi']
	controller_busy_time_lo        int @[json: 'controller-busy-time-lo']
	controller_busy_time_hi        int @[json: 'controller-busy-time-hi']
	power_cycles_lo                int @[json: 'power-cycles-lo']
	power_cycles_hi                int @[json: 'power-cycles-hi']
	power_on_hours_lo              int @[json: 'power-on-hours-lo']
	power_on_hours_hi              int @[json: 'power-on-hours-hi']
	unsafe_shutdowns_lo            int @[json: 'unsafe-shutdowns-lo']
	unsafe_shutdowns_hi            int @[json: 'unsafe-shutdowns-hi']
	media_errors_lo                int @[json: 'media-errors-lo']
	media_errors_hi                int @[json: 'media-errors-hi']
	number_of_error_log_entries_lo int @[json: 'number-of-error-log-entries-lo']
	number_of_error_log_entries_hi int @[json: 'number-of-error-log-entries-hi']
}

struct GuestDiskStats #

struct GuestDiskStats {
	read_sectors    ?int @[json: 'read-sectors']
	read_ios        ?int @[json: 'read-ios']
	read_merges     ?int @[json: 'read-merges']
	write_sectors   ?int @[json: 'write-sectors']
	write_ios       ?int @[json: 'write-ios']
	write_merges    ?int @[json: 'write-merges']
	discard_sectors ?int @[json: 'discard-sectors']
	discard_ios     ?int @[json: 'discard-ios']
	discard_merges  ?int @[json: 'discard-merges']
	flush_ios       ?int @[json: 'flush-ios']
	read_ticks      ?int @[json: 'read-ticks']
	write_ticks     ?int @[json: 'write-ticks']
	discard_ticks   ?int @[json: 'discard-ticks']
	flush_ticks     ?int @[json: 'flush-ticks']
	ios_pgr         ?int @[json: 'ios-pgr']
	total_ticks     ?int @[json: 'total-ticks']
	weight_ticks    ?int @[json: 'weight-ticks']
}

struct GuestDiskStatsInfo #

struct GuestDiskStatsInfo {
pub:
	name  string
	major int
	minor int
	stats GuestDiskStats
}

struct GuestExecParams #

@[params]
struct GuestExecParams {
pub:
	args           ?[]string
	env            ?[]string
	input_data     ?string
	capture_output ?bool
}

struct GuestExecStatus #

struct GuestExecStatus {
pub:
	exited        bool
	exitcode      ?int
	signal        ?int
	out_data      ?string @[json: 'out-data']
	err_data      ?string @[json: 'err-data']
	out_truncated ?bool   @[json: 'out-truncated']
	err_truncated ?bool   @[json: 'err-truncated']
}

struct GuestFileRead #

struct GuestFileRead {
pub:
	count   int
	buf_b64 string @[json: 'buf-b64']
	eof     bool
}

struct GuestFileSeek #

struct GuestFileSeek {
pub:
	position int
	eof      bool
}

struct GuestFileWrite #

struct GuestFileWrite {
pub:
	count int
	eof   bool
}

struct GuestFileWriteParams #

@[params]
struct GuestFileWriteParams {
pub:
	is_encoded bool
	count      ?int
}

struct GuestFilesystemInfo #

struct GuestFilesystemInfo {
pub:
	name                   string
	mountpoint             string
	type                   string
	used_bytes             ?u64 @[json: 'used-bytes']
	total_bytes            ?u64 @[json: 'total-bytes']
	total_bytes_privileged ?u64 @[json: 'total-bytes-privileged']
	disk                   []GuestDiskAddress
}

struct GuestFilesystemTrimResponse #

struct GuestFilesystemTrimResponse {
pub:
	paths []GuestFilesystemTrimResult
}

struct GuestFilesystemTrimResult #

struct GuestFilesystemTrimResult {
	path    string
	error   ?string
	trimmed ?u64
	minimum ?u64
}

struct GuestIpAddress #

struct GuestIpAddress {
pub:
	ip_address      string             @[json: 'ip-address']
	ip_address_type GuestIpAddressType @[json: 'ip-address-type']
	prefix          int
}

struct GuestLinuxCpuStats #

struct GuestLinuxCpuStats {
pub:
	cpu       int
	user      int
	nice      int
	system    int
	idle      int
	iowait    ?int
	irq       ?int
	sofirq    ?int
	steal     ?int
	guest     ?int
	guestnice ?int
}

struct GuestLoadAverage #

struct GuestLoadAverage {
	load1m  f64
	load5m  f64
	load15m f64
}

struct GuestLogicalProcessor #

struct GuestLogicalProcessor {
pub:
	logical_id  int @[json: 'logical-id']
	online      bool
	can_offline ?bool @[json: 'can-offline']
}

struct GuestMemoryBlock #

struct GuestMemoryBlock {
pub:
	phys_index  int @[json: 'phys-index']
	online      bool
	can_offline ?bool @[json: 'can-offline']
}

struct GuestMemoryBlockInfo #

struct GuestMemoryBlockInfo {
	size int
}

struct GuestMemoryBlockResponse #

struct GuestMemoryBlockResponse {
pub:
	phys_index int @[json: 'phys-index']
	response   GuestMemoryBlockResponseType
	error_code ?int @[json: 'error-code']
}

struct GuestNetworkInterface #

struct GuestNetworkInterface {
pub:
	name             string
	hardware_address ?string           @[json: 'hardware-address']
	ip_addresses     ?[]GuestIpAddress @[json: 'ip-addresses']
	statistics       ?GuestNetworkInterfaceStat
}

struct GuestNetworkInterfaceStat #

struct GuestNetworkInterfaceStat {
pub:
	rx_bytes   int @[json: 'rx-bytes']
	rx_packets int @[json: 'rx-packets']
	rx_errs    int @[json: 'rx-errs']
	rx_dropped int @[json: 'rx-dropped']
	tx_bytes   int @[json: 'tx-bytes']
	tx_packets int @[json: 'tx-packets']
	tx_errs    int @[json: 'tx-errs']
	tx_dropped int @[json: 'tx-dropped']
}

struct GuestNetworkRoute #

struct GuestNetworkRoute {
pub:
	iface        string
	destination  string
	metric       int
	gateway      ?string
	mask         ?string
	irtt         ?int
	flags        ?int
	refcnt       ?int
	use          ?int
	window       ?int
	mtu          ?int
	desprefixlen ?string
	source       ?string
	srcprefixlen ?string
	nexthop      ?string
	version      int
}

struct GuestOSInfo #

struct GuestOSInfo {
pub:
	kernel_release ?string @[json: 'kernel-release']
	kernel_version ?string @[json: 'kernel-version']
	machine        ?string
	id             ?string
	name           ?string
	pretty_name    ?string @[json: 'pretty-name']
	version        ?string
	version_id     ?string @[json: 'version-id']
	variant        ?string
	variant_id     ?string @[json: 'variant-id']
}

struct GuestPCIAddress #

struct GuestPCIAddress {
pub:
	domain   int
	bus      int
	slot     int
	function int
}

struct GuestTimezone #

struct GuestTimezone {
	zone   ?string
	offset int
}

struct GuestUser #

struct GuestUser {
pub:
	user       string
	domain     string
	login_time f64 @[json: 'login-time']
}