update patch with openeuler !54

Signed-off-by: imxcc <xingchaochao@huawei.com>
This commit is contained in:
imxcc 2022-02-22 00:16:20 +08:00 committed by yezengruan
parent 3b3e670760
commit d5dde37654
19 changed files with 2683 additions and 1 deletions

View File

@ -101,7 +101,7 @@
Summary: Library providing a simple virtualization API
Name: libvirt
Version: 6.2.0
Release: 31
Release: 32
License: LGPLv2+
URL: https://libvirt.org/
@ -197,6 +197,24 @@ Patch0084: tests-Replace-deprecated-ASN1-code.patch
Patch0085: tests-disabale-storage-tests.patch
Patch0086: Revert-tests-disabale-storage-tests.patch
Patch0087: hotpatch-virsh-support-autoload-mode.patch
Patch0088: virQEMUBuildCommandLineJSON-Allow-skipping-certain-k.patch
Patch0089: virQEMUBuildCommandLineJSON-Add-possibility-for-usin.patch
Patch0090: util-virqemu-Introduce-virQEMUBuildNetdevCommandline.patch
Patch0091: util-json-Introduce-virJSONValueObjectAppendStringPr.patch
Patch0092: qemuBuildChannelsCommandLine-Use-typecasted-switch-f.patch
Patch0093: qemuBuildChannelsCommandLine-Extract-common-formatti.patch
Patch0094: qemuBuildChannelChrDeviceStr-Remove-formatting-of-pr.patch
Patch0095: qemuMonitorJSON-Add-Remove-Netdev-Refactor-cleanup.patch
Patch0096: qemuBuildHostNetStr-Stop-using-ipv6-net-convenience-.patch
Patch0097: qemu-command-Generate-netdev-command-line-via-JSON-c.patch
Patch0098: qemuBuildChannelGuestfwdNetdevProps-Convert-to-gener.patch
Patch0099: qemuMonitorAddNetdev-Convert-to-the-native-JSON-prop.patch
Patch0100: virCommand-Introduce-virCommandGetArgList.patch
Patch0101: testutilsqemuschema-Introduce-testQEMUSchemaValidate.patch
Patch0102: testCompareXMLToArgv-Split-out-preparation-and-comma.patch
Patch0103: virQEMUBuildNetdevCommandlineFromJSON-Prepare-for-qu.patch
Patch0104: qemu-Prepare-for-testing-of-netdev_add-props-via-qem.patch
Patch0105: qemuxml2argvtest-Add-QAPI-QMP-schema-validation-for-.patch
Requires: libvirt-daemon = %{version}-%{release}
Requires: libvirt-daemon-config-network = %{version}-%{release}
@ -1931,6 +1949,26 @@ exit 0
%changelog
* Mon Feb 21 2022 imxcc <xingchaochao@huawei.com>
- virQEMUBuildCommandLineJSON: Allow skipping certain keys
- virQEMUBuildCommandLineJSON: Add possibility for using 'on/off' instead of 'yes/no'
- util: virqemu: Introduce virQEMUBuildNetdevCommandlineFromJSON
- util: json: Introduce virJSONValueObjectAppendStringPrintf
- qemuBuildChannelsCommandLine: Use typecasted switch for channel type
- qemuBuildChannelsCommandLine: Extract common formatting of 'chardev'
- qemuBuildChannelChrDeviceStr: Remove formatting of properties for -netdev
- qemuMonitorJSON(Add|Remove)Netdev: Refactor cleanup
- qemuBuildHostNetStr: Stop using 'ipv6-net' convenience argument
- qemu: command: Generate -netdev command line via JSON->cmdline conversion
- qemuBuildChannelGuestfwdNetdevProps: Convert to generating JSON props
- qemuMonitorAddNetdev: Convert to the native JSON props object
- virCommand: Introduce virCommandGetArgList
- testutilsqemuschema: Introduce testQEMUSchemaValidateCommand
- testCompareXMLToArgv: Split out preparation and command formatting
- virQEMUBuildNetdevCommandlineFromJSON: Prepare for quirky 'guestfwd'
- qemu: Prepare for testing of 'netdev_add' props via qemuxml2argvtest
- qemuxml2argvtest: Add QAPI/QMP schema validation for -blockdev and -netdev
* Sat Feb 12 2022 imxcc <xingchaochao@huawei.com>
- hotpatch: virsh support autoload mode

View File

@ -0,0 +1,305 @@
From fb869a0d3a28591d17a9f047eafd3b77513d6d77 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 15 May 2020 14:24:21 +0200
Subject: [PATCH 17/18] qemu: Prepare for testing of 'netdev_add' props via
qemuxml2argvtest
qemuxml2argv test suite is way more comprehensive than the hotplug
suite. Since we share the code paths for monitor and command line
hotplug we can easily test the properties of devices against the QAPI
schema.
To achieve this we'll need to skip the JSON->commandline conversion for
the test run so that we can analyze the pure properties. This patch adds
flags for the comand line generator and hook them into the
JSON->commandline convertor for -netdev. An upcoming patch will make use
of this new infrastructure.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_command.c | 28 +++++++++++++++++-----------
src/qemu/qemu_command.h | 7 ++++++-
src/qemu/qemu_driver.c | 2 +-
src/qemu/qemu_process.c | 11 +++++++++--
src/qemu/qemu_process.h | 1 +
src/util/virqemu.c | 9 ++++++++-
src/util/virqemu.h | 3 ++-
tests/qemuxml2argvtest.c | 6 ++++--
8 files changed, 48 insertions(+), 19 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index bd78bfb31b..dae6b5a7f9 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8027,7 +8027,8 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
virNetDevVPortProfileOp vmop,
bool standalone,
size_t *nnicindexes,
- int **nicindexes)
+ int **nicindexes,
+ unsigned int flags)
{
virDomainDefPtr def = vm->def;
int ret = -1;
@@ -8256,7 +8257,8 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
slirpfdName)))
goto cleanup;
- if (!(host = virQEMUBuildNetdevCommandlineFromJSON(hostnetprops)))
+ if (!(host = virQEMUBuildNetdevCommandlineFromJSON(hostnetprops,
+ (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON))))
goto cleanup;
virCommandAddArgList(cmd, "-netdev", host, NULL);
@@ -8332,7 +8334,8 @@ qemuBuildNetCommandLine(virQEMUDriverPtr driver,
bool standalone,
size_t *nnicindexes,
int **nicindexes,
- unsigned int *bootHostdevNet)
+ unsigned int *bootHostdevNet,
+ unsigned int flags)
{
size_t i;
int last_good_net = -1;
@@ -8356,7 +8359,7 @@ qemuBuildNetCommandLine(virQEMUDriverPtr driver,
if (qemuBuildInterfaceCommandLine(driver, vm, logManager, secManager, cmd, net,
qemuCaps, bootNet, vmop,
standalone, nnicindexes,
- nicindexes) < 0)
+ nicindexes, flags) < 0)
goto error;
last_good_net = i;
@@ -8892,7 +8895,8 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
virQEMUDriverConfigPtr cfg,
const virDomainDef *def,
virQEMUCapsPtr qemuCaps,
- bool chardevStdioLogd)
+ bool chardevStdioLogd,
+ unsigned int flags)
{
size_t i;
unsigned int cdevflags = QEMU_BUILD_CHARDEV_TCP_NOWAIT |
@@ -8921,7 +8925,8 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(channel)))
return -1;
- if (!(netdevstr = virQEMUBuildNetdevCommandlineFromJSON(netdevprops)))
+ if (!(netdevstr = virQEMUBuildNetdevCommandlineFromJSON(netdevprops,
+ (flags & QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON))))
return -1;
virCommandAddArgList(cmd, "-netdev", netdevstr, NULL);
@@ -9857,7 +9862,8 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
bool standalone,
bool enableFips,
size_t *nnicindexes,
- int **nicindexes)
+ int **nicindexes,
+ unsigned int flags)
{
size_t i;
char uuid[VIR_UUID_STRING_BUFLEN];
@@ -9870,9 +9876,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
bool chardevStdioLogd = priv->chardevStdioLogd;
VIR_DEBUG("driver=%p def=%p mon=%p "
- "qemuCaps=%p migrateURI=%s snapshot=%p vmop=%d",
+ "qemuCaps=%p migrateURI=%s snapshot=%p vmop=%d flags=0x%x",
driver, def, priv->monConfig,
- qemuCaps, migrateURI, snapshot, vmop);
+ qemuCaps, migrateURI, snapshot, vmop, flags);
if (qemuBuildCommandLineValidate(driver, def) < 0)
return NULL;
@@ -10017,7 +10023,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
if (qemuBuildNetCommandLine(driver, vm, logManager, secManager, cmd,
qemuCaps, vmop, standalone,
- nnicindexes, nicindexes, &bootHostdevNet) < 0)
+ nnicindexes, nicindexes, &bootHostdevNet, flags) < 0)
return NULL;
if (qemuBuildSmartcardCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
@@ -10033,7 +10039,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
return NULL;
if (qemuBuildChannelsCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
- chardevStdioLogd) < 0)
+ chardevStdioLogd, flags) < 0)
return NULL;
if (qemuBuildConsoleCommandLine(logManager, secManager, cmd, cfg, def, qemuCaps,
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 1e6b23ba05..4b1c2103c5 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -43,6 +43,10 @@
VIR_ENUM_DECL(qemuVideo);
VIR_ENUM_DECL(qemuSoundCodec);
+typedef enum {
+ QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON = 1 << 0,
+} qemuBuildCommandLineFlags;
+
virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver,
virLogManagerPtr logManager,
virSecurityManagerPtr secManager,
@@ -53,7 +57,8 @@ virCommandPtr qemuBuildCommandLine(virQEMUDriverPtr driver,
bool standalone,
bool enableFips,
size_t *nnicindexes,
- int **nicindexes);
+ int **nicindexes,
+ unsigned int flags);
/* Generate the object properties for pr-manager */
virJSONValuePtr qemuBuildPRManagerInfoProps(virStorageSourcePtr src);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2b24881f75..b3ebf3aa9b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7449,7 +7449,7 @@ static char *qemuConnectDomainXMLToNative(virConnectPtr conn,
}
if (!(cmd = qemuProcessCreatePretendCmd(driver, vm, NULL,
- qemuCheckFips(), true,
+ qemuCheckFips(), true, false,
VIR_QEMU_PROCESS_START_COLD)))
goto cleanup;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 818a72d8f9..db564cae36 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -6750,7 +6750,7 @@ qemuProcessLaunch(virConnectPtr conn,
snapshot, vmop,
false,
qemuCheckFips(),
- &nnicindexes, &nicindexes)))
+ &nnicindexes, &nicindexes, 0)))
goto cleanup;
if (incoming && incoming->fd != -1)
@@ -7193,8 +7193,11 @@ qemuProcessCreatePretendCmd(virQEMUDriverPtr driver,
const char *migrateURI,
bool enableFips,
bool standalone,
+ bool jsonPropsValidation,
unsigned int flags)
{
+ unsigned int buildflags = 0;
+
virCheckFlags(VIR_QEMU_PROCESS_START_COLD |
VIR_QEMU_PROCESS_START_PAUSED |
VIR_QEMU_PROCESS_START_AUTODESTROY, NULL);
@@ -7204,6 +7207,9 @@ qemuProcessCreatePretendCmd(virQEMUDriverPtr driver,
if (standalone)
flags |= VIR_QEMU_PROCESS_START_STANDALONE;
+ if (jsonPropsValidation)
+ buildflags = QEMU_BUILD_COMMANDLINE_VALIDATE_KEEP_JSON;
+
if (qemuProcessInit(driver, vm, NULL, QEMU_ASYNC_JOB_NONE,
!!migrateURI, flags) < 0)
return NULL;
@@ -7222,7 +7228,8 @@ qemuProcessCreatePretendCmd(virQEMUDriverPtr driver,
standalone,
enableFips,
NULL,
- NULL);
+ NULL,
+ buildflags);
}
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 3077d3ef9e..15e67b9762 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -101,6 +101,7 @@ virCommandPtr qemuProcessCreatePretendCmd(virQEMUDriverPtr driver,
const char *migrateURI,
bool enableFips,
bool standalone,
+ bool jsonPropsValidation,
unsigned int flags);
int qemuProcessInit(virQEMUDriverPtr driver,
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
index 9823ebc14d..321ddeb7e3 100644
--- a/src/util/virqemu.c
+++ b/src/util/virqemu.c
@@ -292,16 +292,23 @@ virQEMUBuildCommandLineJSON(virJSONValuePtr value,
/**
* virQEMUBuildNetdevCommandlineFromJSON:
* @props: JSON properties describing a netdev
+ * @rawjson: don't transform to commandline args, but just stringify json
*
* Converts @props into arguments for -netdev including all the quirks and
* differences between the monitor and command line syntax.
+ *
+ * @rawjson is meant for testing of the schema in the xml2argvtest
*/
char *
-virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props)
+virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props,
+ bool rawjson)
{
const char *type = virJSONValueObjectGetString(props, "type");
g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+ if (rawjson)
+ return virJSONValueToString(props, false);
+
virBufferAsprintf(&buf, "%s,", type);
if (virQEMUBuildCommandLineJSON(props, &buf, "type", true,
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
index 22f47851df..b1296cb657 100644
--- a/src/util/virqemu.h
+++ b/src/util/virqemu.h
@@ -50,7 +50,8 @@ int virQEMUBuildCommandLineJSON(virJSONValuePtr value,
virQEMUBuildCommandLineJSONArrayFormatFunc array);
char *
-virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props);
+virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props,
+ bool rawjson);
int virQEMUBuildObjectCommandlineFromJSON(virBufferPtr buf,
virJSONValuePtr objprops);
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 762d65f521..2217e2d81e 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -400,7 +400,8 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv,
virDomainObjPtr vm,
const char *migrateURI,
struct testQemuInfo *info,
- unsigned int flags)
+ unsigned int flags,
+ bool jsonPropsValidation)
{
size_t i;
@@ -475,6 +476,7 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv,
return qemuProcessCreatePretendCmd(drv, vm, migrateURI,
(flags & FLAG_FIPS), false,
+ jsonPropsValidation,
VIR_QEMU_PROCESS_START_COLD);
}
@@ -570,7 +572,7 @@ testCompareXMLToArgv(const void *data)
virResetLastError();
if (!(cmd = testCompareXMLToArgvCreateArgs(&driver, vm, migrateURI, info,
- flags))) {
+ flags, false))) {
if (flags & FLAG_EXPECT_FAILURE)
goto ok;
goto cleanup;
--
2.23.0.windows.1

View File

@ -0,0 +1,354 @@
From 0ab9df24cbe5b6cfd2aa259aaaef2f8fb2696ce2 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 22:50:59 +0200
Subject: [PATCH 10/18] qemu: command: Generate -netdev command line via
JSON->cmdline conversion
The 'netdev_add' command was recently formally described in qemu via the
QMP schema. This means that it also requires the arguments to be
properly formatted. Our current approach is to generate the command line
and then use qemuMonitorJSONKeywordStringToJSON to get the JSON
properties for the monitor. This will not work if we need to pass some
fields as numbers or booleans.
In this step we re-do internals of qemuBuildHostNetStr to format a JSON
object which is converted back via virQEMUBuildNetdevCommandlineFromJSON
to the equivalent command line. This will later allow fixing of the
monitor code to use the JSON object directly rather than rely on the
conversion.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_command.c | 163 +++++++++++++++++++++++++---------------
src/qemu/qemu_command.h | 12 +--
src/qemu/qemu_hotplug.c | 13 +++-
3 files changed, 119 insertions(+), 69 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 688c9db851..141657b3e4 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3910,7 +3910,7 @@ qemuBuildNicDevStr(virDomainDefPtr def,
}
-char *
+virJSONValuePtr
qemuBuildHostNetStr(virDomainNetDefPtr net,
char **tapfd,
size_t tapfdSize,
@@ -3919,10 +3919,11 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
const char *slirpfd)
{
bool is_tap = false;
- g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
virDomainNetType netType = virDomainNetGetActualType(net);
size_t i;
+ g_autoptr(virJSONValue) netprops = NULL;
+
if (net->script && netType != VIR_DOMAIN_NET_TYPE_ETHERNET) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
_("scripts are not supported on interfaces of type %s"),
@@ -3940,54 +3941,75 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
case VIR_DOMAIN_NET_TYPE_NETWORK:
case VIR_DOMAIN_NET_TYPE_DIRECT:
case VIR_DOMAIN_NET_TYPE_ETHERNET:
- virBufferAddLit(&buf, "tap,");
+ if (virJSONValueObjectCreate(&netprops, "s:type", "tap", NULL) < 0)
+ return NULL;
+
/* for one tapfd 'fd=' shall be used,
* for more than one 'fds=' is the right choice */
if (tapfdSize == 1) {
- virBufferAsprintf(&buf, "fd=%s,", tapfd[0]);
+ if (virJSONValueObjectAdd(netprops, "s:fd", tapfd[0], NULL) < 0)
+ return NULL;
} else {
- virBufferAddLit(&buf, "fds=");
- for (i = 0; i < tapfdSize; i++) {
- if (i)
- virBufferAddChar(&buf, ':');
- virBufferAdd(&buf, tapfd[i], -1);
- }
- virBufferAddChar(&buf, ',');
+ g_auto(virBuffer) fdsbuf = VIR_BUFFER_INITIALIZER;
+
+ for (i = 0; i < tapfdSize; i++)
+ virBufferAsprintf(&fdsbuf, "%s:", tapfd[i]);
+
+ virBufferTrim(&fdsbuf, ":");
+
+ if (virJSONValueObjectAdd(netprops,
+ "s:fds", virBufferCurrentContent(&fdsbuf),
+ NULL) < 0)
+ return NULL;
}
+
is_tap = true;
break;
case VIR_DOMAIN_NET_TYPE_CLIENT:
- virBufferAsprintf(&buf, "socket,connect=%s:%d,",
- net->data.socket.address,
- net->data.socket.port);
+ if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
+ virJSONValueObjectAppendStringPrintf(netprops, "connect", "%s:%d",
+ net->data.socket.address,
+ net->data.socket.port) < 0)
+ return NULL;
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
- virBufferAsprintf(&buf, "socket,listen=%s:%d,",
- NULLSTR_EMPTY(net->data.socket.address),
- net->data.socket.port);
+ if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
+ virJSONValueObjectAppendStringPrintf(netprops, "listen", "%s:%d",
+ NULLSTR_EMPTY(net->data.socket.address),
+ net->data.socket.port) < 0)
+ return NULL;
break;
case VIR_DOMAIN_NET_TYPE_MCAST:
- virBufferAsprintf(&buf, "socket,mcast=%s:%d,",
- net->data.socket.address,
- net->data.socket.port);
+ if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
+ virJSONValueObjectAppendStringPrintf(netprops, "mcast", "%s:%d",
+ net->data.socket.address,
+ net->data.socket.port) < 0)
+ return NULL;
break;
case VIR_DOMAIN_NET_TYPE_UDP:
- virBufferAsprintf(&buf, "socket,udp=%s:%d,localaddr=%s:%d,",
- net->data.socket.address,
- net->data.socket.port,
- net->data.socket.localaddr,
- net->data.socket.localport);
+ if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
+ virJSONValueObjectAppendStringPrintf(netprops, "udp", "%s:%d",
+ net->data.socket.address,
+ net->data.socket.port) < 0 ||
+ virJSONValueObjectAppendStringPrintf(netprops, "localaddr", "%s:%d",
+ net->data.socket.localaddr,
+ net->data.socket.localport) < 0)
+ return NULL;
break;
case VIR_DOMAIN_NET_TYPE_USER:
if (slirpfd) {
- virBufferAsprintf(&buf, "socket,fd=%s,", slirpfd);
+ if (virJSONValueObjectCreate(&netprops, "s:type", "socket", NULL) < 0 ||
+ virJSONValueObjectAppendString(netprops, "fd", slirpfd) < 0)
+ return NULL;
} else {
- virBufferAddLit(&buf, "user,");
+ if (virJSONValueObjectCreate(&netprops, "s:type", "user", NULL) < 0)
+ return NULL;
+
for (i = 0; i < net->guestIP.nips; i++) {
const virNetDevIPAddr *ip = net->guestIP.ips[i];
g_autofree char *addr = NULL;
@@ -3996,29 +4018,40 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
return NULL;
if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET)) {
- virBufferAsprintf(&buf, "net=%s", addr);
+ g_autofree char *ipv4netaddr = NULL;
+
if (ip->prefix)
- virBufferAsprintf(&buf, "/%u", ip->prefix);
- virBufferAddChar(&buf, ',');
+ ipv4netaddr = g_strdup_printf("%s/%u", addr, ip->prefix);
+ else
+ ipv4netaddr = g_strdup(addr);
+
+ if (virJSONValueObjectAppendString(netprops, "net", ipv4netaddr) < 0)
+ return NULL;
} else if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6)) {
- virBufferAsprintf(&buf, "ipv6-prefix=%s,", addr);
- if (ip->prefix)
- virBufferAsprintf(&buf, "ipv6-prefixlen=%u,", ip->prefix);
+ if (virJSONValueObjectAppendString(netprops, "ipv6-prefix", addr) < 0)
+ return NULL;
+ if (ip->prefix &&
+ virJSONValueObjectAppendNumberUlong(netprops, "ipv6-prefixlen",
+ ip->prefix) < 0)
+ return NULL;
}
}
}
break;
case VIR_DOMAIN_NET_TYPE_INTERNAL:
- virBufferAddLit(&buf, "user,");
+ if (virJSONValueObjectCreate(&netprops, "s:type", "user", NULL) < 0)
+ return NULL;
break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
- virBufferAsprintf(&buf, "vhost-user,chardev=char%s,",
- net->info.alias);
- if (net->driver.virtio.queues > 1)
- virBufferAsprintf(&buf, "queues=%u,",
- net->driver.virtio.queues);
+ if (virJSONValueObjectCreate(&netprops, "s:type", "vhost-user", NULL) < 0 ||
+ virJSONValueObjectAppendStringPrintf(netprops, "chardev", "char%s", net->info.alias) < 0)
+ return NULL;
+
+ if (net->driver.virtio.queues > 1 &&
+ virJSONValueObjectAppendNumberUlong(netprops, "queues", net->driver.virtio.queues) < 0)
+ return NULL;
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV:
@@ -4027,31 +4060,38 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
break;
}
- virBufferAsprintf(&buf, "id=host%s,", net->info.alias);
+ if (virJSONValueObjectAppendStringPrintf(netprops, "id", "host%s", net->info.alias) < 0)
+ return NULL;
if (is_tap) {
if (vhostfdSize) {
- virBufferAddLit(&buf, "vhost=on,");
+ if (virJSONValueObjectAppendBoolean(netprops, "vhost", true) < 0)
+ return NULL;
+
if (vhostfdSize == 1) {
- virBufferAsprintf(&buf, "vhostfd=%s,", vhostfd[0]);
+ if (virJSONValueObjectAdd(netprops, "s:vhostfd", vhostfd[0], NULL) < 0)
+ return NULL;
} else {
- virBufferAddLit(&buf, "vhostfds=");
- for (i = 0; i < vhostfdSize; i++) {
- if (i)
- virBufferAddChar(&buf, ':');
- virBufferAdd(&buf, vhostfd[i], -1);
- }
- virBufferAddChar(&buf, ',');
+ g_auto(virBuffer) fdsbuf = VIR_BUFFER_INITIALIZER;
+
+ for (i = 0; i < vhostfdSize; i++)
+ virBufferAsprintf(&fdsbuf, "%s:", vhostfd[i]);
+
+ virBufferTrim(&fdsbuf, ":");
+
+ if (virJSONValueObjectAdd(netprops,
+ "s:vhostfds", virBufferCurrentContent(&fdsbuf),
+ NULL) < 0)
+ return NULL;
}
}
- if (net->tune.sndbuf_specified)
- virBufferAsprintf(&buf, "sndbuf=%lu,", net->tune.sndbuf);
- }
-
- virBufferTrim(&buf, ",");
+ if (net->tune.sndbuf_specified &&
+ virJSONValueObjectAppendNumberUlong(netprops, "sndbuf", net->tune.sndbuf) < 0)
+ return NULL;
+ }
- return virBufferContentAndReset(&buf);
+ return g_steal_pointer(&netprops);
}
@@ -8006,6 +8046,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
bool requireNicdev = false;
qemuSlirpPtr slirp;
size_t i;
+ g_autoptr(virJSONValue) hostnetprops = NULL;
if (!bootindex)
@@ -8209,11 +8250,15 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
if (chardev)
virCommandAddArgList(cmd, "-chardev", chardev, NULL);
- if (!(host = qemuBuildHostNetStr(net,
- tapfdName, tapfdSize,
- vhostfdName, vhostfdSize,
- slirpfdName)))
+ if (!(hostnetprops = qemuBuildHostNetStr(net,
+ tapfdName, tapfdSize,
+ vhostfdName, vhostfdSize,
+ slirpfdName)))
goto cleanup;
+
+ if (!(host = virQEMUBuildNetdevCommandlineFromJSON(hostnetprops)))
+ goto cleanup;
+
virCommandAddArgList(cmd, "-netdev", host, NULL);
/* Possible combinations:
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 274084821b..00d9a9da8f 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -89,12 +89,12 @@ qemuBuildChrDeviceStr(char **deviceStr,
char *
qemuBuildChannelGuestfwdNetdevProps(virDomainChrDefPtr chr);
-char *qemuBuildHostNetStr(virDomainNetDefPtr net,
- char **tapfd,
- size_t tapfdSize,
- char **vhostfd,
- size_t vhostfdSize,
- const char *slirpfd);
+virJSONValuePtr qemuBuildHostNetStr(virDomainNetDefPtr net,
+ char **tapfd,
+ size_t tapfdSize,
+ char **vhostfd,
+ size_t vhostfdSize,
+ const char *slirpfd);
/* Current, best practice */
char *qemuBuildNicDevStr(virDomainDefPtr def,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index ee97397235..1877aef1b0 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -54,6 +54,7 @@
#include "virstoragefile.h"
#include "virstring.h"
#include "virtime.h"
+#include "virqemu.h"
#define VIR_FROM_THIS VIR_FROM_QEMU
@@ -1157,6 +1158,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
size_t vhostfdSize = 0;
size_t queueSize = 0;
g_autofree char *nicstr = NULL;
+ g_autoptr(virJSONValue) netprops = NULL;
g_autofree char *netstr = NULL;
int ret = -1;
bool releaseaddr = false;
@@ -1382,10 +1384,13 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
for (i = 0; i < vhostfdSize; i++)
vhostfdName[i] = g_strdup_printf("vhostfd-%s%zu", net->info.alias, i);
- if (!(netstr = qemuBuildHostNetStr(net,
- tapfdName, tapfdSize,
- vhostfdName, vhostfdSize,
- slirpfdName)))
+ if (!(netprops = qemuBuildHostNetStr(net,
+ tapfdName, tapfdSize,
+ vhostfdName, vhostfdSize,
+ slirpfdName)))
+ goto cleanup;
+
+ if (!(netstr = virQEMUBuildNetdevCommandlineFromJSON(netprops)))
goto cleanup;
qemuDomainObjEnterMonitor(driver, vm);
--
2.23.0.windows.1

View File

@ -0,0 +1,152 @@
From f0b20bfdd5e0967da8b98a1c66649c23a94b3d3c Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 13:01:59 +0200
Subject: [PATCH 07/18] qemuBuildChannelChrDeviceStr: Remove formatting of
properties for -netdev
The output of the function is fed as argument to '-device' command line
argument or 'device_add' monitor command except for 'guestfwd' channels
where it needs to be fed to -netdev/netdev_add. This is confusing and
error prone. Split it up since the caller needs to know which
command/option to use anyways, so the caller can call the appropriate
function without any magic.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_command.c | 36 ++++++++++++++++++++----------------
src/qemu/qemu_command.h | 3 +++
src/qemu/qemu_hotplug.c | 18 +++++++++++++-----
3 files changed, 36 insertions(+), 21 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 579e78ea75..056a74fb60 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8872,7 +8872,7 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
switch ((virDomainChrChannelTargetType) channel->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
- if (qemuBuildChrDeviceStr(&netdevstr, def, channel, qemuCaps) < 0)
+ if (!(netdevstr = qemuBuildChannelGuestfwdNetdevProps(channel)))
return -1;
virCommandAddArgList(cmd, "-netdev", netdevstr, NULL);
break;
@@ -10140,36 +10140,40 @@ qemuBuildParallelChrDeviceStr(char **deviceStr,
return 0;
}
-static int
-qemuBuildChannelChrDeviceStr(char **deviceStr,
- const virDomainDef *def,
- virDomainChrDefPtr chr)
+
+char *
+qemuBuildChannelGuestfwdNetdevProps(virDomainChrDefPtr chr)
{
- int ret = -1;
g_autofree char *addr = NULL;
int port;
- switch ((virDomainChrChannelTargetType)chr->targetType) {
- case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
+ if (!(addr = virSocketAddrFormat(chr->target.addr)))
+ return NULL;
- addr = virSocketAddrFormat(chr->target.addr);
- if (!addr)
- return ret;
- port = virSocketAddrGetPort(chr->target.addr);
+ port = virSocketAddrGetPort(chr->target.addr);
+
+ return g_strdup_printf("user,guestfwd=tcp:%s:%i-chardev:char%s,id=%s",
+ addr, port, chr->info.alias, chr->info.alias);
+}
- *deviceStr = g_strdup_printf("user,guestfwd=tcp:%s:%i-chardev:char%s,id=%s",
- addr, port, chr->info.alias, chr->info.alias);
- break;
+static int
+qemuBuildChannelChrDeviceStr(char **deviceStr,
+ const virDomainDef *def,
+ virDomainChrDefPtr chr)
+{
+ switch ((virDomainChrChannelTargetType)chr->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
if (!(*deviceStr = qemuBuildVirtioSerialPortDevStr(def, chr)))
return -1;
break;
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
+ /* guestfwd is as a netdev handled separately */
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
- return ret;
+ return -1;
}
return 0;
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index bc3ba44fb3..274084821b 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -86,6 +86,9 @@ qemuBuildChrDeviceStr(char **deviceStr,
virDomainChrDefPtr chr,
virQEMUCapsPtr qemuCaps);
+char *
+qemuBuildChannelGuestfwdNetdevProps(virDomainChrDefPtr chr);
+
char *qemuBuildHostNetStr(virDomainNetDefPtr net,
char **tapfd,
size_t tapfdSize,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 60d0729f1e..ee97397235 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2108,6 +2108,7 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
virErrorPtr orig_err;
virDomainDefPtr vmdef = vm->def;
g_autofree char *devstr = NULL;
+ g_autofree char *netdevstr = NULL;
virDomainChrSourceDefPtr dev = chr->source;
g_autofree char *charAlias = NULL;
bool chardevAttached = false;
@@ -2146,8 +2147,13 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
goto cleanup;
teardowncgroup = true;
- if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
- goto cleanup;
+ if (guestfwd) {
+ if (!(netdevstr = qemuBuildChannelGuestfwdNetdevProps(chr)))
+ goto cleanup;
+ } else {
+ if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
+ goto cleanup;
+ }
if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
goto cleanup;
@@ -2166,11 +2172,13 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
goto exit_monitor;
chardevAttached = true;
- if (guestfwd) {
- if (qemuMonitorAddNetdev(priv->mon, devstr,
+ if (netdevstr) {
+ if (qemuMonitorAddNetdev(priv->mon, netdevstr,
NULL, NULL, 0, NULL, NULL, 0, -1, NULL) < 0)
goto exit_monitor;
- } else {
+ }
+
+ if (devstr) {
if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
goto exit_monitor;
}
--
2.23.0.windows.1

View File

@ -0,0 +1,128 @@
From 17e751be222dd86959f71afda2fca8b0ed09f55b Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 15 May 2020 09:46:08 +0200
Subject: [PATCH 11/18] qemuBuildChannelGuestfwdNetdevProps: Convert to
generating JSON props
Syntax of guestfwd channel also needs to be modified to conform to the
QAPI schema.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_command.c | 37 +++++++++++++++++++++++++++++++------
src/qemu/qemu_command.h | 2 +-
src/qemu/qemu_hotplug.c | 6 +++++-
3 files changed, 37 insertions(+), 8 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 141657b3e4..bd78bfb31b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8903,6 +8903,7 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
for (i = 0; i < def->nchannels; i++) {
virDomainChrDefPtr channel = def->channels[i];
g_autofree char *chardevstr = NULL;
+ g_autoptr(virJSONValue) netdevprops = NULL;
g_autofree char *netdevstr = NULL;
if (!(chardevstr = qemuBuildChrChardevStr(logManager, secManager,
@@ -8917,8 +8918,12 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
switch ((virDomainChrChannelTargetType) channel->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
- if (!(netdevstr = qemuBuildChannelGuestfwdNetdevProps(channel)))
+ if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(channel)))
return -1;
+
+ if (!(netdevstr = virQEMUBuildNetdevCommandlineFromJSON(netdevprops)))
+ return -1;
+
virCommandAddArgList(cmd, "-netdev", netdevstr, NULL);
break;
@@ -10186,19 +10191,39 @@ qemuBuildParallelChrDeviceStr(char **deviceStr,
}
-char *
+virJSONValuePtr
qemuBuildChannelGuestfwdNetdevProps(virDomainChrDefPtr chr)
{
+ g_autoptr(virJSONValue) guestfwdarr = virJSONValueNewArray();
+ g_autoptr(virJSONValue) guestfwdstrobj = virJSONValueNewObject();
g_autofree char *addr = NULL;
- int port;
+ virJSONValuePtr ret = NULL;
if (!(addr = virSocketAddrFormat(chr->target.addr)))
return NULL;
- port = virSocketAddrGetPort(chr->target.addr);
+ /* this may seem weird, but qemu indeed decided that 'guestfwd' parameter
+ * is an array of objects which have just one member named 'str' which
+ * contains the description */
+ if (virJSONValueObjectAppendStringPrintf(guestfwdstrobj, "str",
+ "tcp:%s:%i-chardev:char%s",
+ addr,
+ virSocketAddrGetPort(chr->target.addr),
+ chr->info.alias) < 0)
+ return NULL;
+
+ if (virJSONValueArrayAppend(guestfwdarr, guestfwdstrobj) < 0)
+ return NULL;
+ guestfwdstrobj = NULL;
- return g_strdup_printf("user,guestfwd=tcp:%s:%i-chardev:char%s,id=%s",
- addr, port, chr->info.alias, chr->info.alias);
+ if (virJSONValueObjectCreate(&ret,
+ "s:type", "user",
+ "a:guestfwd", &guestfwdarr,
+ "s:id", chr->info.alias,
+ NULL) < 0)
+ return NULL;
+
+ return ret;
}
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 00d9a9da8f..1e6b23ba05 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -86,7 +86,7 @@ qemuBuildChrDeviceStr(char **deviceStr,
virDomainChrDefPtr chr,
virQEMUCapsPtr qemuCaps);
-char *
+virJSONValuePtr
qemuBuildChannelGuestfwdNetdevProps(virDomainChrDefPtr chr);
virJSONValuePtr qemuBuildHostNetStr(virDomainNetDefPtr net,
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 1877aef1b0..24a898166d 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -2113,6 +2113,7 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
virErrorPtr orig_err;
virDomainDefPtr vmdef = vm->def;
g_autofree char *devstr = NULL;
+ g_autoptr(virJSONValue) netdevprops = NULL;
g_autofree char *netdevstr = NULL;
virDomainChrSourceDefPtr dev = chr->source;
g_autofree char *charAlias = NULL;
@@ -2153,7 +2154,10 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
teardowncgroup = true;
if (guestfwd) {
- if (!(netdevstr = qemuBuildChannelGuestfwdNetdevProps(chr)))
+ if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(chr)))
+ goto cleanup;
+
+ if (!(netdevstr = virQEMUBuildNetdevCommandlineFromJSON(netdevprops)))
goto cleanup;
} else {
if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
--
2.23.0.windows.1

View File

@ -0,0 +1,72 @@
From 31c32f8d76a447899ff4a5c551c06a2888814111 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 12:51:21 +0200
Subject: [PATCH 06/18] qemuBuildChannelsCommandLine: Extract common formatting
of 'chardev'
Both active branches create the same backend chardev. Since there is no
other case, extract it before the switch so that we don't have to
duplicate it.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_command.c | 32 +++++++++++---------------------
1 file changed, 11 insertions(+), 21 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7c4db11ae2..579e78ea75 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8857,37 +8857,27 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
for (i = 0; i < def->nchannels; i++) {
virDomainChrDefPtr channel = def->channels[i];
- char *devstr;
+ g_autofree char *chardevstr = NULL;
+ g_autofree char *netdevstr = NULL;
- switch ((virDomainChrChannelTargetType) channel->targetType) {
- case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
- if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
+ if (!(chardevstr = qemuBuildChrChardevStr(logManager, secManager,
cmd, cfg, def,
channel->source,
channel->info.alias,
qemuCaps, cdevflags)))
- return -1;
- virCommandAddArg(cmd, "-chardev");
- virCommandAddArg(cmd, devstr);
- VIR_FREE(devstr);
+ return -1;
- if (qemuBuildChrDeviceStr(&devstr, def, channel, qemuCaps) < 0)
+ virCommandAddArg(cmd, "-chardev");
+ virCommandAddArg(cmd, chardevstr);
+
+ switch ((virDomainChrChannelTargetType) channel->targetType) {
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
+ if (qemuBuildChrDeviceStr(&netdevstr, def, channel, qemuCaps) < 0)
return -1;
- virCommandAddArgList(cmd, "-netdev", devstr, NULL);
- VIR_FREE(devstr);
+ virCommandAddArgList(cmd, "-netdev", netdevstr, NULL);
break;
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO:
- if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
- cmd, cfg, def,
- channel->source,
- channel->info.alias,
- qemuCaps, cdevflags)))
- return -1;
- virCommandAddArg(cmd, "-chardev");
- virCommandAddArg(cmd, devstr);
- VIR_FREE(devstr);
-
if (qemuBuildChrDeviceCommandLine(cmd, def, channel, qemuCaps) < 0)
return -1;
break;
--
2.23.0.windows.1

View File

@ -0,0 +1,42 @@
From 2aac11e296b60464c0ef4870879b6e75d5e0ee46 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 12:32:55 +0200
Subject: [PATCH 05/18] qemuBuildChannelsCommandLine: Use typecasted switch for
channel type
Cover all cases of the enum.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_command.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c3ad041959..7c4db11ae2 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -8859,7 +8859,7 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
virDomainChrDefPtr channel = def->channels[i];
char *devstr;
- switch (channel->targetType) {
+ switch ((virDomainChrChannelTargetType) channel->targetType) {
case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD:
if (!(devstr = qemuBuildChrChardevStr(logManager, secManager,
cmd, cfg, def,
@@ -8891,6 +8891,11 @@ qemuBuildChannelsCommandLine(virLogManagerPtr logManager,
if (qemuBuildChrDeviceCommandLine(cmd, def, channel, qemuCaps) < 0)
return -1;
break;
+
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_XEN:
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_NONE:
+ case VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_LAST:
+ return -1;
}
}
--
2.23.0.windows.1

View File

@ -0,0 +1,68 @@
From ed5210b67f18478af5669976abb6b61c3bd576e0 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 12:02:55 +0200
Subject: [PATCH 09/18] qemuBuildHostNetStr: Stop using 'ipv6-net' convenience
argument
In qemu the argument of 'ipv6-net' is split up into 'ipv6-prefix' and
'ipv6-prefixlen'. Additionally now that 'netdev_add' was qapified, only
the real properties are allowed. Switch to using them explicitly.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_command.c | 20 ++++++++++----------
tests/qemuxml2argvdata/net-user-addr.args | 3 ++-
2 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 056a74fb60..688c9db851 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -3991,20 +3991,20 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
for (i = 0; i < net->guestIP.nips; i++) {
const virNetDevIPAddr *ip = net->guestIP.ips[i];
g_autofree char *addr = NULL;
- const char *prefix = "";
if (!(addr = virSocketAddrFormat(&ip->address)))
return NULL;
- if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET))
- prefix = "net=";
- if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6))
- prefix = "ipv6-net=";
-
- virBufferAsprintf(&buf, "%s%s", prefix, addr);
- if (ip->prefix)
- virBufferAsprintf(&buf, "/%u", ip->prefix);
- virBufferAddChar(&buf, ',');
+ if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET)) {
+ virBufferAsprintf(&buf, "net=%s", addr);
+ if (ip->prefix)
+ virBufferAsprintf(&buf, "/%u", ip->prefix);
+ virBufferAddChar(&buf, ',');
+ } else if (VIR_SOCKET_ADDR_IS_FAMILY(&ip->address, AF_INET6)) {
+ virBufferAsprintf(&buf, "ipv6-prefix=%s,", addr);
+ if (ip->prefix)
+ virBufferAsprintf(&buf, "ipv6-prefixlen=%u,", ip->prefix);
+ }
}
}
break;
diff --git a/tests/qemuxml2argvdata/net-user-addr.args b/tests/qemuxml2argvdata/net-user-addr.args
index 6cc82d9e62..5f1de305e0 100644
--- a/tests/qemuxml2argvdata/net-user-addr.args
+++ b/tests/qemuxml2argvdata/net-user-addr.args
@@ -27,6 +27,7 @@ server,nowait \
-usb \
-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
-device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 \
--netdev user,net=172.17.2.0/24,ipv6-net=2001:db8:ac10:fd01::/64,id=hostnet0 \
+-netdev user,net=172.17.2.0/24,ipv6-prefix=2001:db8:ac10:fd01::,\
+ipv6-prefixlen=64,id=hostnet0 \
-device rtl8139,netdev=hostnet0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,\
addr=0x3
--
2.23.0.windows.1

View File

@ -0,0 +1,198 @@
From 2d555c8e864c8ba7dbc7a22e37712b70b59e5293 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 15 May 2020 11:36:28 +0200
Subject: [PATCH 12/18] qemuMonitorAddNetdev: Convert to the native JSON props
object
Now that all code paths generate JSON props we can remove the conversion
to command line arguments and back in the monitor code.
Note that the test which is removed in this commit will be replaced by a
stronger testsuite later.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_hotplug.c | 14 +++-----------
src/qemu/qemu_monitor.c | 8 ++++----
src/qemu/qemu_monitor.h | 2 +-
src/qemu/qemu_monitor_json.c | 15 +++------------
src/qemu/qemu_monitor_json.h | 2 +-
tests/qemumonitorjsontest.c | 2 --
6 files changed, 12 insertions(+), 31 deletions(-)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 24a898166d..d7bcb6a99f 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1159,7 +1159,6 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
size_t queueSize = 0;
g_autofree char *nicstr = NULL;
g_autoptr(virJSONValue) netprops = NULL;
- g_autofree char *netstr = NULL;
int ret = -1;
bool releaseaddr = false;
bool iface_connected = false;
@@ -1390,9 +1389,6 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
slirpfdName)))
goto cleanup;
- if (!(netstr = virQEMUBuildNetdevCommandlineFromJSON(netprops)))
- goto cleanup;
-
qemuDomainObjEnterMonitor(driver, vm);
if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
@@ -1404,7 +1400,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
charDevPlugged = true;
}
- if (qemuMonitorAddNetdev(priv->mon, netstr,
+ if (qemuMonitorAddNetdev(priv->mon, &netprops,
tapfd, tapfdName, tapfdSize,
vhostfd, vhostfdName, vhostfdSize,
slirpfd, slirpfdName) < 0) {
@@ -2114,7 +2110,6 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
virDomainDefPtr vmdef = vm->def;
g_autofree char *devstr = NULL;
g_autoptr(virJSONValue) netdevprops = NULL;
- g_autofree char *netdevstr = NULL;
virDomainChrSourceDefPtr dev = chr->source;
g_autofree char *charAlias = NULL;
bool chardevAttached = false;
@@ -2156,9 +2151,6 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
if (guestfwd) {
if (!(netdevprops = qemuBuildChannelGuestfwdNetdevProps(chr)))
goto cleanup;
-
- if (!(netdevstr = virQEMUBuildNetdevCommandlineFromJSON(netdevprops)))
- goto cleanup;
} else {
if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
goto cleanup;
@@ -2181,8 +2173,8 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
goto exit_monitor;
chardevAttached = true;
- if (netdevstr) {
- if (qemuMonitorAddNetdev(priv->mon, netdevstr,
+ if (netdevprops) {
+ if (qemuMonitorAddNetdev(priv->mon, &netdevprops,
NULL, NULL, 0, NULL, NULL, 0, -1, NULL) < 0)
goto exit_monitor;
}
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index cc62948c9c..9f4432ab3a 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -2667,7 +2667,7 @@ qemuMonitorCloseFileHandle(qemuMonitorPtr mon,
int
qemuMonitorAddNetdev(qemuMonitorPtr mon,
- const char *netdevstr,
+ virJSONValuePtr *props,
int *tapfd, char **tapfdName, int tapfdSize,
int *vhostfd, char **vhostfdName, int vhostfdSize,
int slirpfd, char *slirpfdName)
@@ -2675,10 +2675,10 @@ qemuMonitorAddNetdev(qemuMonitorPtr mon,
int ret = -1;
size_t i = 0, j = 0;
- VIR_DEBUG("netdevstr=%s tapfd=%p tapfdName=%p tapfdSize=%d"
+ VIR_DEBUG("props=%p tapfd=%p tapfdName=%p tapfdSize=%d"
"vhostfd=%p vhostfdName=%p vhostfdSize=%d"
"slirpfd=%d slirpfdName=%s",
- netdevstr, tapfd, tapfdName, tapfdSize,
+ props, tapfd, tapfdName, tapfdSize,
vhostfd, vhostfdName, vhostfdSize, slirpfd, slirpfdName);
QEMU_CHECK_MONITOR(mon);
@@ -2696,7 +2696,7 @@ qemuMonitorAddNetdev(qemuMonitorPtr mon,
qemuMonitorSendFileHandle(mon, slirpfdName, slirpfd) < 0)
goto cleanup;
- ret = qemuMonitorJSONAddNetdev(mon, netdevstr);
+ ret = qemuMonitorJSONAddNetdev(mon, props);
cleanup:
if (ret < 0) {
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 68e21dcaee..7a3240f00a 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -881,7 +881,7 @@ int qemuMonitorCloseFileHandle(qemuMonitorPtr mon,
const char *fdname);
int qemuMonitorAddNetdev(qemuMonitorPtr mon,
- const char *netdevstr,
+ virJSONValuePtr *props,
int *tapfd, char **tapfdName, int tapfdSize,
int *vhostfd, char **vhostfdName, int vhostfdSize,
int slirpfd, char *slirpfdName);
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e6b5c7140e..c1d92b2009 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3993,23 +3993,14 @@ int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon,
int
qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
- const char *netdevstr)
+ virJSONValuePtr *props)
{
g_autoptr(virJSONValue) cmd = NULL;
g_autoptr(virJSONValue) reply = NULL;
- g_autoptr(virJSONValue) args = NULL;
-
- cmd = qemuMonitorJSONMakeCommand("netdev_add", NULL);
- if (!cmd)
- return -1;
-
- args = qemuMonitorJSONKeywordStringToJSON(netdevstr, "type");
- if (!args)
- return -1;
+ virJSONValuePtr pr = g_steal_pointer(props);
- if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
+ if (!(cmd = qemuMonitorJSONMakeCommandInternal("netdev_add", pr)))
return -1;
- args = NULL; /* obj owns reference to args now */
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
return -1;
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 05a46b4fe2..dd25e5d6e6 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -210,7 +210,7 @@ int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon,
const char *fdname);
int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
- const char *netdevstr);
+ virJSONValuePtr *props);
int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
const char *alias);
diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
index 472775a3cf..2ec143f476 100644
--- a/tests/qemumonitorjsontest.c
+++ b/tests/qemumonitorjsontest.c
@@ -1308,7 +1308,6 @@ GEN_TEST_FUNC(qemuMonitorJSONDump, "dummy_protocol", "elf",
true)
GEN_TEST_FUNC(qemuMonitorJSONGraphicsRelocate, VIR_DOMAIN_GRAPHICS_TYPE_SPICE,
"localhost", 12345, 12346, "certsubjectval")
-GEN_TEST_FUNC(qemuMonitorJSONAddNetdev, "id=net0,type=test")
GEN_TEST_FUNC(qemuMonitorJSONRemoveNetdev, "net0")
GEN_TEST_FUNC(qemuMonitorJSONDelDevice, "ide0")
GEN_TEST_FUNC(qemuMonitorJSONAddDevice, "some_dummy_devicestr")
@@ -3192,7 +3191,6 @@ mymain(void)
DO_TEST_GEN(qemuMonitorJSONMigrate);
DO_TEST_GEN(qemuMonitorJSONDump);
DO_TEST_GEN(qemuMonitorJSONGraphicsRelocate);
- DO_TEST_GEN(qemuMonitorJSONAddNetdev);
DO_TEST_GEN(qemuMonitorJSONRemoveNetdev);
DO_TEST_GEN(qemuMonitorJSONDelDevice);
DO_TEST_GEN(qemuMonitorJSONAddDevice);
--
2.23.0.windows.1

View File

@ -0,0 +1,107 @@
From 3e1026fb3619aae6b1be4879797474d10d22a54c Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 15 May 2020 11:16:32 +0200
Subject: [PATCH 08/18] qemuMonitorJSON(Add|Remove)Netdev: Refactor cleanup
Use automatic pointer cleanup for virJSONValuePtrs to get rid of the
cleanup label and ret variable.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/qemu/qemu_monitor_json.c | 52 +++++++++++++++---------------------
1 file changed, 22 insertions(+), 30 deletions(-)
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ef25764a98..e6b5c7140e 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -3991,13 +3991,13 @@ int qemuMonitorJSONCloseFileHandle(qemuMonitorPtr mon,
}
-int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
- const char *netdevstr)
+int
+qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
+ const char *netdevstr)
{
- int ret = -1;
- virJSONValuePtr cmd = NULL;
- virJSONValuePtr reply = NULL;
- virJSONValuePtr args = NULL;
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+ g_autoptr(virJSONValue) args = NULL;
cmd = qemuMonitorJSONMakeCommand("netdev_add", NULL);
if (!cmd)
@@ -4005,49 +4005,41 @@ int qemuMonitorJSONAddNetdev(qemuMonitorPtr mon,
args = qemuMonitorJSONKeywordStringToJSON(netdevstr, "type");
if (!args)
- goto cleanup;
+ return -1;
if (virJSONValueObjectAppend(cmd, "arguments", args) < 0)
- goto cleanup;
+ return -1;
args = NULL; /* obj owns reference to args now */
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
- goto cleanup;
+ return -1;
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
- goto cleanup;
+ return -1;
- ret = 0;
- cleanup:
- virJSONValueFree(args);
- virJSONValueFree(cmd);
- virJSONValueFree(reply);
- return ret;
+ return 0;
}
-int qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
- const char *alias)
+int
+qemuMonitorJSONRemoveNetdev(qemuMonitorPtr mon,
+ const char *alias)
{
- int ret = -1;
- virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("netdev_del",
- "s:id", alias,
- NULL);
- virJSONValuePtr reply = NULL;
+ g_autoptr(virJSONValue) cmd = qemuMonitorJSONMakeCommand("netdev_del",
+ "s:id", alias,
+ NULL);
+ g_autoptr(virJSONValue) reply = NULL;
+
if (!cmd)
return -1;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
- goto cleanup;
+ return -1;
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
- goto cleanup;
+ return -1;
- ret = 0;
- cleanup:
- virJSONValueFree(cmd);
- virJSONValueFree(reply);
- return ret;
+ return 0;
}
--
2.23.0.windows.1

View File

@ -0,0 +1,181 @@
From 63e167446b11121a0e375ad28375b6f5a44a5d95 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 15 May 2020 14:33:10 +0200
Subject: [PATCH 18/18] qemuxml2argvtest: Add QAPI/QMP schema validation for
-blockdev and -netdev
Our hotplug test cases are weak in comparison to the qemuxml2argvtest.
Use all the the input data to also validate the arguments for -netdev
and -blockdev against the appropriate commands of the QMP schema.
Note that currently it's done just for the _CAPS versions of tests but
commenting out a line in the test file allows to validate even cases
which don't use real capabilities.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
tests/Makefile.am | 2 +-
tests/qemuxml2argvtest.c | 76 ++++++++++++++++++++++++++++++++++++++++
tests/testutilsqemu.c | 5 +++
tests/testutilsqemu.h | 1 +
4 files changed, 83 insertions(+), 1 deletion(-)
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ada5b8fc57..e5440906d1 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -569,7 +569,7 @@ qemuxml2argvtest_SOURCES = \
testutils.c testutils.h \
virfilewrapper.c virfilewrapper.h \
$(NULL)
-qemuxml2argvtest_LDADD = libqemutestdriver.la \
+qemuxml2argvtest_LDADD = libqemutestdriver.la libqemumonitortestutils.la \
$(LDADDS) $(LIBXML_LIBS)
libqemuxml2argvmock_la_SOURCES = \
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 2217e2d81e..dc871d5698 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -18,6 +18,7 @@
# include "qemu/qemu_migration.h"
# include "qemu/qemu_process.h"
# include "qemu/qemu_slirp.h"
+# include "qemu/qemu_qapi.h"
# include "datatypes.h"
# include "conf/storage_conf.h"
# include "cpu/cpu_map.h"
@@ -26,6 +27,8 @@
# include "virmock.h"
# include "virfilewrapper.h"
# include "configmake.h"
+# include "testutilsqemuschema.h"
+# include "qemu/qemu_monitor_json.h"
# define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW
# include "qemu/qemu_capspriv.h"
@@ -481,6 +484,76 @@ testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv,
}
+static int
+testCompareXMLToArgvValidateSchema(virQEMUDriverPtr drv,
+ virDomainObjPtr vm,
+ const char *migrateURI,
+ struct testQemuInfo *info,
+ unsigned int flags)
+{
+ VIR_AUTOSTRINGLIST args = NULL;
+ size_t nargs = 0;
+ size_t i;
+ g_autoptr(virHashTable) schema = NULL;
+ g_autoptr(virCommand) cmd = NULL;
+
+ if (info->schemafile)
+ schema = testQEMUSchemaLoad(info->schemafile);
+
+ /* comment out with line comment to enable schema checking for non _CAPS tests
+ if (!schema)
+ schema = testQEMUSchemaLoadLatest(virArchToString(info->arch));
+ // */
+
+ if (!schema)
+ return 0;
+
+ if (!(cmd = testCompareXMLToArgvCreateArgs(drv, vm, migrateURI, info, flags,
+ true)))
+ return -1;
+
+ if (virCommandGetArgList(cmd, &args, &nargs) < 0)
+ return -1;
+
+ for (i = 0; i < nargs; i++) {
+ g_auto(virBuffer) debug = VIR_BUFFER_INITIALIZER;
+ g_autoptr(virJSONValue) jsonargs = NULL;
+
+ if (STREQ(args[i], "-blockdev")) {
+ if (!(jsonargs = virJSONValueFromString(args[i + 1])))
+ return -1;
+
+ if (testQEMUSchemaValidateCommand("blockdev-add", jsonargs,
+ schema, &debug) < 0) {
+ VIR_TEST_VERBOSE("failed to validate -blockdev '%s' against QAPI schema: %s",
+ args[i + 1], virBufferCurrentContent(&debug));
+ return -1;
+ }
+
+ i++;
+ } else if (STREQ(args[i], "-netdev")) {
+ if (!(jsonargs = virJSONValueFromString(args[i + 1])))
+ return -1;
+
+ /* skip the validation for pre-QAPIfication cases */
+ if (virQEMUQAPISchemaPathExists("netdev_add/arg-type/type/!string", schema))
+ continue;
+
+ if (testQEMUSchemaValidateCommand("netdev_add", jsonargs,
+ schema, &debug) < 0) {
+ VIR_TEST_VERBOSE("failed to validate -netdev '%s' against QAPI schema: %s",
+ args[i + 1], virBufferCurrentContent(&debug));
+ return -1;
+ }
+
+ i++;
+ }
+ }
+
+ return 0;
+}
+
+
static int
testCompareXMLToArgv(const void *data)
{
@@ -582,6 +655,9 @@ testCompareXMLToArgv(const void *data)
goto cleanup;
}
+ if (testCompareXMLToArgvValidateSchema(&driver, vm, migrateURI, info, flags) < 0)
+ goto cleanup;
+
if (!(actualargv = virCommandToString(cmd, false)))
goto cleanup;
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index f3b4e2b3b2..bae1fa828b 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -767,6 +767,10 @@ testQemuInfoSetArgs(struct testQemuInfo *info,
if (stripmachinealiases)
virQEMUCapsStripMachineAliases(qemuCaps);
info->flags |= FLAG_REAL_CAPS;
+
+ /* provide path to the replies file for schema testing */
+ capsfile[strlen(capsfile) - 3] = '\0';
+ info->schemafile = g_strdup_printf("%sreplies", capsfile);
}
if (!qemuCaps) {
@@ -793,5 +797,6 @@ testQemuInfoClear(struct testQemuInfo *info)
{
VIR_FREE(info->infile);
VIR_FREE(info->outfile);
+ VIR_FREE(info->schemafile);
virObjectUnref(info->qemuCaps);
}
diff --git a/tests/testutilsqemu.h b/tests/testutilsqemu.h
index edee6e450c..e7c5032012 100644
--- a/tests/testutilsqemu.h
+++ b/tests/testutilsqemu.h
@@ -64,6 +64,7 @@ struct testQemuInfo {
unsigned int flags;
unsigned int parseFlags;
virArch arch;
+ char *schemafile;
};
virCapsPtr testQemuCapsInit(void);
--
2.23.0.windows.1

View File

@ -0,0 +1,204 @@
From fb0de8df975557e74af01a0eee0d25c08981c02a Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 15 May 2020 08:50:31 +0200
Subject: [PATCH 15/18] testCompareXMLToArgv: Split out preparation and command
formatting
There are multiple steps of setting up the domain definition prior to
formatting the command line for the tests. Extract it to a separate
function so that it's self-contained and also will allow re-running the
command line formatting which will be necessary for QMP schema
validation tests.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
tests/qemuxml2argvtest.c | 158 +++++++++++++++++++++------------------
1 file changed, 86 insertions(+), 72 deletions(-)
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 2153e44c5a..762d65f521 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -395,6 +395,90 @@ testCheckExclusiveFlags(int flags)
}
+static virCommandPtr
+testCompareXMLToArgvCreateArgs(virQEMUDriverPtr drv,
+ virDomainObjPtr vm,
+ const char *migrateURI,
+ struct testQemuInfo *info,
+ unsigned int flags)
+{
+ size_t i;
+
+ for (i = 0; i < vm->def->nhostdevs; i++) {
+ virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
+
+ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+ hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+ hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
+ hostdev->source.subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
+ }
+ }
+
+ for (i = 0; i < vm->def->nfss; i++) {
+ virDomainFSDefPtr fs = vm->def->fss[i];
+ char *s;
+
+ if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS ||
+ QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock)
+ continue;
+
+ s = g_strdup_printf("/tmp/lib/domain--1-guest/fs%zu.vhost-fs.sock", i);
+ QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock = s;
+ }
+
+ if (vm->def->vsock) {
+ virDomainVsockDefPtr vsock = vm->def->vsock;
+ qemuDomainVsockPrivatePtr vsockPriv =
+ (qemuDomainVsockPrivatePtr)vsock->privateData;
+
+ if (vsock->auto_cid == VIR_TRISTATE_BOOL_YES)
+ vsock->guest_cid = 42;
+
+ vsockPriv->vhostfd = 6789;
+ }
+
+ if (vm->def->tpm) {
+ switch (vm->def->tpm->type) {
+ case VIR_DOMAIN_TPM_TYPE_EMULATOR:
+ VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path);
+ vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test");
+ vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE;
+ break;
+ case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+ case VIR_DOMAIN_TPM_TYPE_LAST:
+ break;
+ }
+ }
+
+ for (i = 0; i < vm->def->nvideos; i++) {
+ virDomainVideoDefPtr video = vm->def->videos[i];
+
+ if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER) {
+ qemuDomainVideoPrivatePtr vpriv = QEMU_DOMAIN_VIDEO_PRIVATE(video);
+
+ vpriv->vhost_user_fd = 1729;
+ }
+ }
+
+ if (flags & FLAG_SLIRP_HELPER) {
+ for (i = 0; i < vm->def->nnets; i++) {
+ virDomainNetDefPtr net = vm->def->nets[i];
+
+ if (net->type == VIR_DOMAIN_NET_TYPE_USER &&
+ virQEMUCapsGet(info->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
+ qemuSlirpPtr slirp = qemuSlirpNew();
+ slirp->fd[0] = 42;
+ QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp = slirp;
+ }
+ }
+ }
+
+ return qemuProcessCreatePretendCmd(drv, vm, migrateURI,
+ (flags & FLAG_FIPS), false,
+ VIR_QEMU_PROCESS_START_COLD);
+}
+
+
static int
testCompareXMLToArgv(const void *data)
{
@@ -409,7 +493,6 @@ testCompareXMLToArgv(const void *data)
virConnectPtr conn;
char *log = NULL;
virCommandPtr cmd = NULL;
- size_t i;
qemuDomainObjPrivatePtr priv = NULL;
if (info->arch != VIR_ARCH_NONE && info->arch != VIR_ARCH_X86_64)
@@ -486,77 +569,8 @@ testCompareXMLToArgv(const void *data)
VIR_FREE(log);
virResetLastError();
- for (i = 0; i < vm->def->nhostdevs; i++) {
- virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
-
- if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
- hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
- hostdev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT) {
- hostdev->source.subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
- }
- }
-
- for (i = 0; i < vm->def->nfss; i++) {
- virDomainFSDefPtr fs = vm->def->fss[i];
- char *s;
-
- if (fs->fsdriver != VIR_DOMAIN_FS_DRIVER_TYPE_VIRTIOFS)
- continue;
-
- s = g_strdup_printf("/tmp/lib/domain--1-guest/fs%zu.vhost-fs.sock", i);
- QEMU_DOMAIN_FS_PRIVATE(fs)->vhostuser_fs_sock = s;
- }
-
- if (vm->def->vsock) {
- virDomainVsockDefPtr vsock = vm->def->vsock;
- qemuDomainVsockPrivatePtr vsockPriv =
- (qemuDomainVsockPrivatePtr)vsock->privateData;
-
- if (vsock->auto_cid == VIR_TRISTATE_BOOL_YES)
- vsock->guest_cid = 42;
-
- vsockPriv->vhostfd = 6789;
- }
-
- if (vm->def->tpm) {
- switch (vm->def->tpm->type) {
- case VIR_DOMAIN_TPM_TYPE_EMULATOR:
- VIR_FREE(vm->def->tpm->data.emulator.source.data.file.path);
- vm->def->tpm->data.emulator.source.data.file.path = g_strdup("/dev/test");
- vm->def->tpm->data.emulator.source.type = VIR_DOMAIN_CHR_TYPE_FILE;
- break;
- case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
- case VIR_DOMAIN_TPM_TYPE_LAST:
- break;
- }
- }
-
- for (i = 0; i < vm->def->nvideos; i++) {
- virDomainVideoDefPtr video = vm->def->videos[i];
-
- if (video->backend == VIR_DOMAIN_VIDEO_BACKEND_TYPE_VHOSTUSER) {
- qemuDomainVideoPrivatePtr vpriv = QEMU_DOMAIN_VIDEO_PRIVATE(video);
-
- vpriv->vhost_user_fd = 1729;
- }
- }
-
- if (flags & FLAG_SLIRP_HELPER) {
- for (i = 0; i < vm->def->nnets; i++) {
- virDomainNetDefPtr net = vm->def->nets[i];
-
- if (net->type == VIR_DOMAIN_NET_TYPE_USER &&
- virQEMUCapsGet(info->qemuCaps, QEMU_CAPS_DBUS_VMSTATE)) {
- qemuSlirpPtr slirp = qemuSlirpNew();
- slirp->fd[0] = 42;
- QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp = slirp;
- }
- }
- }
-
- if (!(cmd = qemuProcessCreatePretendCmd(&driver, vm, migrateURI,
- (flags & FLAG_FIPS), false,
- VIR_QEMU_PROCESS_START_COLD))) {
+ if (!(cmd = testCompareXMLToArgvCreateArgs(&driver, vm, migrateURI, info,
+ flags))) {
if (flags & FLAG_EXPECT_FAILURE)
goto ok;
goto cleanup;
--
2.23.0.windows.1

View File

@ -0,0 +1,94 @@
From 740581f96fa4007d6549e82131a9ef48a6478149 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 4 Mar 2020 10:22:19 +0100
Subject: [PATCH 14/18] testutilsqemuschema: Introduce
testQEMUSchemaValidateCommand
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The new helper splits out all steps necessary to validate a QMP command
against the schema.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
---
tests/testutilsqemuschema.c | 44 +++++++++++++++++++++++++++++++++++++
tests/testutilsqemuschema.h | 6 +++++
2 files changed, 50 insertions(+)
diff --git a/tests/testutilsqemuschema.c b/tests/testutilsqemuschema.c
index 7b82ff27b2..fe8501f3a0 100644
--- a/tests/testutilsqemuschema.c
+++ b/tests/testutilsqemuschema.c
@@ -517,6 +517,50 @@ testQEMUSchemaValidate(virJSONValuePtr obj,
}
+/**
+ * testQEMUSchemaValidateCommand:
+ * @command: command to validate
+ * @arguments: arguments of @command to validate
+ * @schema: hash table containing schema entries
+ * @debug: a virBuffer which will be filled with debug information if provided
+ *
+ * Validates whether @command and its @arguments conform to the QAPI schema
+ * passed in via @schema. Returns 0, if the command and args match @schema,
+ * -1 if it does not and -2 if there is a problem with the schema or with
+ * internals.
+ *
+ * @debug is filled with information regarding the validation process
+ */
+int
+testQEMUSchemaValidateCommand(const char *command,
+ virJSONValuePtr arguments,
+ virHashTablePtr schema,
+ virBufferPtr debug)
+{
+ g_autofree char *schemapatharguments = g_strdup_printf("%s/arg-type", command);
+ g_autoptr(virJSONValue) emptyargs = NULL;
+ virJSONValuePtr schemarootcommand;
+ virJSONValuePtr schemarootarguments;
+
+ if (virQEMUQAPISchemaPathGet(command, schema, &schemarootcommand) < 0 ||
+ !schemarootcommand) {
+ virBufferAsprintf(debug, "ERROR: command '%s' not found in the schema", command);
+ return -1;
+ }
+
+ if (!arguments)
+ arguments = emptyargs = virJSONValueNewObject();
+
+ if (virQEMUQAPISchemaPathGet(schemapatharguments, schema, &schemarootarguments) < 0 ||
+ !schemarootarguments) {
+ virBufferAsprintf(debug, "ERROR: failed to look up 'arg-type' of '%s'", command);
+ return -1;
+ }
+
+ return testQEMUSchemaValidateRecurse(arguments, schemarootarguments, schema, debug);
+}
+
+
/**
* testQEMUSchemaGetLatest:
*
diff --git a/tests/testutilsqemuschema.h b/tests/testutilsqemuschema.h
index 84ee9a9670..e3a375b038 100644
--- a/tests/testutilsqemuschema.h
+++ b/tests/testutilsqemuschema.h
@@ -28,6 +28,12 @@ testQEMUSchemaValidate(virJSONValuePtr obj,
virHashTablePtr schema,
virBufferPtr debug);
+int
+testQEMUSchemaValidateCommand(const char *command,
+ virJSONValuePtr arguments,
+ virHashTablePtr schema,
+ virBufferPtr debug);
+
virJSONValuePtr
testQEMUSchemaGetLatest(const char* arch);
--
2.23.0.windows.1

View File

@ -0,0 +1,73 @@
From 0924902c3814677f9f328f521a95d4a79635d81a Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 08:09:56 +0200
Subject: [PATCH 04/18] util: json: Introduce
virJSONValueObjectAppendStringPrintf
Add a variant similar to virJSONValueObjectAppendString which also
formats more complex value strings with printf syntax.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virjson.c | 17 +++++++++++++++++
src/util/virjson.h | 2 ++
3 files changed, 20 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 84f3bd57ca..726e7a21f9 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2349,6 +2349,7 @@ virJSONValueObjectAppendNumberLong;
virJSONValueObjectAppendNumberUint;
virJSONValueObjectAppendNumberUlong;
virJSONValueObjectAppendString;
+virJSONValueObjectAppendStringPrintf;
virJSONValueObjectCreate;
virJSONValueObjectCreateVArgs;
virJSONValueObjectDeflatten;
diff --git a/src/util/virjson.c b/src/util/virjson.c
index dc662bf8e9..6921eccb60 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -649,6 +649,23 @@ virJSONValueObjectAppendString(virJSONValuePtr object,
}
+int
+virJSONValueObjectAppendStringPrintf(virJSONValuePtr object,
+ const char *key,
+ const char *fmt,
+ ...)
+{
+ va_list ap;
+ g_autofree char *str = NULL;
+
+ va_start(ap, fmt);
+ str = g_strdup_vprintf(fmt, ap);
+ va_end(ap);
+
+ return virJSONValueObjectInsertString(object, key, str, false);
+}
+
+
int
virJSONValueObjectPrependString(virJSONValuePtr object,
const char *key,
diff --git a/src/util/virjson.h b/src/util/virjson.h
index 0894e91b59..588c977650 100644
--- a/src/util/virjson.h
+++ b/src/util/virjson.h
@@ -127,6 +127,8 @@ int virJSONValueObjectGetBoolean(virJSONValuePtr object, const char *key, bool *
int virJSONValueObjectIsNull(virJSONValuePtr object, const char *key);
int virJSONValueObjectAppendString(virJSONValuePtr object, const char *key, const char *value);
+int virJSONValueObjectAppendStringPrintf(virJSONValuePtr object, const char *key, const char *fmt, ...)
+ G_GNUC_PRINTF(3, 4);
int virJSONValueObjectPrependString(virJSONValuePtr object, const char *key, const char *value);
int virJSONValueObjectAppendNumberInt(virJSONValuePtr object, const char *key, int number);
int virJSONValueObjectAppendNumberUint(virJSONValuePtr object, const char *key, unsigned int number);
--
2.23.0.windows.1

View File

@ -0,0 +1,81 @@
From b9ff1a5a81df23f0a138a7f6d7d3ab0654f669e2 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 10:10:16 +0200
Subject: [PATCH 03/18] util: virqemu: Introduce
virQEMUBuildNetdevCommandlineFromJSON
In preparation for converting the generator of -netdev to generate JSON
which will be used to do the command line rather than the other way
around we need to introduce a convertor which properly configures
virQEMUBuildCommandLineJSON for the quirks of -netdev.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virqemu.c | 22 ++++++++++++++++++++++
src/util/virqemu.h | 3 +++
3 files changed, 26 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index bac96e140e..84f3bd57ca 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2902,6 +2902,7 @@ virQEMUBuildCommandLineJSON;
virQEMUBuildCommandLineJSONArrayBitmap;
virQEMUBuildCommandLineJSONArrayNumbered;
virQEMUBuildDriveCommandlineFromJSON;
+virQEMUBuildNetdevCommandlineFromJSON;
virQEMUBuildObjectCommandlineFromJSON;
virQEMUBuildQemuImgKeySecretOpts;
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
index 549f88fcd5..0f8cab29df 100644
--- a/src/util/virqemu.c
+++ b/src/util/virqemu.c
@@ -252,6 +252,28 @@ virQEMUBuildCommandLineJSON(virJSONValuePtr value,
}
+/**
+ * virQEMUBuildNetdevCommandlineFromJSON:
+ * @props: JSON properties describing a netdev
+ *
+ * Converts @props into arguments for -netdev including all the quirks and
+ * differences between the monitor and command line syntax.
+ */
+char *
+virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props)
+{
+ const char *type = virJSONValueObjectGetString(props, "type");
+ g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
+
+ virBufferAsprintf(&buf, "%s,", type);
+
+ if (virQEMUBuildCommandLineJSON(props, &buf, "type", true, NULL) < 0)
+ return NULL;
+
+ return virBufferContentAndReset(&buf);
+}
+
+
static int
virQEMUBuildObjectCommandlineFromJSONInternal(virBufferPtr buf,
const char *type,
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
index 67a5711613..22f47851df 100644
--- a/src/util/virqemu.h
+++ b/src/util/virqemu.h
@@ -49,6 +49,9 @@ int virQEMUBuildCommandLineJSON(virJSONValuePtr value,
bool onOff,
virQEMUBuildCommandLineJSONArrayFormatFunc array);
+char *
+virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props);
+
int virQEMUBuildObjectCommandlineFromJSON(virBufferPtr buf,
virJSONValuePtr objprops);
--
2.23.0.windows.1

View File

@ -0,0 +1,77 @@
From 548ea1fcfcfbfc40fab04301e780d28ebe4320a4 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Wed, 13 May 2020 17:55:21 +0200
Subject: [PATCH 13/18] virCommand: Introduce virCommandGetArgList
The helper returns a list of arguments of a virCommand. This will be
useful in tests where we'll inspect certain already formatted arguments.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/vircommand.c | 23 +++++++++++++++++++++++
src/util/vircommand.h | 1 +
3 files changed, 25 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 726e7a21f9..861a4892be 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1829,6 +1829,7 @@ virCommandDaemonize;
virCommandDoAsyncIO;
virCommandExec;
virCommandFree;
+virCommandGetArgList;
virCommandGetGID;
virCommandGetUID;
virCommandHandshakeNotify;
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index b84fb40948..86e4c5cd39 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -2167,6 +2167,29 @@ virCommandToString(virCommandPtr cmd, bool linebreaks)
}
+int
+virCommandGetArgList(virCommandPtr cmd,
+ char ***args,
+ size_t *nargs)
+{
+ size_t i;
+
+ if (cmd->has_error) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("invalid use of command API"));
+ return -1;
+ }
+
+ *args = g_new0(char *, cmd->nargs);
+ *nargs = cmd->nargs - 1;
+
+ for (i = 1; i < cmd->nargs; i++)
+ (*args)[i - 1] = g_strdup(cmd->args[i]);
+
+ return 0;
+}
+
+
#ifndef WIN32
/*
* Manage input and output to the child process.
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index 4e6cb0ac0d..854bfe6576 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -171,6 +171,7 @@ void virCommandWriteArgLog(virCommandPtr cmd,
int logfd);
char *virCommandToString(virCommandPtr cmd, bool linebreaks) G_GNUC_WARN_UNUSED_RESULT;
+int virCommandGetArgList(virCommandPtr cmd, char ***args, size_t *nargs);
int virCommandExec(virCommandPtr cmd, gid_t *groups, int ngroups) G_GNUC_WARN_UNUSED_RESULT;
--
2.23.0.windows.1

View File

@ -0,0 +1,218 @@
From b80d9efd8af5de335e3c1de24b74d2e647832458 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 22:45:24 +0200
Subject: [PATCH 02/18] virQEMUBuildCommandLineJSON: Add possibility for using
'on/off' instead of 'yes/no'
In some cases we use 'on/off' for command line arguments. Add a switch
which will select the preferred spelling for a specific usage.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/util/virqemu.c | 44 ++++++++++++++++++++++++-------------
src/util/virqemu.h | 10 ++++++---
tests/qemucommandutiltest.c | 2 +-
3 files changed, 37 insertions(+), 19 deletions(-)
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
index 0e6fa412bc..549f88fcd5 100644
--- a/src/util/virqemu.c
+++ b/src/util/virqemu.c
@@ -37,6 +37,7 @@ struct virQEMUCommandLineJSONIteratorData {
const char *prefix;
virBufferPtr buf;
const char *skipKey;
+ bool onOff;
virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc;
};
@@ -46,6 +47,7 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
virJSONValuePtr value,
virBufferPtr buf,
const char *skipKey,
+ bool onOff,
virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc,
bool nested);
@@ -55,7 +57,8 @@ int
virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
virJSONValuePtr array,
virBufferPtr buf,
- const char *skipKey G_GNUC_UNUSED)
+ const char *skipKey G_GNUC_UNUSED,
+ bool onOff G_GNUC_UNUSED)
{
ssize_t pos = -1;
ssize_t end;
@@ -84,7 +87,8 @@ int
virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
virJSONValuePtr array,
virBufferPtr buf,
- const char *skipKey)
+ const char *skipKey,
+ bool onOff)
{
virJSONValuePtr member;
size_t i;
@@ -95,7 +99,7 @@ virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
prefix = g_strdup_printf("%s.%zu", key, i);
- if (virQEMUBuildCommandLineJSONRecurse(prefix, member, buf, skipKey,
+ if (virQEMUBuildCommandLineJSONRecurse(prefix, member, buf, skipKey, onOff,
virQEMUBuildCommandLineJSONArrayNumbered,
true) < 0)
return 0;
@@ -122,11 +126,11 @@ virQEMUBuildCommandLineJSONIterate(const char *key,
tmpkey = g_strdup_printf("%s.%s", data->prefix, key);
return virQEMUBuildCommandLineJSONRecurse(tmpkey, value, data->buf,
- data->skipKey,
+ data->skipKey, data->onOff,
data->arrayFunc, false);
} else {
return virQEMUBuildCommandLineJSONRecurse(key, value, data->buf,
- data->skipKey,
+ data->skipKey, data->onOff,
data->arrayFunc, false);
}
}
@@ -137,10 +141,11 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
virJSONValuePtr value,
virBufferPtr buf,
const char *skipKey,
+ bool onOff,
virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc,
bool nested)
{
- struct virQEMUCommandLineJSONIteratorData data = { key, buf, skipKey, arrayFunc };
+ struct virQEMUCommandLineJSONIteratorData data = { key, buf, skipKey, onOff, arrayFunc };
virJSONType type = virJSONValueGetType(value);
virJSONValuePtr elem;
bool tmp;
@@ -165,10 +170,17 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
case VIR_JSON_TYPE_BOOLEAN:
virJSONValueGetBoolean(value, &tmp);
- if (tmp)
- virBufferAsprintf(buf, "%s=yes,", key);
- else
- virBufferAsprintf(buf, "%s=no,", key);
+ if (onOff) {
+ if (tmp)
+ virBufferAsprintf(buf, "%s=on,", key);
+ else
+ virBufferAsprintf(buf, "%s=off,", key);
+ } else {
+ if (tmp)
+ virBufferAsprintf(buf, "%s=yes,", key);
+ else
+ virBufferAsprintf(buf, "%s=no,", key);
+ }
break;
@@ -180,7 +192,7 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
return -1;
}
- if (!arrayFunc || arrayFunc(key, value, buf, skipKey) < 0) {
+ if (!arrayFunc || arrayFunc(key, value, buf, skipKey, onOff) < 0) {
/* fallback, treat the array as a non-bitmap, adding the key
* for each member */
for (i = 0; i < virJSONValueArraySize(value); i++) {
@@ -188,7 +200,7 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
/* recurse to avoid duplicating code */
if (virQEMUBuildCommandLineJSONRecurse(key, elem, buf, skipKey,
- arrayFunc, true) < 0)
+ onOff, arrayFunc, true) < 0)
return -1;
}
}
@@ -216,6 +228,7 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
* @value: json object containing the value
* @buf: otuput buffer
* @skipKey: name of key that will be handled separately by caller
+ * @onOff: Use 'on' and 'off' for boolean values rather than 'yes' and 'no'
* @arrayFunc: array formatter function to allow for different syntax
*
* Formats JSON value object into command line parameters suitable for use with
@@ -227,9 +240,10 @@ int
virQEMUBuildCommandLineJSON(virJSONValuePtr value,
virBufferPtr buf,
const char *skipKey,
+ bool onOff,
virQEMUBuildCommandLineJSONArrayFormatFunc array)
{
- if (virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, skipKey, array, false) < 0)
+ if (virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, skipKey, onOff, array, false) < 0)
return -1;
virBufferTrim(buf, ",");
@@ -255,7 +269,7 @@ virQEMUBuildObjectCommandlineFromJSONInternal(virBufferPtr buf,
if (props) {
virBufferAddLit(buf, ",");
- if (virQEMUBuildCommandLineJSON(props, buf, NULL,
+ if (virQEMUBuildCommandLineJSON(props, buf, NULL, false,
virQEMUBuildCommandLineJSONArrayBitmap) < 0)
return -1;
}
@@ -282,7 +296,7 @@ virQEMUBuildDriveCommandlineFromJSON(virJSONValuePtr srcdef)
virBuffer buf = VIR_BUFFER_INITIALIZER;
char *ret = NULL;
- if (virQEMUBuildCommandLineJSON(srcdef, &buf, NULL,
+ if (virQEMUBuildCommandLineJSON(srcdef, &buf, NULL, false,
virQEMUBuildCommandLineJSONArrayNumbered) < 0)
goto cleanup;
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
index 9d3db7c2a2..67a5711613 100644
--- a/src/util/virqemu.h
+++ b/src/util/virqemu.h
@@ -30,19 +30,23 @@
typedef int (*virQEMUBuildCommandLineJSONArrayFormatFunc)(const char *key,
virJSONValuePtr array,
virBufferPtr buf,
- const char *skipKey);
+ const char *skipKey,
+ bool onOff);
int virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
virJSONValuePtr array,
virBufferPtr buf,
- const char *skipKey);
+ const char *skipKey,
+ bool onOff);
int virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
virJSONValuePtr array,
virBufferPtr buf,
- const char *skipKey);
+ const char *skipKey,
+ bool onOff);
int virQEMUBuildCommandLineJSON(virJSONValuePtr value,
virBufferPtr buf,
const char *skipKey,
+ bool onOff,
virQEMUBuildCommandLineJSONArrayFormatFunc array);
int virQEMUBuildObjectCommandlineFromJSON(virBufferPtr buf,
diff --git a/tests/qemucommandutiltest.c b/tests/qemucommandutiltest.c
index 923776e642..049fd2f0b0 100644
--- a/tests/qemucommandutiltest.c
+++ b/tests/qemucommandutiltest.c
@@ -47,7 +47,7 @@ testQemuCommandBuildFromJSON(const void *opaque)
return -1;
}
- if (virQEMUBuildCommandLineJSON(val, &buf, NULL, data->arrayfunc) < 0) {
+ if (virQEMUBuildCommandLineJSON(val, &buf, NULL, false, data->arrayfunc) < 0) {
fprintf(stderr,
"\nvirQEMUBuildCommandlineJSON failed process JSON:\n%s\n",
data->props);
--
2.23.0.windows.1

View File

@ -0,0 +1,202 @@
From b1e8b606813b1097cdb3a0d9e9f04c629d7bcf29 Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Thu, 14 May 2020 09:41:48 +0200
Subject: [PATCH 01/18] virQEMUBuildCommandLineJSON: Allow skipping certain
keys
Allow reusing this for formatting of netdev_add arguments into -netdev.
We need to be able to skip the 'type' property as it's used without the
prefix by our generator.
Add infrastructure which allows skipping property with a specific name.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/util/virqemu.c | 30 +++++++++++++++++++++---------
src/util/virqemu.h | 10 +++++++---
tests/qemucommandutiltest.c | 2 +-
3 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
index 78a9e0480b..0e6fa412bc 100644
--- a/src/util/virqemu.c
+++ b/src/util/virqemu.c
@@ -36,6 +36,7 @@ VIR_LOG_INIT("util.qemu");
struct virQEMUCommandLineJSONIteratorData {
const char *prefix;
virBufferPtr buf;
+ const char *skipKey;
virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc;
};
@@ -44,6 +45,7 @@ static int
virQEMUBuildCommandLineJSONRecurse(const char *key,
virJSONValuePtr value,
virBufferPtr buf,
+ const char *skipKey,
virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc,
bool nested);
@@ -52,7 +54,8 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
int
virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
virJSONValuePtr array,
- virBufferPtr buf)
+ virBufferPtr buf,
+ const char *skipKey G_GNUC_UNUSED)
{
ssize_t pos = -1;
ssize_t end;
@@ -80,7 +83,8 @@ virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
int
virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
virJSONValuePtr array,
- virBufferPtr buf)
+ virBufferPtr buf,
+ const char *skipKey)
{
virJSONValuePtr member;
size_t i;
@@ -91,7 +95,7 @@ virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
prefix = g_strdup_printf("%s.%zu", key, i);
- if (virQEMUBuildCommandLineJSONRecurse(prefix, member, buf,
+ if (virQEMUBuildCommandLineJSONRecurse(prefix, member, buf, skipKey,
virQEMUBuildCommandLineJSONArrayNumbered,
true) < 0)
return 0;
@@ -109,15 +113,20 @@ virQEMUBuildCommandLineJSONIterate(const char *key,
{
struct virQEMUCommandLineJSONIteratorData *data = opaque;
+ if (STREQ_NULLABLE(key, data->skipKey))
+ return 0;
+
if (data->prefix) {
g_autofree char *tmpkey = NULL;
tmpkey = g_strdup_printf("%s.%s", data->prefix, key);
return virQEMUBuildCommandLineJSONRecurse(tmpkey, value, data->buf,
+ data->skipKey,
data->arrayFunc, false);
} else {
return virQEMUBuildCommandLineJSONRecurse(key, value, data->buf,
+ data->skipKey,
data->arrayFunc, false);
}
}
@@ -127,10 +136,11 @@ static int
virQEMUBuildCommandLineJSONRecurse(const char *key,
virJSONValuePtr value,
virBufferPtr buf,
+ const char *skipKey,
virQEMUBuildCommandLineJSONArrayFormatFunc arrayFunc,
bool nested)
{
- struct virQEMUCommandLineJSONIteratorData data = { key, buf, arrayFunc };
+ struct virQEMUCommandLineJSONIteratorData data = { key, buf, skipKey, arrayFunc };
virJSONType type = virJSONValueGetType(value);
virJSONValuePtr elem;
bool tmp;
@@ -170,14 +180,14 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
return -1;
}
- if (!arrayFunc || arrayFunc(key, value, buf) < 0) {
+ if (!arrayFunc || arrayFunc(key, value, buf, skipKey) < 0) {
/* fallback, treat the array as a non-bitmap, adding the key
* for each member */
for (i = 0; i < virJSONValueArraySize(value); i++) {
elem = virJSONValueArrayGet((virJSONValuePtr)value, i);
/* recurse to avoid duplicating code */
- if (virQEMUBuildCommandLineJSONRecurse(key, elem, buf,
+ if (virQEMUBuildCommandLineJSONRecurse(key, elem, buf, skipKey,
arrayFunc, true) < 0)
return -1;
}
@@ -205,6 +215,7 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
* virQEMUBuildCommandLineJSON:
* @value: json object containing the value
* @buf: otuput buffer
+ * @skipKey: name of key that will be handled separately by caller
* @arrayFunc: array formatter function to allow for different syntax
*
* Formats JSON value object into command line parameters suitable for use with
@@ -215,9 +226,10 @@ virQEMUBuildCommandLineJSONRecurse(const char *key,
int
virQEMUBuildCommandLineJSON(virJSONValuePtr value,
virBufferPtr buf,
+ const char *skipKey,
virQEMUBuildCommandLineJSONArrayFormatFunc array)
{
- if (virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, array, false) < 0)
+ if (virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, skipKey, array, false) < 0)
return -1;
virBufferTrim(buf, ",");
@@ -243,7 +255,7 @@ virQEMUBuildObjectCommandlineFromJSONInternal(virBufferPtr buf,
if (props) {
virBufferAddLit(buf, ",");
- if (virQEMUBuildCommandLineJSON(props, buf,
+ if (virQEMUBuildCommandLineJSON(props, buf, NULL,
virQEMUBuildCommandLineJSONArrayBitmap) < 0)
return -1;
}
@@ -270,7 +282,7 @@ virQEMUBuildDriveCommandlineFromJSON(virJSONValuePtr srcdef)
virBuffer buf = VIR_BUFFER_INITIALIZER;
char *ret = NULL;
- if (virQEMUBuildCommandLineJSON(srcdef, &buf,
+ if (virQEMUBuildCommandLineJSON(srcdef, &buf, NULL,
virQEMUBuildCommandLineJSONArrayNumbered) < 0)
goto cleanup;
diff --git a/src/util/virqemu.h b/src/util/virqemu.h
index 227325e80e..9d3db7c2a2 100644
--- a/src/util/virqemu.h
+++ b/src/util/virqemu.h
@@ -29,16 +29,20 @@
typedef int (*virQEMUBuildCommandLineJSONArrayFormatFunc)(const char *key,
virJSONValuePtr array,
- virBufferPtr buf);
+ virBufferPtr buf,
+ const char *skipKey);
int virQEMUBuildCommandLineJSONArrayBitmap(const char *key,
virJSONValuePtr array,
- virBufferPtr buf);
+ virBufferPtr buf,
+ const char *skipKey);
int virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
virJSONValuePtr array,
- virBufferPtr buf);
+ virBufferPtr buf,
+ const char *skipKey);
int virQEMUBuildCommandLineJSON(virJSONValuePtr value,
virBufferPtr buf,
+ const char *skipKey,
virQEMUBuildCommandLineJSONArrayFormatFunc array);
int virQEMUBuildObjectCommandlineFromJSON(virBufferPtr buf,
diff --git a/tests/qemucommandutiltest.c b/tests/qemucommandutiltest.c
index c5b3e7b735..923776e642 100644
--- a/tests/qemucommandutiltest.c
+++ b/tests/qemucommandutiltest.c
@@ -47,7 +47,7 @@ testQemuCommandBuildFromJSON(const void *opaque)
return -1;
}
- if (virQEMUBuildCommandLineJSON(val, &buf, data->arrayfunc) < 0) {
+ if (virQEMUBuildCommandLineJSON(val, &buf, NULL, data->arrayfunc) < 0) {
fprintf(stderr,
"\nvirQEMUBuildCommandlineJSON failed process JSON:\n%s\n",
data->props);
--
2.23.0.windows.1

View File

@ -0,0 +1,88 @@
From 9df86be1d8d974dc6bcf174c63814cd4492ddd5e Mon Sep 17 00:00:00 2001
From: Peter Krempa <pkrempa@redhat.com>
Date: Fri, 15 May 2020 10:59:40 +0200
Subject: [PATCH 16/18] virQEMUBuildNetdevCommandlineFromJSON: Prepare for
quirky 'guestfwd'
QEMU models guestfwd as:
'guestfwd': [
{ "str": "tcp:10.0.2.1:4600-chardev:charchannel0" },
{ "str": "...."},
]
but the command line as:
guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,guestfwd=...
I guess the original idea was to make it extensible while not worrying
about adding another object for it. Either way it requires us to add yet
another JSON->cmdline convertor for arrays.
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
src/util/virqemu.c | 40 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 39 insertions(+), 1 deletion(-)
diff --git a/src/util/virqemu.c b/src/util/virqemu.c
index 0f8cab29df..9823ebc14d 100644
--- a/src/util/virqemu.c
+++ b/src/util/virqemu.c
@@ -109,6 +109,43 @@ virQEMUBuildCommandLineJSONArrayNumbered(const char *key,
}
+/**
+ * This array convertor is for quirky cases where the QMP schema mandates an
+ * array of objects with only one attribute 'str' which needs to be formatted as
+ * repeated key-value pairs without the 'str' being printed:
+ *
+ * 'guestfwd': [
+ * { "str": "tcp:10.0.2.1:4600-chardev:charchannel0" },
+ * { "str": "...."},
+ * ]
+ *
+ * guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,guestfwd=...
+ */
+static int
+virQEMUBuildCommandLineJSONArrayObjectsStr(const char *key,
+ virJSONValuePtr array,
+ virBufferPtr buf,
+ const char *skipKey G_GNUC_UNUSED,
+ bool onOff G_GNUC_UNUSED)
+{
+ g_auto(virBuffer) tmp = VIR_BUFFER_INITIALIZER;
+ size_t i;
+
+ for (i = 0; i < virJSONValueArraySize(array); i++) {
+ virJSONValuePtr member = virJSONValueArrayGet(array, i);
+ const char *str = virJSONValueObjectGetString(member, "str");
+
+ if (!str)
+ return -1;
+
+ virBufferAsprintf(&tmp, "%s=%s,", key, str);
+ }
+
+ virBufferAddBuffer(buf, &tmp);
+ return 0;
+}
+
+
/* internal iterator to handle nested object formatting */
static int
virQEMUBuildCommandLineJSONIterate(const char *key,
@@ -267,7 +304,8 @@ virQEMUBuildNetdevCommandlineFromJSON(virJSONValuePtr props)
virBufferAsprintf(&buf, "%s,", type);
- if (virQEMUBuildCommandLineJSON(props, &buf, "type", true, NULL) < 0)
+ if (virQEMUBuildCommandLineJSON(props, &buf, "type", true,
+ virQEMUBuildCommandLineJSONArrayObjectsStr) < 0)
return NULL;
return virBufferContentAndReset(&buf);
--
2.23.0.windows.1