When converting QEMU argv into a virDomainDefPtr, also extract
the pidfile, monitor character device config and the monitor
mode.
* src/qemu/qemu_command.c, src/qemu/qemu_command.h: Extract
pidfile & monitor config from QEMU argv
* src/qemu/qemu_driver.c, tests/qemuargv2xmltest.c: Add extra
params when calling qemuParseCommandLineString
---
src/qemu/qemu_command.c | 150 +++++++++++++++++++++++++++------------------
src/qemu/qemu_command.h | 10 +++-
src/qemu/qemu_driver.c | 9 +++-
tests/qemuargv2xmltest.c | 3 +-
4 files changed, 108 insertions(+), 64 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 6e4480e..e711f0e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5510,84 +5510,80 @@ cleanup:
/*
* Tries to parse a QEMU serial/parallel device
*/
-static virDomainChrDefPtr
-qemuParseCommandLineChr(const char *val)
+static int
+qemuParseCommandLineChr(virDomainChrSourceDefPtr source,
+ const char *val)
{
- virDomainChrDefPtr def;
-
- if (!(def = virDomainChrDefNew()))
- goto error;
-
if (STREQ(val, "null")) {
- def->source.type = VIR_DOMAIN_CHR_TYPE_NULL;
+ source->type = VIR_DOMAIN_CHR_TYPE_NULL;
} else if (STREQ(val, "vc")) {
- def->source.type = VIR_DOMAIN_CHR_TYPE_VC;
+ source->type = VIR_DOMAIN_CHR_TYPE_VC;
} else if (STREQ(val, "pty")) {
- def->source.type = VIR_DOMAIN_CHR_TYPE_PTY;
+ source->type = VIR_DOMAIN_CHR_TYPE_PTY;
} else if (STRPREFIX(val, "file:")) {
- def->source.type = VIR_DOMAIN_CHR_TYPE_FILE;
- def->source.data.file.path = strdup(val+strlen("file:"));
- if (!def->source.data.file.path)
+ source->type = VIR_DOMAIN_CHR_TYPE_FILE;
+ source->data.file.path = strdup(val+strlen("file:"));
+ if (!source->data.file.path)
goto no_memory;
} else if (STRPREFIX(val, "pipe:")) {
- def->source.type = VIR_DOMAIN_CHR_TYPE_PIPE;
- def->source.data.file.path = strdup(val+strlen("pipe:"));
- if (!def->source.data.file.path)
+ source->type = VIR_DOMAIN_CHR_TYPE_PIPE;
+ source->data.file.path = strdup(val+strlen("pipe:"));
+ if (!source->data.file.path)
goto no_memory;
} else if (STREQ(val, "stdio")) {
- def->source.type = VIR_DOMAIN_CHR_TYPE_STDIO;
+ source->type = VIR_DOMAIN_CHR_TYPE_STDIO;
} else if (STRPREFIX(val, "udp:")) {
const char *svc1, *host2, *svc2;
- def->source.type = VIR_DOMAIN_CHR_TYPE_UDP;
+ source->type = VIR_DOMAIN_CHR_TYPE_UDP;
val += strlen("udp:");
svc1 = strchr(val, ':');
host2 = svc1 ? strchr(svc1, '@') : NULL;
svc2 = host2 ? strchr(host2, ':') : NULL;
if (svc1)
- def->source.data.udp.connectHost = strndup(val, svc1-val);
+ source->data.udp.connectHost = strndup(val, svc1-val);
else
- def->source.data.udp.connectHost = strdup(val);
+ source->data.udp.connectHost = strdup(val);
- if (!def->source.data.udp.connectHost)
+ if (!source->data.udp.connectHost)
goto no_memory;
if (svc1) {
svc1++;
if (host2)
- def->source.data.udp.connectService = strndup(svc1, host2-svc1);
+ source->data.udp.connectService = strndup(svc1, host2-svc1);
else
- def->source.data.udp.connectService = strdup(svc1);
+ source->data.udp.connectService = strdup(svc1);
- if (!def->source.data.udp.connectService)
+ if (!source->data.udp.connectService)
goto no_memory;
}
if (host2) {
host2++;
if (svc2)
- def->source.data.udp.bindHost = strndup(host2, svc2-host2);
+ source->data.udp.bindHost = strndup(host2, svc2-host2);
else
- def->source.data.udp.bindHost = strdup(host2);
+ source->data.udp.bindHost = strdup(host2);
- if (!def->source.data.udp.bindHost)
+ if (!source->data.udp.bindHost)
goto no_memory;
}
if (svc2) {
svc2++;
- def->source.data.udp.bindService = strdup(svc2);
- if (!def->source.data.udp.bindService)
+ source->data.udp.bindService = strdup(svc2);
+ if (!source->data.udp.bindService)
goto no_memory;
}
} else if (STRPREFIX(val, "tcp:") ||
STRPREFIX(val, "telnet:")) {
const char *opt, *svc;
- def->source.type = VIR_DOMAIN_CHR_TYPE_TCP;
+ source->type = VIR_DOMAIN_CHR_TYPE_TCP;
if (STRPREFIX(val, "tcp:")) {
val += strlen("tcp:");
} else {
val += strlen("telnet:");
- def->source.data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
+ source->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
}
svc = strchr(val, ':');
if (!svc) {
@@ -5597,38 +5593,38 @@ qemuParseCommandLineChr(const char *val)
}
opt = strchr(svc, ',');
if (opt && strstr(opt, "server"))
- def->source.data.tcp.listen = true;
+ source->data.tcp.listen = true;
- def->source.data.tcp.host = strndup(val, svc-val);
- if (!def->source.data.tcp.host)
+ source->data.tcp.host = strndup(val, svc-val);
+ if (!source->data.tcp.host)
goto no_memory;
svc++;
if (opt) {
- def->source.data.tcp.service = strndup(svc, opt-svc);
+ source->data.tcp.service = strndup(svc, opt-svc);
} else {
- def->source.data.tcp.service = strdup(svc);
+ source->data.tcp.service = strdup(svc);
}
- if (!def->source.data.tcp.service)
+ if (!source->data.tcp.service)
goto no_memory;
} else if (STRPREFIX(val, "unix:")) {
const char *opt;
val += strlen("unix:");
opt = strchr(val, ',');
- def->source.type = VIR_DOMAIN_CHR_TYPE_UNIX;
+ source->type = VIR_DOMAIN_CHR_TYPE_UNIX;
if (opt) {
if (strstr(opt, "listen"))
- def->source.data.nix.listen = true;
- def->source.data.nix.path = strndup(val, opt-val);
+ source->data.nix.listen = true;
+ source->data.nix.path = strndup(val, opt-val);
} else {
- def->source.data.nix.path = strdup(val);
+ source->data.nix.path = strdup(val);
}
- if (!def->source.data.nix.path)
+ if (!source->data.nix.path)
goto no_memory;
} else if (STRPREFIX(val, "/dev")) {
- def->source.type = VIR_DOMAIN_CHR_TYPE_DEV;
- def->source.data.file.path = strdup(val);
- if (!def->source.data.file.path)
+ source->type = VIR_DOMAIN_CHR_TYPE_DEV;
+ source->data.file.path = strdup(val);
+ if (!source->data.file.path)
goto no_memory;
} else {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
@@ -5636,13 +5632,12 @@ qemuParseCommandLineChr(const char *val)
goto error;
}
- return def;
+ return 0;
no_memory:
virReportOOMError();
error:
- virDomainChrDefFree(def);
- return NULL;
+ return -1;
}
@@ -5816,7 +5811,10 @@ error:
*/
virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
const char **progenv,
- const char **progargv)
+ const char **progargv,
+ char **pidfile,
+ virDomainChrSourceDefPtr *monConfig,
+ bool *monJSON)
{
virDomainDefPtr def;
int i;
@@ -5829,6 +5827,13 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
int nvirtiodisk = 0;
qemuDomainCmdlineDefPtr cmd = NULL;
+ if (pidfile)
+ *pidfile = NULL;
+ if (monConfig)
+ *monConfig = NULL;
+ if (monJSON)
+ *monJSON = false;
+
if (!progargv[0]) {
qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("no emulator path found"));
@@ -6185,7 +6190,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
WANT_VALUE();
if (STRNEQ(val, "none")) {
virDomainChrDefPtr chr;
- if (!(chr = qemuParseCommandLineChr(val)))
+
+ if (!(chr = virDomainChrDefNew()))
+ goto error;
+
+ if (qemuParseCommandLineChr(&chr->source, val) < 0)
goto error;
if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
virDomainChrDefFree(chr);
@@ -6199,7 +6208,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
WANT_VALUE();
if (STRNEQ(val, "none")) {
virDomainChrDefPtr chr;
- if (!(chr = qemuParseCommandLineChr(val)))
+
+ if (!(chr = virDomainChrDefNew()))
+ goto error;
+
+ if (qemuParseCommandLineChr(&chr->source, val) < 0)
goto error;
if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
virDomainChrDefFree(chr);
@@ -6376,13 +6389,25 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
/* ignore, always added by libvirt */
} else if (STREQ(arg, "-pidfile")) {
WANT_VALUE();
- /* ignore, used by libvirt as needed */
+ if (pidfile)
+ if (!(*pidfile = strdup(val)))
+ goto no_memory;
} else if (STREQ(arg, "-incoming")) {
WANT_VALUE();
/* ignore, used via restore/migrate APIs */
} else if (STREQ(arg, "-monitor")) {
WANT_VALUE();
- /* ignore, used internally by libvirt */
+ if (monConfig) {
+ virDomainChrSourceDefPtr chr;
+
+ if (VIR_ALLOC(chr) < 0)
+ goto no_memory;
+
+ if (qemuParseCommandLineChr(chr, val) < 0)
+ goto error;
+
+ *monConfig = chr;
+ }
} else if (STREQ(arg, "-S")) {
/* ignore, always added by libvirt */
} else {
@@ -6523,11 +6548,6 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
VIR_FREE(nics);
- if (!def->name) {
- if (!(def->name = strdup("unnamed")))
- goto no_memory;
- }
-
if (virDomainDefAddImplicitControllers(def) < 0)
goto error;
@@ -6546,12 +6566,21 @@ error:
VIR_FREE(cmd);
virDomainDefFree(def);
VIR_FREE(nics);
+ if (monConfig) {
+ virDomainChrSourceDefFree(*monConfig);
+ *monConfig = NULL;
+ }
+ if (pidfile)
+ VIR_FREE(*pidfile);
return NULL;
}
virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
- const char *args)
+ const char *args,
+ char **pidfile,
+ virDomainChrSourceDefPtr *monConfig,
+ bool *monJSON)
{
const char **progenv = NULL;
const char **progargv = NULL;
@@ -6561,7 +6590,8 @@ virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
if (qemuStringToArgvEnv(args, &progenv, &progargv) < 0)
goto cleanup;
- def = qemuParseCommandLine(caps, progenv, progargv);
+ def = qemuParseCommandLine(caps, progenv, progargv,
+ pidfile, monConfig, monJSON);
cleanup:
for (i = 0 ; progargv && progargv[i] ; i++)
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 96ec669..89502b7 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -142,9 +142,15 @@ int qemudCanonicalizeMachine(struct qemud_driver *driver,
virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
const char **progenv,
- const char **progargv);
+ const char **progargv,
+ char **pidfile,
+ virDomainChrSourceDefPtr *monConfig,
+ bool *monJSON);
virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
- const char *args);
+ const char *args,
+ char **pidfile,
+ virDomainChrSourceDefPtr *monConfig,
+ bool *monJSON);
int qemuDomainAssignPCIAddresses(virDomainDefPtr def);
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 363a361..9486594 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -3887,11 +3887,18 @@ static char *qemuDomainXMLFromNative(virConnectPtr conn,
}
qemuDriverLock(driver);
- def = qemuParseCommandLineString(driver->caps, config);
+ def = qemuParseCommandLineString(driver->caps, config,
+ NULL, NULL, NULL);
qemuDriverUnlock(driver);
if (!def)
goto cleanup;
+ if (!def->name &&
+ !(def->name = strdup("unnamed"))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
cleanup:
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index db68b60..bade95d 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -45,7 +45,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
if (virtTestLoadFile(xml, &expectxml) < 0)
goto fail;
- if (!(vmdef = qemuParseCommandLineString(driver.caps, cmd)))
+ if (!(vmdef = qemuParseCommandLineString(driver.caps, cmd,
+ NULL, NULL, NULL)))
goto fail;
if ((log = virtTestLogContentAndReset()) == NULL)
--
1.7.4.4