Change extract pidfile & monitor config from QEMU command line

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
This commit is contained in:
Daniel P. Berrange 2011-06-17 15:31:02 +01:00
parent accfe952eb
commit ebbae359ff
4 changed files with 112 additions and 64 deletions

View File

@ -5530,84 +5530,80 @@ cleanup:
/* /*
* Tries to parse a QEMU serial/parallel device * Tries to parse a QEMU serial/parallel device
*/ */
static virDomainChrDefPtr static int
qemuParseCommandLineChr(const char *val) qemuParseCommandLineChr(virDomainChrSourceDefPtr source,
const char *val)
{ {
virDomainChrDefPtr def;
if (!(def = virDomainChrDefNew()))
goto error;
if (STREQ(val, "null")) { if (STREQ(val, "null")) {
def->source.type = VIR_DOMAIN_CHR_TYPE_NULL; source->type = VIR_DOMAIN_CHR_TYPE_NULL;
} else if (STREQ(val, "vc")) { } 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")) { } 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:")) { } else if (STRPREFIX(val, "file:")) {
def->source.type = VIR_DOMAIN_CHR_TYPE_FILE; source->type = VIR_DOMAIN_CHR_TYPE_FILE;
def->source.data.file.path = strdup(val+strlen("file:")); source->data.file.path = strdup(val+strlen("file:"));
if (!def->source.data.file.path) if (!source->data.file.path)
goto no_memory; goto no_memory;
} else if (STRPREFIX(val, "pipe:")) { } else if (STRPREFIX(val, "pipe:")) {
def->source.type = VIR_DOMAIN_CHR_TYPE_PIPE; source->type = VIR_DOMAIN_CHR_TYPE_PIPE;
def->source.data.file.path = strdup(val+strlen("pipe:")); source->data.file.path = strdup(val+strlen("pipe:"));
if (!def->source.data.file.path) if (!source->data.file.path)
goto no_memory; goto no_memory;
} else if (STREQ(val, "stdio")) { } 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:")) { } else if (STRPREFIX(val, "udp:")) {
const char *svc1, *host2, *svc2; const char *svc1, *host2, *svc2;
def->source.type = VIR_DOMAIN_CHR_TYPE_UDP; source->type = VIR_DOMAIN_CHR_TYPE_UDP;
val += strlen("udp:"); val += strlen("udp:");
svc1 = strchr(val, ':'); svc1 = strchr(val, ':');
host2 = svc1 ? strchr(svc1, '@') : NULL; host2 = svc1 ? strchr(svc1, '@') : NULL;
svc2 = host2 ? strchr(host2, ':') : NULL; svc2 = host2 ? strchr(host2, ':') : NULL;
if (svc1) if (svc1)
def->source.data.udp.connectHost = strndup(val, svc1-val); source->data.udp.connectHost = strndup(val, svc1-val);
else 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; goto no_memory;
if (svc1) { if (svc1) {
svc1++; svc1++;
if (host2) if (host2)
def->source.data.udp.connectService = strndup(svc1, host2-svc1); source->data.udp.connectService = strndup(svc1, host2-svc1);
else 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; goto no_memory;
} }
if (host2) { if (host2) {
host2++; host2++;
if (svc2) if (svc2)
def->source.data.udp.bindHost = strndup(host2, svc2-host2); source->data.udp.bindHost = strndup(host2, svc2-host2);
else 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; goto no_memory;
} }
if (svc2) { if (svc2) {
svc2++; svc2++;
def->source.data.udp.bindService = strdup(svc2); source->data.udp.bindService = strdup(svc2);
if (!def->source.data.udp.bindService) if (!source->data.udp.bindService)
goto no_memory; goto no_memory;
} }
} else if (STRPREFIX(val, "tcp:") || } else if (STRPREFIX(val, "tcp:") ||
STRPREFIX(val, "telnet:")) { STRPREFIX(val, "telnet:")) {
const char *opt, *svc; const char *opt, *svc;
def->source.type = VIR_DOMAIN_CHR_TYPE_TCP; source->type = VIR_DOMAIN_CHR_TYPE_TCP;
if (STRPREFIX(val, "tcp:")) { if (STRPREFIX(val, "tcp:")) {
val += strlen("tcp:"); val += strlen("tcp:");
} else { } else {
val += strlen("telnet:"); 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, ':'); svc = strchr(val, ':');
if (!svc) { if (!svc) {
@ -5617,38 +5613,38 @@ qemuParseCommandLineChr(const char *val)
} }
opt = strchr(svc, ','); opt = strchr(svc, ',');
if (opt && strstr(opt, "server")) 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); source->data.tcp.host = strndup(val, svc-val);
if (!def->source.data.tcp.host) if (!source->data.tcp.host)
goto no_memory; goto no_memory;
svc++; svc++;
if (opt) { if (opt) {
def->source.data.tcp.service = strndup(svc, opt-svc); source->data.tcp.service = strndup(svc, opt-svc);
} else { } 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; goto no_memory;
} else if (STRPREFIX(val, "unix:")) { } else if (STRPREFIX(val, "unix:")) {
const char *opt; const char *opt;
val += strlen("unix:"); val += strlen("unix:");
opt = strchr(val, ','); opt = strchr(val, ',');
def->source.type = VIR_DOMAIN_CHR_TYPE_UNIX; source->type = VIR_DOMAIN_CHR_TYPE_UNIX;
if (opt) { if (opt) {
if (strstr(opt, "listen")) if (strstr(opt, "listen"))
def->source.data.nix.listen = true; source->data.nix.listen = true;
def->source.data.nix.path = strndup(val, opt-val); source->data.nix.path = strndup(val, opt-val);
} else { } 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; goto no_memory;
} else if (STRPREFIX(val, "/dev")) { } else if (STRPREFIX(val, "/dev")) {
def->source.type = VIR_DOMAIN_CHR_TYPE_DEV; source->type = VIR_DOMAIN_CHR_TYPE_DEV;
def->source.data.file.path = strdup(val); source->data.file.path = strdup(val);
if (!def->source.data.file.path) if (!source->data.file.path)
goto no_memory; goto no_memory;
} else { } else {
qemuReportError(VIR_ERR_INTERNAL_ERROR, qemuReportError(VIR_ERR_INTERNAL_ERROR,
@ -5656,13 +5652,12 @@ qemuParseCommandLineChr(const char *val)
goto error; goto error;
} }
return def; return 0;
no_memory: no_memory:
virReportOOMError(); virReportOOMError();
error: error:
virDomainChrDefFree(def); return -1;
return NULL;
} }
@ -5839,7 +5834,10 @@ error:
*/ */
virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
const char **progenv, const char **progenv,
const char **progargv) const char **progargv,
char **pidfile,
virDomainChrSourceDefPtr *monConfig,
bool *monJSON)
{ {
virDomainDefPtr def; virDomainDefPtr def;
int i; int i;
@ -5852,6 +5850,13 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
int nvirtiodisk = 0; int nvirtiodisk = 0;
qemuDomainCmdlineDefPtr cmd = NULL; qemuDomainCmdlineDefPtr cmd = NULL;
if (pidfile)
*pidfile = NULL;
if (monConfig)
*monConfig = NULL;
if (monJSON)
*monJSON = false;
if (!progargv[0]) { if (!progargv[0]) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, qemuReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("no emulator path found")); "%s", _("no emulator path found"));
@ -6205,7 +6210,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
WANT_VALUE(); WANT_VALUE();
if (STRNEQ(val, "none")) { if (STRNEQ(val, "none")) {
virDomainChrDefPtr chr; virDomainChrDefPtr chr;
if (!(chr = qemuParseCommandLineChr(val)))
if (!(chr = virDomainChrDefNew()))
goto error;
if (qemuParseCommandLineChr(&chr->source, val) < 0)
goto error; goto error;
if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) { if (VIR_REALLOC_N(def->serials, def->nserials+1) < 0) {
virDomainChrDefFree(chr); virDomainChrDefFree(chr);
@ -6219,7 +6228,11 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
WANT_VALUE(); WANT_VALUE();
if (STRNEQ(val, "none")) { if (STRNEQ(val, "none")) {
virDomainChrDefPtr chr; virDomainChrDefPtr chr;
if (!(chr = qemuParseCommandLineChr(val)))
if (!(chr = virDomainChrDefNew()))
goto error;
if (qemuParseCommandLineChr(&chr->source, val) < 0)
goto error; goto error;
if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) { if (VIR_REALLOC_N(def->parallels, def->nparallels+1) < 0) {
virDomainChrDefFree(chr); virDomainChrDefFree(chr);
@ -6396,13 +6409,25 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
/* ignore, always added by libvirt */ /* ignore, always added by libvirt */
} else if (STREQ(arg, "-pidfile")) { } else if (STREQ(arg, "-pidfile")) {
WANT_VALUE(); WANT_VALUE();
/* ignore, used by libvirt as needed */ if (pidfile)
if (!(*pidfile = strdup(val)))
goto no_memory;
} else if (STREQ(arg, "-incoming")) { } else if (STREQ(arg, "-incoming")) {
WANT_VALUE(); WANT_VALUE();
/* ignore, used via restore/migrate APIs */ /* ignore, used via restore/migrate APIs */
} else if (STREQ(arg, "-monitor")) { } else if (STREQ(arg, "-monitor")) {
WANT_VALUE(); 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")) { } else if (STREQ(arg, "-S")) {
/* ignore, always added by libvirt */ /* ignore, always added by libvirt */
} else { } else {
@ -6543,11 +6568,6 @@ virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
VIR_FREE(nics); VIR_FREE(nics);
if (!def->name) {
if (!(def->name = strdup("unnamed")))
goto no_memory;
}
if (virDomainDefAddImplicitControllers(def) < 0) if (virDomainDefAddImplicitControllers(def) < 0)
goto error; goto error;
@ -6566,12 +6586,21 @@ error:
VIR_FREE(cmd); VIR_FREE(cmd);
virDomainDefFree(def); virDomainDefFree(def);
VIR_FREE(nics); VIR_FREE(nics);
if (monConfig) {
virDomainChrSourceDefFree(*monConfig);
*monConfig = NULL;
}
if (pidfile)
VIR_FREE(*pidfile);
return NULL; return NULL;
} }
virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps, virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
const char *args) const char *args,
char **pidfile,
virDomainChrSourceDefPtr *monConfig,
bool *monJSON)
{ {
const char **progenv = NULL; const char **progenv = NULL;
const char **progargv = NULL; const char **progargv = NULL;
@ -6581,7 +6610,8 @@ virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
if (qemuStringToArgvEnv(args, &progenv, &progargv) < 0) if (qemuStringToArgvEnv(args, &progenv, &progargv) < 0)
goto cleanup; goto cleanup;
def = qemuParseCommandLine(caps, progenv, progargv); def = qemuParseCommandLine(caps, progenv, progargv,
pidfile, monConfig, monJSON);
cleanup: cleanup:
for (i = 0 ; progargv && progargv[i] ; i++) for (i = 0 ; progargv && progargv[i] ; i++)

View File

@ -140,11 +140,21 @@ int qemuOpenVhostNet(virDomainDefPtr def,
int qemudCanonicalizeMachine(struct qemud_driver *driver, int qemudCanonicalizeMachine(struct qemud_driver *driver,
virDomainDefPtr def); virDomainDefPtr def);
/*
* NB: def->name can be NULL upon return and the caller
* *must* decide how to fill in a name in this case
*/
virDomainDefPtr qemuParseCommandLine(virCapsPtr caps, virDomainDefPtr qemuParseCommandLine(virCapsPtr caps,
const char **progenv, const char **progenv,
const char **progargv); const char **progargv,
char **pidfile,
virDomainChrSourceDefPtr *monConfig,
bool *monJSON);
virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps, virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
const char *args); const char *args,
char **pidfile,
virDomainChrSourceDefPtr *monConfig,
bool *monJSON);
int qemuDomainAssignPCIAddresses(virDomainDefPtr def); int qemuDomainAssignPCIAddresses(virDomainDefPtr def);
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def); qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);

View File

@ -3899,11 +3899,18 @@ static char *qemuDomainXMLFromNative(virConnectPtr conn,
} }
qemuDriverLock(driver); qemuDriverLock(driver);
def = qemuParseCommandLineString(driver->caps, config); def = qemuParseCommandLineString(driver->caps, config,
NULL, NULL, NULL);
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
if (!def) if (!def)
goto cleanup; goto cleanup;
if (!def->name &&
!(def->name = strdup("unnamed"))) {
virReportOOMError();
goto cleanup;
}
xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE); xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);
cleanup: cleanup:

View File

@ -45,7 +45,8 @@ static int testCompareXMLToArgvFiles(const char *xml,
if (virtTestLoadFile(xml, &expectxml) < 0) if (virtTestLoadFile(xml, &expectxml) < 0)
goto fail; goto fail;
if (!(vmdef = qemuParseCommandLineString(driver.caps, cmd))) if (!(vmdef = qemuParseCommandLineString(driver.caps, cmd,
NULL, NULL, NULL)))
goto fail; goto fail;
if ((log = virtTestLogContentAndReset()) == NULL) if ((log = virtTestLogContentAndReset()) == NULL)