Enable specifying a virtio console device with:
<console type='pty'>
<target type='virtio'/>
</console>
Signed-off-by: Cole Robinson <crobinso(a)redhat.com>
---
docs/formatdomain.html.in | 18 +++++++-
docs/schemas/domain.rng | 5 ++-
src/conf/domain_conf.c | 32 +++++++++++----
src/conf/domain_conf.h | 1 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_conf.c | 44 +++++++++++++++++++-
src/qemu/qemu_driver.c | 2 +
.../qemuxml2argv-console-virtio.args | 1 +
.../qemuxml2argv-console-virtio.xml | 27 ++++++++++++
tests/qemuxml2argvtest.c | 2 +
.../qemuxml2xmlout-console-virtio.xml | 29 +++++++++++++
tests/qemuxml2xmltest.c | 1 +
12 files changed, 151 insertions(+), 12 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml
create mode 100644 tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8714a14..b23a1c2 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1124,8 +1124,16 @@ 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>
+ A virtio console device is exposed in the
+ guest as /dev/hvc[0-7] (for more information, see
+ <a
href="http://fedoraproject.org/wiki/Features/VirtioSerial">h...>)
+ <span class="since">Since 0.8.3</span>
</p>
<pre>
@@ -1135,6 +1143,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' port='0'/>
+ </console>
</devices>
...</pre>
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index 1421711..833c018 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1216,6 +1216,7 @@
<value>xen</value>
<value>serial</value>
<value>uml</value>
+ <value>virtio</value>
</choice>
</attribute>
</define>
@@ -1292,7 +1293,9 @@
</optional>
<empty/>
</group>
- <ref name="qemucdev"/>
+ <choice>
+ <ref name="qemucdev"/>
+ </choice>
</choice>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c9f2d25..1ff189c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -173,7 +173,8 @@ VIR_ENUM_IMPL(virDomainChrConsoleTarget,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST,
"serial",
"xen",
- "uml")
+ "uml",
+ "virtio")
VIR_ENUM_IMPL(virDomainChrDevice, VIR_DOMAIN_CHR_DEVICE_TYPE_LAST,
"monitor",
@@ -2426,13 +2427,12 @@ virDomainChrTargetTypeFromString(virCapsPtr caps,
case VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE:
target = virDomainChrConsoleTargetTypeFromString(targetType);
- /* Fall through */
+ break;
case VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL:
case VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL:
default:
/* No target type yet*/
- target = 0;
break;
}
@@ -4567,7 +4567,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_CONSOLE_TARGET_TYPE_SERIAL) {
if (def->nserials != 0) {
virDomainChrDefFree(chr);
} else {
@@ -5111,7 +5112,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++) {
@@ -5128,6 +5129,21 @@ static int
virDomainDefMaybeAddVirtioSerialController(virDomainDefPtr def)
}
}
+ if (def->console) {
+ virDomainChrDefPtr console = def->console;
+
+ if (console->targetType == VIR_DOMAIN_CHR_CONSOLE_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;
}
@@ -5722,14 +5738,14 @@ virDomainChrDefFormat(virBufferPtr buf,
virBufferVSprintf(buf, " <%s type='%s'",
elementName, type);
if (def->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+ def->target.port == 0 &&
def->type == VIR_DOMAIN_CHR_TYPE_PTY &&
!(flags & VIR_DOMAIN_XML_INACTIVE) &&
def->data.file.path) {
- virBufferEscapeString(buf, " tty='%s'>\n",
+ virBufferEscapeString(buf, " tty='%s'",
def->data.file.path);
- } else {
- virBufferAddLit(buf, ">\n");
}
+ virBufferAddLit(buf, ">\n");
switch (def->type) {
case VIR_DOMAIN_CHR_TYPE_NULL:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index c82dc60..fe09dbc 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -334,6 +334,7 @@ enum virDomainChrConsoleTargetType {
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL = 0,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_UML,
+ VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO,
VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_LAST,
};
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6b83cb9..b5944a7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -228,6 +228,7 @@ virDomainSnapshotAssignDef;
virDomainObjAssignDef;
virDomainChrDefForeach;
virDomainDiskDefForeachPath;
+virDomainChrConsoleTargetTypeToString;
# domain_event.h
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 3f77e6a..f79775b 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2028,6 +2028,10 @@ qemuAssignDeviceAliases(virDomainDefPtr def, unsigned long long
qemuCmdFlags)
if (virAsprintf(&def->channels[i]->info.alias, "channel%d",
i) < 0)
goto no_memory;
}
+ if (def->console) {
+ if (virAsprintf(&def->console->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;
@@ -3334,7 +3338,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 */
@@ -4526,6 +4533,41 @@ int qemudBuildCommandLine(virConnectPtr conn,
}
}
+ /* Explicit console devices */
+ if (def->console) {
+ virDomainChrDefPtr console = def->console;
+ char *devstr;
+
+ switch(console->targetType) {
+ case VIR_DOMAIN_CHR_CONSOLE_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_CONSOLE_TARGET_TYPE_SERIAL:
+ break;
+
+ default:
+ qemuReportError(VIR_ERR_NO_SUPPORT,
+ _("unsupported console target type %s"),
+
NULLSTR(virDomainChrConsoleTargetTypeToString(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 4558674..4d21035 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -2229,6 +2229,8 @@ 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");
+ if (vm->def->console)
+ LOOKUP_PTYS(&vm->def->console, 1, "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..a55000f
--- /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=0x2 -hda
/dev/HostVG/QEMUGuest1 -chardev pty,id=console0 -device virtconsole,chardev=console0 -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..fd72421
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-console-virtio.xml
@@ -0,0 +1,27 @@
+<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'/>
+ </console>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 566ab6b..017aad8 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -353,6 +353,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 |
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml
new file mode 100644
index 0000000..431dd34
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-console-virtio.xml
@@ -0,0 +1,29 @@
+<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'/>
+ <controller type='virtio-serial' index='0'/>
+ <console type='pty'>
+ <target type='virtio' port='0'/>
+ </console>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 08e0e73..dca9b9b 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -182,6 +182,7 @@ mymain(int argc, char **argv)
DO_TEST_DIFFERENT("channel-virtio-auto");
DO_TEST_DIFFERENT("console-compat-auto");
DO_TEST_DIFFERENT("disk-scsi-device-auto");
+ DO_TEST_DIFFERENT("console-virtio");
virCapabilitiesFree(driver.caps);
--
1.7.1.1