[libvirt] [PATCH 5/5] qemu: virtio console support

Cole Robinson crobinso at redhat.com
Wed Jul 14 19:44:56 UTC 2010


Enable specifying a virtio console device with:

<console type='pty'>
  <target type='virtio' name='arbitrary.virtio.serial.port.name'/>
</console>

Signed-off-by: Cole Robinson <crobinso at redhat.com>
---
 docs/formatdomain.html.in                          |   19 ++++++-
 docs/schemas/domain.rng                            |   14 +++++-
 src/conf/domain_conf.c                             |   52 ++++++++++++++------
 src/libvirt_private.syms                           |    1 +
 src/qemu/qemu_conf.c                               |   44 ++++++++++++++++-
 src/qemu/qemu_driver.c                             |    1 +
 .../qemuxml2argv-console-virtio.args               |    1 +
 .../qemuxml2argv-console-virtio.xml                |   30 +++++++++++
 tests/qemuxml2argvtest.c                           |    2 +
 9 files changed, 145 insertions(+), 19 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index b569811..49ba76d 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1124,8 +1124,17 @@ qemu-kvm -net nic,model=? /dev/null
 
     <p>
       This represents the primary console. This can be the paravirtualized
-      console with Xen guests, or duplicates the primary serial port for fully
-      virtualized guests without a paravirtualized console.
+      console with Xen guests, virtio console for QEMU/KVM, or duplicates
+      the primary serial port for fully virtualized guests without a
+      paravirtualized console.
+    </p>
+
+    <p>
+      virtio console target information is specified in the same way as
+      the virtio channel device. The console device is exposed in the
+      guest as /dev/hvc[0-7] (for more information, see
+      <a href="http://fedoraproject.org/wiki/Features/VirtioSerial">http://fedoraproject.org/wiki/Features/VirtioSerial</a>)
+      <span class="since">Since 0.8.3</span>
     </p>
 
 <pre>
@@ -1135,6 +1144,12 @@ qemu-kvm -net nic,model=? /dev/null
       <source path='/dev/pts/4'/>
       <target port='0'/>
     </console>
+
+    <!-- KVM virtio console -->
+    <console type='pty'>
+      <source path='/dev/pts/5'/>
+      <target type='virtio' name='arbitrary.virtio.serial.port.name'/>
+    </console>
   </devices>
   ...</pre>
 
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 1d56f5b..fcb4c23 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1267,7 +1267,19 @@
           </optional>
           <empty/>
         </group>
-        <ref name="qemucdev"/>
+        <choice>
+          <ref name="qemucdev"/>
+          <group>
+            <ref name="qemucdevSrcType"/>
+            <interleave>
+              <ref name="qemucdevSrcDef"/>
+              <ref name="virtioTarget"/>
+              <optional>
+                <ref name="address"/>
+              </optional>
+            </interleave>
+          </group>
+        </choice>
       </choice>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0793ac0..dba7255 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -2454,30 +2454,35 @@ virDomainChrDefParseXML(xmlNodePtr node,
                 if (protocol == NULL)
                     protocol = virXMLPropString(cur, "type");
             } else if (xmlStrEqual(cur->name, BAD_CAST "target")) {
-                def->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_DEFAULT;
+                bool typeRequired = (def->deviceType ==
+                                    VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL);
+                bool typeAccepted = (typeRequired ||
+                                     (def->deviceType ==
+                                    VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE));
 
+                def->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_DEFAULT;
                 if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_MONITOR) {
                     /* Don't target <target> info for monitor device */
                     def->targetType = VIR_DOMAIN_CHR_TARGET_TYPE_NONE;
 
-                } else if (def->deviceType ==
-                            VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL) {
+                } else if (typeAccepted) {
                     targetType = virXMLPropString(cur, "type");
-                    if (targetType == NULL) {
+                    if (targetType == NULL && typeRequired) {
                         virDomainReportError(VIR_ERR_XML_ERROR, "%s",
                                              _("character device target does "
                                                "not define a type"));
                         goto error;
                     }
 
-                    if ((def->targetType =
-                        virDomainChrTargetTypeFromString(targetType)) < 0)
-                    {
-                        virDomainReportError(VIR_ERR_XML_ERROR,
-                                             _("unknown target type for "
-                                               "character device: %s"),
-                                             targetType);
-                        goto error;
+                    if (targetType) {
+                        if ((def->targetType =
+                            virDomainChrTargetTypeFromString(targetType)) < 0) {
+                            virDomainReportError(VIR_ERR_XML_ERROR,
+                                                 _("unknown target type for "
+                                                   "character device: %s"),
+                                                 targetType);
+                            goto error;
+                        }
                     }
                 }
 
@@ -4400,7 +4405,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
         if (!chr)
             goto error;
 
-        chr->target.port = i;
+        if (chr->targetType == VIR_DOMAIN_CHR_TARGET_TYPE_DEFAULT)
+            chr->target.port = i;
 
         /* Back compat handling for the first console device */
         if (i == 0) {
@@ -4408,7 +4414,8 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
             * For HVM console actually created a serial device
             * while for non-HVM it was a parvirt console
             */
-            if (STREQ(def->os.type, "hvm")) {
+            if (STREQ(def->os.type, "hvm") &&
+                chr->targetType == VIR_DOMAIN_CHR_TARGET_TYPE_DEFAULT) {
                 if (def->nserials != 0) {
                     virDomainChrDefFree(chr);
                 } else {
@@ -4907,7 +4914,7 @@ static int virDomainDefAddDiskControllersForType(virDomainDefPtr def,
 
 static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
 {
-    /* Look for any virtio serial device */
+    /* Look for any virtio serial or virtio console devs */
     int i;
 
     for (i = 0 ; i < def->nchannels ; i++) {
@@ -4924,6 +4931,21 @@ static int virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
         }
     }
 
+    for (i = 0 ; i < def->nconsoles ; i++) {
+        virDomainChrDefPtr console = def->consoles[i];
+
+        if (console->targetType == VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO) {
+            int idx = 0;
+            if (console->info.type ==
+                VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL)
+                idx = console->info.addr.vioserial.controller;
+
+            if (virDomainDefMaybeAddController(def,
+                VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL, idx) < 0)
+                return -1;
+        }
+    }
+
     return 0;
 }
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 778ceb1..a7a6c45 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -225,6 +225,7 @@ virDomainSnapshotDefFormat;
 virDomainSnapshotAssignDef;
 virDomainObjAssignDef;
 virDomainChrDefForeach;
+virDomainChrTargetTypeToString;
 
 
 # domain_event.h
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 62b4fb7..ba9ee00 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2015,6 +2015,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long qemuCmdFlags)
         if (virAsprintf(&def->channels[i]->info.alias, "channel%d", i) < 0)
             goto no_memory;
     }
+    for (i = 0; i < def->nconsoles ; i++) {
+        if (virAsprintf(&def->consoles[i]->info.alias, "console%d", i) < 0)
+            goto no_memory;
+    }
     if (def->watchdog) {
         if (virAsprintf(&def->watchdog->info.alias, "watchdog%d", 0) < 0)
             goto no_memory;
@@ -3237,7 +3241,10 @@ char *
 qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev)
 {
     virBuffer buf = VIR_BUFFER_INITIALIZER;
-    virBufferAddLit(&buf, "virtserialport");
+    if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE)
+        virBufferAddLit(&buf, "virtconsole");
+    else
+        virBufferAddLit(&buf, "virtserialport");
 
     if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
         /* Check it's a virtio-serial address */
@@ -4429,6 +4436,41 @@ int qemudBuildCommandLine(virConnectPtr conn,
         }
     }
 
+    /* Explicit console devices */
+    for (i = 0 ; i < def->nconsoles ; i++) {
+        virDomainChrDefPtr console = def->consoles[i];
+        char *devstr;
+
+        switch(console->targetType) {
+        case VIR_DOMAIN_CHR_TARGET_TYPE_VIRTIO:
+            if (!(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
+                qemuReportError(VIR_ERR_NO_SUPPORT, "%s",
+                    _("virtio channel requires QEMU to support -device"));
+                goto error;
+            }
+
+            ADD_ARG_LIT("-chardev");
+            if (!(devstr = qemuBuildChrChardevStr(console)))
+                goto error;
+            ADD_ARG(devstr);
+
+            ADD_ARG_LIT("-device");
+            if (!(devstr = qemuBuildVirtioSerialPortDevStr(console)))
+                goto error;
+            ADD_ARG(devstr);
+            break;
+
+        case VIR_DOMAIN_CHR_TARGET_TYPE_DEFAULT:
+            break;
+
+        default:
+            qemuReportError(VIR_ERR_NO_SUPPORT,
+                            _("unsupported console target type %s"),
+                            NULLSTR(virDomainChrTargetTypeToString(console->targetType)));
+            goto error;
+        }
+    }
+
     ADD_ARG_LIT("-usb");
     for (i = 0 ; i < def->ninputs ; i++) {
         virDomainInputDefPtr input = def->inputs[i];
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0510124..4780277 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2027,6 +2027,7 @@ qemudFindCharDevicePTYsMonitor(virDomainObjPtr vm,
     LOOKUP_PTYS(vm->def->serials,   vm->def->nserials,   "serial");
     LOOKUP_PTYS(vm->def->parallels, vm->def->nparallels, "parallel");
     LOOKUP_PTYS(vm->def->channels,  vm->def->nchannels,  "channel");
+    LOOKUP_PTYS(vm->def->consoles,  vm->def->nconsoles,  "console");
 #undef LOOKUP_PTYS
 
     return 0;
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args
new file mode 100644
index 0000000..b048648
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args
@@ -0,0 +1 @@
+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 virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x4 -hda /dev/HostVG/QEMUGuest1 -chardev pty,id=console0 -device virtconsole,chardev=console0,name=org.linux-kvm.virtio-console1 -chardev pty,id=console1 -device virtconsole,chardev=console1,name=org.linux-kvm.virtio-console2 -usb -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml
new file mode 100644
index 0000000..1b7efb4
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml
@@ -0,0 +1,30 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219200</memory>
+  <currentMemory>219200</currentMemory>
+  <vcpu cpuset='1-4,8-20,525'>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' bus='ide'/>
+      <address type='drive' controller='0' bus='0' unit='0'/>
+    </disk>
+    <controller type='ide' index='0'/>
+    <console type='pty'>
+      <target type='virtio' name='org.linux-kvm.virtio-console1'/>
+    </console>
+    <console type='pty'>
+      <target type='virtio' name='org.linux-kvm.virtio-console2'/>
+    </console>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index ad1379b..45252dd 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -348,6 +348,8 @@ mymain(int argc, char **argv)
             QEMUD_CMD_FLAG_NODEFCONFIG);
     DO_TEST("channel-virtio-auto", QEMUD_CMD_FLAG_DEVICE |
             QEMUD_CMD_FLAG_NODEFCONFIG);
+    DO_TEST("console-virtio", QEMUD_CMD_FLAG_DEVICE |
+            QEMUD_CMD_FLAG_NODEFCONFIG);
 
     DO_TEST("watchdog", 0);
     DO_TEST("watchdog-device", QEMUD_CMD_FLAG_DEVICE |
-- 
1.6.6.1




More information about the libvir-list mailing list