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