-Fri Apr 25 12:21:28 EST 2008 Daniel P. Berrange <berrange@redhat.coM>
+Fri Apr 25 16:45:28 EST 2008 Daniel P. Berrange <berrange@redhat.com>
+
+ * src/internal.c: Convenience macros for fixed arrays
+ * src/qemu_driver.c: Extract TTY paths for serial and parallel
+ devices too
+ * src/qemu_conf.c, src/qemu_conf.h: Support arbitrary serial
+ and parallel devices.
+ * tests/qemuxml2argvtest.c, tests/qemuxml2xmltest.c: Add tests
+ for serial and parallel devices
+ * tests/qemuxml2argvdata/*: Updated and added data files for
+ new test cases
+
+Fri Apr 25 12:21:28 EST 2008 Daniel P. Berrange <berrange@redhat.com>
* docs/page.xsl, docs/libvir.css: Re-arrange layout to workaround
IE6 bugs
#define STRNEQLEN(a,b,n) (strncmp((a),(b),(n)) != 0)
#define STRCASENEQLEN(a,b,n) (strncasecmp((a),(b),(n)) != 0)
+
+#define NUL_TERMINATE(buf) do { (buf)[sizeof(buf)-1] = '\0'; } while (0)
+#define ARRAY_CARDINALITY(Array) (sizeof (Array) / sizeof *(Array))
+
/* If configured with --enable-debug=yes then library calls
* are printed to stderr for debugging.
*/
struct qemud_vm_disk_def *disk = def->disks;
struct qemud_vm_net_def *net = def->nets;
struct qemud_vm_input_def *input = def->inputs;
+ struct qemud_vm_chr_def *serial = def->serials;
+ struct qemud_vm_chr_def *parallel = def->parallels;
while (disk) {
struct qemud_vm_disk_def *prev = disk;
input = input->next;
free(prev);
}
+ while (serial) {
+ struct qemud_vm_chr_def *prev = serial;
+ serial = serial->next;
+ free(prev);
+ }
+ while (parallel) {
+ struct qemud_vm_chr_def *prev = parallel;
+ parallel = parallel->next;
+ free(prev);
+ }
xmlFree(def->keymap);
free(def);
}
}
+/* Parse the XML definition for a character device
+ * @param net pre-allocated & zero'd net record
+ * @param node XML nodeset to parse for net definition
+ * @return 0 on success, -1 on failure
+ *
+ * The XML we're dealing with looks like
+ *
+ * <serial type="pty">
+ * <source path="/dev/pts/3"/>
+ * <target port="1"/>
+ * </serial>
+ *
+ * <serial type="dev">
+ * <source path="/dev/ttyS0"/>
+ * <target port="1"/>
+ * </serial>
+ *
+ * <serial type="tcp">
+ * <source mode="connect" host="0.0.0.0" service="2445"/>
+ * <target port="1"/>
+ * </serial>
+ *
+ * <serial type="tcp">
+ * <source mode="bind" host="0.0.0.0" service="2445"/>
+ * <target port="1"/>
+ * </serial>
+ *
+ * <serial type="udp">
+ * <source mode="bind" host="0.0.0.0" service="2445"/>
+ * <source mode="connect" host="0.0.0.0" service="2445"/>
+ * <target port="1"/>
+ * </serial>
+ *
+ * <serial type="unix">
+ * <source mode="bind" path="/tmp/foo"/>
+ * <target port="1"/>
+ * </serial>
+ *
+ */
+static int qemudParseCharXML(virConnectPtr conn,
+ struct qemud_vm_chr_def *chr,
+ int portNum,
+ xmlNodePtr node) {
+ xmlNodePtr cur;
+ xmlChar *type = NULL;
+ xmlChar *bindHost = NULL;
+ xmlChar *bindService = NULL;
+ xmlChar *connectHost = NULL;
+ xmlChar *connectService = NULL;
+ xmlChar *path = NULL;
+ xmlChar *mode = NULL;
+ xmlChar *protocol = NULL;
+ int ret = -1;
+
+ chr->srcType = QEMUD_CHR_SRC_TYPE_PTY;
+ type = xmlGetProp(node, BAD_CAST "type");
+ if (type != NULL) {
+ if (xmlStrEqual(type, BAD_CAST "null"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_NULL;
+ else if (xmlStrEqual(type, BAD_CAST "vc"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_VC;
+ else if (xmlStrEqual(type, BAD_CAST "pty"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_PTY;
+ else if (xmlStrEqual(type, BAD_CAST "dev"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_DEV;
+ else if (xmlStrEqual(type, BAD_CAST "file"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_FILE;
+ else if (xmlStrEqual(type, BAD_CAST "pipe"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_PIPE;
+ else if (xmlStrEqual(type, BAD_CAST "stdio"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_STDIO;
+ else if (xmlStrEqual(type, BAD_CAST "udp"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_UDP;
+ else if (xmlStrEqual(type, BAD_CAST "tcp"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_TCP;
+ else if (xmlStrEqual(type, BAD_CAST "unix"))
+ chr->srcType = QEMUD_CHR_SRC_TYPE_UNIX;
+ else
+ chr->srcType = QEMUD_CHR_SRC_TYPE_NULL;
+ }
+
+ cur = node->children;
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (xmlStrEqual(cur->name, BAD_CAST "source")) {
+ if (mode == NULL)
+ mode = xmlGetProp(cur, BAD_CAST "mode");
+
+ switch (chr->srcType) {
+ case QEMUD_CHR_SRC_TYPE_PTY:
+ case QEMUD_CHR_SRC_TYPE_DEV:
+ case QEMUD_CHR_SRC_TYPE_FILE:
+ case QEMUD_CHR_SRC_TYPE_PIPE:
+ case QEMUD_CHR_SRC_TYPE_UNIX:
+ if (path == NULL)
+ path = xmlGetProp(cur, BAD_CAST "path");
+
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_UDP:
+ case QEMUD_CHR_SRC_TYPE_TCP:
+ if (mode == NULL ||
+ STREQ((const char *)mode, "connect")) {
+
+ if (connectHost == NULL)
+ connectHost = xmlGetProp(cur, BAD_CAST "host");
+ if (connectService == NULL)
+ connectService = xmlGetProp(cur, BAD_CAST "service");
+ } else {
+ if (bindHost == NULL)
+ bindHost = xmlGetProp(cur, BAD_CAST "host");
+ if (bindService == NULL)
+ bindService = xmlGetProp(cur, BAD_CAST "service");
+ }
+
+ if (chr->srcType == QEMUD_CHR_SRC_TYPE_UDP) {
+ xmlFree(mode);
+ mode = NULL;
+ }
+ }
+ } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
+ if (protocol == NULL)
+ protocol = xmlGetProp(cur, BAD_CAST "type");
+ }
+ }
+ cur = cur->next;
+ }
+
+
+ chr->dstPort = portNum;
+
+ switch (chr->srcType) {
+ case QEMUD_CHR_SRC_TYPE_NULL:
+ /* Nada */
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_VC:
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_PTY:
+ /* @path attribute is an output only property - pty is auto-allocted */
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_DEV:
+ case QEMUD_CHR_SRC_TYPE_FILE:
+ case QEMUD_CHR_SRC_TYPE_PIPE:
+ if (path == NULL) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Missing source path attribute for char device"));
+ goto cleanup;
+ }
+
+ strncpy(chr->srcData.file.path, (const char *)path,
+ sizeof(chr->srcData.file.path));
+ NUL_TERMINATE(chr->srcData.file.path);
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_STDIO:
+ /* Nada */
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_TCP:
+ if (mode == NULL ||
+ STREQ((const char *)mode, "connect")) {
+ if (connectHost == NULL) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Missing source host attribute for char device"));
+ goto cleanup;
+ }
+ if (connectService == NULL) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Missing source service attribute for char device"));
+ goto cleanup;
+ }
+
+ strncpy(chr->srcData.tcp.host, (const char *)connectHost,
+ sizeof(chr->srcData.tcp.host));
+ NUL_TERMINATE(chr->srcData.tcp.host);
+ strncpy(chr->srcData.tcp.service, (const char *)connectService,
+ sizeof(chr->srcData.tcp.service));
+ NUL_TERMINATE(chr->srcData.tcp.service);
+
+ chr->srcData.tcp.listen = 0;
+ } else {
+ if (bindHost == NULL) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Missing source host attribute for char device"));
+ goto cleanup;
+ }
+ if (bindService == NULL) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Missing source service attribute for char device"));
+ goto cleanup;
+ }
+
+ strncpy(chr->srcData.tcp.host, (const char *)bindHost,
+ sizeof(chr->srcData.tcp.host));
+ NUL_TERMINATE(chr->srcData.tcp.host);
+ strncpy(chr->srcData.tcp.service, (const char *)bindService,
+ sizeof(chr->srcData.tcp.service));
+ NUL_TERMINATE(chr->srcData.tcp.service);
+
+ chr->srcData.tcp.listen = 1;
+ }
+ if (protocol != NULL &&
+ STREQ((const char *)protocol, "telnet"))
+ chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET;
+ else
+ chr->srcData.tcp.protocol = QEMUD_CHR_SRC_TCP_PROTOCOL_RAW;
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_UDP:
+ if (connectService == NULL) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Missing source service attribute for char device"));
+ goto cleanup;
+ }
+
+ if (connectHost != NULL) {
+ strncpy(chr->srcData.udp.connectHost, (const char *)connectHost,
+ sizeof(chr->srcData.udp.connectHost));
+ NUL_TERMINATE(chr->srcData.udp.connectHost);
+ }
+ strncpy(chr->srcData.udp.connectService, (const char *)connectService,
+ sizeof(chr->srcData.udp.connectService));
+ NUL_TERMINATE(chr->srcData.udp.connectService);
+
+ if (bindHost != NULL) {
+ strncpy(chr->srcData.udp.bindHost, (const char *)bindHost,
+ sizeof(chr->srcData.udp.bindHost));
+ NUL_TERMINATE(chr->srcData.udp.bindHost);
+ }
+ if (bindService != NULL) {
+ strncpy(chr->srcData.udp.bindService, (const char *)bindService,
+ sizeof(chr->srcData.udp.bindService));
+ NUL_TERMINATE(chr->srcData.udp.bindService);
+ }
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_UNIX:
+ if (path == NULL) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("Missing source path attribute for char device"));
+ goto cleanup;
+ }
+
+ if (mode != NULL &&
+ STRNEQ((const char *)mode, "connect"))
+ chr->srcData.nix.listen = 1;
+ else
+ chr->srcData.nix.listen = 0;
+
+ strncpy(chr->srcData.nix.path, (const char *)path,
+ sizeof(chr->srcData.nix.path));
+ NUL_TERMINATE(chr->srcData.nix.path);
+ break;
+ }
+
+ ret = 0;
+
+cleanup:
+ xmlFree(mode);
+ xmlFree(protocol);
+ xmlFree(type);
+ xmlFree(bindHost);
+ xmlFree(bindService);
+ xmlFree(connectHost);
+ xmlFree(connectService);
+ xmlFree(path);
+
+ return ret;
+}
+
+
+static int qemudParseCharXMLDevices(virConnectPtr conn,
+ xmlXPathContextPtr ctxt,
+ const char *xpath,
+ unsigned int *ndevs,
+ struct qemud_vm_chr_def **devs)
+{
+ xmlXPathObjectPtr obj;
+ int i, ret = -1;
+
+ obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+ if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
+ (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
+ struct qemud_vm_chr_def *prev = *devs;
+ if (ndevs == NULL &&
+ obj->nodesetval->nodeNr > 1) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ "%s", _("too many character devices"));
+ goto cleanup;
+ }
+
+ for (i = 0; i < obj->nodesetval->nodeNr; i++) {
+ struct qemud_vm_chr_def *chr = calloc(1, sizeof(*chr));
+ if (!chr) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
+ "%s",
+ _("failed to allocate space for char device"));
+ goto cleanup;
+ }
+
+ if (qemudParseCharXML(conn, chr, i, obj->nodesetval->nodeTab[i]) < 0) {
+ free(chr);
+ goto cleanup;
+ }
+ if (ndevs)
+ (*ndevs)++;
+ chr->next = NULL;
+ if (i == 0) {
+ *devs = chr;
+ } else {
+ prev->next = chr;
+ }
+ prev = chr;
+ }
+ }
+
+ ret = 0;
+
+cleanup:
+ xmlXPathFreeObject(obj);
+ return ret;
+}
+
+
/* Parse the XML definition for a network interface */
static int qemudParseInputXML(virConnectPtr conn,
struct qemud_vm_input_def *input,
}
}
xmlXPathFreeObject(obj);
+ obj = NULL;
+
+ /* analysis of the character devices */
+ if (qemudParseCharXMLDevices(conn, ctxt,
+ "/domain/devices/parallel",
+ &def->nparallels,
+ &def->parallels) < 0)
+ goto error;
+ if (qemudParseCharXMLDevices(conn, ctxt,
+ "/domain/devices/serial",
+ &def->nserials,
+ &def->serials) < 0)
+ goto error;
+
+ /*
+ * If no serial devices were listed, then look for console
+ * devices which is the legacy syntax for the same thing
+ */
+ if (def->nserials == 0) {
+ obj = xmlXPathEval(BAD_CAST "/domain/devices/console", ctxt);
+ if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
+ (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
+ struct qemud_vm_chr_def *chr = calloc(1, sizeof(*chr));
+ if (!chr) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
+ "%s",
+ _("failed to allocate space for char device"));
+ goto error;
+ }
+
+ if (qemudParseCharXML(conn, chr, 0, obj->nodesetval->nodeTab[0]) < 0) {
+ free(chr);
+ goto error;
+ }
+ def->nserials = 1;
+ def->serials = chr;
+ }
+ xmlXPathFreeObject(obj);
+ }
/* analysis of the network devices */
return NULL;
}
+static int qemudBuildCommandLineChrDevStr(struct qemud_vm_chr_def *dev,
+ char *buf,
+ int buflen)
+{
+ switch (dev->srcType) {
+ case QEMUD_CHR_SRC_TYPE_NULL:
+ strncpy(buf, "null", buflen);
+ buf[buflen-1] = '\0';
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_VC:
+ strncpy(buf, "vc", buflen);
+ buf[buflen-1] = '\0';
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_PTY:
+ strncpy(buf, "pty", buflen);
+ buf[buflen-1] = '\0';
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_DEV:
+ if (snprintf(buf, buflen, "%s",
+ dev->srcData.file.path) >= buflen)
+ return -1;
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_FILE:
+ if (snprintf(buf, buflen, "file:%s",
+ dev->srcData.file.path) >= buflen)
+ return -1;
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_PIPE:
+ if (snprintf(buf, buflen, "pipe:%s",
+ dev->srcData.file.path) >= buflen)
+ return -1;
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_STDIO:
+ strncpy(buf, "stdio", buflen);
+ buf[buflen-1] = '\0';
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_UDP:
+ if (snprintf(buf, buflen, "udp:%s:%s@%s:%s",
+ dev->srcData.udp.connectHost,
+ dev->srcData.udp.connectService,
+ dev->srcData.udp.bindHost,
+ dev->srcData.udp.bindService) >= buflen)
+ return -1;
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_TCP:
+ if (snprintf(buf, buflen, "%s:%s:%s%s",
+ dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET ? "telnet" : "tcp",
+ dev->srcData.tcp.host,
+ dev->srcData.tcp.service,
+ dev->srcData.tcp.listen ? ",listen" : "") >= buflen)
+ return -1;
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_UNIX:
+ if (snprintf(buf, buflen, "unix:%s%s",
+ dev->srcData.nix.path,
+ dev->srcData.nix.listen ? ",listen" : "") >= buflen)
+ return -1;
+ break;
+ }
+
+ return 0;
+}
+
/*
* Constructs a argv suitable for launching qemu with config defined
* for a given virtual machine.
struct qemud_vm_disk_def *disk = vm->def->disks;
struct qemud_vm_net_def *net = vm->def->nets;
struct qemud_vm_input_def *input = vm->def->inputs;
+ struct qemud_vm_chr_def *serial = vm->def->serials;
+ struct qemud_vm_chr_def *parallel = vm->def->parallels;
struct utsname ut;
int disableKQEMU = 0;
(vm->def->nnets > 0 ? (4 * vm->def->nnets) : 2) + /* networks */
1 + /* usb */
2 * vm->def->ninputs + /* input devices */
+ (vm->def->nserials > 0 ? (2 * vm->def->nserials) : 2) + /* character devices */
+ (vm->def->nparallels > 0 ? (2 * vm->def->nparallels) : 2) + /* character devices */
2 + /* memory*/
2 + /* cpus */
2 + /* boot device */
}
}
+ if (!serial) {
+ if (!((*argv)[++n] = strdup("-serial")))
+ goto no_memory;
+ if (!((*argv)[++n] = strdup("none")))
+ goto no_memory;
+ } else {
+ while (serial) {
+ char buf[4096];
+
+ if (qemudBuildCommandLineChrDevStr(serial, buf, sizeof(buf)) < 0)
+ goto error;
+
+ if (!((*argv)[++n] = strdup("-serial")))
+ goto no_memory;
+ if (!((*argv)[++n] = strdup(buf)))
+ goto no_memory;
+
+ serial = serial->next;
+ }
+ }
+
+ if (!parallel) {
+ if (!((*argv)[++n] = strdup("-parallel")))
+ goto no_memory;
+ if (!((*argv)[++n] = strdup("none")))
+ goto no_memory;
+ } else {
+ while (parallel) {
+ char buf[4096];
+
+ if (qemudBuildCommandLineChrDevStr(parallel, buf, sizeof(buf)) < 0)
+ goto error;
+
+ if (!((*argv)[++n] = strdup("-parallel")))
+ goto no_memory;
+ if (!((*argv)[++n] = strdup(buf)))
+ goto no_memory;
+
+ parallel = parallel->next;
+ }
+ }
+
if (!((*argv)[++n] = strdup("-usb")))
goto no_memory;
while (input) {
return 0;
}
+static int qemudGenerateXMLChar(virBufferPtr buf,
+ const struct qemud_vm_chr_def *dev,
+ const char *type)
+{
+ const char *const types[] = {
+ "null",
+ "vc",
+ "pty",
+ "dev",
+ "file",
+ "pipe",
+ "stdio",
+ "udp",
+ "tcp",
+ "unix"
+ };
+ /*verify(ARRAY_CARDINALITY(types) == QEMUD_CHR_SRC_TYPE_LAST);*/
+
+ if (dev->srcType < 0 || dev->srcType >= QEMUD_CHR_SRC_TYPE_LAST)
+ return -1;
+
+ /* Compat with legacy <console tty='/dev/pts/5'/> syntax */
+ if (STREQ(type, "console") &&
+ dev->srcType == QEMUD_CHR_SRC_TYPE_PTY &&
+ dev->srcData.file.path[0] != '\0') {
+ if (virBufferVSprintf(buf, " <%s type='%s' tty='%s'>\n",
+ type, types[dev->srcType],
+ dev->srcData.file.path) < 0)
+ return -1;
+ } else {
+ if (virBufferVSprintf(buf, " <%s type='%s'>\n",
+ type, types[dev->srcType]) < 0)
+ return -1;
+ }
+
+ switch (dev->srcType) {
+ case QEMUD_CHR_SRC_TYPE_NULL:
+ case QEMUD_CHR_SRC_TYPE_VC:
+ case QEMUD_CHR_SRC_TYPE_STDIO:
+ /* nada */
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_PTY:
+ case QEMUD_CHR_SRC_TYPE_DEV:
+ case QEMUD_CHR_SRC_TYPE_FILE:
+ case QEMUD_CHR_SRC_TYPE_PIPE:
+ if (dev->srcType != QEMUD_CHR_SRC_TYPE_PTY ||
+ dev->srcData.file.path[0]) {
+ if (virBufferVSprintf(buf, " <source path='%s'/>\n",
+ dev->srcData.file.path) < 0)
+ return -1;
+ }
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_UDP:
+ if (dev->srcData.udp.bindService[0] != '\0' &&
+ dev->srcData.udp.bindHost[0] != '\0') {
+ if (virBufferVSprintf(buf, " <source mode='bind' host='%s' service='%s'/>\n",
+ dev->srcData.udp.bindHost,
+ dev->srcData.udp.bindService) < 0)
+ return -1;
+ } else if (dev->srcData.udp.bindHost[0] !='\0') {
+ if (virBufferVSprintf(buf, " <source mode='bind' host='%s'/>\n",
+ dev->srcData.udp.bindHost) < 0)
+ return -1;
+ } else if (dev->srcData.udp.bindService[0] != '\0') {
+ if (virBufferVSprintf(buf, " <source mode='bind' service='%s'/>\n",
+ dev->srcData.udp.bindService) < 0)
+ return -1;
+ }
+
+ if (dev->srcData.udp.connectService[0] != '\0' &&
+ dev->srcData.udp.connectHost[0] != '\0') {
+ if (virBufferVSprintf(buf, " <source mode='connect' host='%s' service='%s'/>\n",
+ dev->srcData.udp.connectHost,
+ dev->srcData.udp.connectService) < 0)
+ return -1;
+ } else if (dev->srcData.udp.connectHost[0] != '\0') {
+ if (virBufferVSprintf(buf, " <source mode='connect' host='%s'/>\n",
+ dev->srcData.udp.connectHost) < 0)
+ return -1;
+ } else if (dev->srcData.udp.connectService[0] != '\0') {
+ if (virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n",
+ dev->srcData.udp.connectService) < 0)
+ return -1;
+ }
+
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_TCP:
+ if (virBufferVSprintf(buf, " <source mode='%s' host='%s' service='%s'/>\n",
+ dev->srcData.tcp.listen ? "bind" : "connect",
+ dev->srcData.tcp.host,
+ dev->srcData.tcp.service) < 0)
+ return -1;
+ if (virBufferVSprintf(buf, " <protocol type='%s'/>\n",
+ dev->srcData.tcp.protocol == QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET
+ ? "telnet" : "raw") < 0)
+ return -1;
+ break;
+
+ case QEMUD_CHR_SRC_TYPE_UNIX:
+ if (virBufferVSprintf(buf, " <source mode='%s' path='%s'/>\n",
+ dev->srcData.nix.listen ? "bind" : "connect",
+ dev->srcData.nix.path) < 0)
+ return -1;
+ break;
+ }
+
+ if (virBufferVSprintf(buf, " <target port='%d'/>\n",
+ dev->dstPort) < 0)
+ return -1;
+
+ if (virBufferVSprintf(buf, " </%s>\n",
+ type) < 0)
+ return -1;
+
+ return 0;
+}
+
+
/* Generate an XML document describing the guest's configuration */
char *qemudGenerateXML(virConnectPtr conn,
struct qemud_driver *driver ATTRIBUTE_UNUSED,
virBufferPtr buf = 0;
unsigned char *uuid;
char uuidstr[VIR_UUID_STRING_BUFLEN];
- struct qemud_vm_disk_def *disk;
- struct qemud_vm_net_def *net;
- struct qemud_vm_input_def *input;
+ const struct qemud_vm_disk_def *disk;
+ const struct qemud_vm_net_def *net;
+ const struct qemud_vm_input_def *input;
+ const struct qemud_vm_chr_def *chr;
const char *type = NULL;
int n;
net = net->next;
}
+ chr = def->serials;
+ while (chr) {
+ if (qemudGenerateXMLChar(buf, chr, "serial") < 0)
+ goto no_memory;
+
+ chr = chr->next;
+ }
+
+ chr = def->parallels;
+ while (chr) {
+ if (qemudGenerateXMLChar(buf, chr, "parallel") < 0)
+ goto no_memory;
+
+ chr = chr->next;
+ }
+
+ /* First serial device is the primary console */
+ if (def->nserials > 0 &&
+ qemudGenerateXMLChar(buf, def->serials, "console") < 0)
+ goto no_memory;
+
input = def->inputs;
while (input) {
if (input->bus != QEMU_INPUT_BUS_PS2 &&
break;
}
- if (def->graphicsType == QEMUD_GRAPHICS_VNC) {
- }
-
if (virBufferAddLit(buf, " </devices>\n") < 0)
goto no_memory;
struct qemud_vm_net_def *next;
};
+enum qemu_vm_chr_dst_type {
+ QEMUD_CHR_SRC_TYPE_NULL,
+ QEMUD_CHR_SRC_TYPE_VC,
+ QEMUD_CHR_SRC_TYPE_PTY,
+ QEMUD_CHR_SRC_TYPE_DEV,
+ QEMUD_CHR_SRC_TYPE_FILE,
+ QEMUD_CHR_SRC_TYPE_PIPE,
+ QEMUD_CHR_SRC_TYPE_STDIO,
+ QEMUD_CHR_SRC_TYPE_UDP,
+ QEMUD_CHR_SRC_TYPE_TCP,
+ QEMUD_CHR_SRC_TYPE_UNIX,
+
+ QEMUD_CHR_SRC_TYPE_LAST,
+};
+
+enum {
+ QEMUD_CHR_SRC_TCP_PROTOCOL_RAW,
+ QEMUD_CHR_SRC_TCP_PROTOCOL_TELNET,
+};
+
+struct qemud_vm_chr_def {
+ int dstPort;
+
+ int srcType;
+ union {
+ struct {
+ char path[PATH_MAX];
+ } file; /* pty, file, pipe, or device */
+ struct {
+ char host[BR_INET_ADDR_MAXLEN];
+ char service[BR_INET_ADDR_MAXLEN];
+ int listen;
+ int protocol;
+ } tcp;
+ struct {
+ char bindHost[BR_INET_ADDR_MAXLEN];
+ char bindService[BR_INET_ADDR_MAXLEN];
+ char connectHost[BR_INET_ADDR_MAXLEN];
+ char connectService[BR_INET_ADDR_MAXLEN];
+ } udp;
+ struct {
+ char path[PATH_MAX];
+ int listen;
+ } nix;
+ } srcData;
+
+ struct qemud_vm_chr_def *next;
+};
enum qemu_vm_input_type {
QEMU_INPUT_TYPE_MOUSE,
char vncListen[BR_INET_ADDR_MAXLEN];
char *keymap;
- int ndisks;
+ unsigned int ndisks;
struct qemud_vm_disk_def *disks;
- int nnets;
+ unsigned int nnets;
struct qemud_vm_net_def *nets;
- int ninputs;
+ unsigned int ninputs;
struct qemud_vm_input_def *inputs;
+
+ unsigned int nserials;
+ struct qemud_vm_chr_def *serials;
+
+ unsigned int nparallels;
+ struct qemud_vm_chr_def *parallels;
};
/* Guest VM runtime state */
const char *what)
{
#define MONITOR_TIMEOUT 3000
-
int got = 0;
buf[0] = '\0';
return ret;
}
-static int qemudExtractMonitorPath(const char *haystack, char *path, int pathmax) {
+static int qemudExtractMonitorPath(const char *haystack,
+ size_t *offset,
+ char *path, int pathmax) {
static const char needle[] = "char device redirected to";
char *tmp;
- if (!(tmp = strstr(haystack, needle)))
+ /* First look for our magic string */
+ if (!(tmp = strstr(haystack + *offset, needle)))
return -1;
+ /* Grab all the trailing data */
strncpy(path, tmp+sizeof(needle), pathmax-1);
path[pathmax-1] = '\0';
- while (*path) {
- /*
- * The monitor path ends at first whitespace char
- * so lets search for it & NULL terminate it there
- */
- if (isspace(to_uchar(*path))) {
- *path = '\0';
+ /*
+ * And look for first whitespace character and nul terminate
+ * to mark end of the pty path
+ */
+ tmp = path;
+ while (*tmp) {
+ if (isspace(to_uchar(*tmp))) {
+ *tmp = '\0';
+ *offset += (sizeof(needle)-1) + strlen(path);
return 0;
}
- path++;
+ tmp++;
}
/*
* We found a path, but didn't find any whitespace,
* so it must be still incomplete - we should at
- * least see a \n
+ * least see a \n - indicate that we want to carry
+ * on trying again
*/
return -1;
}
static int
-qemudOpenMonitorPath(virConnectPtr conn,
- struct qemud_driver *driver,
- struct qemud_vm *vm,
- const char *output,
- int fd ATTRIBUTE_UNUSED)
+qemudFindCharDevicePTYs(virConnectPtr conn,
+ struct qemud_driver *driver,
+ struct qemud_vm *vm,
+ const char *output,
+ int fd ATTRIBUTE_UNUSED)
{
char monitor[PATH_MAX];
+ size_t offset = 0;
+ struct qemud_vm_chr_def *chr;
- if (qemudExtractMonitorPath(output, monitor, sizeof(monitor)) < 0)
+ /* The order in which QEMU prints out the PTY paths is
+ the order in which it procsses its monitor, serial
+ and parallel device args. This code must match that
+ ordering.... */
+
+ /* So first comes the monitor device */
+ if (qemudExtractMonitorPath(output, &offset, monitor, sizeof(monitor)) < 0)
return 1; /* keep reading */
+ /* then the serial devices */
+ chr = vm->def->serials;
+ while (chr) {
+ if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) {
+ if (qemudExtractMonitorPath(output, &offset,
+ chr->srcData.file.path,
+ sizeof(chr->srcData.file.path)) < 0)
+ return 1; /* keep reading */
+ }
+ chr = chr->next;
+ }
+
+ /* and finally the parallel devices */
+ chr = vm->def->parallels;
+ while (chr) {
+ if (chr->srcType == QEMUD_CHR_SRC_TYPE_PTY) {
+ if (qemudExtractMonitorPath(output, &offset,
+ chr->srcData.file.path,
+ sizeof(chr->srcData.file.path)) < 0)
+ return 1; /* keep reading */
+ }
+ chr = chr->next;
+ }
+
+ /* Got them all, so now open the monitor console */
return qemudOpenMonitor(conn, driver, vm, monitor);
}
int ret = qemudReadMonitorOutput(conn,
driver, vm, vm->stderr,
buf, sizeof(buf),
- qemudOpenMonitorPath,
+ qemudFindCharDevicePTYs,
"console");
buf[sizeof(buf)-1] = '\0';
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot d -cdrom /dev/cdrom -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot d -cdrom /dev/cdrom -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot a -hda /dev/HostVG/QEMUGuest1 -fda /tmp/firmware.img -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot a -hda /dev/HostVG/QEMUGuest1 -fda /tmp/firmware.img -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot n -hda /dev/HostVG/QEMUGuest1 -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot n -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -localtime -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -localtime -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
\ No newline at end of file
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial pty -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -cdrom /root/boot.iso -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -cdrom /root/boot.iso -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -fda /dev/fd0 -fdb /tmp/firmware.img -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -fda /dev/fd0 -fdb /tmp/firmware.img -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -hdb /dev/HostVG/QEMUGuest2 -hdc /tmp/data.img -hdd /tmp/logs.img -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -hdb /dev/HostVG/QEMUGuest2 -hdc /tmp/data.img -hdd /tmp/logs.img -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb -vnc 127.0.0.1:3
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -vnc 127.0.0.1:3
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb -usbdevice mouse
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -usbdevice mouse
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb -usbdevice tablet
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb -usbdevice tablet
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-reboot -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-reboot -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -usb
\ No newline at end of file
-/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net nic,macaddr=00:11:22:33:44:55,vlan=0 -net user,vlan=0 -usb
\ No newline at end of file
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net nic,macaddr=00:11:22:33:44:55,vlan=0 -net user,vlan=0 -serial none -parallel none -usb
\ No newline at end of file
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial none -parallel tcp:127.0.0.1:9999,listen -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <parallel type='tcp'>
+ <source mode='bind' host='127.0.0.1' service='9999'/>
+ <protocol type='raw'/>
+ <target port='0'/>
+ </parallel>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial /dev/ttyS2 -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='dev'>
+ <source path='/dev/ttyS2'/>
+ <target port='0'/>
+ </serial>
+ <console type='dev'>
+ <source path='/dev/ttyS2'/>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial file:/tmp/serial.log -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='file'>
+ <source path='/tmp/serial.log'/>
+ <target port='0'/>
+ </serial>
+ <console type='file'>
+ <source path='/tmp/serial.log'/>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial pty -serial file:/tmp/serial.log -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <serial type='file'>
+ <source path='/tmp/serial.log'/>
+ <target port='1'/>
+ </serial>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial pty -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='pty'>
+ <target port='0'/>
+ </serial>
+ <console type='pty'>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial telnet:127.0.0.1:9999,listen -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='tcp'>
+ <source mode='bind' host='127.0.0.1' service='9999'/>
+ <protocol type='telnet'/>
+ <target port='0'/>
+ </serial>
+ <console type='tcp'>
+ <source mode='bind' host='127.0.0.1' service='9999'/>
+ <protocol type='telnet'/>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial tcp:127.0.0.1:9999 -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='tcp'>
+ <source mode='connect' host='127.0.0.1' service='9999'/>
+ <protocol type='raw'/>
+ <target port='0'/>
+ </serial>
+ <console type='tcp'>
+ <source mode='connect' host='127.0.0.1' service='9999'/>
+ <protocol type='raw'/>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial udp:127.0.0.1:9998@127.0.0.1:9999 -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='udp'>
+ <source mode='bind' host='127.0.0.1' service='9999'/>
+ <source mode='connect' host='127.0.0.1' service='9998'/>
+ <target port='0'/>
+ </serial>
+ <console type='udp'>
+ <source mode='bind' host='127.0.0.1' service='9999'/>
+ <source mode='connect' host='127.0.0.1' service='9998'/>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial unix:/tmp/serial.sock -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='unix'>
+ <source mode='connect' path='/tmp/serial.sock'/>
+ <target port='0'/>
+ </serial>
+ <console type='unix'>
+ <source mode='connect' path='/tmp/serial.sock'/>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
--- /dev/null
+/usr/bin/qemu -M pc -m 214 -smp 1 -nographic -monitor pty -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net none -serial vc -parallel none -usb
\ No newline at end of file
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219200</memory>
+ <currentMemory>219200</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda'/>
+ </disk>
+ <serial type='vc'>
+ <target port='0'/>
+ </serial>
+ <console type='vc'>
+ <target port='0'/>
+ </console>
+ </devices>
+</domain>
#include "qemu_conf.h"
static char *progname;
-static char *abs_top_srcdir;
+static char *abs_srcdir;
static struct qemud_driver driver;
#define MAX_FILE 4096
tmp++;
}
- if (strcmp(expectargv, actualargv)) {
- if (getenv("DEBUG_TESTS")) {
- printf("Expect %4d '%s'\n", (int)strlen(expectargv), expectargv);
- printf("Actual %4d '%s'\n", (int)strlen(actualargv), actualargv);
- }
+ if (STRNEQ(expectargv, actualargv)) {
+ virtTestDifference(stderr, expectargv, actualargv);
goto fail;
}
static int testCompareXMLToArgvHelper(const void *data) {
char xml[PATH_MAX];
char args[PATH_MAX];
- snprintf(xml, PATH_MAX, "%s/tests/qemuxml2argvdata/qemuxml2argv-%s.xml",
- abs_top_srcdir, (const char*)data);
- snprintf(args, PATH_MAX, "%s/tests/qemuxml2argvdata/qemuxml2argv-%s.args",
- abs_top_srcdir, (const char*)data);
+ snprintf(xml, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml",
+ abs_srcdir, (const char*)data);
+ snprintf(args, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.args",
+ abs_srcdir, (const char*)data);
return testCompareXMLToArgvFiles(xml, args);
}
main(int argc, char **argv)
{
int ret = 0;
+ char cwd[PATH_MAX];
progname = argv[0];
exit(EXIT_FAILURE);
}
- abs_top_srcdir = getenv("abs_top_srcdir");
- if (!abs_top_srcdir)
- return 1;
+ abs_srcdir = getenv("abs_srcdir");
+ if (!abs_srcdir)
+ abs_srcdir = getcwd(cwd, sizeof(cwd));
driver.caps = qemudCapsInit();
- if (virtTestRun("QEMU XML-2-ARGV minimal",
- 1, testCompareXMLToArgvHelper, "minimal") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Boot CDROM",
- 1, testCompareXMLToArgvHelper, "boot-cdrom") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Boot Network",
- 1, testCompareXMLToArgvHelper, "boot-network") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Boot Floppy",
- 1, testCompareXMLToArgvHelper, "boot-floppy") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Clock UTC",
- 1, testCompareXMLToArgvHelper, "clock-utc") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Clock Localtime",
- 1, testCompareXMLToArgvHelper, "clock-localtime") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Disk CDROM",
- 1, testCompareXMLToArgvHelper, "disk-cdrom") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Disk Floppy",
- 1, testCompareXMLToArgvHelper, "disk-floppy") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Disk Many",
- 1, testCompareXMLToArgvHelper, "disk-many") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Graphics VNC",
- 1, testCompareXMLToArgvHelper, "graphics-vnc") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Graphics SDL",
- 1, testCompareXMLToArgvHelper, "graphics-sdl") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Input USB Mouse",
- 1, testCompareXMLToArgvHelper, "input-usbmouse") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Input USB Tablet",
- 1, testCompareXMLToArgvHelper, "input-usbtablet") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Misc ACPI",
- 1, testCompareXMLToArgvHelper, "misc-acpi") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Misc No Reboot",
- 1, testCompareXMLToArgvHelper, "misc-no-reboot") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Net User",
- 1, testCompareXMLToArgvHelper, "net-user") < 0)
- ret = -1;
-
+#define DO_TEST(name) \
+ if (virtTestRun("QEMU XML-2-ARGV " name, \
+ 1, testCompareXMLToArgvHelper, (name)) < 0) \
+ ret = -1
+
+ DO_TEST("minimal");
+ DO_TEST("boot-cdrom");
+ DO_TEST("boot-network");
+ DO_TEST("boot-floppy");
+ DO_TEST("clock-utc");
+ DO_TEST("clock-localtime");
+ DO_TEST("disk-cdrom");
+ DO_TEST("disk-floppy");
+ DO_TEST("disk-many");
+ DO_TEST("graphics-vnc");
+ DO_TEST("graphics-sdl");
+ DO_TEST("input-usbmouse");
+ DO_TEST("input-usbtablet");
+ DO_TEST("misc-acpi");
+ DO_TEST("misc-no-reboot");
+ DO_TEST("net-user");
+
+ DO_TEST("serial-vc");
+ DO_TEST("serial-pty");
+ DO_TEST("serial-dev");
+ DO_TEST("serial-file");
+ DO_TEST("serial-unix");
+ DO_TEST("serial-tcp");
+ DO_TEST("serial-udp");
+ DO_TEST("serial-tcp-telnet");
+ DO_TEST("serial-many");
+ DO_TEST("parallel-tcp");
+ DO_TEST("console-compat");
virCapabilitiesFree(driver.caps);
#include "qemu_conf.h"
static char *progname;
-static char *abs_top_srcdir;
+static char *abs_srcdir;
static struct qemud_driver driver;
#define MAX_FILE 4096
if (!(actual = qemudGenerateXML(NULL, &driver, &vm, vmdef, 0)))
goto fail;
- if (strcmp(xmlData, actual)) {
- if (getenv("DEBUG_TESTS")) {
- printf("Expect %4d '%s'\n", (int)strlen(xmlData), xmlData);
- printf("Actual %4d '%s'\n", (int)strlen(actual), actual);
- }
+ if (STRNEQ(xmlData, actual)) {
+ virtTestDifference(stderr, xmlData, actual);
goto fail;
}
static int testCompareXMLToXMLHelper(const void *data) {
char xml[PATH_MAX];
- snprintf(xml, PATH_MAX, "%s/tests/qemuxml2argvdata/qemuxml2argv-%s.xml",
- abs_top_srcdir, (const char*)data);
+ snprintf(xml, PATH_MAX, "%s/qemuxml2argvdata/qemuxml2argv-%s.xml",
+ abs_srcdir, (const char*)data);
return testCompareXMLToXMLFiles(xml);
}
main(int argc, char **argv)
{
int ret = 0;
+ char cwd[PATH_MAX];
progname = argv[0];
exit(EXIT_FAILURE);
}
- abs_top_srcdir = getenv("abs_top_srcdir");
- if (!abs_top_srcdir)
- return 1;
-
+ abs_srcdir = getenv("abs_srcdir");
+ if (!abs_srcdir)
+ abs_srcdir = getcwd(cwd, sizeof(cwd));
driver.caps = qemudCapsInit();
- if (virtTestRun("QEMU XML-2-ARGV minimal",
- 1, testCompareXMLToXMLHelper, "minimal") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Boot CDROM",
- 1, testCompareXMLToXMLHelper, "boot-cdrom") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Boot Network",
- 1, testCompareXMLToXMLHelper, "boot-network") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Boot Floppy",
- 1, testCompareXMLToXMLHelper, "boot-floppy") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Clock UTC",
- 1, testCompareXMLToXMLHelper, "clock-utc") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Clock Localtime",
- 1, testCompareXMLToXMLHelper, "clock-localtime") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Disk CDROM",
- 1, testCompareXMLToXMLHelper, "disk-cdrom") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Disk Floppy",
- 1, testCompareXMLToXMLHelper, "disk-floppy") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Disk Many",
- 1, testCompareXMLToXMLHelper, "disk-many") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Graphics VNC",
- 1, testCompareXMLToXMLHelper, "graphics-vnc") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Graphics SDL",
- 1, testCompareXMLToXMLHelper, "graphics-sdl") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Input USB Mouse",
- 1, testCompareXMLToXMLHelper, "input-usbmouse") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Input USB Tablet",
- 1, testCompareXMLToXMLHelper, "input-usbtablet") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Misc ACPI",
- 1, testCompareXMLToXMLHelper, "misc-acpi") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Misc No Reboot",
- 1, testCompareXMLToXMLHelper, "misc-no-reboot") < 0)
- ret = -1;
-
- if (virtTestRun("QEMU XML-2-ARGV Net User",
- 1, testCompareXMLToXMLHelper, "net-user") < 0)
- ret = -1;
+#define DO_TEST(name) \
+ if (virtTestRun("QEMU XML-2-XML " name, \
+ 1, testCompareXMLToXMLHelper, (name)) < 0) \
+ ret = -1
+
+ DO_TEST("minimal");
+ DO_TEST("boot-cdrom");
+ DO_TEST("boot-network");
+ DO_TEST("boot-floppy");
+ DO_TEST("clock-utc");
+ DO_TEST("clock-localtime");
+ DO_TEST("disk-cdrom");
+ DO_TEST("disk-floppy");
+ DO_TEST("disk-many");
+ DO_TEST("graphics-vnc");
+ DO_TEST("graphics-sdl");
+ DO_TEST("input-usbmouse");
+ DO_TEST("input-usbtablet");
+ DO_TEST("misc-acpi");
+ DO_TEST("misc-no-reboot");
+ DO_TEST("net-user");
+
+ DO_TEST("serial-vc");
+ DO_TEST("serial-pty");
+ DO_TEST("serial-dev");
+ DO_TEST("serial-file");
+ DO_TEST("serial-unix");
+ DO_TEST("serial-tcp");
+ DO_TEST("serial-udp");
+ DO_TEST("serial-tcp-telnet");
+ DO_TEST("serial-many");
+ DO_TEST("parallel-tcp");
+ DO_TEST("console-compat");
virCapabilitiesFree(driver.caps);