提交 4a51447a 编写于 作者: M Michal Privoznik

qemu_monitor: Introduce qemuMonitorAttachCharDev

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.
上级 41e826d5
......@@ -3622,3 +3622,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);
}
......@@ -701,6 +701,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
......
......@@ -4766,6 +4766,29 @@ error:
return NULL;
}
static virJSONValuePtr
qemuMonitorJSONBuildUnixSocketAddress(const char *path)
{
virJSONValuePtr addr = NULL;
virJSONValuePtr data = NULL;
if (!(data = virJSONValueNewObject()) ||
!(addr = virJSONValueNewObject()))
goto error;
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,
......@@ -4941,3 +4964,162 @@ 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 = NULL;
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:
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;
}
int
qemuMonitorJSONAttachCharDev(qemuMonitorPtr mon,
const char *chrID,
virDomainChrSourceDefPtr chr)
{
int ret = -1;
virJSONValuePtr cmd;
virJSONValuePtr reply = NULL;
if (!(cmd = qemuMonitorJSONAttachCharDevCommand(chrID, chr)))
return ret;
if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
goto cleanup;
if (qemuMonitorJSONCheckError(cmd, reply) < 0)
goto cleanup;
if (chr->type == VIR_DOMAIN_CHR_TYPE_PTY) {
virJSONValuePtr data;
const char *path;
if (!(data = virJSONValueObjectGet(reply, "return"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("chardev-add reply was missing return data"));
goto cleanup;
}
if (!(path = virJSONValueObjectGetString(data, "pty"))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("chardev-add reply was missing pty path"));
goto cleanup;
}
if (VIR_STRDUP(chr->data.file.path, path) < 0)
goto cleanup;
}
ret = 0;
cleanup:
virJSONValueFree(cmd);
virJSONValueFree(reply);
return ret;
}
......@@ -353,4 +353,7 @@ int qemuMonitorJSONGetTPMTypes(qemuMonitorPtr mon,
char ***tpmtypes)
ATTRIBUTE_NONNULL(2);
int qemuMonitorJSONAttachCharDev(qemuMonitorPtr mon,
const char *chrID,
virDomainChrSourceDefPtr chr);
#endif /* QEMU_MONITOR_JSON_H */
......@@ -594,6 +594,86 @@ cleanup:
return ret;
}
static int
testQemuMonitorJSONAttachChardev(const void *data)
{
const virDomainXMLOptionPtr xmlopt = (virDomainXMLOptionPtr)data;
qemuMonitorTestPtr test = qemuMonitorTestNew(true, xmlopt);
virDomainChrSourceDef chr;
int ret = 0;
if (!test)
return -1;
#define DO_CHECK(chrID, reply, fail) \
if (qemuMonitorTestAddItem(test, "chardev-add", reply) < 0) \
goto cleanup; \
if (qemuMonitorAttachCharDev(qemuMonitorTestGetMonitor(test), \
chrID, &chr) < 0) \
ret = fail ? ret : -1; \
else \
ret = fail ? -1 : ret; \
#define CHECK(chrID, reply) \
DO_CHECK(chrID, reply, false)
#define CHECK_FAIL(chrID, reply) \
DO_CHECK(chrID, reply, true)
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_NULL };
CHECK("chr_null", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type =VIR_DOMAIN_CHR_TYPE_VC };
CHECK("chr_vc", "{\"return\": {}}");
#define PTY_PATH "/dev/ttyS0"
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PTY };
CHECK("chr_pty", "{\"return\": {\"pty\" : \"" PTY_PATH "\"}}");
if (STRNEQ_NULLABLE(PTY_PATH, chr.data.file.path)) {
VIR_FREE(chr.data.file.path);
virReportError(VIR_ERR_INTERNAL_ERROR,
"expected PTY path: %s got: %s",
PTY_PATH, NULLSTR(chr.data.file.path));
ret = -1;
}
VIR_FREE(chr.data.file.path);
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PTY };
CHECK_FAIL("chr_pty_fail", "{\"return\": {}}");
#undef PTY_PATH
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_FILE };
CHECK("chr_file", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_DEV };
CHECK("chr_dev", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_TCP };
CHECK("chr_tcp", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_UDP };
CHECK("chr_udp", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_UNIX };
CHECK("chr_unix", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_SPICEVMC };
CHECK_FAIL("chr_spicevmc", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_PIPE };
CHECK_FAIL("chr_pipe", "{\"return\": {}}");
chr = (virDomainChrSourceDef) { .type = VIR_DOMAIN_CHR_TYPE_STDIO };
CHECK_FAIL("chr_stdio", "{\"return\": {}}");
#undef CHECK
#undef CHECK_FAIL
#undef DO_CHECK
cleanup:
qemuMonitorTestFree(test);
return ret;
}
static int
mymain(void)
......@@ -623,6 +703,7 @@ mymain(void)
DO_TEST(GetCommands);
DO_TEST(GetTPMModels);
DO_TEST(GetCommandLineOptionParameters);
DO_TEST(AttachChardev);
virObjectUnref(xmlopt);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册