代码拉取完成,页面将自动刷新
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
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。