From 0873b688c6771a6901d7ec95f5b8e88cc957947b Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 23 Feb 2011 18:27:23 +0000 Subject: [PATCH] Allow multiple consoles per virtual guest While Xen only has a single paravirt console, UML, and QEMU both support multiple paravirt consoles. The LXC driver can also be trivially made to support multiple consoles. This patch extends the XML to allow multiple elements in the XML. It also makes the UML and QEMU drivers support this config. * src/conf/domain_conf.c, src/conf/domain_conf.h: Allow multiple devices * src/lxc/lxc_driver.c, src/xen/xen_driver.c, src/xenxs/xen_sxpr.c, src/xenxs/xen_xm.c: Update for internal API changes * src/security/security_selinux.c, src/security/virt-aa-helper.c: Only label consoles that aren't a copy of the serial device * src/qemu/qemu_command.c, src/qemu/qemu_driver.c, src/qemu/qemu_process.c, src/uml/uml_conf.c, src/uml/uml_driver.c: Support multiple console devices * tests/qemuxml2xmltest.c, tests/qemuxml2argvtest.c: Extra tests for multiple virtio consoles. Set QEMU_CAPS_CHARDEV for all console /channel tests * tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args, tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args: Update for correct chardev syntax * tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args, tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml: New test file --- docs/formatdomain.html.in | 25 +++- src/conf/domain_conf.c | 112 +++++++++++++----- src/conf/domain_conf.h | 4 +- src/lxc/lxc_driver.c | 20 +++- src/qemu/qemu_command.c | 12 +- src/qemu/qemu_driver.c | 12 +- src/qemu/qemu_process.c | 8 +- src/security/security_selinux.c | 10 ++ src/security/virt-aa-helper.c | 16 ++- src/uml/uml_conf.c | 8 +- src/uml/uml_driver.c | 10 +- src/xen/xen_driver.c | 4 +- src/xenxs/xen_sxpr.c | 17 ++- src/xenxs/xen_xm.c | 11 +- .../qemuxml2argv-channel-virtio-auto.args | 5 +- .../qemuxml2argv-channel-virtio.args | 5 +- .../qemuxml2argv-console-virtio-many.args | 12 ++ .../qemuxml2argv-console-virtio-many.xml | 41 +++++++ .../qemuxml2argv-console-virtio.args | 5 +- tests/qemuxml2argvtest.c | 8 +- tests/qemuxml2xmltest.c | 1 + 21 files changed, 256 insertions(+), 90 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index c3e7752f8b..cbad196d9b 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2681,12 +2681,29 @@ qemu-kvm -net nic,model=? /dev/null
Console

- This represents the primary console. This can be the paravirtualized - console with Xen guests, virtio console for QEMU/KVM, or duplicates - the primary serial port for fully virtualized guests without a - paravirtualized console. + The console element is used to represent interactive consoles. Depending + on the type of guest in use, the consoles might be paravirtualized devices, + or they might be a clone of a serial device, according to the following + rules:

+
    +
  • If no targetType attribue is set, then the default + device type is according to the hypervisor's rules. The default + type will be added when re-querying the XML fed into libvirt. + For fully virtualized guests, the default device type will usually + be a serial port.
  • +
  • If the targetType attribute is serial, + then if no <serial> element exists, the console + element will be copied to the serial element. If a <serial> + element does already exist, the console element will be ignored.
  • +
  • If the targetType attribute is not serial, + it will be treated normally.
  • +
  • Only the first console element may use a targetType + of serial. Secondary consoles must all be paravirtualized. +
  • +
+

A virtio console device is exposed in the guest as /dev/hvc[0-7] (for more information, see diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 6e2d421527..e88a1cfdac 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1227,7 +1227,9 @@ void virDomainDefFree(virDomainDefPtr def) virDomainChrDefFree(def->channels[i]); VIR_FREE(def->channels); - virDomainChrDefFree(def->console); + for (i = 0 ; i < def->nconsoles ; i++) + virDomainChrDefFree(def->consoles[i]); + VIR_FREE(def->consoles); for (i = 0 ; i < def->nsounds ; i++) virDomainSoundDefFree(def->sounds[i]); @@ -1618,6 +1620,9 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def, for (i = 0; i < def->nchannels ; i++) if (cb(def, &def->channels[i]->info, opaque) < 0) return -1; + for (i = 0; i < def->nconsoles ; i++) + if (cb(def, &def->consoles[i]->info, opaque) < 0) + return -1; for (i = 0; i < def->ninputs ; i++) if (cb(def, &def->inputs[i]->info, opaque) < 0) return -1; @@ -1630,9 +1635,6 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def, if (def->memballoon) if (cb(def, &def->memballoon->info, opaque) < 0) return -1; - if (def->console) - if (cb(def, &def->console->info, opaque) < 0) - return -1; for (i = 0; i < def->nhubs ; i++) if (cb(def, &def->hubs[i]->info, opaque) < 0) return -1; @@ -7203,20 +7205,46 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } VIR_FREE(nodes); - if ((node = virXPathNode("./devices/console[1]", ctxt)) != NULL) { + if ((n = virXPathNodeSet("./devices/console", ctxt, &nodes)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("cannot extract console devices")); + goto error; + } + if (n && VIR_ALLOC_N(def->consoles, n) < 0) + goto no_memory; + + for (i = 0 ; i < n ; i++) { virDomainChrDefPtr chr = virDomainChrDefParseXML(caps, - node, + nodes[i], flags); if (!chr) goto error; - chr->target.port = 0; /* - * For HVM console actually created a serial device - * while for non-HVM it was a parvirt console + * Some really crazy backcompat stuff for consoles + * + * Historically the first (and only) '' + * element in an HVM guest was treated as being + * an alias for a device. + * + * So if we see that this console device should + * be a serial device, then we move the config + * over to def->serials[0] (or discard it if + * that already exists + * + * We then fill def->consoles[0] with a stub + * just so we get sequencing correct for consoles + * > 0 */ if (STREQ(def->os.type, "hvm") && - chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) { + (chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)) { + if (i != 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only the first console can be a serial port")); + goto error; + } + + /* Either discard or move this chr to the serial config */ if (def->nserials != 0) { virDomainChrDefFree(chr); } else { @@ -7224,14 +7252,24 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, virDomainChrDefFree(chr); goto no_memory; } + chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; def->nserials = 1; def->serials[0] = chr; - chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; + chr->target.port = 0; } - } else { - def->console = chr; + + /* And create a stub placeholder */ + if (VIR_ALLOC(chr) < 0) + goto no_memory; + chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL; } + + chr->target.port = i; + + def->consoles[def->nconsoles++] = chr; } + VIR_FREE(nodes); if ((n = virXPathNodeSet("./devices/channel", ctxt, &nodes)) < 0) { goto error; @@ -8677,14 +8715,17 @@ bool virDomainDefCheckABIStability(virDomainDefPtr src, if (!virDomainChannelDefCheckABIStability(src->channels[i], dst->channels[i])) goto cleanup; - if ((!src->console && dst->console) || - (src->console && !dst->console)) { + if (src->nconsoles != dst->nconsoles) { virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target domain console count %d does not match source %d"), - dst->console ? 1 : 0, src->console ? 1 : 0); + dst->nconsoles, src->nconsoles); goto cleanup; } + for (i = 0 ; i < src->nconsoles ; i++) + if (!virDomainConsoleDefCheckABIStability(src->consoles[i], dst->consoles[i])) + goto cleanup; + if (src->nhubs != dst->nhubs) { virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("Target domain hub device count %d does not match source %d"), @@ -8696,9 +8737,6 @@ bool virDomainDefCheckABIStability(virDomainDefPtr src, if (!virDomainHubDefCheckABIStability(src->hubs[i], dst->hubs[i])) goto cleanup; - if (src->console && - !virDomainConsoleDefCheckABIStability(src->console, dst->console)) - goto cleanup; if ((!src->watchdog && dst->watchdog) || (src->watchdog && !dst->watchdog)) { @@ -8820,8 +8858,8 @@ static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def) } } - if (def->console) { - virDomainChrDefPtr console = def->console; + for (i = 0 ; i < def->nconsoles ; i++) { + virDomainChrDefPtr console = def->consoles[i]; if (console->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) { int idx = 0; @@ -11079,15 +11117,27 @@ virDomainDefFormatInternal(virDomainDefPtr def, if (virDomainChrDefFormat(buf, def->parallels[n], flags) < 0) goto cleanup; - /* If there's a PV console that's preferred.. */ - if (def->console) { - if (virDomainChrDefFormat(buf, def->console, flags) < 0) - goto cleanup; - } else if (def->nserials != 0) { - /* ..else for legacy compat duplicate the first serial device as a - * console */ + for (n = 0 ; n < def->nconsoles ; n++) { virDomainChrDef console; - memcpy(&console, def->serials[0], sizeof(console)); + /* Back compat, ignore the console element for hvm guests + * if it is type == serial + */ + if (STREQ(def->os.type, "hvm") && + (def->consoles[n]->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) && + (n < def->nserials)) { + memcpy(&console, def->serials[n], sizeof(console)); + console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + } else { + memcpy(&console, def->consoles[n], sizeof(console)); + } + if (virDomainChrDefFormat(buf, &console, flags) < 0) + goto cleanup; + } + if (STREQ(def->os.type, "hvm") && + def->nconsoles == 0 && + def->nserials > 0) { + virDomainChrDef console; + memcpy(&console, def->serials[n], sizeof(console)); console.deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; if (virDomainChrDefFormat(buf, &console, flags) < 0) goto cleanup; @@ -12690,9 +12740,9 @@ int virDomainChrDefForeach(virDomainDefPtr def, if (abortOnError && rc != 0) goto done; } - if (def->console) { + for (i = 0 ; i < def->nconsoles ; i++) { if ((iter)(def, - def->console, + def->consoles[i], opaque) < 0) rc = -1; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index f74f4bb7b6..c33e253213 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1455,6 +1455,9 @@ struct _virDomainDef { int nchannels; virDomainChrDefPtr *channels; + int nconsoles; + virDomainChrDefPtr *consoles; + size_t nleases; virDomainLeaseDefPtr *leases; @@ -1462,7 +1465,6 @@ struct _virDomainDef { virDomainHubDefPtr *hubs; /* Only 1 */ - virDomainChrDefPtr console; virSecurityLabelDef seclabel; virDomainWatchdogDefPtr watchdog; virDomainMemballoonDefPtr memballoon; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 4096626613..45ef3bd212 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1680,10 +1680,18 @@ static int lxcVmStart(virConnectPtr conn, _("Failed to allocate tty")); goto cleanup; } - if (vm->def->console && - vm->def->console->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { - VIR_FREE(vm->def->console->source.data.file.path); - vm->def->console->source.data.file.path = parentTtyPath; + if (vm->def->nconsoles) { + if (vm->def->nconsoles > 1) { + lxcError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Only one console supported")); + goto cleanup; + } + if (vm->def->consoles[0]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) { + VIR_FREE(vm->def->consoles[0]->source.data.file.path); + vm->def->consoles[0]->source.data.file.path = parentTtyPath; + } else { + VIR_FREE(parentTtyPath); + } } else { VIR_FREE(parentTtyPath); } @@ -3026,8 +3034,8 @@ lxcDomainOpenConsole(virDomainPtr dom, _("Named device aliases are not supported")); goto cleanup; } else { - if (vm->def->console) - chr = vm->def->console; + if (vm->def->nconsoles) + chr = vm->def->consoles[0]; else if (vm->def->nserials) chr = vm->def->serials[0]; } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index dc92fa3ebd..826c1d37a0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -716,16 +716,16 @@ qemuAssignDeviceAliases(virDomainDefPtr def, virBitmapPtr qemuCaps) if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0) goto no_memory; } - for (i = 0; i < def->nsmartcards ; i++) { - if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0) + for (i = 0; i < def->nconsoles ; i++) { + if (virAsprintf(&def->consoles[i]->info.alias, "console%d", i) < 0) goto no_memory; } for (i = 0; i < def->nhubs ; i++) { if (virAsprintf(&def->hubs[i]->info.alias, "hub%d", i) < 0) goto no_memory; } - if (def->console) { - if (virAsprintf(&def->console->info.alias, "console%d", i) < 0) + for (i = 0; i < def->nsmartcards ; i++) { + if (virAsprintf(&def->smartcards[i]->info.alias, "smartcard%d", i) < 0) goto no_memory; } if (def->watchdog) { @@ -4498,8 +4498,8 @@ qemuBuildCommandLine(virConnectPtr conn, } /* Explicit console devices */ - if (def->console) { - virDomainChrDefPtr console = def->console; + for (i = 0 ; i < def->nconsoles ; i++) { + virDomainChrDefPtr console = def->consoles[i]; char *devstr; switch(console->targetType) { diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5e49ff458b..118197a05e 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -10519,9 +10519,11 @@ qemuDomainOpenConsole(virDomainPtr dom, } if (dev_name) { - if (vm->def->console && - STREQ(dev_name, vm->def->console->info.alias)) - chr = vm->def->console; + for (i = 0 ; !chr && i < vm->def->nconsoles ; i++) { + if (vm->def->consoles[i]->info.alias && + STREQ(dev_name, vm->def->consoles[i]->info.alias)) + chr = vm->def->consoles[i]; + } for (i = 0 ; !chr && i < vm->def->nserials ; i++) { if (STREQ(dev_name, vm->def->serials[i]->info.alias)) chr = vm->def->serials[i]; @@ -10531,8 +10533,8 @@ qemuDomainOpenConsole(virDomainPtr dom, chr = vm->def->parallels[i]; } } else { - if (vm->def->console) - chr = vm->def->console; + if (vm->def->nconsoles) + chr = vm->def->consoles[0]; else if (vm->def->nserials) chr = vm->def->serials[0]; } diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 47164f7b47..2882ef8f6b 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -1112,8 +1112,8 @@ qemuProcessFindCharDevicePTYsMonitor(virDomainObjPtr vm, paths, chardevfmt) < 0) return -1; - if (vm->def->console && - qemuProcessLookupPTYs(&vm->def->console, 1, paths, chardevfmt) < 0) + if (qemuProcessLookupPTYs(vm->def->consoles, vm->def->nconsoles, + paths, chardevfmt) < 0) return -1; return 0; @@ -1161,8 +1161,8 @@ qemuProcessFindCharDevicePTYs(virDomainObjPtr vm, } } - if (vm->def->console) { - virDomainChrDefPtr chr = vm->def->console; + for (i = 0 ; i < vm->def->nconsoles ; i++) { + virDomainChrDefPtr chr = vm->def->consoles[i]; if (chr->source.type == VIR_DOMAIN_CHR_TYPE_PTY && chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO) { if ((ret = qemuProcessExtractTTYPath(output, &offset, diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index e1a257d183..78c0d45643 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -888,6 +888,11 @@ SELinuxRestoreSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, { virDomainObjPtr vm = opaque; + /* This is taken care of by processing of def->serials */ + if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && + dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) + return 0; + return SELinuxRestoreSecurityChardevLabel(vm, &dev->source); } @@ -1228,6 +1233,11 @@ SELinuxSetSecurityChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED, { virDomainObjPtr vm = opaque; + /* This is taken care of by processing of def->serials */ + if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && + dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL) + return 0; + return SELinuxSetSecurityChardevLabel(vm, &dev->source); } diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c index ad4b8a7cfd..71a4586f31 100644 --- a/src/security/virt-aa-helper.c +++ b/src/security/virt-aa-helper.c @@ -925,12 +925,16 @@ get_files(vahControl * ctl) ctl->def->serials[i]->source.type) != 0) goto clean; - if (ctl->def->console && ctl->def->console->source.data.file.path) - if (vah_add_file_chardev(&buf, - ctl->def->console->source.data.file.path, - "rw", - ctl->def->console->source.type) != 0) - goto clean; + for (i = 0; i < ctl->def->nconsoles; i++) + if (ctl->def->consoles[i] && + (ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY || + ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_DEV || + ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_FILE || + ctl->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_PIPE) && + ctl->def->consoles[i]->source.data.file.path) + if (vah_add_file(&buf, + ctl->def->consoles[i]->source.data.file.path, "rw") != 0) + goto clean; for (i = 0 ; i < ctl->def->nparallels; i++) if (ctl->def->parallels[i] && diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c index 7b5e094c4d..4459a2a3ed 100644 --- a/src/uml/uml_conf.c +++ b/src/uml/uml_conf.c @@ -466,9 +466,13 @@ virCommandPtr umlBuildCommandLine(virConnectPtr conn, } for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) { + virDomainChrDefPtr chr = NULL; char *ret = NULL; - if (i == 0 && vm->def->console) - ret = umlBuildCommandLineChr(vm->def->console, "con", cmd); + for (j = 0 ; j < vm->def->nconsoles ; j++) + if (vm->def->consoles[j]->target.port == i) + chr = vm->def->consoles[j]; + if (chr) + ret = umlBuildCommandLineChr(chr, "con", cmd); if (!ret) if (virAsprintf(&ret, "con%d=none", i) < 0) goto no_memory; diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 16ab73a170..44529f0eca 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -248,10 +248,10 @@ umlIdentifyChrPTY(struct uml_driver *driver, { int i; - if (dom->def->console && - dom->def->console->source.type == VIR_DOMAIN_CHR_TYPE_PTY) + for (i = 0 ; i < dom->def->nserials; i++) + if (dom->def->consoles[i]->source.type == VIR_DOMAIN_CHR_TYPE_PTY) if (umlIdentifyOneChrPTY(driver, dom, - dom->def->console, "con") < 0) + dom->def->consoles[i], "con") < 0) return -1; for (i = 0 ; i < dom->def->nserials; i++) @@ -2390,8 +2390,8 @@ umlDomainOpenConsole(virDomainPtr dom, _("Named device aliases are not supported")); goto cleanup; } else { - if (vm->def->console) - chr = vm->def->console; + if (vm->def->nconsoles) + chr = vm->def->consoles[0]; else if (vm->def->nserials) chr = vm->def->serials[0]; } diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index b3e7782890..beb2ba31af 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -2136,8 +2136,8 @@ xenUnifiedDomainOpenConsole(virDomainPtr dom, if (!def) goto cleanup; - if (def->console) - chr = def->console; + if (def->nconsoles) + chr = def->consoles[0]; else if (def->nserials) chr = def->serials[0]; diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c index d44b0dc55a..e0bc043a23 100644 --- a/src/xenxs/xen_sxpr.c +++ b/src/xenxs/xen_sxpr.c @@ -202,7 +202,6 @@ xenParseSxprChar(const char *value, } } - /* Compat with legacy syntax */ switch (def->source.type) { case VIR_DOMAIN_CHR_TYPE_PTY: if (tty != NULL && @@ -1395,12 +1394,15 @@ xenParseSxpr(const struct sexpr *root, def->parallels[def->nparallels++] = chr; } } else { + def->nconsoles = 1; + if (VIR_ALLOC_N(def->consoles, 1) < 0) + goto no_memory; /* Fake a paravirt console, since that's not in the sexpr */ - if (!(def->console = xenParseSxprChar("pty", tty))) + if (!(def->consoles[0] = xenParseSxprChar("pty", tty))) goto error; - def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; - def->console->target.port = 0; - def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; + def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + def->consoles[0]->target.port = 0; + def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; } VIR_FREE(tty); @@ -1613,6 +1615,11 @@ xenFormatSxprChr(virDomainChrDefPtr def, if (def->source.data.nix.listen) virBufferAddLit(buf, ",server,nowait"); break; + + default: + XENXS_ERROR(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported chr device type '%s'"), type); + return -1; } if (virBufferError(buf)) { diff --git a/src/xenxs/xen_xm.c b/src/xenxs/xen_xm.c index ff173d8de3..a2ef8c8d7b 100644 --- a/src/xenxs/xen_xm.c +++ b/src/xenxs/xen_xm.c @@ -1066,11 +1066,14 @@ xenParseXM(virConfPtr conf, int xendConfigVersion, } } } else { - if (!(def->console = xenParseSxprChar("pty", NULL))) + def->nconsoles = 1; + if (VIR_ALLOC_N(def->consoles, 1) < 0) + goto no_memory; + if (!(def->consoles[0] = xenParseSxprChar("pty", NULL))) goto cleanup; - def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; - def->console->target.port = 0; - def->console->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; + def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + def->consoles[0]->target.port = 0; + def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN; } if (hvm) { diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args index e3fbc24808..715bda6843 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args @@ -1,6 +1,7 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ -pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ -unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ virtio-serial-pci,id=virtio-serial0,max_ports=16,vectors=4,bus=pci.0,addr=0x3 \ -device virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -device \ virtio-serial-pci,id=virtio-serial2,bus=pci.0,addr=0x4 -hda \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args index 5356bccc31..d46ed67e01 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio.args @@ -1,6 +1,7 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ -pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ -unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -hda \ /dev/HostVG/QEMUGuest1 -chardev pty,id=charchannel0 -device virtserialport,\ bus=virtio-serial1.0,nr=3,chardev=charchannel0,id=channel0,\ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args new file mode 100644 index 0000000000..8af25496bb --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.args @@ -0,0 +1,12 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ +virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 -hda \ +/dev/HostVG/QEMUGuest1 -chardev pty,id=charserial0 \ +-device isa-serial,chardev=charserial0,id=serial0 -chardev pty,id=charconsole1 \ +-device virtconsole,chardev=charconsole1,id=console1 -chardev \ +pty,id=charconsole2 -device virtconsole,chardev=charconsole2,id=console2 \ +-chardev pty,id=charconsole3 -device virtconsole,chardev=charconsole3,\ +id=console3 -usb -device virtio-balloon-pci,id=balloon0,\ +bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml new file mode 100644 index 0000000000..e65fb744f2 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio-many.xml @@ -0,0 +1,41 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219100 + 219100 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +

+ + + + + + + + + + + + + + + + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args index 7e852ff7b9..9f23c27f22 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args @@ -1,6 +1,7 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ -pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ -unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -chardev \ +socket,id=charmonitor,path=/tmp/test-monitor,server,nowait -mon \ +chardev=charmonitor,id=monitor,mode=readline -no-acpi -boot c -device \ virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x3 -hda \ /dev/HostVG/QEMUGuest1 -chardev pty,id=charconsole0 -device virtconsole,\ chardev=charconsole0,id=console0 -usb -device virtio-balloon-pci,id=balloon0,\ diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 4d6db01925..d9a6e8da5b 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -474,11 +474,13 @@ mymain(void) DO_TEST("channel-guestfwd", false, QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); DO_TEST("channel-virtio", false, - QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("channel-virtio-auto", false, - QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("console-virtio", false, - QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG); + QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); + DO_TEST("console-virtio-many", false, + QEMU_CAPS_DEVICE, QEMU_CAPS_CHARDEV, QEMU_CAPS_NODEFCONFIG); DO_TEST("channel-spicevmc", false, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV_SPICEVMC); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index af635d9596..3f375209a4 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -174,6 +174,7 @@ mymain(void) DO_TEST("serial-many"); DO_TEST("parallel-tcp"); DO_TEST("console-compat"); + DO_TEST("console-virtio-many"); DO_TEST("channel-guestfwd"); DO_TEST("channel-virtio");