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(a)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">h...>)
+ <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