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 <crobi...@redhat.com>
---
 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@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to