Change console handling to a proper device list, as done for other character devices. Even though certain drivers can actually handle multiple consoles, for now just maintain existing behavior where possible. Signed-off-by: Cole Robinson <crobinso@xxxxxxxxxx> --- src/conf/domain_conf.c | 72 ++++++++++++------- src/conf/domain_conf.h | 5 +- src/lxc/lxc_driver.c | 8 +- src/uml/uml_conf.c | 4 +- src/uml/uml_driver.c | 6 +- src/xen/xend_internal.c | 12 +++- src/xen/xm_internal.c | 15 ++++- .../xml2sexprdata/xml2sexpr-pv-multi-console.sexpr | 1 + tests/xml2sexprdata/xml2sexpr-pv-multi-console.xml | 24 +++++++ tests/xml2sexprtest.c | 1 + 10 files changed, 106 insertions(+), 42 deletions(-) create mode 100644 tests/xml2sexprdata/xml2sexpr-pv-multi-console.sexpr create mode 100644 tests/xml2sexprdata/xml2sexpr-pv-multi-console.xml diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index e4d52ff..0793ac0 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -703,7 +703,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]); @@ -995,6 +997,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; @@ -1004,9 +1009,6 @@ int virDomainDeviceInfoIterate(virDomainDefPtr def, if (def->watchdog) if (cb(def, &def->watchdog->info, opaque) < 0) return -1; - if (def->console) - if (cb(def, &def->console->info, opaque) < 0) - return -1; return 0; } @@ -4384,31 +4386,45 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, } VIR_FREE(nodes); - if ((node = virXPathNode("./devices/console[1]", ctxt)) != NULL) { - virDomainChrDefPtr chr = virDomainChrDefParseXML(node, + 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(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 - */ - if (STREQ(def->os.type, "hvm")) { - if (def->nserials != 0) { - virDomainChrDefFree(chr); - } else { - if (VIR_ALLOC_N(def->serials, 1) < 0) { + chr->target.port = i; + + /* Back compat handling for the first console device */ + if (i == 0) { + /* + * For HVM console actually created a serial device + * while for non-HVM it was a parvirt console + */ + if (STREQ(def->os.type, "hvm")) { + if (def->nserials != 0) { virDomainChrDefFree(chr); - goto no_memory; + } else { + if (VIR_ALLOC_N(def->serials, 1) < 0) { + virDomainChrDefFree(chr); + goto no_memory; + } + def->nserials = 1; + def->serials[0] = chr; + chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; } - def->nserials = 1; - def->serials[0] = chr; - chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL; + } else { + def->consoles[def->nconsoles++] = chr; } } else { - def->console = chr; + def->consoles[def->nconsoles++] = chr; } } @@ -5496,9 +5512,10 @@ virDomainChrDefFormat(virBufferPtr buf, return -1; } - /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ virBufferVSprintf(buf, " <%s type='%s'", elementName, type); + + /* Compat with legacy <console tty='/dev/pts/5'/> syntax */ if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE && def->type == VIR_DOMAIN_CHR_TYPE_PTY && !(flags & VIR_DOMAIN_XML_INACTIVE) && @@ -6213,9 +6230,10 @@ char *virDomainDefFormat(virDomainDefPtr def, goto cleanup; /* If there's a PV console that's preferred.. */ - if (def->console) { - if (virDomainChrDefFormat(&buf, def->console, flags) < 0) - goto cleanup; + if (def->nconsoles) { + for (n = 0 ; n < def->nconsoles ; n++) + if (virDomainChrDefFormat(&buf, def->consoles[n], flags) < 0) + goto cleanup; } else if (def->nserials != 0) { /* ..else for legacy compat duplicate the first serial device as a * console */ @@ -7260,9 +7278,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 75dc29a..1361d38 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -875,8 +875,9 @@ struct _virDomainDef { int nchannels; virDomainChrDefPtr *channels; - /* Only 1 */ - virDomainChrDefPtr console; + int nconsoles; + virDomainChrDefPtr *consoles; + virSecurityLabelDef seclabel; virDomainWatchdogDefPtr watchdog; virCPUDefPtr cpu; diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 462bc9c..9b0969e 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -1273,10 +1273,10 @@ static int lxcVmStart(virConnectPtr conn, _("Failed to allocate tty")); goto cleanup; } - if (vm->def->console && - vm->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY) { - VIR_FREE(vm->def->console->data.file.path); - vm->def->console->data.file.path = parentTtyPath; + if (vm->def->nconsoles > 0 && + vm->def->consoles[0]->type == VIR_DOMAIN_CHR_TYPE_PTY) { + VIR_FREE(vm->def->consoles[0]->data.file.path); + vm->def->consoles[0]->data.file.path = parentTtyPath; } else { VIR_FREE(parentTtyPath); } diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c index 785d627..6715a94 100644 --- a/src/uml/uml_conf.c +++ b/src/uml/uml_conf.c @@ -500,8 +500,8 @@ int umlBuildCommandLine(virConnectPtr conn, for (i = 0 ; i < UML_MAX_CHAR_DEVICE ; i++) { char *ret; - if (i == 0 && vm->def->console) - ret = umlBuildCommandLineChr(vm->def->console, "con"); + if (i == 0 && vm->def->nconsoles > 0) + ret = umlBuildCommandLineChr(vm->def->consoles[0], "con"); else 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 110179e..aa8cbef 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -231,10 +231,10 @@ umlIdentifyChrPTY(struct uml_driver *driver, { int i; - if (dom->def->console && - dom->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY) + if (dom->def->nconsoles > 0 && + dom->def->consoles[0]->type == VIR_DOMAIN_CHR_TYPE_PTY) if (umlIdentifyOneChrPTY(driver, dom, - dom->def->console, "con") < 0) + dom->def->consoles[0], "con") < 0) return -1; for (i = 0 ; i < dom->def->nserials; i++) diff --git a/src/xen/xend_internal.c b/src/xen/xend_internal.c index a492231..02383ca 100644 --- a/src/xen/xend_internal.c +++ b/src/xen/xend_internal.c @@ -2364,9 +2364,17 @@ xenDaemonParseSxpr(virConnectPtr conn, } } else { /* Fake a paravirt console, since that's not in the sexpr */ - if (!(def->console = xenDaemonParseSxprChar("pty", tty))) + virDomainChrDefPtr chr; + + if ((chr = xenDaemonParseSxprChar("pty", tty)) == NULL) goto error; - def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + if (VIR_REALLOC_N(def->consoles, def->nconsoles+1) < 0) { + virDomainChrDefFree(chr); + goto no_memory; + } + + chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + def->consoles[def->nconsoles++] = chr; } VIR_FREE(tty); diff --git a/src/xen/xm_internal.c b/src/xen/xm_internal.c index 4230504..7756662 100644 --- a/src/xen/xm_internal.c +++ b/src/xen/xm_internal.c @@ -1438,9 +1438,20 @@ xenXMDomainConfigParse(virConnectPtr conn, virConfPtr conf) { def->nserials++; } } else { - if (!(def->console = xenDaemonParseSxprChar("pty", NULL))) + virDomainChrDefPtr chr; + + if ((chr = xenDaemonParseSxprChar("pty", NULL)) == NULL) goto cleanup; - def->console->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + + if (chr) { + if (VIR_ALLOC_N(def->consoles, 1) < 0) { + virDomainChrDefFree(chr); + goto no_memory; + } + chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE; + def->consoles[0] = chr; + def->nconsoles++; + } } if (hvm) { diff --git a/tests/xml2sexprdata/xml2sexpr-pv-multi-console.sexpr b/tests/xml2sexprdata/xml2sexpr-pv-multi-console.sexpr new file mode 100644 index 0000000..60db610 --- /dev/null +++ b/tests/xml2sexprdata/xml2sexpr-pv-multi-console.sexpr @@ -0,0 +1 @@ +(vm (name 'pvtest')(memory 420)(maxmem 420)(vcpus 2)(uuid '596a5d21-71f4-8fb2-e068-e2386a5c413e')(on_poweroff 'destroy')(on_reboot 'destroy')(on_crash 'destroy')(image (linux (kernel '/var/lib/xen/vmlinuz.2Dn2YT')(ramdisk '/var/lib/xen/initrd.img.0u-Vhq')(args ' method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os ')))(device (vbd (dev 'xvda')(uname 'file:/root/some.img')(mode 'w')))) \ No newline at end of file diff --git a/tests/xml2sexprdata/xml2sexpr-pv-multi-console.xml b/tests/xml2sexprdata/xml2sexpr-pv-multi-console.xml new file mode 100644 index 0000000..4f9c869 --- /dev/null +++ b/tests/xml2sexprdata/xml2sexpr-pv-multi-console.xml @@ -0,0 +1,24 @@ +<domain type='xen' id='15'> + <name>pvtest</name> + <uuid>596a5d2171f48fb2e068e2386a5c413e</uuid> + <os> + <type>linux</type> + <kernel>/var/lib/xen/vmlinuz.2Dn2YT</kernel> + <initrd>/var/lib/xen/initrd.img.0u-Vhq</initrd> + <cmdline> method=http://download.fedora.devel.redhat.com/pub/fedora/linux/core/test/5.91/x86_64/os </cmdline> + </os> + <memory>430080</memory> + <vcpu>2</vcpu> + <on_poweroff>destroy</on_poweroff> + <on_reboot>destroy</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <disk type='file' device='disk'> + <source file='/root/some.img'/> + <target dev='xvda'/> + </disk> + <console tty='/dev/pts/4'/> + <console tty='/dev/pts/5'/> + <console tty='/dev/pts/6'/> + </devices> +</domain> diff --git a/tests/xml2sexprtest.c b/tests/xml2sexprtest.c index 0455dc4..920ee29 100644 --- a/tests/xml2sexprtest.c +++ b/tests/xml2sexprtest.c @@ -113,6 +113,7 @@ mymain(int argc, char **argv) DO_TEST("pv-vfb-new", "pv-vfb-new", "pvtest", 3); DO_TEST("pv-vfb-new-auto", "pv-vfb-new-auto", "pvtest", 3); DO_TEST("pv-bootloader", "pv-bootloader", "pvtest", 1); + DO_TEST("pv-multi-console", "pv-multi-console", "pvtest", 2); DO_TEST("disk-file", "disk-file", "pvtest", 2); DO_TEST("disk-block", "disk-block", "pvtest", 2); -- 1.6.6.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list