QGA(QEMU Guest Agent) Add Custom Command
Preface
Suppose you have virtio serial port
setup, check with
virsh qemu-agent-command ${VMNAME} '{"execute":"guest-info"}'
Setup
- Host: Ubuntu 16.04 Desktop x64
- Guest: Ubuntu 16.04 Server x64
- Host: QEMU/KVM apt install
- Guest: QEMU Guest Agent git source
Get QEMU Guest Agent Source Code
QEMU Guest Agent is part of the QEMU code repository, so we need to get the whole QEMU code base first.
git clone git://git.qemu.org/qemu.git
cd qemu
git submodule init
git submodule update --recursive
./configure
Some dependency packages may be needed.
Overview
To add a custom command like this
virsh qemu-agent-command ${VMNAME} '{"execute":"${custom-command}"}'
to the QEMU Guest Agent, only two files need to be modified.
They are qemu/qga/qapi-schema.json
and qemu/qga/commands-posix.c
.
Of cource, if your guest OS is Windows, edit qemu/qga/commands-win32.c
instead.
1. qapi-schema.json
Add this
##
# @NetConfigResult:
##
{ 'struct': 'NetConfigResult',
'data': { 'errcode': 'int', '*errmsg': 'str' } }
##
# @net-config:
#
# Returns: @NetConfigResult
##
{ 'command': 'net-config',
'data': { 'mac': 'str', 'ip_address': 'str',
'ip_address_type': 'str', 'netmask': 'str',
'*gateway': 'str' },
'returns': 'NetConfigResult' }
-
The first part
NetConfigResult
is a custom struct in which the result of the commandnet-config
will be returned(output).In this case,
errcode
anderrmsg
will be returned.The
*
beforeerrmsg
means thaterrmsg
is optional.We will come to that later in the
commands-posix.c
part. -
'command': 'net-config'
means the newly added command isnet-config
,and
'returns': 'NetConfigResult'
means that the result of its execution is in the form ofNetConfigResult
, the struct we added before.The
data
part is the input for ournet-config
command, it can be used like thisvirsh qemu-agent-command ${VMNAME} '{"execute":"net-config", "arguments":{"mac": "00:00:00:00:00:00", "ip_address": "192.168.122.173", "ip_address_type": "ipv4", "netmask": "255.255.255.0", "gateway": "192.168.122.1"}}'
Similarly, the
*
beforegateway
means its optional.
2. commands-posix.c
Define a new function for net-config
NetConfigResult *qmp_net_config(const char *mac, const char *ip_address,
const char *ip_address_type, const char *netmask,
bool has_gateway, const char *gateway, Error **errp)
Replace net-config
in qmp_net_config
with your command name.
Pay attention to the underline _
, it replaces the dash -
in net-config
.
Because the input variable gateway
is made optional, we have a new bool type parameter has_gateway
.
The returned NetConfigResult
can be initialized by
NetConfigResult *result = g_new0(NetConfigResult, 64);
result->has_errmsg = true;
if result->has_errmsg = true
, errmsg
will be included in NetConfigResult.
When passing value to result->errmsg
, use g_strdup_printf()
instead of memcpy or direct assignment.
Debug
cd
to the root directory of qemu
make qemu-ga
sudo make install qemu-ga
Then run
sudo qemu-ga -v
to debug.
Conclusion
There you have it, a custom command for QEMU Guest Agent.
I will not dive into how I implemented the qmp_net_config
fuction, which is for sure a tedious work.
Reference
- https://qemu.weilnetz.de/doc/qemu-ga-ref.html
- http://wiki.stoney-cloud.org/wiki/Qemu_Guest_Agent_Integration
- https://danielfresh.github.io/2016/04/20/qemu-ga-windows/
- https://www.cnblogs.com/biangbiang/p/3222458.html
- http://blog.nsfocus.net/easy-kvm-virtualization/
- http://www.voidcn.com/article/p-qokqicls-bdc.html