[libvirt] [PATCH] qemu: introduce spiceport serial backend

Signed-off-by: Martin Kletzander <mkletzan@redhat.com> --- Notes: This applies on top of "qemu: minor cleanups": https://www.redhat.com/archives/libvir-list/2014-January/msg01584.html docs/formatdomain.html.in | 22 +++++ docs/schemas/domaincommon.rng | 4 + src/conf/domain_audit.c | 3 +- src/conf/domain_conf.c | 40 ++++++++- src/conf/domain_conf.h | 6 +- src/qemu/qemu_capabilities.c | 8 ++ src/qemu/qemu_capabilities.h | 3 +- src/qemu/qemu_command.c | 96 +++++++++++++--------- src/qemu/qemu_monitor_json.c | 3 +- tests/qemucapabilitiesdata/caps_1.5.3-1.caps | 1 + tests/qemucapabilitiesdata/caps_1.6.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_1.6.50-1.caps | 1 + .../qemuxml2argv-serial-spiceport-nospice.args | 6 ++ .../qemuxml2argv-serial-spiceport-nospice.xml | 40 +++++++++ .../qemuxml2argv-serial-spiceport.args | 13 +++ .../qemuxml2argv-serial-spiceport.xml | 43 ++++++++++ tests/qemuxml2argvtest.c | 7 ++ tests/qemuxml2xmltest.c | 2 + 18 files changed, 255 insertions(+), 44 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fd02864..20ee61e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4252,6 +4252,10 @@ qemu-kvm -net nic,model=? /dev/null <source path='/dev/pts/3'/> <target port='0'/> </serial> + <serial type='spiceport'> + <source channel='org.qemu.console.serial.0'/> + <target port='0'/> + </serial> <console type='pty'> <source path='/dev/pts/4'/> <target port='0'/> @@ -4711,6 +4715,24 @@ qemu-kvm -net nic,model=? /dev/null <pre> ... <devices> + <serial type="spiceport"> + <source channel="org.qemu.console.serial.0"/> + <target port="1"/> + </serial> + </devices> + ...</pre> + + <h6><a name="elementsCharSpiceport">Spice channel</a></h6> + + <p> + The character device is accessible through spice connection + under a channel name specified in the <code>channel</code> + attribute. <span class="since">Since 1.2.2</span> + </p> + +<pre> + ... + <devices> <serial type="unix"> <source mode="bind" path="/tmp/foo"/> <target port="1"/> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 7f55f24..3063d5a 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2876,6 +2876,7 @@ <value>vc</value> <value>pty</value> <value>spicevmc</value> + <value>spiceport</value> </choice> </define> @@ -2946,6 +2947,9 @@ <attribute name="wiremode"/> </optional> <optional> + <attribute name="channel"/> + </optional> + <optional> <ref name='devSeclabel'/> </optional> </element> diff --git a/src/conf/domain_audit.c b/src/conf/domain_audit.c index 11cf5c8..b6564c2 100644 --- a/src/conf/domain_audit.c +++ b/src/conf/domain_audit.c @@ -1,7 +1,7 @@ /* * domain_audit.c: Domain audit management * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -81,6 +81,7 @@ virDomainAuditChardevPath(virDomainChrSourceDefPtr chr) case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_SPICEVMC: + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_LAST: return NULL; } diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fa1ecb5..8cdd0e9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -437,7 +437,8 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST, "udp", "tcp", "unix", - "spicevmc") + "spicevmc", + "spiceport") VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST, "raw", @@ -1583,6 +1584,12 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, STREQ_NULLABLE(src->data.nix.path, tgt->data.nix.path); break; + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + return STREQ_NULLABLE(src->data.spiceport.channel, + tgt->data.spiceport.channel); + return true; + break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -7090,6 +7097,9 @@ error: return ret; } +#define SERIAL_CHANNEL_NAME_CHARS \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-." + /* Parse the source half of the XML definition for a character device, * where node is the first element of node->children of the parent * element. def->type must already be valid. Return -1 on failure, @@ -7110,6 +7120,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, char *path = NULL; char *mode = NULL; char *protocol = NULL; + char *channel = NULL; int remaining = 0; while (cur != NULL) { @@ -7154,6 +7165,11 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, VIR_FREE(mode); break; + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!channel) + channel = virXMLPropString(cur, "channel"); + break; + case VIR_DOMAIN_CHR_TYPE_LAST: case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: @@ -7293,6 +7309,21 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, def->data.nix.path = path; path = NULL; break; + + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!channel) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing source channel attribute for char device")); + goto error; + } + if (strcspn(channel, SERIAL_CHANNEL_NAME_CHARS)) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid character in source channel for char device")); + goto error; + } + def->data.spiceport.channel = channel; + channel = NULL; + break; } cleanup: @@ -7303,6 +7334,7 @@ cleanup: VIR_FREE(connectHost); VIR_FREE(connectService); VIR_FREE(path); + VIR_FREE(channel); return remaining; @@ -15651,6 +15683,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " path='%s'", def->data.nix.path); virBufferAddLit(buf, "/>\n"); break; + + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + virBufferAsprintf(buf, "<source channel='%s'/>\n", + def->data.spiceport.channel); + break; + } virBufferAdjustIndent(buf, -6); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d8f2e49..b07aa8f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1,7 +1,7 @@ /* * domain_conf.h: domain XML processing * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -1104,6 +1104,7 @@ enum virDomainChrType { VIR_DOMAIN_CHR_TYPE_TCP, VIR_DOMAIN_CHR_TYPE_UNIX, VIR_DOMAIN_CHR_TYPE_SPICEVMC, + VIR_DOMAIN_CHR_TYPE_SPICEPORT, VIR_DOMAIN_CHR_TYPE_LAST }; @@ -1152,6 +1153,9 @@ struct _virDomainChrSourceDef { bool listen; } nix; int spicevmc; + struct { + char *channel; + } spiceport; } data; }; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 8aec293..317b374 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -248,6 +248,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "pvpanic", "enable-fips", "spice-file-xfer-disable", + "spiceport", ); struct _virQEMUCaps { @@ -1012,6 +1013,8 @@ virQEMUCapsComputeCmdFlags(const char *help, virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV); if (strstr(help, "-chardev spicevmc")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEVMC); + if (strstr(help, "-chardev spiceport")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT); } if (strstr(help, "-balloon")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_BALLOON); @@ -2570,6 +2573,11 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (qemuCaps->version >= 1006000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); + /* -chardev spiceport is supported from 1.4.0, + * but it's in qapi only since 1.5.0 */ + if (qemuCaps->version >= 1005000) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT); + if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0) goto cleanup; if (virQEMUCapsProbeQMPEvents(qemuCaps, mon) < 0) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 23dccce..a4eecb6 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -1,7 +1,7 @@ /* * qemu_capabilities.h: QEMU capabilities generation * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -202,6 +202,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_PANIC = 161, /* -device pvpanic */ QEMU_CAPS_ENABLE_FIPS = 162, /* -enable-fips */ QEMU_CAPS_SPICE_FILE_XFER_DISABLE = 163, /* -spice disable-agent-file-xfer */ + QEMU_CAPS_CHARDEV_SPICEPORT = 164, /* -chardev spiceport */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7e1cd53..c1635e0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5977,6 +5977,16 @@ qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias, virDomainChrSpicevmcTypeToString(dev->data.spicevmc)); break; + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("spiceport not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "spiceport,id=char%s,name=%s", alias, + dev->data.spiceport.channel); + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported chardev '%s'"), @@ -6075,6 +6085,8 @@ qemuBuildChrArgStr(virDomainChrSourceDefPtr dev, const char *prefix) case VIR_DOMAIN_CHR_TYPE_SPICEVMC: /* spicevmc doesn't have any '-serial' compatible option */ + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + /* spiceport doesn't have any '-serial' compatible option */ case VIR_DOMAIN_CHR_TYPE_LAST: /* coverity[dead_error_begin] */ break; @@ -7709,6 +7721,7 @@ qemuBuildCommandLine(virConnectPtr conn, int vnc = 0; int spice = 0; int usbcontroller = 0; + int actualSerials = 0; bool usblegacy = false; bool mlock = false; int contOrder[] = { @@ -7738,6 +7751,20 @@ qemuBuildCommandLine(virConnectPtr conn, emulator = def->emulator; + for (i = 0; i < def->ngraphics; ++i) { + switch (def->graphics[i]->type) { + case VIR_DOMAIN_GRAPHICS_TYPE_SDL: + ++sdl; + break; + case VIR_DOMAIN_GRAPHICS_TYPE_VNC: + ++vnc; + break; + case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: + ++spice; + break; + } + } + /* * do not use boot=on for drives when not using KVM since this * is not supported at all in upstream QEmu. @@ -8804,35 +8831,39 @@ qemuBuildCommandLine(virConnectPtr conn, virCommandAddArgBuffer(cmd, &opt); } - if (!def->nserials) { - /* If we have -device, then we set -nodefault already */ - if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) - virCommandAddArgList(cmd, "-serial", "none", NULL); - } else { - for (i = 0; i < def->nserials; i++) { - virDomainChrDefPtr serial = def->serials[i]; - char *devstr; + for (i = 0; i < def->nserials; i++) { + virDomainChrDefPtr serial = def->serials[i]; + char *devstr; - /* Use -chardev with -device if they are available */ - if (virQEMUCapsSupportsChardev(def, qemuCaps, serial)) { - virCommandAddArg(cmd, "-chardev"); - if (!(devstr = qemuBuildChrChardevStr(&serial->source, - serial->info.alias, - qemuCaps))) - goto error; - virCommandAddArg(cmd, devstr); - VIR_FREE(devstr); + if (serial->source.type == VIR_DOMAIN_CHR_TYPE_SPICEPORT && !spice) + continue; - if (qemuBuildChrDeviceCommandLine(cmd, def, serial, qemuCaps) < 0) - goto error; - } else { - virCommandAddArg(cmd, "-serial"); - if (!(devstr = qemuBuildChrArgStr(&serial->source, NULL))) - goto error; - virCommandAddArg(cmd, devstr); - VIR_FREE(devstr); - } + /* Use -chardev with -device if they are available */ + if (virQEMUCapsSupportsChardev(def, qemuCaps, serial)) { + virCommandAddArg(cmd, "-chardev"); + if (!(devstr = qemuBuildChrChardevStr(&serial->source, + serial->info.alias, + qemuCaps))) + goto error; + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); + + if (qemuBuildChrDeviceCommandLine(cmd, def, serial, qemuCaps) < 0) + goto error; + } else { + virCommandAddArg(cmd, "-serial"); + if (!(devstr = qemuBuildChrArgStr(&serial->source, NULL))) + goto error; + virCommandAddArg(cmd, devstr); + VIR_FREE(devstr); } + actualSerials++; + } + + if (!actualSerials) { + /* If we have -device, then we set -nodefault already */ + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) + virCommandAddArgList(cmd, "-serial", "none", NULL); } if (!def->nparallels) { @@ -9019,19 +9050,6 @@ qemuBuildCommandLine(virConnectPtr conn, } } - for (i = 0; i < def->ngraphics; ++i) { - switch (def->graphics[i]->type) { - case VIR_DOMAIN_GRAPHICS_TYPE_SDL: - ++sdl; - break; - case VIR_DOMAIN_GRAPHICS_TYPE_VNC: - ++vnc; - break; - case VIR_DOMAIN_GRAPHICS_TYPE_SPICE: - ++spice; - break; - } - } if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_0_10) && sdl + vnc + spice > 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("only 1 graphics device is supported")); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index ec3b958..5e825ac 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -1,7 +1,7 @@ /* * qemu_monitor_json.c: interaction with QEMU monitor console * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -5318,6 +5318,7 @@ qemuMonitorJSONAttachCharDevCommand(const char *chrID, break; case VIR_DOMAIN_CHR_TYPE_SPICEVMC: + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: case VIR_DOMAIN_CHR_TYPE_PIPE: case VIR_DOMAIN_CHR_TYPE_STDIO: case VIR_DOMAIN_CHR_TYPE_LAST: diff --git a/tests/qemucapabilitiesdata/caps_1.5.3-1.caps b/tests/qemucapabilitiesdata/caps_1.5.3-1.caps index 1e5bb74..adf8531 100644 --- a/tests/qemucapabilitiesdata/caps_1.5.3-1.caps +++ b/tests/qemucapabilitiesdata/caps_1.5.3-1.caps @@ -134,4 +134,5 @@ <flag name='boot-strict'/> <flag name='pvpanic'/> <flag name='reboot-timeout'/> + <flag name='spiceport'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps index 61542a8..e6b2f76 100644 --- a/tests/qemucapabilitiesdata/caps_1.6.0-1.caps +++ b/tests/qemucapabilitiesdata/caps_1.6.0-1.caps @@ -140,4 +140,5 @@ <flag name='reboot-timeout'/> <flag name='enable-fips'/> <flag name='spice-file-xfer-disable'/> + <flag name='spiceport'/> </qemuCaps> diff --git a/tests/qemucapabilitiesdata/caps_1.6.50-1.caps b/tests/qemucapabilitiesdata/caps_1.6.50-1.caps index 8ce17aa..e6b8117 100644 --- a/tests/qemucapabilitiesdata/caps_1.6.50-1.caps +++ b/tests/qemucapabilitiesdata/caps_1.6.50-1.caps @@ -138,4 +138,5 @@ <flag name='pvpanic'/> <flag name='reboot-timeout'/> <flag name='spice-file-xfer-disable'/> + <flag name='spiceport'/> </qemuCaps> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args new file mode 100644 index 0000000..1e27394 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args @@ -0,0 +1,6 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \ +/usr/bin/qemu \ +-name QEMUGuest1 -S -M pc -m 214 -smp 1 -nographic -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \ +-usb -hda /dev/HostVG/QEMUGuest1 -net none -serial \ +none -parallel none diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml new file mode 100644 index 0000000..06a99a3 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml @@ -0,0 +1,40 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <title>A description of the test machine.</title> + <description> + A test of qemu's minimal configuration. + This test also tests the description and title elements. + </description> + <memory unit='KiB'>219100</memory> + <currentMemory unit='KiB'>219100</currentMemory> + <vcpu placement='static' 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' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <serial type='spiceport'> + <source channel='org.qemu.console.serial.0'/> + <target port='0'/> + </serial> + <console type='spiceport'> + <source channel='org.qemu.console.serial.0'/> + <target type='serial' port='0'/> + </console> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args new file mode 100644 index 0000000..8c631b1 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args @@ -0,0 +1,13 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=spice \ +/usr/bin/qemu -S -M pc -m 214 -smp 1 -nodefconfig -nodefaults \ +-chardev socket,id=charmonitor,path=/tmp/test-monitor,server,nowait \ +-mon chardev=charmonitor,id=monitor,mode=readline \ +-no-acpi -boot c -usb \ +-hda /dev/HostVG/QEMUGuest1 \ +-chardev spiceport,id=charserial0,name=org.qemu.console.serial.0 \ +-device isa-serial,chardev=charserial0,id=serial0 \ +-device usb-tablet,id=input0 \ +-spice port=5903,tls-port=5904,addr=127.0.0.1,x509-dir=/etc/pki/libvirt-spice \ +-device \ +qxl-vga,id=video0,ram_size=67107840,vram_size=67107840,bus=pci.0,addr=0x2 \ +-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml new file mode 100644 index 0000000..1e42ee6 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml @@ -0,0 +1,43 @@ +<domain type='qemu'> + <name>QEMUGuest1</name> + <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid> + <memory unit='KiB'>219136</memory> + <currentMemory unit='KiB'>219136</currentMemory> + <vcpu placement='static' 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' target='0' unit='0'/> + </disk> + <controller type='usb' index='0'/> + <controller type='ide' index='0'/> + <controller type='pci' index='0' model='pci-root'/> + <serial type='spiceport'> + <source channel='org.qemu.console.serial.0'/> + <target port='0'/> + </serial> + <console type='spiceport'> + <source channel='org.qemu.console.serial.0'/> + <target type='serial' port='0'/> + </console> + <input type='tablet' bus='usb'/> + <input type='mouse' bus='ps2'/> + <graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'> + <listen type='address' address='127.0.0.1'/> + </graphics> + <video> + <model type='qxl' ram='65535' vram='65535' heads='1'/> + </video> + <memballoon model='virtio'/> + </devices> +</domain> diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index a25264e..ad785d4 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -939,6 +939,13 @@ mymain(void) DO_TEST("serial-udp", NONE); DO_TEST("serial-tcp-telnet", NONE); DO_TEST("serial-many", NONE); + DO_TEST("serial-spiceport", + QEMU_CAPS_CHARDEV, QEMU_CAPS_DEVICE, + QEMU_CAPS_NODEFCONFIG, QEMU_CAPS_DEVICE_VIDEO_PRIMARY, + QEMU_CAPS_DEVICE_QXL, QEMU_CAPS_DEVICE_QXL_VGA, + QEMU_CAPS_SPICE, QEMU_CAPS_CHARDEV_SPICEPORT); + DO_TEST("serial-spiceport-nospice", QEMU_CAPS_NAME); + DO_TEST("parallel-tcp", NONE); DO_TEST("console-compat", NONE); DO_TEST("console-compat-auto", NONE); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index 41d1904..c57d7af 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -239,6 +239,8 @@ mymain(void) DO_TEST("serial-udp"); DO_TEST("serial-tcp-telnet"); DO_TEST("serial-many"); + DO_TEST("serial-spiceport"); + DO_TEST("serial-spiceport-nospice"); DO_TEST("parallel-tcp"); DO_TEST("console-compat"); DO_TEST("console-virtio-many"); -- 1.8.5.3

Hey, Not a full review yet as I have only been looking at the doc so far. On Mon, Feb 03, 2014 at 05:41:00PM +0100, Martin Kletzander wrote:
Signed-off-by: Martin Kletzander <mkletzan@redhat.com> ---
Notes: This applies on top of "qemu: minor cleanups":
https://www.redhat.com/archives/libvir-list/2014-January/msg01584.html
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fd02864..20ee61e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4252,6 +4252,10 @@ qemu-kvm -net nic,model=? /dev/null <source path='/dev/pts/3'/> <target port='0'/> </serial> + <serial type='spiceport'> + <source channel='org.qemu.console.serial.0'/> + <target port='0'/> + </serial> <console type='pty'> <source path='/dev/pts/4'/> <target port='0'/> @@ -4711,6 +4715,24 @@ qemu-kvm -net nic,model=? /dev/null <pre> ... <devices> + <serial type="spiceport"> + <source channel="org.qemu.console.serial.0"/> + <target port="1"/> + </serial> + </devices> + ...</pre> + + <h6><a name="elementsCharSpiceport">Spice channel</a></h6> + + <p> + The character device is accessible through spice connection + under a channel name specified in the <code>channel</code> + attribute. <span class="since">Since 1.2.2</span> + </p> + +<pre> + ... + <devices> <serial type="unix"> <source mode="bind" path="/tmp/foo"/> <target port="1"/>
This bit is wrong as the doc ends up as * UNIX domain socket client/server description spiceport sample XML * Spice channel description unix domain socket sample XML Regarding the way it's exposed, you have chosen to go with <devices> <serial type="spiceport"> <source channel="org.qemu.console.serial.0"/> <target port="1"/> </serial> </devices> This exposes the 'org.qemu.console.serial.0' spiceport as a serial port in the guest. This spiceport can then be used by client applications to interact with the guest. This is very similar to what is done for the spice agent channel (a virtio serial port is made available in the guest and is used for client<->guest communication). Wouldn't it be more consistent to use <channel type="spiceport"> <target type="virtio" name="org.qemu.console.serial.0"/> </channel> here? When I gave some thoughts about how to expose spiceport in libvirt, I got confused as in addition to this guest<->spice client channel, spiceport is much more generic and can also be used to create some host<->spice client channels (eg forward a local host socket/... over to the client through spice). If we use <channel>, maybe this can be added later with <channel type="spiceport"> <target type="host" name="org.qemu.console.serial.0"/> <source ... /> </channel> ? (thinking out loud, and something which can be added when there is need for it) Christophe

On Tue, Feb 04, 2014 at 01:34:38PM +0100, Christophe Fergeau wrote:
Hey,
Not a full review yet as I have only been looking at the doc so far.
On Mon, Feb 03, 2014 at 05:41:00PM +0100, Martin Kletzander wrote:
Signed-off-by: Martin Kletzander <mkletzan@redhat.com> ---
Notes: This applies on top of "qemu: minor cleanups":
https://www.redhat.com/archives/libvir-list/2014-January/msg01584.html
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index fd02864..20ee61e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -4252,6 +4252,10 @@ qemu-kvm -net nic,model=? /dev/null <source path='/dev/pts/3'/> <target port='0'/> </serial> + <serial type='spiceport'> + <source channel='org.qemu.console.serial.0'/> + <target port='0'/> + </serial> <console type='pty'> <source path='/dev/pts/4'/> <target port='0'/> @@ -4711,6 +4715,24 @@ qemu-kvm -net nic,model=? /dev/null <pre> ... <devices> + <serial type="spiceport"> + <source channel="org.qemu.console.serial.0"/> + <target port="1"/> + </serial> + </devices> + ...</pre> + + <h6><a name="elementsCharSpiceport">Spice channel</a></h6> + + <p> + The character device is accessible through spice connection + under a channel name specified in the <code>channel</code> + attribute. <span class="since">Since 1.2.2</span> + </p> + +<pre> + ... + <devices> <serial type="unix"> <source mode="bind" path="/tmp/foo"/> <target port="1"/>
This bit is wrong as the doc ends up as * UNIX domain socket client/server description spiceport sample XML
* Spice channel description unix domain socket sample XML
Yes, my fault, I copy-pasted the previous target type and then changed the wrong one.
Regarding the way it's exposed, you have chosen to go with <devices> <serial type="spiceport"> <source channel="org.qemu.console.serial.0"/> <target port="1"/> </serial> </devices>
This exposes the 'org.qemu.console.serial.0' spiceport as a serial port in the guest. This spiceport can then be used by client applications to interact with the guest. This is very similar to what is done for the spice agent channel (a virtio serial port is made available in the guest and is used for client<->guest communication). Wouldn't it be more consistent to use <channel type="spiceport"> <target type="virtio" name="org.qemu.console.serial.0"/> </channel> here?
When I gave some thoughts about how to expose spiceport in libvirt, I got confused as in addition to this guest<->spice client channel, spiceport is much more generic and can also be used to create some host<->spice client channels (eg forward a local host socket/... over to the client through spice). If we use <channel>, maybe this can be added later with <channel type="spiceport"> <target type="host" name="org.qemu.console.serial.0"/> <source ... /> </channel> ? (thinking out loud, and something which can be added when there is need for it)
Christophe
The thing is that when you use spicevmc, the channel going through the guest (target -- frontend in the guest) is identified using the virtio channel name because it is virtio-serial-port. That's what you see in the XML. For the source (backend on host) there are only three spicevmc channel names to use: vdagent, smartcard and usbredir. We don't offer to choose that names since there is only one possible usage for each of those. OTOH with spiceport, you can choose the channel name yourself, have them as many as you want and since it provides _backend_ connection (source for the chardev), it is identified by this name in the _client_. From the technical POV, you can interconnect spiceport as a source with any other target that qemu supports. But that doesn't change the fact that spiceport is only used as a backend and is not seen in the guest. In the example I went with using isa-serial as a target, because that was the usage mentioned in the mail thanks to which I started working on it [1], but I to meet your needs you can go with: <channel type="spiceport"> <source channel="org.qemu.console.serial.0"/> <target type="virtio" name="whatever-name.you.want"/> </channel> which works with this patch too as it merely adds the backend to the mix. In this case it won't be serial port, but virtio-port (channel); that means you'll see '/dev/virtio-ports/whatever-name.you.want' in the guest instead of '/dev/ttyS0'. Martin P.S.: Due to spicevmc channel being implemented the way it is, it took me non-trivial amount of time to figure out how to expose this and I went through more "designs" before I figured this is just a backend, nothing else :) [1] http://lists.freedesktop.org/archives/spice-devel/2014-January/015919.html

On Tue, Feb 04, 2014 at 02:25:03PM +0100, Martin Kletzander wrote:
On Tue, Feb 04, 2014 at 01:34:38PM +0100, Christophe Fergeau wrote:
Regarding the way it's exposed, you have chosen to go with <devices> <serial type="spiceport"> <source channel="org.qemu.console.serial.0"/> <target port="1"/> </serial> </devices>
This exposes the 'org.qemu.console.serial.0' spiceport as a serial port in the guest. This spiceport can then be used by client applications to interact with the guest. This is very similar to what is done for the spice agent channel (a virtio serial port is made available in the guest and is used for client<->guest communication). Wouldn't it be more consistent to use <channel type="spiceport"> <target type="virtio" name="org.qemu.console.serial.0"/> </channel> here?
When I gave some thoughts about how to expose spiceport in libvirt, I got confused as in addition to this guest<->spice client channel, spiceport is much more generic and can also be used to create some host<->spice client channels (eg forward a local host socket/... over to the client through spice). If we use <channel>, maybe this can be added later with <channel type="spiceport"> <target type="host" name="org.qemu.console.serial.0"/> <source ... /> </channel> ? (thinking out loud, and something which can be added when there is need for it)
From the technical POV, you can interconnect spiceport as a source with any other target that qemu supports. [...]
In the example I went with using isa-serial as a target, because that was the usage mentioned in the mail thanks to which I started working on it [1], but I to meet your needs you can go with:
<channel type="spiceport"> <source channel="org.qemu.console.serial.0"/> <target type="virtio" name="whatever-name.you.want"/> </channel>
which works with this patch too
Ah, I missed this was possible, hence the comments. It would probably be worth it to add a !isa-serial example either to the documentation or to the commit log. Thanks for the detailed explanation!
P.S.: Due to spicevmc channel being implemented the way it is, it took me non-trivial amount of time to figure out how to expose this and I went through more "designs" before I figured this is just a backend, nothing else :)
Yeah, had trouble wrapping my head around exposing spiceport when I gave it a quick look, good that you managed to get on top of it ;) Christophe

On Mon, Feb 03, 2014 at 05:41:00PM +0100, Martin Kletzander wrote:
signed-off-by: martin kletzander <mkletzan@redhat.com> ---
notes: this applies on top of "qemu: minor cleanups":
https://www.redhat.com/archives/libvir-list/2014-january/msg01584.html
docs/formatdomain.html.in | 22 +++++ docs/schemas/domaincommon.rng | 4 + src/conf/domain_audit.c | 3 +- src/conf/domain_conf.c | 40 ++++++++- src/conf/domain_conf.h | 6 +- src/qemu/qemu_capabilities.c | 8 ++ src/qemu/qemu_capabilities.h | 3 +- src/qemu/qemu_command.c | 96 +++++++++++++--------- src/qemu/qemu_monitor_json.c | 3 +- tests/qemucapabilitiesdata/caps_1.5.3-1.caps | 1 + tests/qemucapabilitiesdata/caps_1.6.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_1.6.50-1.caps | 1 + .../qemuxml2argv-serial-spiceport-nospice.args | 6 ++ .../qemuxml2argv-serial-spiceport-nospice.xml | 40 +++++++++ .../qemuxml2argv-serial-spiceport.args | 13 +++ .../qemuxml2argv-serial-spiceport.xml | 43 ++++++++++ tests/qemuxml2argvtest.c | 7 ++ tests/qemuxml2xmltest.c | 2 + 18 files changed, 255 insertions(+), 44 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fa1ecb5..8cdd0e9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -437,7 +437,8 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST, "udp", "tcp", "unix", - "spicevmc") + "spicevmc", + "spiceport")
VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST, "raw", @@ -1583,6 +1584,12 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, STREQ_NULLABLE(src->data.nix.path, tgt->data.nix.path); break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + return STREQ_NULLABLE(src->data.spiceport.channel, + tgt->data.spiceport.channel); + return true;
this 'return true' is not needed
+ break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -7090,6 +7097,9 @@ error: return ret; }
+#define SERIAL_CHANNEL_NAME_CHARS \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-." + /* Parse the source half of the XML definition for a character device, * where node is the first element of node->children of the parent * element. def->type must already be valid. Return -1 on failure, @@ -7110,6 +7120,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, char *path = NULL; char *mode = NULL; char *protocol = NULL; + char *channel = NULL; int remaining = 0;
while (cur != NULL) { @@ -7154,6 +7165,11 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, VIR_FREE(mode); break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!channel) + channel = virXMLPropString(cur, "channel"); + break; + case VIR_DOMAIN_CHR_TYPE_LAST: case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: @@ -7293,6 +7309,21 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, def->data.nix.path = path; path = NULL; break; + + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!channel) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing source channel attribute for char device")); + goto error; + }
Code before that uses VIR_ERR_INTERNAL_ERROR for missing attributes, but VIR_ERR_XML_ERROR seems indeed better.
+ if (strcspn(channel, SERIAL_CHANNEL_NAME_CHARS)) {
If I understood the man page correctly, strcspn will return the number of characters at the beginning of channel which are not in SERIAL_CHANNEL_NAME_CHARS. It seems this won't catch "org.éâò". The net code does: if (strspn(channel, SERIAL_CHANNEL_NAME_CHARS) < strlen(channel)) { which seems ok.
+ virReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid character in source channel for char device"));
The network code uses VIR_ERR_INVALID_ARG here.
+ goto error; + } + def->data.spiceport.channel = channel; + channel = NULL; + break; }
cleanup: @@ -7303,6 +7334,7 @@ cleanup: VIR_FREE(connectHost); VIR_FREE(connectService); VIR_FREE(path); + VIR_FREE(channel);
return remaining;
@@ -15651,6 +15683,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " path='%s'", def->data.nix.path); virBufferAddLit(buf, "/>\n"); break; + + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + virBufferAsprintf(buf, "<source channel='%s'/>\n", + def->data.spiceport.channel); + break; + } virBufferAdjustIndent(buf, -6);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d8f2e49..b07aa8f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1,7 +1,7 @@ /* * domain_conf.h: domain XML processing * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -1104,6 +1104,7 @@ enum virDomainChrType { VIR_DOMAIN_CHR_TYPE_TCP, VIR_DOMAIN_CHR_TYPE_UNIX, VIR_DOMAIN_CHR_TYPE_SPICEVMC, + VIR_DOMAIN_CHR_TYPE_SPICEPORT,
VIR_DOMAIN_CHR_TYPE_LAST }; @@ -1152,6 +1153,9 @@ struct _virDomainChrSourceDef { bool listen; } nix; int spicevmc; + struct { + char *channel; + } spiceport; } data; };
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 8aec293..317b374 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -248,6 +248,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "pvpanic", "enable-fips", "spice-file-xfer-disable", + "spiceport", );
struct _virQEMUCaps { @@ -1012,6 +1013,8 @@ virQEMUCapsComputeCmdFlags(const char *help, virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV); if (strstr(help, "-chardev spicevmc")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEVMC); + if (strstr(help, "-chardev spiceport")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT); } if (strstr(help, "-balloon")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_BALLOON); @@ -2570,6 +2573,11 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (qemuCaps->version >= 1006000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
+ /* -chardev spiceport is supported from 1.4.0, + * but it's in qapi only since 1.5.0 */ + if (qemuCaps->version >= 1005000) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT); +
I'd tend to put this before if (qemuCaps->version >= 1006000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); so that the qemu version tests are sorted by version.
if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0) goto cleanup; if (virQEMUCapsProbeQMPEvents(qemuCaps, mon) < 0) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 23dccce..a4eecb6 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -1,7 +1,7 @@ /* * qemu_capabilities.h: QEMU capabilities generation * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -202,6 +202,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_PANIC = 161, /* -device pvpanic */ QEMU_CAPS_ENABLE_FIPS = 162, /* -enable-fips */ QEMU_CAPS_SPICE_FILE_XFER_DISABLE = 163, /* -spice disable-agent-file-xfer */ + QEMU_CAPS_CHARDEV_SPICEPORT = 164, /* -chardev spiceport */
QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7e1cd53..c1635e0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5977,6 +5977,16 @@ qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias, virDomainChrSpicevmcTypeToString(dev->data.spicevmc)); break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("spiceport not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "spiceport,id=char%s,name=%s", alias, + dev->data.spiceport.channel); + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported chardev '%s'"), @@ -6075,6 +6085,8 @@ qemuBuildChrArgStr(virDomainChrSourceDefPtr dev, const char *prefix)
case VIR_DOMAIN_CHR_TYPE_SPICEVMC: /* spicevmc doesn't have any '-serial' compatible option */ + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + /* spiceport doesn't have any '-serial' compatible option */
As you suggested when I raised this for TYPE_SPICEVMC, you can remove the confusing comment for TYPE_SPICE_PORT too. Rest of the patch looks good. Christophe

On Wed, Feb 05, 2014 at 03:38:49PM +0100, Christophe Fergeau wrote:
On Mon, Feb 03, 2014 at 05:41:00PM +0100, Martin Kletzander wrote:
signed-off-by: martin kletzander <mkletzan@redhat.com> ---
notes: this applies on top of "qemu: minor cleanups":
https://www.redhat.com/archives/libvir-list/2014-january/msg01584.html
docs/formatdomain.html.in | 22 +++++ docs/schemas/domaincommon.rng | 4 + src/conf/domain_audit.c | 3 +- src/conf/domain_conf.c | 40 ++++++++- src/conf/domain_conf.h | 6 +- src/qemu/qemu_capabilities.c | 8 ++ src/qemu/qemu_capabilities.h | 3 +- src/qemu/qemu_command.c | 96 +++++++++++++--------- src/qemu/qemu_monitor_json.c | 3 +- tests/qemucapabilitiesdata/caps_1.5.3-1.caps | 1 + tests/qemucapabilitiesdata/caps_1.6.0-1.caps | 1 + tests/qemucapabilitiesdata/caps_1.6.50-1.caps | 1 + .../qemuxml2argv-serial-spiceport-nospice.args | 6 ++ .../qemuxml2argv-serial-spiceport-nospice.xml | 40 +++++++++ .../qemuxml2argv-serial-spiceport.args | 13 +++ .../qemuxml2argv-serial-spiceport.xml | 43 ++++++++++ tests/qemuxml2argvtest.c | 7 ++ tests/qemuxml2xmltest.c | 2 + 18 files changed, 255 insertions(+), 44 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport-nospice.xml create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-serial-spiceport.xml
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index fa1ecb5..8cdd0e9 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -437,7 +437,8 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST, "udp", "tcp", "unix", - "spicevmc") + "spicevmc", + "spiceport")
VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST, "raw", @@ -1583,6 +1584,12 @@ virDomainChrSourceDefIsEqual(const virDomainChrSourceDef *src, STREQ_NULLABLE(src->data.nix.path, tgt->data.nix.path); break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + return STREQ_NULLABLE(src->data.spiceport.channel, + tgt->data.spiceport.channel); + return true;
this 'return true' is not needed
I was probably cleaning this out so many times I over-cleaned it to double returns.
+ break; + case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: case VIR_DOMAIN_CHR_TYPE_STDIO: @@ -7090,6 +7097,9 @@ error: return ret; }
+#define SERIAL_CHANNEL_NAME_CHARS \ + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-." + /* Parse the source half of the XML definition for a character device, * where node is the first element of node->children of the parent * element. def->type must already be valid. Return -1 on failure, @@ -7110,6 +7120,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, char *path = NULL; char *mode = NULL; char *protocol = NULL; + char *channel = NULL; int remaining = 0;
while (cur != NULL) { @@ -7154,6 +7165,11 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, VIR_FREE(mode); break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!channel) + channel = virXMLPropString(cur, "channel"); + break; + case VIR_DOMAIN_CHR_TYPE_LAST: case VIR_DOMAIN_CHR_TYPE_NULL: case VIR_DOMAIN_CHR_TYPE_VC: @@ -7293,6 +7309,21 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def, def->data.nix.path = path; path = NULL; break; + + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!channel) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing source channel attribute for char device")); + goto error; + }
Code before that uses VIR_ERR_INTERNAL_ERROR for missing attributes, but VIR_ERR_XML_ERROR seems indeed better.
Yes, at least from what I remembered the previous one should be XML_ERROR as well, but I didn't want to mix the cleanup with introducing spiceport.
+ if (strcspn(channel, SERIAL_CHANNEL_NAME_CHARS)) {
If I understood the man page correctly, strcspn will return the number of characters at the beginning of channel which are not in SERIAL_CHANNEL_NAME_CHARS. It seems this won't catch "org.éâò". The net code does: if (strspn(channel, SERIAL_CHANNEL_NAME_CHARS) < strlen(channel)) { which seems ok.
I missed that it calculates only the "prefix" length and used strcspn instead of strspn, so this code is all wrong.
+ virReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid character in source channel for char device"));
The network code uses VIR_ERR_INVALID_ARG here.
Hard to say what's better, it's an argument in XML, so both are sensible, but I'll change that for v2.
+ goto error; + } + def->data.spiceport.channel = channel; + channel = NULL; + break; }
cleanup: @@ -7303,6 +7334,7 @@ cleanup: VIR_FREE(connectHost); VIR_FREE(connectService); VIR_FREE(path); + VIR_FREE(channel);
return remaining;
@@ -15651,6 +15683,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf, virBufferEscapeString(buf, " path='%s'", def->data.nix.path); virBufferAddLit(buf, "/>\n"); break; + + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + virBufferAsprintf(buf, "<source channel='%s'/>\n", + def->data.spiceport.channel); + break; + } virBufferAdjustIndent(buf, -6);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d8f2e49..b07aa8f 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1,7 +1,7 @@ /* * domain_conf.h: domain XML processing * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006-2008 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -1104,6 +1104,7 @@ enum virDomainChrType { VIR_DOMAIN_CHR_TYPE_TCP, VIR_DOMAIN_CHR_TYPE_UNIX, VIR_DOMAIN_CHR_TYPE_SPICEVMC, + VIR_DOMAIN_CHR_TYPE_SPICEPORT,
VIR_DOMAIN_CHR_TYPE_LAST }; @@ -1152,6 +1153,9 @@ struct _virDomainChrSourceDef { bool listen; } nix; int spicevmc; + struct { + char *channel; + } spiceport; } data; };
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 8aec293..317b374 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -248,6 +248,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST, "pvpanic", "enable-fips", "spice-file-xfer-disable", + "spiceport", );
struct _virQEMUCaps { @@ -1012,6 +1013,8 @@ virQEMUCapsComputeCmdFlags(const char *help, virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV); if (strstr(help, "-chardev spicevmc")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEVMC); + if (strstr(help, "-chardev spiceport")) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT); } if (strstr(help, "-balloon")) virQEMUCapsSet(qemuCaps, QEMU_CAPS_BALLOON); @@ -2570,6 +2573,11 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps, if (qemuCaps->version >= 1006000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY);
+ /* -chardev spiceport is supported from 1.4.0, + * but it's in qapi only since 1.5.0 */ + if (qemuCaps->version >= 1005000) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT); +
I'd tend to put this before if (qemuCaps->version >= 1006000) virQEMUCapsSet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY); so that the qemu version tests are sorted by version.
if (virQEMUCapsProbeQMPCommands(qemuCaps, mon) < 0) goto cleanup; if (virQEMUCapsProbeQMPEvents(qemuCaps, mon) < 0) diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 23dccce..a4eecb6 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -1,7 +1,7 @@ /* * qemu_capabilities.h: QEMU capabilities generation * - * Copyright (C) 2006-2013 Red Hat, Inc. + * Copyright (C) 2006-2014 Red Hat, Inc. * Copyright (C) 2006 Daniel P. Berrange * * This library is free software; you can redistribute it and/or @@ -202,6 +202,7 @@ enum virQEMUCapsFlags { QEMU_CAPS_DEVICE_PANIC = 161, /* -device pvpanic */ QEMU_CAPS_ENABLE_FIPS = 162, /* -enable-fips */ QEMU_CAPS_SPICE_FILE_XFER_DISABLE = 163, /* -spice disable-agent-file-xfer */ + QEMU_CAPS_CHARDEV_SPICEPORT = 164, /* -chardev spiceport */
QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7e1cd53..c1635e0 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -5977,6 +5977,16 @@ qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias, virDomainChrSpicevmcTypeToString(dev->data.spicevmc)); break;
+ case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_CHARDEV_SPICEPORT)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("spiceport not supported in this QEMU binary")); + goto error; + } + virBufferAsprintf(&buf, "spiceport,id=char%s,name=%s", alias, + dev->data.spiceport.channel); + break; + default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("unsupported chardev '%s'"), @@ -6075,6 +6085,8 @@ qemuBuildChrArgStr(virDomainChrSourceDefPtr dev, const char *prefix)
case VIR_DOMAIN_CHR_TYPE_SPICEVMC: /* spicevmc doesn't have any '-serial' compatible option */ + case VIR_DOMAIN_CHR_TYPE_SPICEPORT: + /* spiceport doesn't have any '-serial' compatible option */
As you suggested when I raised this for TYPE_SPICEVMC, you can remove the confusing comment for TYPE_SPICE_PORT too.
Definitely, I just posted it before seeing that. Thanks for the review, v2 coming up. Martin
Rest of the patch looks good.
Christophe
participants (2)
-
Christophe Fergeau
-
Martin Kletzander