The function being introduced is responsible for preparing and
executing 'chardev-add' qemu monitor command. Moreover, in case
of PTY chardev, the corresponding pty path is updated.
---
src/qemu/qemu_monitor.c | 21 +++++
src/qemu/qemu_monitor.h | 3 +
src/qemu/qemu_monitor_json.c | 191 +++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_monitor_json.h | 3 +
4 files changed, 218 insertions(+)
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 4deb2d6..1025e50 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -3570,3 +3570,24 @@ int qemuMonitorGetTPMTypes(qemuMonitorPtr mon,
return qemuMonitorJSONGetTPMTypes(mon, tpmtypes);
}
+
+int qemuMonitorAttachCharDev(qemuMonitorPtr mon,
+ const char *chrID,
+ virDomainChrSourceDefPtr chr)
+{
+ VIR_DEBUG("mon=%p chrID=%s chr=%p", mon, chrID, chr);
+
+ if (!mon) {
+ virReportError(VIR_ERR_INVALID_ARG, "%s",
+ _("monitor must not be NULL"));
+ return -1;
+ }
+
+ if (!mon->json) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("JSON monitor is required"));
+ return -1;
+ }
+
+ return qemuMonitorJSONAttachCharDev(mon, chrID, chr);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index f39f009..77de325 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -689,6 +689,9 @@ int qemuMonitorGetTPMModels(qemuMonitorPtr mon,
int qemuMonitorGetTPMTypes(qemuMonitorPtr mon,
char ***tpmtypes);
+int qemuMonitorAttachCharDev(qemuMonitorPtr mon,
+ const char *chrID,
+ virDomainChrSourceDefPtr chr);
/**
* When running two dd process and using <> redirection, we need a
* shell that will not truncate files. These two strings serve that
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 5544a66..d944d01 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -4678,6 +4678,30 @@ error:
return NULL;
}
+static virJSONValuePtr
+qemuMonitorJSONBuildUnixSocketAddress(const char *path)
+{
+ virJSONValuePtr addr = NULL;
+ virJSONValuePtr data = NULL;
+
+ if (!(data = virJSONValueNewObject()) ||
+ !(addr = virJSONValueNewObject()))
+ goto error;
+
+ /* port is really expected as a string here by qemu */
+ if (virJSONValueObjectAppendString(data, "path", path) < 0 ||
+ virJSONValueObjectAppendString(addr, "type", "unix") < 0
||
+ virJSONValueObjectAppend(addr, "data", data) < 0)
+ goto error;
+
+ return addr;
+error:
+ virReportOOMError();
+ virJSONValueFree(data);
+ virJSONValueFree(addr);
+ return NULL;
+}
+
int
qemuMonitorJSONNBDServerStart(qemuMonitorPtr mon,
const char *host,
@@ -4859,3 +4883,170 @@ int qemuMonitorJSONGetTPMTypes(qemuMonitorPtr mon,
{
return qemuMonitorJSONGetStringArray(mon, "query-tpm-types", tpmtypes);
}
+
+static virJSONValuePtr
+qemuMonitorJSONAttachCharDevCommand(const char *chrID,
+ const virDomainChrSourceDefPtr chr)
+{
+ virJSONValuePtr ret;
+ virJSONValuePtr backend;
+ virJSONValuePtr data = NULL;
+ virJSONValuePtr addr = NULL;
+ const char *backend_type;
+ bool telnet;
+
+ if (!(backend = virJSONValueNewObject()) ||
+ !(data = virJSONValueNewObject())) {
+ goto no_memory;
+ }
+
+ switch ((enum virDomainChrType) chr->type) {
+ case VIR_DOMAIN_CHR_TYPE_NULL:
+ case VIR_DOMAIN_CHR_TYPE_VC:
+ backend_type = "null";
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_PTY:
+ backend_type = "pty";
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_FILE:
+ backend_type = "file";
+ if (virJSONValueObjectAppendString(data, "out", chr->data.file.path)
< 0)
+ goto no_memory;
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_DEV:
+ backend_type = STRPREFIX(chrID, "parallel") ? "parallel" :
"serial";
+ if (virJSONValueObjectAppendString(data, "device",
+ chr->data.file.path) < 0)
+ goto no_memory;
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_TCP:
+ backend_type = "socket";
+ addr = qemuMonitorJSONBuildInetSocketAddress(chr->data.tcp.host,
+ chr->data.tcp.service);
+ if (!addr ||
+ virJSONValueObjectAppend(data, "addr", addr) < 0)
+ goto no_memory;
+ addr = NULL;
+
+ telnet = chr->data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
+
+ if (virJSONValueObjectAppendBoolean(data, "wait", false) < 0 ||
+ virJSONValueObjectAppendBoolean(data, "telnet", telnet) < 0 ||
+ virJSONValueObjectAppendBoolean(data, "server",
chr->data.tcp.listen) < 0)
+ goto no_memory;
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UDP:
+ backend_type = "socket";
+ addr = qemuMonitorJSONBuildInetSocketAddress(chr->data.udp.connectHost,
+ chr->data.udp.connectService);
+ if (!addr ||
+ virJSONValueObjectAppend(data, "addr", addr) < 0)
+ goto no_memory;
+ addr = NULL;
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_UNIX:
+ backend_type = "socket";
+ addr = qemuMonitorJSONBuildUnixSocketAddress(chr->data.nix.path);
+
+ if (!addr ||
+ virJSONValueObjectAppend(data, "addr", addr) < 0)
+ goto no_memory;
+ addr = NULL;
+
+ if (virJSONValueObjectAppendBoolean(data, "wait", false) < 0 ||
+ virJSONValueObjectAppendBoolean(data, "server",
chr->data.nix.listen) < 0)
+ goto no_memory;
+ break;
+
+ case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
+ case VIR_DOMAIN_CHR_TYPE_PIPE:
+ case VIR_DOMAIN_CHR_TYPE_STDIO:
+ case VIR_DOMAIN_CHR_TYPE_LAST:
+ default:
+ virReportError(VIR_ERR_OPERATION_FAILED,
+ _("Unsupported char device type '%d'"),
+ chr->type);
+ goto error;
+ }
+
+ if (virJSONValueObjectAppendString(backend, "type", backend_type) < 0
||
+ virJSONValueObjectAppend(backend, "data", data) < 0)
+ goto no_memory;
+ data = NULL;
+
+ if (!(ret = qemuMonitorJSONMakeCommand("chardev-add",
+ "s:id", chrID,
+ "a:backend", backend,
+ NULL)))
+ goto error;
+
+ return ret;
+
+no_memory:
+ virReportOOMError();
+error:
+ virJSONValueFree(addr);
+ virJSONValueFree(data);
+ virJSONValueFree(backend);
+ return NULL;
+}
+
+static int
+qemuMonitorJSONAttachCharDevInfo(virJSONValuePtr reply,
+ virDomainChrSourceDefPtr chr)
+{
+ virJSONValuePtr data;
+ const char *path;
+
+ if (chr->type != VIR_DOMAIN_CHR_TYPE_PTY)
+ return 0;
+
+ if (!(data = virJSONValueObjectGet(reply, "return"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("chardev-add reply was missing return data"));
+ return -1;
+ }
+
+ if (!(path = virJSONValueObjectGetString(data, "pty"))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("chardev-add reply was missing pty path"));
+ return -1;
+ }
+
+ if (!(chr->data.file.path = strdup(path))) {
+ virReportOOMError();
+ return -1;
+ }
+ return 0;
+}
+
+int
+qemuMonitorJSONAttachCharDev(qemuMonitorPtr mon,
+ const char *chrID,
+ virDomainChrSourceDefPtr chr)
+{
+ int ret = -1;
+ virJSONValuePtr cmd;
+ virJSONValuePtr reply = NULL;
+
+ if (!(cmd = qemuMonitorJSONAttachCharDevCommand(chrID, chr)))
+ return ret;
+
+ ret = qemuMonitorJSONCommand(mon, cmd, &reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONCheckError(cmd, reply);
+
+ if (ret == 0)
+ ret = qemuMonitorJSONAttachCharDevInfo(reply, chr);
+
+ virJSONValueFree(cmd);
+ virJSONValueFree(reply);
+ return ret;
+}
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 5ee0d84..8996e02 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -349,4 +349,7 @@ int qemuMonitorJSONGetTPMTypes(qemuMonitorPtr mon,
char ***tpmtypes)
ATTRIBUTE_NONNULL(2);
+int qemuMonitorJSONAttachCharDev(qemuMonitorPtr mon,
+ const char *chrID,
+ virDomainChrSourceDefPtr chr);
#endif /* QEMU_MONITOR_JSON_H */
--
1.8.1.5