It's now unused and utterly obsolete. Signed-off-by: Peter Krempa <pkrempa@xxxxxxxxxx> --- src/qemu/qemu_parse_command.c | 2622 +-------------------------------- src/qemu/qemu_parse_command.h | 14 - 2 files changed, 1 insertion(+), 2635 deletions(-) diff --git a/src/qemu/qemu_parse_command.c b/src/qemu/qemu_parse_command.c index b522882c78..b49aa92fb3 100644 --- a/src/qemu/qemu_parse_command.c +++ b/src/qemu/qemu_parse_command.c @@ -21,363 +21,17 @@ #include <config.h> -#include "qemu_command.h" #include "qemu_parse_command.h" -#include "dirname.h" #include "viralloc.h" #include "virlog.h" -#include "virsecret.h" #include "virstring.h" -#include "c-ctype.h" +#include "virerror.h" #define VIR_FROM_THIS VIR_FROM_QEMU VIR_LOG_INIT("qemu.qemu_parse_command"); -static int -qemuParseRBDString(virDomainDiskDefPtr disk) -{ - char *source = disk->src->path; - int ret; - - disk->src->path = NULL; - - ret = virStorageSourceParseRBDColonString(source, disk->src); - - VIR_FREE(source); - return ret; -} - - -static int -qemuParseDriveURIString(virDomainDiskDefPtr def, virURIPtr uri, - const char *scheme) -{ - int ret = -1; - char *transp = NULL; - char *sock = NULL; - char *volimg = NULL; - char *secret = NULL; - VIR_AUTOPTR(virStorageAuthDef) authdef = NULL; - - if (VIR_ALLOC(def->src->hosts) < 0) - goto error; - - transp = strchr(uri->scheme, '+'); - if (transp) - *transp++ = 0; - - if (STRNEQ(uri->scheme, scheme)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid transport/scheme '%s'"), uri->scheme); - goto error; - } - - if (!transp) { - def->src->hosts->transport = VIR_STORAGE_NET_HOST_TRANS_TCP; - } else { - def->src->hosts->transport = virStorageNetHostTransportTypeFromString(transp); - if (def->src->hosts->transport < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid %s transport type '%s'"), scheme, transp); - goto error; - } - } - def->src->nhosts = 0; /* set to 1 once everything succeeds */ - - if (def->src->hosts->transport != VIR_STORAGE_NET_HOST_TRANS_UNIX) { - if (VIR_STRDUP(def->src->hosts->name, uri->server) < 0) - goto error; - - def->src->hosts->port = uri->port; - } else { - def->src->hosts->name = NULL; - def->src->hosts->port = 0; - if (uri->query) { - if (STRPREFIX(uri->query, "socket=")) { - sock = strchr(uri->query, '=') + 1; - if (VIR_STRDUP(def->src->hosts->socket, sock) < 0) - goto error; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid query parameter '%s'"), uri->query); - goto error; - } - } - } - if (uri->path) { - volimg = uri->path + 1; /* skip the prefix slash */ - VIR_FREE(def->src->path); - if (VIR_STRDUP(def->src->path, volimg) < 0) - goto error; - } else { - VIR_FREE(def->src->path); - } - - if (uri->user) { - const char *secrettype; - /* formulate authdef for disk->src->auth */ - if (VIR_ALLOC(authdef) < 0) - goto error; - - secret = strchr(uri->user, ':'); - if (secret) - *secret = '\0'; - - if (VIR_STRDUP(authdef->username, uri->user) < 0) - goto error; - if (STREQ(scheme, "iscsi")) { - secrettype = - virSecretUsageTypeToString(VIR_SECRET_USAGE_TYPE_ISCSI); - if (VIR_STRDUP(authdef->secrettype, secrettype) < 0) - goto error; - } - VIR_STEAL_PTR(def->src->auth, authdef); - - /* Cannot formulate a secretType (eg, usage or uuid) given - * what is provided. - */ - } - - def->src->nhosts = 1; - ret = 0; - - cleanup: - virURIFree(uri); - - return ret; - - error: - virStorageNetHostDefClear(def->src->hosts); - VIR_FREE(def->src->hosts); - goto cleanup; -} - -static int -qemuParseGlusterString(virDomainDiskDefPtr def) -{ - virURIPtr uri = NULL; - - if (!(uri = virURIParse(def->src->path))) - return -1; - - return qemuParseDriveURIString(def, uri, "gluster"); -} - -static int -qemuParseISCSIString(virDomainDiskDefPtr def) -{ - virURIPtr uri = NULL; - char *slash; - unsigned lun; - - if (!(uri = virURIParse(def->src->path))) - return -1; - - if (uri->path && - (slash = strchr(uri->path + 1, '/')) != NULL) { - - if (slash[1] == '\0') { - *slash = '\0'; - } else if (virStrToLong_ui(slash + 1, NULL, 10, &lun) == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid name '%s' for iSCSI disk"), - def->src->path); - virURIFree(uri); - return -1; - } - } - - return qemuParseDriveURIString(def, uri, "iscsi"); -} - -static int -qemuParseNBDString(virDomainDiskDefPtr disk) -{ - virStorageNetHostDefPtr h = NULL; - char *host, *port; - char *src; - - virURIPtr uri = NULL; - - if (strstr(disk->src->path, "://")) { - if (!(uri = virURIParse(disk->src->path))) - return -1; - return qemuParseDriveURIString(disk, uri, "nbd"); - } - - if (VIR_ALLOC(h) < 0) - goto error; - - host = disk->src->path + strlen("nbd:"); - if (STRPREFIX(host, "unix:/")) { - src = strchr(host + strlen("unix:"), ':'); - if (src) - *src++ = '\0'; - - h->transport = VIR_STORAGE_NET_HOST_TRANS_UNIX; - if (VIR_STRDUP(h->socket, host + strlen("unix:")) < 0) - goto error; - } else { - port = strchr(host, ':'); - if (!port) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse nbd filename '%s'"), disk->src->path); - goto error; - } - - *port++ = '\0'; - if (VIR_STRDUP(h->name, host) < 0) - goto error; - - src = strchr(port, ':'); - if (src) - *src++ = '\0'; - - if (virStringParsePort(port, &h->port) < 0) - goto error; - } - - if (src && STRPREFIX(src, "exportname=")) { - if (VIR_STRDUP(src, strchr(src, '=') + 1) < 0) - goto error; - } else { - src = NULL; - } - - VIR_FREE(disk->src->path); - disk->src->path = src; - disk->src->nhosts = 1; - disk->src->hosts = h; - return 0; - - error: - virStorageNetHostDefClear(h); - VIR_FREE(h); - return -1; -} - - -/* - * This method takes a string representing a QEMU command line ARGV set - * optionally prefixed by a list of environment variables. It then tries - * to split it up into a NULL terminated list of env & argv, splitting - * on space - */ -static int qemuStringToArgvEnv(const char *args, - char ***retenv, - char ***retargv) -{ - char **arglist = NULL; - size_t argcount = 0; - size_t argalloc = 0; - size_t envend; - size_t i; - const char *curr = args; - const char *start; - char **progenv = NULL; - char **progargv = NULL; - - /* Iterate over string, splitting on sequences of ' ' */ - while (curr && *curr != '\0') { - char *arg; - const char *next; - - start = curr; - /* accept a space in CEPH_ARGS */ - if (STRPREFIX(curr, "CEPH_ARGS=-m ")) - start += strlen("CEPH_ARGS=-m "); - if (*start == '\'') { - if (start == curr) - curr++; - next = strchr(start + 1, '\''); - } else if (*start == '"') { - if (start == curr) - curr++; - next = strchr(start + 1, '"'); - } else { - next = strchr(start, ' '); - } - if (!next) - next = strchr(curr, '\n'); - - if (VIR_STRNDUP(arg, curr, next ? next - curr : -1) < 0) - goto error; - - if (next && (*next == '\'' || *next == '"')) - next++; - - if (VIR_RESIZE_N(arglist, argalloc, argcount, 2) < 0) { - VIR_FREE(arg); - goto error; - } - - arglist[argcount++] = arg; - arglist[argcount] = NULL; - - while (next && c_isspace(*next)) - next++; - - curr = next; - } - - /* Iterate over list of args, finding first arg not containing - * the '=' character (eg, skip over env vars FOO=bar) */ - for (envend = 0; ((envend < argcount) && - (strchr(arglist[envend], '=') != NULL)); - envend++) - ; /* nada */ - - /* Copy the list of env vars */ - if (envend > 0) { - if (VIR_REALLOC_N(progenv, envend+1) < 0) - goto error; - for (i = 0; i < envend; i++) - progenv[i] = arglist[i]; - progenv[i] = NULL; - } - - /* Copy the list of argv */ - if (VIR_REALLOC_N(progargv, argcount-envend + 1) < 0) - goto error; - for (i = envend; i < argcount; i++) - progargv[i-envend] = arglist[i]; - progargv[i-envend] = NULL; - - VIR_FREE(arglist); - - *retenv = progenv; - *retargv = progargv; - - return 0; - - error: - VIR_FREE(progenv); - VIR_FREE(progargv); - virStringListFree(arglist); - return -1; -} - - -/* - * Search for a named env variable, and return the value part - */ -static const char *qemuFindEnv(char **progenv, - const char *name) -{ - size_t i; - int len = strlen(name); - - for (i = 0; progenv && progenv[i]; i++) { - if (STREQLEN(progenv[i], name, len) && - progenv[i][len] == '=') - return progenv[i] + len + 1; - } - return NULL; -} - - void qemuParseKeywordsFree(int nkeywords, char **keywords, @@ -493,2277 +147,3 @@ qemuParseKeywords(const char *str, qemuParseKeywordsFree(keywordCount, keywords, values); return -1; } - - -/* qemuParseCommandLineVnc - * - * Tries to parse the various "-vnc ..." argument formats. - */ -static int -qemuParseCommandLineVnc(virDomainDefPtr def, - const char *val) -{ - int ret = -1; - virDomainGraphicsDefPtr vnc = NULL; - char *listenAddr = NULL; - char *tmp; - - if (VIR_ALLOC(vnc) < 0) - goto cleanup; - vnc->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC; - - if (STRPREFIX(val, "unix:")) { - /* -vnc unix:/some/big/path */ - if (virDomainGraphicsListenAppendSocket(vnc, val + 5) < 0) - goto cleanup; - } else { - /* - * -vnc 127.0.0.1:4 - * -vnc [2001:1:2:3:4:5:1234:1234]:4 - * -vnc some.host.name:4 - */ - char *opts; - char *port; - const char *sep = ":"; - if (val[0] == '[') - sep = "]:"; - tmp = strstr(val, sep); - if (!tmp) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("missing VNC port number in '%s'"), val); - goto cleanup; - } - port = tmp + strlen(sep); - if (virStrToLong_i(port, &opts, 10, - &vnc->data.vnc.port) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse VNC port '%s'"), port); - goto cleanup; - } - if (val[0] == '[') - val++; - if (VIR_STRNDUP(listenAddr, val, tmp-val) < 0 || - virDomainGraphicsListenAppendAddress(vnc, listenAddr) < 0) - goto cleanup; - - if (*opts == ',') { - char *orig_opts; - - if (VIR_STRDUP(orig_opts, opts + 1) < 0) - goto cleanup; - opts = orig_opts; - - while (opts && *opts) { - char *nextopt = strchr(opts, ','); - if (nextopt) - *(nextopt++) = '\0'; - - if (STRPREFIX(opts, "websocket")) { - char *websocket = opts + strlen("websocket"); - if (*(websocket++) == '=' && - *websocket) { - /* If the websocket continues with - * '=<something>', we'll parse it */ - if (virStrToLong_i(websocket, - NULL, 0, - &vnc->data.vnc.websocket) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse VNC " - "WebSocket port '%s'"), - websocket); - VIR_FREE(orig_opts); - goto cleanup; - } - } else { - /* Otherwise, we'll compute the port the same - * way QEMU does, by adding a 5700 to the - * display value. */ - vnc->data.vnc.websocket = - vnc->data.vnc.port + 5700; - } - } else if (STRPREFIX(opts, "share=")) { - char *sharePolicy = opts + strlen("share="); - if (sharePolicy && *sharePolicy) { - int policy = - virDomainGraphicsVNCSharePolicyTypeFromString(sharePolicy); - - if (policy < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown vnc display sharing policy '%s'"), - sharePolicy); - VIR_FREE(orig_opts); - goto cleanup; - } else { - vnc->data.vnc.sharePolicy = policy; - } - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("missing vnc sharing policy")); - VIR_FREE(orig_opts); - goto cleanup; - } - } - - opts = nextopt; - } - VIR_FREE(orig_opts); - } - vnc->data.vnc.port += 5900; - vnc->data.vnc.autoport = false; - } - - if (VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, vnc) < 0) - goto cleanup; - - ret = 0; - - cleanup: - virDomainGraphicsDefFree(vnc); - VIR_FREE(listenAddr); - return ret; -} - - -/* - * Tries to parse new style QEMU -drive args. - * - * eg -drive file=/dev/HostVG/VirtData1,if=ide,index=1 - * - * Will fail if not using the 'index' keyword - */ -static virDomainDiskDefPtr -qemuParseCommandLineDisk(virDomainXMLOptionPtr xmlopt, - const char *val, - virDomainDefPtr dom, - int nvirtiodisk, - bool old_style_ceph_args) -{ - virDomainDiskDefPtr def = NULL; - char **keywords; - char **values; - int nkeywords; - size_t i; - int idx = -1; - int busid = -1; - int unitid = -1; - - if (qemuParseKeywords(val, - &keywords, - &values, - &nkeywords, - 0) < 0) - return NULL; - - if (!(def = virDomainDiskDefNew(xmlopt))) - goto cleanup; - - if (qemuDomainIsPSeries(dom)) - def->bus = VIR_DOMAIN_DISK_BUS_SCSI; - else - def->bus = VIR_DOMAIN_DISK_BUS_IDE; - def->device = VIR_DOMAIN_DISK_DEVICE_DISK; - def->src->type = VIR_STORAGE_TYPE_FILE; - - for (i = 0; i < nkeywords; i++) { - if (STREQ(keywords[i], "file")) { - if (values[i] && STRNEQ(values[i], "")) { - def->src->path = values[i]; - values[i] = NULL; - if (STRPREFIX(def->src->path, "/dev/")) - def->src->type = VIR_STORAGE_TYPE_BLOCK; - else if (STRPREFIX(def->src->path, "nbd:") || - STRPREFIX(def->src->path, "nbd+")) { - def->src->type = VIR_STORAGE_TYPE_NETWORK; - def->src->protocol = VIR_STORAGE_NET_PROTOCOL_NBD; - - if (qemuParseNBDString(def) < 0) - goto error; - } else if (STRPREFIX(def->src->path, "rbd:")) { - char *p = def->src->path; - - def->src->type = VIR_STORAGE_TYPE_NETWORK; - def->src->protocol = VIR_STORAGE_NET_PROTOCOL_RBD; - if (VIR_STRDUP(def->src->path, p + strlen("rbd:")) < 0) - goto error; - /* old-style CEPH_ARGS env variable is parsed later */ - if (!old_style_ceph_args && qemuParseRBDString(def) < 0) { - VIR_FREE(p); - goto error; - } - - VIR_FREE(p); - } else if (STRPREFIX(def->src->path, "gluster:") || - STRPREFIX(def->src->path, "gluster+")) { - def->src->type = VIR_STORAGE_TYPE_NETWORK; - def->src->protocol = VIR_STORAGE_NET_PROTOCOL_GLUSTER; - - if (qemuParseGlusterString(def) < 0) - goto error; - } else if (STRPREFIX(def->src->path, "iscsi:")) { - def->src->type = VIR_STORAGE_TYPE_NETWORK; - def->src->protocol = VIR_STORAGE_NET_PROTOCOL_ISCSI; - - if (qemuParseISCSIString(def) < 0) - goto error; - } else if (STRPREFIX(def->src->path, "sheepdog:")) { - char *p = def->src->path; - char *port, *vdi; - - def->src->type = VIR_STORAGE_TYPE_NETWORK; - def->src->protocol = VIR_STORAGE_NET_PROTOCOL_SHEEPDOG; - if (VIR_STRDUP(def->src->path, p + strlen("sheepdog:")) < 0) - goto error; - VIR_FREE(p); - - /* def->src->path must be [vdiname] or [host]:[port]:[vdiname] */ - port = strchr(def->src->path, ':'); - if (port) { - *port = '\0'; - vdi = strchr(port + 1, ':'); - if (!vdi) { - *port = ':'; - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse sheepdog filename '%s'"), - def->src->path); - goto error; - } - port++; - *vdi++ = '\0'; - if (VIR_ALLOC(def->src->hosts) < 0) - goto error; - def->src->nhosts = 1; - def->src->hosts->name = def->src->path; - if (virStringParsePort(port, &def->src->hosts->port) < 0) - goto error; - def->src->hosts->transport = VIR_STORAGE_NET_HOST_TRANS_TCP; - def->src->hosts->socket = NULL; - if (VIR_STRDUP(def->src->path, vdi) < 0) - goto error; - } - } else if (STRPREFIX(def->src->path, "vxhs:")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("VxHS protocol does not support URI syntax '%s'"), - def->src->path); - goto error; - } else { - def->src->type = VIR_STORAGE_TYPE_FILE; - } - } else { - def->src->type = VIR_STORAGE_TYPE_FILE; - } - } else if (STREQ(keywords[i], "if")) { - if (STREQ(values[i], "ide")) { - def->bus = VIR_DOMAIN_DISK_BUS_IDE; - if (qemuDomainIsPSeries(dom)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("pseries systems do not support ide devices '%s'"), val); - goto error; - } - } else if (STREQ(values[i], "scsi")) { - def->bus = VIR_DOMAIN_DISK_BUS_SCSI; - } else if (STREQ(values[i], "floppy")) { - def->bus = VIR_DOMAIN_DISK_BUS_FDC; - def->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; - } else if (STREQ(values[i], "virtio")) { - def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO; - } else if (STREQ(values[i], "xen")) { - def->bus = VIR_DOMAIN_DISK_BUS_XEN; - } else if (STREQ(values[i], "sd")) { - def->bus = VIR_DOMAIN_DISK_BUS_SD; - } - } else if (STREQ(keywords[i], "media")) { - if (STREQ(values[i], "cdrom")) { - def->device = VIR_DOMAIN_DISK_DEVICE_CDROM; - def->src->readonly = true; - } else if (STREQ(values[i], "floppy")) { - def->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; - } - } else if (STREQ(keywords[i], "format")) { - if (virDomainDiskSetDriver(def, "qemu") < 0) - goto error; - def->src->format = virStorageFileFormatTypeFromString(values[i]); - } else if (STREQ(keywords[i], "cache")) { - if (STREQ(values[i], "off") || - STREQ(values[i], "none")) - def->cachemode = VIR_DOMAIN_DISK_CACHE_DISABLE; - else if (STREQ(values[i], "writeback") || - STREQ(values[i], "on")) - def->cachemode = VIR_DOMAIN_DISK_CACHE_WRITEBACK; - else if (STREQ(values[i], "writethrough")) - def->cachemode = VIR_DOMAIN_DISK_CACHE_WRITETHRU; - else if (STREQ(values[i], "directsync")) - def->cachemode = VIR_DOMAIN_DISK_CACHE_DIRECTSYNC; - else if (STREQ(values[i], "unsafe")) - def->cachemode = VIR_DOMAIN_DISK_CACHE_UNSAFE; - } else if (STREQ(keywords[i], "werror")) { - if (STREQ(values[i], "stop")) - def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_STOP; - else if (STREQ(values[i], "report")) - def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_REPORT; - else if (STREQ(values[i], "ignore")) - def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE; - else if (STREQ(values[i], "enospc")) - def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE; - } else if (STREQ(keywords[i], "rerror")) { - if (STREQ(values[i], "stop")) - def->rerror_policy = VIR_DOMAIN_DISK_ERROR_POLICY_STOP; - else if (STREQ(values[i], "report")) - def->rerror_policy = VIR_DOMAIN_DISK_ERROR_POLICY_REPORT; - else if (STREQ(values[i], "ignore")) - def->rerror_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE; - } else if (STREQ(keywords[i], "index")) { - if (virStrToLong_i(values[i], NULL, 10, &idx) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse drive index '%s'"), val); - goto error; - } - } else if (STREQ(keywords[i], "bus")) { - if (virStrToLong_i(values[i], NULL, 10, &busid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse drive bus '%s'"), val); - goto error; - } - } else if (STREQ(keywords[i], "unit")) { - if (virStrToLong_i(values[i], NULL, 10, &unitid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse drive unit '%s'"), val); - goto error; - } - } else if (STREQ(keywords[i], "readonly")) { - if ((values[i] == NULL) || STREQ(values[i], "on")) - def->src->readonly = true; - } else if (STREQ(keywords[i], "aio")) { - if ((def->iomode = virDomainDiskIoTypeFromString(values[i])) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse io mode '%s'"), values[i]); - goto error; - } - } else if (STREQ(keywords[i], "cyls")) { - if (virStrToLong_ui(values[i], NULL, 10, - &(def->geometry.cylinders)) < 0) { - virDomainDiskDefFree(def); - def = NULL; - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse cylinders value'%s'"), - values[i]); - goto error; - } - } else if (STREQ(keywords[i], "heads")) { - if (virStrToLong_ui(values[i], NULL, 10, - &(def->geometry.heads)) < 0) { - virDomainDiskDefFree(def); - def = NULL; - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse heads value'%s'"), - values[i]); - goto error; - } - } else if (STREQ(keywords[i], "secs")) { - if (virStrToLong_ui(values[i], NULL, 10, - &(def->geometry.sectors)) < 0) { - virDomainDiskDefFree(def); - def = NULL; - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse sectors value'%s'"), - values[i]); - goto error; - } - } else if (STREQ(keywords[i], "trans")) { - def->geometry.trans = - virDomainDiskGeometryTransTypeFromString(values[i]); - if ((def->geometry.trans < VIR_DOMAIN_DISK_TRANS_DEFAULT) || - (def->geometry.trans >= VIR_DOMAIN_DISK_TRANS_LAST)) { - virDomainDiskDefFree(def); - def = NULL; - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse translation value '%s'"), - values[i]); - goto error; - } - } - } - - if (def->rerror_policy == def->error_policy) - def->rerror_policy = 0; - - if (!def->src->path && - def->device == VIR_DOMAIN_DISK_DEVICE_DISK && - def->src->type != VIR_STORAGE_TYPE_NETWORK) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("missing file parameter in drive '%s'"), val); - goto error; - } - if (idx == -1 && - def->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) - idx = nvirtiodisk; - - if (idx == -1 && - unitid == -1 && - busid == -1) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("missing index/unit/bus parameter in drive '%s'"), - val); - goto error; - } - - if (idx == -1) { - if (unitid == -1) - unitid = 0; - if (busid == -1) - busid = 0; - switch (def->bus) { - case VIR_DOMAIN_DISK_BUS_IDE: - idx = (busid * 2) + unitid; - break; - case VIR_DOMAIN_DISK_BUS_SCSI: - idx = (busid * 7) + unitid; - break; - default: - idx = unitid; - break; - } - } - - if (def->bus == VIR_DOMAIN_DISK_BUS_IDE) { - ignore_value(VIR_STRDUP(def->dst, "hda")); - } else if (def->bus == VIR_DOMAIN_DISK_BUS_SCSI || - def->bus == VIR_DOMAIN_DISK_BUS_SD) { - ignore_value(VIR_STRDUP(def->dst, "sda")); - } else if (def->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { - ignore_value(VIR_STRDUP(def->dst, "vda")); - } else if (def->bus == VIR_DOMAIN_DISK_BUS_XEN) { - ignore_value(VIR_STRDUP(def->dst, "xvda")); - } else if (def->bus == VIR_DOMAIN_DISK_BUS_FDC) { - ignore_value(VIR_STRDUP(def->dst, "fda")); - } else { - ignore_value(VIR_STRDUP(def->dst, "hda")); - } - - if (!def->dst) - goto error; - if (STREQ(def->dst, "xvda")) - def->dst[3] = 'a' + idx; - else - def->dst[2] = 'a' + idx; - - if (virDomainDiskDefAssignAddress(xmlopt, def, dom) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("invalid device name '%s'"), def->dst); - goto error; - } - - cleanup: - qemuParseKeywordsFree(nkeywords, keywords, values); - return def; - - error: - virDomainDiskDefFree(def); - def = NULL; - goto cleanup; -} - -/* - * Tries to find a NIC definition matching a vlan we want - */ -static const char * -qemuFindNICForVLAN(int nnics, - const char **nics, - int wantvlan) -{ - size_t i; - for (i = 0; i < nnics; i++) { - int gotvlan; - const char *tmp = strstr(nics[i], "vlan="); - char *end; - if (!tmp) - continue; - - tmp += strlen("vlan="); - - if (virStrToLong_i(tmp, &end, 10, &gotvlan) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse NIC vlan in '%s'"), nics[i]); - return NULL; - } - - if (gotvlan == wantvlan) - return nics[i]; - } - - if (wantvlan == 0 && nnics > 0) - return nics[0]; - - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot find NIC definition for vlan %d"), wantvlan); - return NULL; -} - - -/* - * Tries to parse a QEMU -net backend argument. Gets given - * a list of all known -net frontend arguments to try and - * match up against. Horribly complicated stuff - */ -static virDomainNetDefPtr -qemuParseCommandLineNet(virDomainXMLOptionPtr xmlopt, - const char *val, - int nnics, - const char **nics) -{ - virDomainNetDefPtr def = NULL; - char **keywords = NULL; - char **values = NULL; - int nkeywords; - const char *nic; - int wantvlan = 0; - const char *tmp; - bool genmac = true; - size_t i; - - tmp = strchr(val, ','); - - if (tmp) { - if (qemuParseKeywords(tmp+1, - &keywords, - &values, - &nkeywords, - 0) < 0) - return NULL; - } else { - nkeywords = 0; - } - - if (VIR_ALLOC(def) < 0) - goto cleanup; - - /* 'tap' could turn into libvirt type=ethernet, type=bridge or - * type=network, but we can't tell, so use the generic config */ - if (STRPREFIX(val, "tap,")) - def->type = VIR_DOMAIN_NET_TYPE_ETHERNET; - else if (STRPREFIX(val, "socket")) - def->type = VIR_DOMAIN_NET_TYPE_CLIENT; - else if (STRPREFIX(val, "user")) - def->type = VIR_DOMAIN_NET_TYPE_USER; - else - def->type = VIR_DOMAIN_NET_TYPE_ETHERNET; - - for (i = 0; i < nkeywords; i++) { - if (STREQ(keywords[i], "vlan")) { - if (virStrToLong_i(values[i], NULL, 10, &wantvlan) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse vlan in '%s'"), val); - goto error; - } - } else if (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET && - STREQ(keywords[i], "script") && STRNEQ(values[i], "")) { - def->script = values[i]; - values[i] = NULL; - } else if (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET && - STREQ(keywords[i], "ifname")) { - def->ifname = values[i]; - values[i] = NULL; - } - } - - - /* Done parsing the nic backend. Now to try and find corresponding - * frontend, based off vlan number. NB this assumes a 1-1 mapping - */ - - nic = qemuFindNICForVLAN(nnics, nics, wantvlan); - if (!nic) - goto error; - - if (!STRPREFIX(nic, "nic")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse NIC definition '%s'"), nic); - goto error; - } - - for (i = 0; i < nkeywords; i++) { - VIR_FREE(keywords[i]); - VIR_FREE(values[i]); - } - VIR_FREE(keywords); - VIR_FREE(values); - - if (STRPREFIX(nic, "nic,")) { - if (qemuParseKeywords(nic + strlen("nic,"), - &keywords, - &values, - &nkeywords, - 0) < 0) { - goto error; - } - } else { - nkeywords = 0; - } - - for (i = 0; i < nkeywords; i++) { - if (STREQ(keywords[i], "macaddr")) { - genmac = false; - if (virMacAddrParse(values[i], &def->mac) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unable to parse mac address '%s'"), - values[i]); - goto error; - } - } else if (STREQ(keywords[i], "model")) { - if (virDomainNetSetModelString(def, values[i]) < 0) - goto error; - VIR_FREE(values[i]); - } else if (STREQ(keywords[i], "vhost")) { - if ((values[i] == NULL) || STREQ(values[i], "on")) { - def->driver.virtio.name = VIR_DOMAIN_NET_BACKEND_TYPE_VHOST; - } else if (STREQ(keywords[i], "off")) { - def->driver.virtio.name = VIR_DOMAIN_NET_BACKEND_TYPE_QEMU; - } - } else if (STREQ(keywords[i], "sndbuf") && values[i]) { - if (virStrToLong_ul(values[i], NULL, 10, &def->tune.sndbuf) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse sndbuf size in '%s'"), val); - goto error; - } - def->tune.sndbuf_specified = true; - } - } - - if (genmac) - virDomainNetGenerateMAC(xmlopt, &def->mac); - - cleanup: - qemuParseKeywordsFree(nkeywords, keywords, values); - return def; - - error: - virDomainNetDefFree(def); - def = NULL; - goto cleanup; -} - - -/* - * Tries to parse a QEMU PCI device - */ -static virDomainHostdevDefPtr -qemuParseCommandLinePCI(const char *val) -{ - int bus = 0, slot = 0, func = 0; - const char *start; - char *end; - virDomainHostdevDefPtr def = virDomainHostdevDefNew(); - - if (!def) - goto error; - - if (!STRPREFIX(val, "host=")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown PCI device syntax '%s'"), val); - goto error; - } - - start = val + strlen("host="); - if (virStrToLong_i(start, &end, 16, &bus) < 0 || *end != ':') { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot extract PCI device bus '%s'"), val); - goto error; - } - start = end + 1; - if (virStrToLong_i(start, &end, 16, &slot) < 0 || *end != '.') { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot extract PCI device slot '%s'"), val); - goto error; - } - start = end + 1; - if (virStrToLong_i(start, NULL, 16, &func) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot extract PCI device function '%s'"), val); - goto error; - } - - def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; - def->managed = true; - def->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI; - def->source.subsys.u.pci.addr.bus = bus; - def->source.subsys.u.pci.addr.slot = slot; - def->source.subsys.u.pci.addr.function = func; - return def; - - error: - virDomainHostdevDefFree(def); - return NULL; -} - - -/* - * Tries to parse a QEMU USB device - */ -static virDomainHostdevDefPtr -qemuParseCommandLineUSB(const char *val) -{ - virDomainHostdevDefPtr def = virDomainHostdevDefNew(); - virDomainHostdevSubsysUSBPtr usbsrc; - int first = 0, second = 0; - const char *start; - char *end; - - if (!def) - goto error; - usbsrc = &def->source.subsys.u.usb; - - if (!STRPREFIX(val, "host:")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown USB device syntax '%s'"), val); - goto error; - } - - start = val + strlen("host:"); - if (strchr(start, ':')) { - if (virStrToLong_i(start, &end, 16, &first) < 0 || *end != ':') { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot extract USB device vendor '%s'"), val); - goto error; - } - start = end + 1; - if (virStrToLong_i(start, NULL, 16, &second) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot extract USB device product '%s'"), val); - goto error; - } - } else { - if (virStrToLong_i(start, &end, 10, &first) < 0 || *end != '.') { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot extract USB device bus '%s'"), val); - goto error; - } - start = end + 1; - if (virStrToLong_i(start, NULL, 10, &second) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot extract USB device address '%s'"), val); - goto error; - } - } - - def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS; - def->managed = false; - def->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB; - if (*end == '.') { - usbsrc->bus = first; - usbsrc->device = second; - } else { - usbsrc->vendor = first; - usbsrc->product = second; - } - return def; - - error: - virDomainHostdevDefFree(def); - return NULL; -} - - -/* - * Tries to parse a QEMU serial/parallel device - */ -static int -qemuParseCommandLineChr(virDomainChrSourceDefPtr source, - const char *val) -{ - if (STREQ(val, "null")) { - source->type = VIR_DOMAIN_CHR_TYPE_NULL; - } else if (STREQ(val, "vc")) { - source->type = VIR_DOMAIN_CHR_TYPE_VC; - } else if (STREQ(val, "pty")) { - source->type = VIR_DOMAIN_CHR_TYPE_PTY; - } else if (STRPREFIX(val, "file:")) { - source->type = VIR_DOMAIN_CHR_TYPE_FILE; - if (VIR_STRDUP(source->data.file.path, val + strlen("file:")) < 0) - goto error; - } else if (STRPREFIX(val, "pipe:")) { - source->type = VIR_DOMAIN_CHR_TYPE_PIPE; - if (VIR_STRDUP(source->data.file.path, val + strlen("pipe:")) < 0) - goto error; - } else if (STREQ(val, "stdio")) { - source->type = VIR_DOMAIN_CHR_TYPE_STDIO; - } else if (STRPREFIX(val, "udp:")) { - const char *svc1, *host2, *svc2; - 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 && svc1 != val && - VIR_STRNDUP(source->data.udp.connectHost, val, svc1 - val) < 0) - goto error; - - if (svc1) { - svc1++; - if (VIR_STRNDUP(source->data.udp.connectService, svc1, - host2 ? host2 - svc1 : strlen(svc1)) < 0) - goto error; - } - - if (host2) { - host2++; - if (svc2 && svc2 != host2 && - VIR_STRNDUP(source->data.udp.bindHost, host2, svc2 - host2) < 0) - goto error; - } - - if (svc2) { - svc2++; - if (STRNEQ(svc2, "0")) { - if (VIR_STRDUP(source->data.udp.bindService, svc2) < 0) - goto error; - } - } - } else if (STRPREFIX(val, "tcp:") || - STRPREFIX(val, "telnet:")) { - const char *opt, *svc; - source->type = VIR_DOMAIN_CHR_TYPE_TCP; - if (STRPREFIX(val, "tcp:")) { - val += strlen("tcp:"); - } else { - val += strlen("telnet:"); - source->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET; - } - svc = strchr(val, ':'); - if (!svc) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot find port number in character device %s"), val); - goto error; - } - opt = strchr(svc, ','); - if (opt && strstr(opt, "server")) - source->data.tcp.listen = true; - - if (VIR_STRNDUP(source->data.tcp.host, val, svc - val) < 0) - goto error; - svc++; - if (VIR_STRNDUP(source->data.tcp.service, svc, opt ? opt - svc : -1) < 0) - goto error; - } else if (STRPREFIX(val, "unix:")) { - const char *opt; - val += strlen("unix:"); - opt = strchr(val, ','); - source->type = VIR_DOMAIN_CHR_TYPE_UNIX; - if (VIR_STRNDUP(source->data.nix.path, val, opt ? opt - val : -1) < 0) - goto error; - - } else if (STRPREFIX(val, "/dev")) { - source->type = VIR_DOMAIN_CHR_TYPE_DEV; - if (VIR_STRDUP(source->data.file.path, val) < 0) - goto error; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown character device syntax %s"), val); - goto error; - } - - return 0; - - error: - return -1; -} - - -static virCPUDefPtr -qemuInitGuestCPU(virDomainDefPtr dom) -{ - if (!dom->cpu) { - virCPUDefPtr cpu; - - if (VIR_ALLOC(cpu) < 0) - return NULL; - - cpu->type = VIR_CPU_TYPE_GUEST; - cpu->match = VIR_CPU_MATCH_EXACT; - dom->cpu = cpu; - } - - return dom->cpu; -} - - -static int -qemuParseCommandLineCPU(virDomainDefPtr dom, - const char *val) -{ - virCPUDefPtr cpu = NULL; - char **tokens; - char **hv_tokens = NULL; - char *model = NULL; - int ret = -1; - size_t i; - - if (!(tokens = virStringSplit(val, ",", 0))) - goto cleanup; - - if (tokens[0] == NULL) - goto syntax; - - for (i = 0; tokens[i] != NULL; i++) { - if (*tokens[i] == '\0') - goto syntax; - - if (i == 0) { - if (VIR_STRDUP(model, tokens[i]) < 0) - goto cleanup; - - if (STRNEQ(model, "qemu32") && STRNEQ(model, "qemu64")) { - if (!(cpu = qemuInitGuestCPU(dom))) - goto cleanup; - - cpu->model = model; - model = NULL; - } - } else if (*tokens[i] == '+' || *tokens[i] == '-') { - const char *feature = tokens[i] + 1; /* '+' or '-' */ - int policy; - - if (*tokens[i] == '+') - policy = VIR_CPU_FEATURE_REQUIRE; - else - policy = VIR_CPU_FEATURE_DISABLE; - - if (*feature == '\0') - goto syntax; - - if (!ARCH_IS_X86(dom->os.arch)) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("%s platform doesn't support CPU features'"), - virArchToString(dom->os.arch)); - goto cleanup; - } - - if (STREQ(feature, "kvmclock")) { - bool present = (policy == VIR_CPU_FEATURE_REQUIRE); - size_t j; - - for (j = 0; j < dom->clock.ntimers; j++) { - if (dom->clock.timers[j]->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK) - break; - } - - if (j == dom->clock.ntimers) { - virDomainTimerDefPtr timer; - if (VIR_ALLOC(timer) < 0 || - VIR_APPEND_ELEMENT_COPY(dom->clock.timers, - dom->clock.ntimers, timer) < 0) { - VIR_FREE(timer); - goto cleanup; - } - timer->name = VIR_DOMAIN_TIMER_NAME_KVMCLOCK; - timer->present = present; - timer->tickpolicy = -1; - timer->track = -1; - timer->mode = -1; - } else if (dom->clock.timers[j]->present != -1 && - dom->clock.timers[j]->present != present) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("conflicting occurrences of kvmclock feature")); - goto cleanup; - } - } else if (STREQ(feature, "kvm_pv_eoi")) { - if (policy == VIR_CPU_FEATURE_REQUIRE) - dom->apic_eoi = VIR_TRISTATE_SWITCH_ON; - else - dom->apic_eoi = VIR_TRISTATE_SWITCH_OFF; - } else { - if (!cpu) { - if (!(cpu = qemuInitGuestCPU(dom))) - goto cleanup; - - cpu->model = model; - model = NULL; - } - - if (virCPUDefAddFeature(cpu, feature, policy) < 0) - goto cleanup; - } - } else if (STREQ(tokens[i], "hv_crash")) { - size_t j; - for (j = 0; j < dom->npanics; j++) { - if (dom->panics[j]->model == VIR_DOMAIN_PANIC_MODEL_HYPERV) - break; - } - - if (j == dom->npanics) { - virDomainPanicDefPtr panic; - if (VIR_ALLOC(panic) < 0 || - VIR_APPEND_ELEMENT_COPY(dom->panics, - dom->npanics, panic) < 0) { - VIR_FREE(panic); - goto cleanup; - } - panic->model = VIR_DOMAIN_PANIC_MODEL_HYPERV; - } - } else if (STRPREFIX(tokens[i], "hv_")) { - const char *token = tokens[i] + 3; /* "hv_" */ - const char *feature, *value; - int f; - - if (*token == '\0') - goto syntax; - - if (!(hv_tokens = virStringSplit(token, "=", 2))) - goto cleanup; - - feature = hv_tokens[0]; - value = hv_tokens[1]; - - if (*feature == '\0') - goto syntax; - - dom->features[VIR_DOMAIN_FEATURE_HYPERV] = VIR_TRISTATE_SWITCH_ON; - - if ((f = virDomainHypervTypeFromString(feature)) < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("unsupported HyperV Enlightenment feature " - "'%s'"), feature); - goto cleanup; - } - - switch ((virDomainHyperv) f) { - case VIR_DOMAIN_HYPERV_RELAXED: - case VIR_DOMAIN_HYPERV_VAPIC: - case VIR_DOMAIN_HYPERV_VPINDEX: - case VIR_DOMAIN_HYPERV_RUNTIME: - case VIR_DOMAIN_HYPERV_SYNIC: - case VIR_DOMAIN_HYPERV_STIMER: - case VIR_DOMAIN_HYPERV_RESET: - case VIR_DOMAIN_HYPERV_FREQUENCIES: - case VIR_DOMAIN_HYPERV_REENLIGHTENMENT: - case VIR_DOMAIN_HYPERV_TLBFLUSH: - case VIR_DOMAIN_HYPERV_IPI: - case VIR_DOMAIN_HYPERV_EVMCS: - if (value) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("HyperV feature '%s' should not " - "have a value"), feature); - goto cleanup; - } - dom->hyperv_features[f] = VIR_TRISTATE_SWITCH_ON; - break; - - case VIR_DOMAIN_HYPERV_SPINLOCKS: - dom->hyperv_features[f] = VIR_TRISTATE_SWITCH_ON; - if (!value) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("missing HyperV spinlock retry count")); - goto cleanup; - } - - if (virStrToLong_ui(value, NULL, 0, &dom->hyperv_spinlocks) < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("cannot parse HyperV spinlock retry count")); - goto cleanup; - } - - if (dom->hyperv_spinlocks < 0xFFF) - dom->hyperv_spinlocks = 0xFFF; - break; - - case VIR_DOMAIN_HYPERV_VENDOR_ID: - dom->hyperv_features[f] = VIR_TRISTATE_SWITCH_ON; - if (!value) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("missing HyperV vendor_id value")); - goto cleanup; - } - - if (VIR_STRDUP(dom->hyperv_vendor_id, value) < 0) - goto cleanup; - - break; - - case VIR_DOMAIN_HYPERV_LAST: - break; - } - virStringListFree(hv_tokens); - hv_tokens = NULL; - } else if (STREQ(tokens[i], "kvm=off")) { - dom->features[VIR_DOMAIN_FEATURE_KVM] = VIR_TRISTATE_SWITCH_ON; - dom->kvm_features[VIR_DOMAIN_KVM_HIDDEN] = VIR_TRISTATE_SWITCH_ON; - } - } - - if (dom->os.arch == VIR_ARCH_X86_64) { - bool is_32bit = false; - if (cpu) { - virCPUDataPtr cpuData = NULL; - - if (cpuEncode(VIR_ARCH_X86_64, cpu, NULL, &cpuData, - NULL, NULL, NULL, NULL) < 0) - goto cleanup; - - is_32bit = (virCPUDataCheckFeature(cpuData, "lm") != 1); - virCPUDataFree(cpuData); - } else if (model) { - is_32bit = STREQ(model, "qemu32"); - } - - if (is_32bit) - dom->os.arch = VIR_ARCH_I686; - } - - ret = 0; - - cleanup: - VIR_FREE(model); - virStringListFree(tokens); - virStringListFree(hv_tokens); - return ret; - - syntax: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown CPU syntax '%s'"), val); - goto cleanup; -} - - -static int -qemuParseCommandLineMem(virDomainDefPtr dom, - const char *val) -{ - unsigned long long mem = 0; - unsigned long long size = 0; - unsigned long long maxmem = 0; - unsigned int slots = 0; - char *end; - size_t i; - int nkws; - char **kws; - char **vals; - int n; - int ret = -1; - - if (qemuParseKeywords(val, &kws, &vals, &nkws, 1) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse memory '%s'"), val); - goto cleanup; - } - - for (i = 0; i < nkws; i++) { - if (vals[i] == NULL) { - if (i > 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse memory '%s'"), val); - goto cleanup; - } - if (virStrToLong_ull(kws[i], &end, 10, &mem) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse memory value '%s'"), kws[i]); - goto cleanup; - } - if (virScaleInteger(&mem, end, 1024*1024, ULLONG_MAX) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot scale memory: %s"), - virGetLastErrorMessage()); - goto cleanup; - } - - size = mem; - - } else { - if (STREQ(kws[i], "size") || STREQ(kws[i], "maxmem")) { - if (virStrToLong_ull(vals[i], &end, 10, &mem) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse memory value '%s'"), vals[i]); - goto cleanup; - } - if (virScaleInteger(&mem, end, 1024*1024, ULLONG_MAX) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot scale memory: %s"), - virGetLastErrorMessage()); - goto cleanup; - } - - STREQ(kws[i], "size") ? (size = mem) : (maxmem = mem); - - } - if (STREQ(kws[i], "slots")) { - if (virStrToLong_i(vals[i], &end, 10, &n) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse slots value '%s'"), vals[i]); - goto cleanup; - } - - slots = n; - - } - } - } - - virDomainDefSetMemoryTotal(dom, size / 1024); - dom->mem.cur_balloon = size / 1024; - dom->mem.memory_slots = slots; - dom->mem.max_memory = maxmem / 1024; - - ret = 0; - - cleanup: - qemuParseKeywordsFree(nkws, kws, vals); - return ret; -} - - -static int -qemuParseCommandLineSmp(virDomainDefPtr dom, - const char *val, - virDomainXMLOptionPtr xmlopt) -{ - unsigned int sockets = 0; - unsigned int cores = 0; - unsigned int threads = 0; - unsigned int maxcpus = 0; - unsigned int vcpus = 0; - size_t i; - int nkws; - char **kws; - char **vals; - int n; - char *end; - int ret; - - if (qemuParseKeywords(val, &kws, &vals, &nkws, 1) < 0) - return -1; - - for (i = 0; i < nkws; i++) { - if (vals[i] == NULL) { - if (i > 0 || - virStrToLong_ui(kws[i], &end, 10, &vcpus) < 0 || *end != '\0') - goto syntax; - } else { - if (virStrToLong_i(vals[i], &end, 10, &n) < 0 || *end != '\0') - goto syntax; - if (STREQ(kws[i], "sockets")) - sockets = n; - else if (STREQ(kws[i], "cores")) - cores = n; - else if (STREQ(kws[i], "threads")) - threads = n; - else if (STREQ(kws[i], "maxcpus")) - maxcpus = n; - else if (STREQ(kws[i], "cpus")) - vcpus = n; - else - goto syntax; - } - } - - if (sockets && cores && threads) { - virCPUDefPtr cpu; - - if (!(cpu = qemuInitGuestCPU(dom))) - goto error; - cpu->sockets = sockets; - cpu->cores = cores; - cpu->threads = threads; - } else if (sockets || cores || threads) { - goto syntax; - } - - if (maxcpus == 0) { - if (cores) { - if (virDomainDefGetVcpusTopology(dom, &maxcpus) < 0) - goto error; - } else { - maxcpus = vcpus; - } - } - - if (maxcpus == 0) - goto syntax; - - if (vcpus == 0) - vcpus = maxcpus; - - if (virDomainDefSetVcpusMax(dom, maxcpus, xmlopt) < 0) - goto error; - - if (virDomainDefSetVcpus(dom, vcpus) < 0) - goto error; - - ret = 0; - - cleanup: - qemuParseKeywordsFree(nkws, kws, vals); - return ret; - - syntax: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse CPU topology '%s'"), val); - error: - ret = -1; - goto cleanup; -} - - -static void -qemuParseCommandLineBootDevs(virDomainDefPtr def, const char *str) -{ - int n, b = 0; - - for (n = 0; str[n] && b < VIR_DOMAIN_BOOT_LAST; n++) { - if (str[n] == 'a') - def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_FLOPPY; - else if (str[n] == 'c') - def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_DISK; - else if (str[n] == 'd') - def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_CDROM; - else if (str[n] == 'n') - def->os.bootDevs[b++] = VIR_DOMAIN_BOOT_NET; - else if (str[n] == ',') - break; - } - def->os.nBootDevs = b; -} - - -/* - * Analyse the env and argv settings and reconstruct a - * virDomainDefPtr representing these settings as closely - * as is practical. This is not an exact science.... - */ -static virDomainDefPtr -qemuParseCommandLine(virFileCachePtr capsCache, - virCapsPtr caps, - virDomainXMLOptionPtr xmlopt, - char **progenv, - char **progargv, - char **pidfile, - virDomainChrSourceDefPtr *monConfig, - bool *monJSON) -{ - virDomainDefPtr def = NULL; - size_t i; - bool nographics = false; - bool fullscreen = false; - char **list = NULL; - char *path; - size_t nnics = 0; - const char **nics = NULL; - int video = VIR_DOMAIN_VIDEO_TYPE_CIRRUS; - int nvirtiodisk = 0; - qemuDomainCmdlineDefPtr cmd = NULL; - virDomainDiskDefPtr disk = NULL; - const char *ceph_args = qemuFindEnv(progenv, "CEPH_ARGS"); - bool have_sdl = false; - virQEMUCapsPtr qemuCaps = NULL; - - if (pidfile) - *pidfile = NULL; - if (monConfig) - *monConfig = NULL; - if (monJSON) - *monJSON = false; - - if (!progargv[0]) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("no emulator path found")); - return NULL; - } - - if (!(qemuCaps = virQEMUCapsCacheLookup(capsCache, progargv[0]))) - goto error; - - if (!(def = virDomainDefNew())) - goto error; - - /* allocate the cmdlinedef up-front; if it's unused, we'll free it later */ - if (VIR_ALLOC(cmd) < 0) - goto error; - - if (virUUIDGenerate(def->uuid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("failed to generate uuid")); - goto error; - } - - def->id = -1; - def->mem.cur_balloon = 64 * 1024; - virDomainDefSetMemoryTotal(def, def->mem.cur_balloon); - if (virDomainDefSetVcpusMax(def, 1, xmlopt) < 0) - goto error; - if (virDomainDefSetVcpus(def, 1) < 0) - goto error; - def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC; - - def->onReboot = VIR_DOMAIN_LIFECYCLE_ACTION_RESTART; - def->onCrash = VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY; - def->onPoweroff = VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY; - def->virtType = VIR_DOMAIN_VIRT_QEMU; - if (VIR_STRDUP(def->emulator, progargv[0]) < 0) - goto error; - - if (!(path = last_component(def->emulator))) - goto error; - - def->os.type = VIR_DOMAIN_OSTYPE_HVM; - if (strstr(path, "kvm")) { - def->virtType = VIR_DOMAIN_VIRT_KVM; - def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON; - } - - if (def->virtType == VIR_DOMAIN_VIRT_KVM) - def->os.arch = caps->host.arch; - else if (STRPREFIX(path, "qemu-system-")) - def->os.arch = virArchFromString(path + strlen("qemu-system-")); - else - def->os.arch = VIR_ARCH_I686; - - if (ARCH_IS_X86(def->os.arch)) - def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ON; - -#define WANT_VALUE() \ - const char *val = progargv[++i]; \ - if (!val) { \ - virReportError(VIR_ERR_INTERNAL_ERROR, \ - _("missing value for %s argument"), arg); \ - goto error; \ - } - - /* One initial loop to get list of NICs, so we - * can correlate them later */ - for (i = 1; progargv[i]; i++) { - const char *arg = progargv[i]; - /* Make sure we have a single - for all options to - simplify next logic */ - if (STRPREFIX(arg, "--")) - arg++; - - if (STREQ(arg, "-net")) { - WANT_VALUE(); - if (STRPREFIX(val, "nic") && - VIR_APPEND_ELEMENT(nics, nnics, val) < 0) - goto error; - } - } - - /* Detect machine type before processing any other arguments, - * because they might depend on it */ - for (i = 1; progargv[i]; i++) { - const char *arg = progargv[i]; - - /* Make sure we have a single - for all options to - simplify next logic */ - if (STRPREFIX(arg, "--")) - arg++; - - if (STREQ(arg, "-M") || - STREQ(arg, "-machine")) { - char *param; - size_t j = 0; - - /* -machine [type=]name[,prop[=value][,...]] - * Set os.machine only if first parameter lacks '=' or - * contains explicit type='...' */ - WANT_VALUE(); - if (!(list = virStringSplit(val, ",", 0))) - goto error; - param = list[0]; - - if (STRPREFIX(param, "type=")) - param += strlen("type="); - if (!strchr(param, '=')) { - if (VIR_STRDUP(def->os.machine, param) < 0) - goto error; - j++; - } - - /* handle all remaining "-machine" parameters */ - while ((param = list[j++])) { - if (STRPREFIX(param, "dump-guest-core=")) { - param += strlen("dump-guest-core="); - def->mem.dump_core = virTristateSwitchTypeFromString(param); - if (def->mem.dump_core <= 0) - def->mem.dump_core = VIR_TRISTATE_SWITCH_ABSENT; - } else if (STRPREFIX(param, "mem-merge=off")) { - def->mem.nosharepages = true; - } else if (STRPREFIX(param, "accel=kvm")) { - def->virtType = VIR_DOMAIN_VIRT_KVM; - def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_TRISTATE_SWITCH_ON; - } else if (STRPREFIX(param, "aes-key-wrap=")) { - if (STREQ(arg, "-M")) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("aes-key-wrap is not supported with " - "this QEMU binary")); - goto error; - } - param += strlen("aes-key-wrap="); - if (!def->keywrap && VIR_ALLOC(def->keywrap) < 0) - goto error; - def->keywrap->aes = virTristateSwitchTypeFromString(param); - if (def->keywrap->aes < 0) - def->keywrap->aes = VIR_TRISTATE_SWITCH_ABSENT; - } else if (STRPREFIX(param, "dea-key-wrap=")) { - if (STREQ(arg, "-M")) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("dea-key-wrap is not supported with " - "this QEMU binary")); - goto error; - } - param += strlen("dea-key-wrap="); - if (!def->keywrap && VIR_ALLOC(def->keywrap) < 0) - goto error; - def->keywrap->dea = virTristateSwitchTypeFromString(param); - if (def->keywrap->dea < 0) - def->keywrap->dea = VIR_TRISTATE_SWITCH_ABSENT; - } - } - virStringListFree(list); - list = NULL; - } - } - - /* If no machine type has been found among the arguments, then figure - * out a reasonable value by using capabilities */ - if (!def->os.machine) { - const char *mach = virQEMUCapsGetDefaultMachine(qemuCaps); - - if (!mach) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Binary '%s' does not have a default machine type " - "and no '-machine' arg is present"), - progargv[0]); - goto error; - } - - if (VIR_STRDUP(def->os.machine, mach) < 0) - goto error; - } - - /* Now the real processing loop */ - for (i = 1; progargv[i]; i++) { - const char *arg = progargv[i]; - bool argRecognized = true; - - /* Make sure we have a single - for all options to - simplify next logic */ - if (STRPREFIX(arg, "--")) - arg++; - - if (STREQ(arg, "-vnc")) { - WANT_VALUE(); - if (qemuParseCommandLineVnc(def, val) < 0) - goto error; - } else if (STREQ(arg, "-sdl")) { - have_sdl = true; - } else if (STREQ(arg, "-m")) { - WANT_VALUE(); - if (qemuParseCommandLineMem(def, val) < 0) - goto error; - } else if (STREQ(arg, "-smp")) { - WANT_VALUE(); - if (qemuParseCommandLineSmp(def, val, xmlopt) < 0) - goto error; - } else if (STREQ(arg, "-uuid")) { - WANT_VALUE(); - if (virUUIDParse(val, def->uuid) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, \ - _("cannot parse UUID '%s'"), val); - goto error; - } - } else if (STRPREFIX(arg, "-hd") || - STRPREFIX(arg, "-sd") || - STRPREFIX(arg, "-fd") || - STREQ(arg, "-cdrom")) { - WANT_VALUE(); - if (!(disk = virDomainDiskDefNew(xmlopt))) - goto error; - - if (STRPREFIX(val, "/dev/")) { - disk->src->type = VIR_STORAGE_TYPE_BLOCK; - } else if (STRPREFIX(val, "nbd:")) { - disk->src->type = VIR_STORAGE_TYPE_NETWORK; - disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_NBD; - } else if (STRPREFIX(val, "rbd:")) { - disk->src->type = VIR_STORAGE_TYPE_NETWORK; - disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_RBD; - val += strlen("rbd:"); - } else if (STRPREFIX(val, "gluster")) { - disk->src->type = VIR_STORAGE_TYPE_NETWORK; - disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_GLUSTER; - } else if (STRPREFIX(val, "sheepdog:")) { - disk->src->type = VIR_STORAGE_TYPE_NETWORK; - disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_SHEEPDOG; - val += strlen("sheepdog:"); - } else if (STRPREFIX(val, "vxhs:")) { - disk->src->type = VIR_STORAGE_TYPE_NETWORK; - disk->src->protocol = VIR_STORAGE_NET_PROTOCOL_VXHS; - val += strlen("vxhs:"); - } else { - disk->src->type = VIR_STORAGE_TYPE_FILE; - } - if (STREQ(arg, "-cdrom")) { - disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; - if (qemuDomainIsPSeries(def)) - disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; - if (VIR_STRDUP(disk->dst, "hdc") < 0) - goto error; - disk->src->readonly = true; - } else { - if (STRPREFIX(arg, "-fd")) { - disk->device = VIR_DOMAIN_DISK_DEVICE_FLOPPY; - disk->bus = VIR_DOMAIN_DISK_BUS_FDC; - } else { - disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; - if (STRPREFIX(arg, "-hd")) - disk->bus = VIR_DOMAIN_DISK_BUS_IDE; - else - disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; - if (qemuDomainIsPSeries(def)) - disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; - } - if (VIR_STRDUP(disk->dst, arg + 1) < 0) - goto error; - } - if (VIR_STRDUP(disk->src->path, val) < 0) - goto error; - - if (disk->src->type == VIR_STORAGE_TYPE_NETWORK) { - char *port; - - switch ((virStorageNetProtocol) disk->src->protocol) { - case VIR_STORAGE_NET_PROTOCOL_NBD: - if (qemuParseNBDString(disk) < 0) - goto error; - break; - case VIR_STORAGE_NET_PROTOCOL_RBD: - /* old-style CEPH_ARGS env variable is parsed later */ - if (!ceph_args && qemuParseRBDString(disk) < 0) - goto error; - break; - case VIR_STORAGE_NET_PROTOCOL_SHEEPDOG: - /* disk->src must be [vdiname] or [host]:[port]:[vdiname] */ - port = strchr(disk->src->path, ':'); - if (port) { - char *vdi; - - *port++ = '\0'; - vdi = strchr(port, ':'); - if (!vdi) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse sheepdog filename '%s'"), val); - goto error; - } - *vdi++ = '\0'; - if (VIR_ALLOC(disk->src->hosts) < 0) - goto error; - disk->src->nhosts = 1; - disk->src->hosts->name = disk->src->path; - if (virStringParsePort(port, &disk->src->hosts->port) < 0) - goto error; - if (VIR_STRDUP(disk->src->path, vdi) < 0) - goto error; - } - break; - case VIR_STORAGE_NET_PROTOCOL_GLUSTER: - if (qemuParseGlusterString(disk) < 0) - goto error; - - break; - case VIR_STORAGE_NET_PROTOCOL_ISCSI: - if (qemuParseISCSIString(disk) < 0) - goto error; - - break; - case VIR_STORAGE_NET_PROTOCOL_VXHS: - virReportError(VIR_ERR_INTERNAL_ERROR, - _("VxHS protocol does not support URI " - "syntax '%s'"), disk->src->path); - goto error; - break; - case VIR_STORAGE_NET_PROTOCOL_HTTP: - case VIR_STORAGE_NET_PROTOCOL_HTTPS: - case VIR_STORAGE_NET_PROTOCOL_FTP: - case VIR_STORAGE_NET_PROTOCOL_FTPS: - case VIR_STORAGE_NET_PROTOCOL_TFTP: - case VIR_STORAGE_NET_PROTOCOL_SSH: - case VIR_STORAGE_NET_PROTOCOL_LAST: - case VIR_STORAGE_NET_PROTOCOL_NONE: - /* ignored for now */ - break; - } - } - - if (virDomainDiskDefAssignAddress(xmlopt, disk, def) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Cannot assign address for device name '%s'"), - disk->dst); - goto error; - } - - if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) - goto error; - } else if (STREQ(arg, "-no-acpi")) { - def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_TRISTATE_SWITCH_ABSENT; - } else if (STREQ(arg, "-no-reboot")) { - def->onReboot = VIR_DOMAIN_LIFECYCLE_ACTION_DESTROY; - } else if (STREQ(arg, "-no-kvm")) { - def->virtType = VIR_DOMAIN_VIRT_QEMU; - } else if (STREQ(arg, "-enable-kvm")) { - def->virtType = VIR_DOMAIN_VIRT_KVM; - } else if (STREQ(arg, "-nographic")) { - nographics = true; - } else if (STREQ(arg, "-display")) { - WANT_VALUE(); - if (STREQ(val, "none")) - nographics = true; - } else if (STREQ(arg, "-full-screen")) { - fullscreen = true; - } else if (STREQ(arg, "-localtime")) { - def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME; - } else if (STREQ(arg, "-kernel")) { - WANT_VALUE(); - if (VIR_STRDUP(def->os.kernel, val) < 0) - goto error; - } else if (STREQ(arg, "-bios")) { - WANT_VALUE(); - if (VIR_ALLOC(def->os.loader) < 0 || - VIR_STRDUP(def->os.loader->path, val) < 0) - goto error; - } else if (STREQ(arg, "-initrd")) { - WANT_VALUE(); - if (VIR_STRDUP(def->os.initrd, val) < 0) - goto error; - } else if (STREQ(arg, "-append")) { - WANT_VALUE(); - if (VIR_STRDUP(def->os.cmdline, val) < 0) - goto error; - } else if (STREQ(arg, "-dtb")) { - WANT_VALUE(); - if (VIR_STRDUP(def->os.dtb, val) < 0) - goto error; - } else if (STREQ(arg, "-boot")) { - const char *token = NULL; - WANT_VALUE(); - - if (!strchr(val, ',')) { - qemuParseCommandLineBootDevs(def, val); - } else { - token = val; - while (token && *token) { - if (STRPREFIX(token, "order=")) { - token += strlen("order="); - qemuParseCommandLineBootDevs(def, token); - } else if (STRPREFIX(token, "menu=on")) { - def->os.bootmenu = 1; - } else if (STRPREFIX(token, "reboot-timeout=")) { - int num; - char *endptr; - if (virStrToLong_i(token + strlen("reboot-timeout="), - &endptr, 10, &num) < 0 || - (*endptr != '\0' && endptr != strchr(token, ','))) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("cannot parse reboot-timeout value")); - goto error; - } - if (num > 65535) - num = 65535; - else if (num < -1) - num = -1; - def->os.bios.rt_delay = num; - def->os.bios.rt_set = true; - } - token = strchr(token, ','); - /* This incrementation has to be done here in order to make it - * possible to pass the token pointer properly into the loop */ - if (token) - token++; - } - } - } else if (STREQ(arg, "-name")) { - char *process; - WANT_VALUE(); - process = strstr(val, ",process="); - if (process == NULL) { - if (VIR_STRDUP(def->name, val) < 0) - goto error; - } else { - if (VIR_STRNDUP(def->name, val, process - val) < 0) - goto error; - } - if (STREQ(def->name, "")) - VIR_FREE(def->name); - } else if (STREQ(arg, "-serial")) { - WANT_VALUE(); - if (STRNEQ(val, "none")) { - virDomainChrDefPtr chr; - - if (!(chr = virDomainChrDefNew(NULL))) - goto error; - - if (qemuParseCommandLineChr(chr->source, val) < 0) { - virDomainChrDefFree(chr); - goto error; - } - chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; - chr->target.port = def->nserials; - if (VIR_APPEND_ELEMENT(def->serials, def->nserials, chr) < 0) { - virDomainChrDefFree(chr); - goto error; - } - } - } else if (STREQ(arg, "-parallel")) { - WANT_VALUE(); - if (STRNEQ(val, "none")) { - virDomainChrDefPtr chr; - - if (!(chr = virDomainChrDefNew(NULL))) - goto error; - - if (qemuParseCommandLineChr(chr->source, val) < 0) { - virDomainChrDefFree(chr); - goto error; - } - chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL; - chr->target.port = def->nparallels; - if (VIR_APPEND_ELEMENT(def->parallels, def->nparallels, chr) < 0) { - virDomainChrDefFree(chr); - goto error; - } - } - } else if (STREQ(arg, "-usbdevice")) { - WANT_VALUE(); - if (STREQ(val, "tablet") || - STREQ(val, "mouse") || - STREQ(val, "keyboard")) { - virDomainInputDefPtr input; - if (VIR_ALLOC(input) < 0) - goto error; - input->bus = VIR_DOMAIN_INPUT_BUS_USB; - if (STREQ(val, "tablet")) - input->type = VIR_DOMAIN_INPUT_TYPE_TABLET; - else if (STREQ(val, "mouse")) - input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE; - else - input->type = VIR_DOMAIN_INPUT_TYPE_KBD; - - if (VIR_APPEND_ELEMENT(def->inputs, def->ninputs, input) < 0) { - virDomainInputDefFree(input); - goto error; - } - } else if (STRPREFIX(val, "disk:")) { - if (!(disk = virDomainDiskDefNew(xmlopt))) - goto error; - if (VIR_STRDUP(disk->src->path, val + strlen("disk:")) < 0) - goto error; - if (STRPREFIX(disk->src->path, "/dev/")) - disk->src->type = VIR_STORAGE_TYPE_BLOCK; - else - disk->src->type = VIR_STORAGE_TYPE_FILE; - disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; - disk->bus = VIR_DOMAIN_DISK_BUS_USB; - disk->removable = VIR_TRISTATE_SWITCH_ABSENT; - if (VIR_STRDUP(disk->dst, "sda") < 0) - goto error; - if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) - goto error; - } else { - virDomainHostdevDefPtr hostdev; - if (!(hostdev = qemuParseCommandLineUSB(val))) - goto error; - if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) { - virDomainHostdevDefFree(hostdev); - goto error; - } - } - } else if (STREQ(arg, "-net")) { - WANT_VALUE(); - if (!STRPREFIX(val, "nic") && STRNEQ(val, "none")) { - virDomainNetDefPtr net; - if (!(net = qemuParseCommandLineNet(xmlopt, val, nnics, nics))) - goto error; - if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0) { - virDomainNetDefFree(net); - goto error; - } - } - } else if (STREQ(arg, "-drive")) { - WANT_VALUE(); - if (!(disk = qemuParseCommandLineDisk(xmlopt, val, def, - nvirtiodisk, - ceph_args != NULL))) - goto error; - if (disk->bus == VIR_DOMAIN_DISK_BUS_VIRTIO) - nvirtiodisk++; - if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) - goto error; - } else if (STREQ(arg, "-pcidevice")) { - virDomainHostdevDefPtr hostdev; - WANT_VALUE(); - if (!(hostdev = qemuParseCommandLinePCI(val))) - goto error; - if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) { - virDomainHostdevDefFree(hostdev); - goto error; - } - } else if (STREQ(arg, "-soundhw")) { - const char *start; - WANT_VALUE(); - start = val; - while (start) { - const char *tmp = strchr(start, ','); - int type = -1; - if (STRPREFIX(start, "pcspk")) { - type = VIR_DOMAIN_SOUND_MODEL_PCSPK; - } else if (STRPREFIX(start, "sb16")) { - type = VIR_DOMAIN_SOUND_MODEL_SB16; - } else if (STRPREFIX(start, "es1370")) { - type = VIR_DOMAIN_SOUND_MODEL_ES1370; - } else if (STRPREFIX(start, "ac97")) { - type = VIR_DOMAIN_SOUND_MODEL_AC97; - } else if (STRPREFIX(start, "hda")) { - type = VIR_DOMAIN_SOUND_MODEL_ICH6; - } - - if (type != -1) { - virDomainSoundDefPtr snd; - if (VIR_ALLOC(snd) < 0) - goto error; - snd->model = type; - if (VIR_APPEND_ELEMENT(def->sounds, def->nsounds, snd) < 0) { - VIR_FREE(snd); - goto error; - } - } - - start = tmp ? tmp + 1 : NULL; - } - } else if (STREQ(arg, "-watchdog")) { - WANT_VALUE(); - int model = virDomainWatchdogModelTypeFromString(val); - - if (model != -1) { - virDomainWatchdogDefPtr wd; - if (VIR_ALLOC(wd) < 0) - goto error; - wd->model = model; - wd->action = VIR_DOMAIN_WATCHDOG_ACTION_RESET; - def->watchdog = wd; - } - } else if (STREQ(arg, "-watchdog-action") && def->watchdog) { - WANT_VALUE(); - int action = virDomainWatchdogActionTypeFromString(val); - - if (action != -1) - def->watchdog->action = action; - } else if (STREQ(arg, "-bootloader")) { - WANT_VALUE(); - if (VIR_STRDUP(def->os.bootloader, val) < 0) - goto error; - } else if (STREQ(arg, "-vmwarevga")) { - video = VIR_DOMAIN_VIDEO_TYPE_VMVGA; - } else if (STREQ(arg, "-std-vga")) { - video = VIR_DOMAIN_VIDEO_TYPE_VGA; - } else if (STREQ(arg, "-vga")) { - WANT_VALUE(); - if (STRNEQ(val, "none")) { - video = qemuVideoTypeFromString(val); - if (video < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("unknown video adapter type '%s'"), val); - goto error; - } - } - } else if (STREQ(arg, "-cpu")) { - WANT_VALUE(); - if (qemuParseCommandLineCPU(def, val) < 0) - goto error; - } else if (STREQ(arg, "-domid")) { - WANT_VALUE(); - /* ignore, generted on the fly */ - } else if (STREQ(arg, "-usb")) { - if (virDomainDefAddUSBController(def, -1, -1) < 0) - goto error; - } else if (STREQ(arg, "-pidfile")) { - WANT_VALUE(); - if (pidfile) - if (VIR_STRDUP(*pidfile, val) < 0) - goto error; - } else if (STREQ(arg, "-incoming")) { - WANT_VALUE(); - /* ignore, used via restore/migrate APIs */ - } else if (STREQ(arg, "-monitor")) { - WANT_VALUE(); - if (monConfig) { - virDomainChrSourceDefPtr chr; - - if (!(chr = virDomainChrSourceDefNew(NULL))) - goto error; - - if (qemuParseCommandLineChr(chr, val) < 0) { - virObjectUnref(chr); - goto error; - } - - *monConfig = chr; - } - } else if (STREQ(arg, "-global") && - STRPREFIX(progargv[i + 1], "PIIX4_PM.disable_s3=")) { - /* We want to parse only the known "-global" parameters, - * so the ones that we don't know are still added to the - * namespace */ - WANT_VALUE(); - - val += strlen("PIIX4_PM.disable_s3="); - if (STREQ(val, "0")) { - def->pm.s3 = VIR_TRISTATE_BOOL_YES; - } else if (STREQ(val, "1")) { - def->pm.s3 = VIR_TRISTATE_BOOL_NO; - } else { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("invalid value for disable_s3 parameter: " - "'%s'"), val); - goto error; - } - - } else if (STREQ(arg, "-global") && - STRPREFIX(progargv[i + 1], "PIIX4_PM.disable_s4=")) { - - WANT_VALUE(); - - val += strlen("PIIX4_PM.disable_s4="); - if (STREQ(val, "0")) { - def->pm.s4 = VIR_TRISTATE_BOOL_YES; - } else if (STREQ(val, "1")) { - def->pm.s4 = VIR_TRISTATE_BOOL_NO; - } else { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("invalid value for disable_s4 parameter: " - "'%s'"), val); - goto error; - } - - } else if (STREQ(arg, "-global") && - STRPREFIX(progargv[i + 1], "spapr-nvram.reg=")) { - WANT_VALUE(); - - if (VIR_ALLOC(def->nvram) < 0) - goto error; - - def->nvram->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO; - def->nvram->info.addr.spaprvio.has_reg = true; - - val += strlen("spapr-nvram.reg="); - if (virStrToLong_ull(val, NULL, 16, - &def->nvram->info.addr.spaprvio.reg) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("cannot parse nvram's address '%s'"), val); - goto error; - } - } else if (STREQ(arg, "-S") || - STREQ(arg, "-nodefaults") || - STREQ(arg, "-nodefconfig")) { - /* ignore, always added by libvirt */ - } else if (STREQ(arg, "-device") && progargv[1 + 1]) { - const char *opts = progargv[i + 1]; - - /* NB: we can't do WANT_VALUE until we're sure that we - * recognize the device, otherwise the !argRecognized - * logic below will be messed up - */ - - if (STRPREFIX(opts, "virtio-balloon")) { - WANT_VALUE(); - if (VIR_ALLOC(def->memballoon) < 0) - goto error; - def->memballoon->model = VIR_DOMAIN_MEMBALLOON_MODEL_VIRTIO; - } else { - /* add in new -device's here */ - - argRecognized = false; - } - } else if (STREQ(arg, "-M") || - STREQ(arg, "-machine")) { - /* This option has already been processed before entering this - * loop, so we just need to skip its argument and move along */ - WANT_VALUE(); - } else { - argRecognized = false; - } - - if (!argRecognized) { - char *tmp = NULL; - /* something we can't yet parse. Add it to the qemu namespace - * cmdline/environment advanced options and hope for the best - */ - VIR_WARN("unknown QEMU argument '%s', adding to the qemu namespace", - arg); - if (VIR_STRDUP(tmp, arg) < 0 || - VIR_APPEND_ELEMENT(cmd->args, cmd->num_args, tmp) < 0) { - VIR_FREE(tmp); - goto error; - } - } - } - -#undef WANT_VALUE - if (def->ndisks > 0 && ceph_args) { - char *hosts, *port, *saveptr = NULL, *token; - virDomainDiskDefPtr first_rbd_disk = NULL; - for (i = 0; i < def->ndisks; i++) { - if (def->disks[i]->src->type == VIR_STORAGE_TYPE_NETWORK && - def->disks[i]->src->protocol == VIR_STORAGE_NET_PROTOCOL_RBD) { - first_rbd_disk = def->disks[i]; - break; - } - } - - if (!first_rbd_disk) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("CEPH_ARGS was set without an rbd disk")); - goto error; - } - - /* CEPH_ARGS should be: -m host1[:port1][,host2[:port2]]... */ - if (!STRPREFIX(ceph_args, "-m ")) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("could not parse CEPH_ARGS '%s'"), ceph_args); - goto error; - } - if (VIR_STRDUP(hosts, strchr(ceph_args, ' ') + 1) < 0) - goto error; - first_rbd_disk->src->nhosts = 0; - token = strtok_r(hosts, ",", &saveptr); - while (token != NULL) { - if (VIR_REALLOC_N(first_rbd_disk->src->hosts, - first_rbd_disk->src->nhosts + 1) < 0) { - VIR_FREE(hosts); - goto error; - } - port = strchr(token, ':'); - if (port) { - *port++ = '\0'; - if (virStringParsePort(port, - &first_rbd_disk->src->hosts[first_rbd_disk->src->nhosts].port) < 0) { - VIR_FREE(hosts); - goto error; - } - } - if (VIR_STRDUP(first_rbd_disk->src->hosts[first_rbd_disk->src->nhosts].name, - token) < 0) { - VIR_FREE(hosts); - goto error; - } - first_rbd_disk->src->hosts[first_rbd_disk->src->nhosts].transport = VIR_STORAGE_NET_HOST_TRANS_TCP; - first_rbd_disk->src->hosts[first_rbd_disk->src->nhosts].socket = NULL; - - first_rbd_disk->src->nhosts++; - token = strtok_r(NULL, ",", &saveptr); - } - VIR_FREE(hosts); - - if (first_rbd_disk->src->nhosts == 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("found no rbd hosts in CEPH_ARGS '%s'"), ceph_args); - goto error; - } - } - - if (!nographics && (def->ngraphics == 0 || have_sdl)) { - virDomainGraphicsDefPtr sdl; - const char *display = qemuFindEnv(progenv, "DISPLAY"); - const char *xauth = qemuFindEnv(progenv, "XAUTHORITY"); - if (VIR_ALLOC(sdl) < 0) - goto error; - sdl->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL; - sdl->data.sdl.fullscreen = fullscreen; - if (VIR_STRDUP(sdl->data.sdl.display, display) < 0) { - VIR_FREE(sdl); - goto error; - } - if (VIR_STRDUP(sdl->data.sdl.xauth, xauth) < 0) { - VIR_FREE(sdl); - goto error; - } - - if (VIR_APPEND_ELEMENT(def->graphics, def->ngraphics, sdl) < 0) { - virDomainGraphicsDefFree(sdl); - goto error; - } - } - - if (def->ngraphics) { - virDomainVideoDefPtr vid; - if (!(vid = virDomainVideoDefNew())) - goto error; - vid->type = video; - - if (VIR_APPEND_ELEMENT(def->videos, def->nvideos, vid) < 0) { - virDomainVideoDefFree(vid); - goto error; - } - } - - /* - * having a balloon is the default, define one with type="none" to avoid it - */ - if (!def->memballoon) { - virDomainMemballoonDefPtr memballoon; - if (VIR_ALLOC(memballoon) < 0) - goto error; - memballoon->model = VIR_DOMAIN_MEMBALLOON_MODEL_NONE; - - def->memballoon = memballoon; - } - - VIR_FREE(nics); - - if (virDomainDefPostParse(def, caps, 0, xmlopt, NULL) < 0) - goto error; - - if (cmd->num_args || cmd->num_env) { - def->ns = *virDomainXMLOptionGetNamespace(xmlopt); - def->namespaceData = cmd; - } - else - qemuDomainCmdlineDefFree(cmd); - - virObjectUnref(qemuCaps); - return def; - - error: - virDomainDiskDefFree(disk); - qemuDomainCmdlineDefFree(cmd); - virDomainDefFree(def); - virStringListFree(list); - VIR_FREE(nics); - if (monConfig) { - virObjectUnref(*monConfig); - *monConfig = NULL; - } - if (pidfile) - VIR_FREE(*pidfile); - virObjectUnref(qemuCaps); - return NULL; -} - - -virDomainDefPtr qemuParseCommandLineString(virFileCachePtr capsCache, - virCapsPtr caps, - virDomainXMLOptionPtr xmlopt, - const char *args, - char **pidfile, - virDomainChrSourceDefPtr *monConfig, - bool *monJSON) -{ - char **progenv = NULL; - char **progargv = NULL; - virDomainDefPtr def = NULL; - - if (qemuStringToArgvEnv(args, &progenv, &progargv) < 0) - goto cleanup; - - def = qemuParseCommandLine(capsCache, caps, xmlopt, progenv, progargv, - pidfile, monConfig, monJSON); - - cleanup: - virStringListFree(progargv); - virStringListFree(progenv); - - return def; -} diff --git a/src/qemu/qemu_parse_command.h b/src/qemu/qemu_parse_command.h index 4dbb08fd59..4af2665eb8 100644 --- a/src/qemu/qemu_parse_command.h +++ b/src/qemu/qemu_parse_command.h @@ -22,22 +22,8 @@ #ifndef LIBVIRT_QEMU_PARSE_COMMAND_H # define LIBVIRT_QEMU_PARSE_COMMAND_H -# include "virfilecache.h" - # define QEMU_QXL_VGAMEM_DEFAULT 16 * 1024 -/* - * NB: def->name can be NULL upon return and the caller - * *must* decide how to fill in a name in this case - */ -virDomainDefPtr qemuParseCommandLineString(virFileCachePtr capsCache, - virCapsPtr caps, - virDomainXMLOptionPtr xmlopt, - const char *args, - char **pidfile, - virDomainChrSourceDefPtr *monConfig, - bool *monJSON); - void qemuParseKeywordsFree(int nkeywords, char **keywords, -- 2.21.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list