mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-02-21 10:52:22 +00:00
spicevmc: support new qemu chardev
Inspired by https://bugzilla.redhat.com/show_bug.cgi?id=615757 Add a new character device backend for virtio serial channels that activates the QEMU spice agent on the main channel using the vdagent spicevmc connection. The <target> must be type='virtio', and supports an optional name that specifies how the guest will see the channel (for now, name must be com.redhat.spice.0). <channel type='spicevmc'> <target type='virtio'/> <address type='virtio-serial' controller='1' bus='0' port='3'/> </channel> * docs/schemas/domain.rng: Support new XML. * docs/formatdomain.html.in: Document it. * src/conf/domain_conf.h (virDomainChrType): New enum value. * src/conf/domain_conf.c (virDomainChr): Add spicevmc. (virDomainChrDefParseXML, virDomainChrSourceDefParseXML) (virDomainChrDefParseTargetXML): Parse and enforce proper use. (virDomainChrSourceDefFormat, virDomainChrDefFormat): Format. * src/qemu/qemu_command.c (qemuBuildChrChardevStr) (qemuBuildCommandLine): Add qemu support. * tests/qemuxml2argvtest.c (domain): New test. * tests/qemuxml2argvdata/qemuxml2argv-channel-spicevmc.xml: New file. * tests/qemuxml2argvdata/qemuxml2argv-channel-spicevmc.args: Likewise. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
f5fd9baac1
commit
be87a1236e
@ -1734,6 +1734,9 @@ qemu-kvm -net nic,model=? /dev/null
|
|||||||
<channel type='pty'>
|
<channel type='pty'>
|
||||||
<target type='virtio' name='arbitrary.virtio.serial.port.name'/>
|
<target type='virtio' name='arbitrary.virtio.serial.port.name'/>
|
||||||
</channel>
|
</channel>
|
||||||
|
<channel type='spicevmc'>
|
||||||
|
<target type='virtio' name='com.redhat.spice.0'/>
|
||||||
|
</channel>
|
||||||
</devices>
|
</devices>
|
||||||
...</pre>
|
...</pre>
|
||||||
|
|
||||||
@ -1759,6 +1762,20 @@ qemu-kvm -net nic,model=? /dev/null
|
|||||||
optional element <code>address</code> can tie the channel to a
|
optional element <code>address</code> can tie the channel to a
|
||||||
particular <code>type='virtio-serial'</code> controller.
|
particular <code>type='virtio-serial'</code> controller.
|
||||||
<span class="since">Since 0.7.7</span></dd>
|
<span class="since">Since 0.7.7</span></dd>
|
||||||
|
|
||||||
|
<dt><code>spicevmc</code></dt>
|
||||||
|
<dd>Paravirtualized SPICE channel. The domain must also have a
|
||||||
|
SPICE server as a <a href="#elementsGraphics">graphics
|
||||||
|
device</a>, at which point the host piggy-backs messages
|
||||||
|
across the <code>main</code> channel. The <code>target</code>
|
||||||
|
element must be present, with
|
||||||
|
attribute <code>type='virtio'</code>; an optional
|
||||||
|
attribute <code>name</code> controls how the guest will have
|
||||||
|
access to the channel, and defaults
|
||||||
|
to <code>name='com.redhat.spice.0'</code>. The
|
||||||
|
optional <code>address</code> element can tie the channel to a
|
||||||
|
particular <code>type='virtio-serial'</code> controller.
|
||||||
|
<span class="since">Since 0.8.8</span></dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<h5><a name="elementsCharHostInterface">Host interface</a></h5>
|
<h5><a name="elementsCharHostInterface">Host interface</a></h5>
|
||||||
|
@ -1475,6 +1475,7 @@
|
|||||||
<value>stdio</value>
|
<value>stdio</value>
|
||||||
<value>vc</value>
|
<value>vc</value>
|
||||||
<value>pty</value>
|
<value>pty</value>
|
||||||
|
<value>spicevmc</value>
|
||||||
</choice>
|
</choice>
|
||||||
</attribute>
|
</attribute>
|
||||||
</define>
|
</define>
|
||||||
@ -1611,7 +1612,7 @@
|
|||||||
<define name="virtioTarget">
|
<define name="virtioTarget">
|
||||||
<element name="target">
|
<element name="target">
|
||||||
<attribute name="type">
|
<attribute name="type">
|
||||||
<value>virtio</value>
|
<value>virtio</value>
|
||||||
</attribute>
|
</attribute>
|
||||||
<optional>
|
<optional>
|
||||||
<attribute name="name"/>
|
<attribute name="name"/>
|
||||||
|
@ -226,7 +226,8 @@ VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
|
|||||||
"stdio",
|
"stdio",
|
||||||
"udp",
|
"udp",
|
||||||
"tcp",
|
"tcp",
|
||||||
"unix")
|
"unix",
|
||||||
|
"spicevmc")
|
||||||
|
|
||||||
VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
|
VIR_ENUM_IMPL(virDomainChrTcpProtocol, VIR_DOMAIN_CHR_TCP_PROTOCOL_LAST,
|
||||||
"raw",
|
"raw",
|
||||||
@ -3065,6 +3066,7 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case VIR_DOMAIN_CHR_TYPE_STDIO:
|
case VIR_DOMAIN_CHR_TYPE_STDIO:
|
||||||
|
case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
|
||||||
/* Nada */
|
/* Nada */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -3254,6 +3256,13 @@ virDomainChrDefParseXML(virCapsPtr caps,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (def->source.type == VIR_DOMAIN_CHR_TYPE_SPICEVMC &&
|
||||||
|
def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
|
||||||
|
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("spicevmc device type only supports virtio"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0)
|
if (virDomainDeviceInfoParseXML(node, &def->info, flags) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
@ -3361,6 +3370,12 @@ virDomainSmartcardDefParseXML(xmlNodePtr node,
|
|||||||
cur = node->children;
|
cur = node->children;
|
||||||
if (virDomainChrSourceDefParseXML(&def->data.passthru, cur) < 0)
|
if (virDomainChrSourceDefParseXML(&def->data.passthru, cur) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (def->data.passthru.type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) {
|
||||||
|
virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("smartcard spicevmc device not supported"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -6843,6 +6858,7 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
|
|||||||
case VIR_DOMAIN_CHR_TYPE_NULL:
|
case VIR_DOMAIN_CHR_TYPE_NULL:
|
||||||
case VIR_DOMAIN_CHR_TYPE_VC:
|
case VIR_DOMAIN_CHR_TYPE_VC:
|
||||||
case VIR_DOMAIN_CHR_TYPE_STDIO:
|
case VIR_DOMAIN_CHR_TYPE_STDIO:
|
||||||
|
case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
|
||||||
/* nada */
|
/* nada */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -413,6 +413,7 @@ enum virDomainChrType {
|
|||||||
VIR_DOMAIN_CHR_TYPE_UDP,
|
VIR_DOMAIN_CHR_TYPE_UDP,
|
||||||
VIR_DOMAIN_CHR_TYPE_TCP,
|
VIR_DOMAIN_CHR_TYPE_TCP,
|
||||||
VIR_DOMAIN_CHR_TYPE_UNIX,
|
VIR_DOMAIN_CHR_TYPE_UNIX,
|
||||||
|
VIR_DOMAIN_CHR_TYPE_SPICEVMC,
|
||||||
|
|
||||||
VIR_DOMAIN_CHR_TYPE_LAST,
|
VIR_DOMAIN_CHR_TYPE_LAST,
|
||||||
};
|
};
|
||||||
@ -432,6 +433,7 @@ typedef virDomainChrSourceDef *virDomainChrSourceDefPtr;
|
|||||||
struct _virDomainChrSourceDef {
|
struct _virDomainChrSourceDef {
|
||||||
int type; /* virDomainChrType */
|
int type; /* virDomainChrType */
|
||||||
union {
|
union {
|
||||||
|
/* no <source> for null, vc, stdio, spicevmc */
|
||||||
struct {
|
struct {
|
||||||
char *path;
|
char *path;
|
||||||
} file; /* pty, file, pipe, or device */
|
} file; /* pty, file, pipe, or device */
|
||||||
|
@ -2006,7 +2006,8 @@ qemuBuildUSBHostdevUsbDevStr(virDomainHostdevDefPtr dev)
|
|||||||
/* This function outputs a -chardev command line option which describes only the
|
/* This function outputs a -chardev command line option which describes only the
|
||||||
* host side of the character device */
|
* host side of the character device */
|
||||||
static char *
|
static char *
|
||||||
qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias)
|
qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias,
|
||||||
|
unsigned long long qemuCmdFlags)
|
||||||
{
|
{
|
||||||
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
virBuffer buf = VIR_BUFFER_INITIALIZER;
|
||||||
bool telnet;
|
bool telnet;
|
||||||
@ -2072,6 +2073,21 @@ qemuBuildChrChardevStr(virDomainChrSourceDefPtr dev, const char *alias)
|
|||||||
dev->data.nix.path,
|
dev->data.nix.path,
|
||||||
dev->data.nix.listen ? ",server,nowait" : "");
|
dev->data.nix.listen ? ",server,nowait" : "");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
|
||||||
|
if (!(qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV_SPICEVMC)) {
|
||||||
|
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("spicevmc not supported in this QEMU binary"));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
virBufferVSprintf(&buf, "spicevmc,id=char%s,name=vdagent", alias);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("unsupported chardev '%s'"),
|
||||||
|
virDomainChrTypeToString(dev->type));
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (virBufferError(&buf)) {
|
if (virBufferError(&buf)) {
|
||||||
@ -2196,6 +2212,14 @@ qemuBuildVirtioSerialPortDevStr(virDomainChrDefPtr dev)
|
|||||||
|
|
||||||
virBufferVSprintf(&buf, ",chardev=char%s,id=%s",
|
virBufferVSprintf(&buf, ",chardev=char%s,id=%s",
|
||||||
dev->info.alias, dev->info.alias);
|
dev->info.alias, dev->info.alias);
|
||||||
|
if (dev->source.type == VIR_DOMAIN_CHR_TYPE_SPICEVMC &&
|
||||||
|
dev->target.name &&
|
||||||
|
STRNEQ(dev->target.name, "com.redhat.spice.0")) {
|
||||||
|
qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
|
||||||
|
_("Unsupported spicevmc target name '%s'"),
|
||||||
|
dev->target.name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
if (dev->target.name) {
|
if (dev->target.name) {
|
||||||
virBufferVSprintf(&buf, ",name=%s", dev->target.name);
|
virBufferVSprintf(&buf, ",name=%s", dev->target.name);
|
||||||
}
|
}
|
||||||
@ -2825,7 +2849,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) {
|
if (qemuCmdFlags & QEMUD_CMD_FLAG_CHARDEV) {
|
||||||
|
|
||||||
virCommandAddArg(cmd, "-chardev");
|
virCommandAddArg(cmd, "-chardev");
|
||||||
if (!(chrdev = qemuBuildChrChardevStr(monitor_chr, "monitor")))
|
if (!(chrdev = qemuBuildChrChardevStr(monitor_chr, "monitor",
|
||||||
|
qemuCmdFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
virCommandAddArg(cmd, chrdev);
|
virCommandAddArg(cmd, chrdev);
|
||||||
VIR_FREE(chrdev);
|
VIR_FREE(chrdev);
|
||||||
@ -3523,7 +3548,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
|
|
||||||
virCommandAddArg(cmd, "-chardev");
|
virCommandAddArg(cmd, "-chardev");
|
||||||
if (!(devstr = qemuBuildChrChardevStr(&smartcard->data.passthru,
|
if (!(devstr = qemuBuildChrChardevStr(&smartcard->data.passthru,
|
||||||
smartcard->info.alias))) {
|
smartcard->info.alias,
|
||||||
|
qemuCmdFlags))) {
|
||||||
virBufferFreeAndReset(&opt);
|
virBufferFreeAndReset(&opt);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -3560,7 +3586,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
|
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
|
||||||
virCommandAddArg(cmd, "-chardev");
|
virCommandAddArg(cmd, "-chardev");
|
||||||
if (!(devstr = qemuBuildChrChardevStr(&serial->source,
|
if (!(devstr = qemuBuildChrChardevStr(&serial->source,
|
||||||
serial->info.alias)))
|
serial->info.alias,
|
||||||
|
qemuCmdFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
virCommandAddArg(cmd, devstr);
|
virCommandAddArg(cmd, devstr);
|
||||||
VIR_FREE(devstr);
|
VIR_FREE(devstr);
|
||||||
@ -3592,7 +3619,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
|
(qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE)) {
|
||||||
virCommandAddArg(cmd, "-chardev");
|
virCommandAddArg(cmd, "-chardev");
|
||||||
if (!(devstr = qemuBuildChrChardevStr(¶llel->source,
|
if (!(devstr = qemuBuildChrChardevStr(¶llel->source,
|
||||||
parallel->info.alias)))
|
parallel->info.alias,
|
||||||
|
qemuCmdFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
virCommandAddArg(cmd, devstr);
|
virCommandAddArg(cmd, devstr);
|
||||||
VIR_FREE(devstr);
|
VIR_FREE(devstr);
|
||||||
@ -3626,7 +3654,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
|
|
||||||
virCommandAddArg(cmd, "-chardev");
|
virCommandAddArg(cmd, "-chardev");
|
||||||
if (!(devstr = qemuBuildChrChardevStr(&channel->source,
|
if (!(devstr = qemuBuildChrChardevStr(&channel->source,
|
||||||
channel->info.alias)))
|
channel->info.alias,
|
||||||
|
qemuCmdFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
virCommandAddArg(cmd, devstr);
|
virCommandAddArg(cmd, devstr);
|
||||||
VIR_FREE(devstr);
|
VIR_FREE(devstr);
|
||||||
@ -3653,7 +3682,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
|
|
||||||
virCommandAddArg(cmd, "-chardev");
|
virCommandAddArg(cmd, "-chardev");
|
||||||
if (!(devstr = qemuBuildChrChardevStr(&channel->source,
|
if (!(devstr = qemuBuildChrChardevStr(&channel->source,
|
||||||
channel->info.alias)))
|
channel->info.alias,
|
||||||
|
qemuCmdFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
virCommandAddArg(cmd, devstr);
|
virCommandAddArg(cmd, devstr);
|
||||||
VIR_FREE(devstr);
|
VIR_FREE(devstr);
|
||||||
@ -3682,7 +3712,8 @@ qemuBuildCommandLine(virConnectPtr conn,
|
|||||||
|
|
||||||
virCommandAddArg(cmd, "-chardev");
|
virCommandAddArg(cmd, "-chardev");
|
||||||
if (!(devstr = qemuBuildChrChardevStr(&console->source,
|
if (!(devstr = qemuBuildChrChardevStr(&console->source,
|
||||||
console->info.alias)))
|
console->info.alias,
|
||||||
|
qemuCmdFlags)))
|
||||||
goto error;
|
goto error;
|
||||||
virCommandAddArg(cmd, devstr);
|
virCommandAddArg(cmd, devstr);
|
||||||
VIR_FREE(devstr);
|
VIR_FREE(devstr);
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
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 \
|
||||||
|
-monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -device \
|
||||||
|
virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa -hda \
|
||||||
|
/dev/HostVG/QEMUGuest1 -chardev spicevmc,id=charchannel0,name=vdagent -device \
|
||||||
|
virtserialport,bus=virtio-serial1.0,nr=3,chardev=charchannel0,id=channel0\
|
||||||
|
,name=com.redhat.spice.0 -usb -spice port=5903,tls-port=5904,addr=127.0.0.1,\
|
||||||
|
x509-dir=/etc/pki/libvirt-spice,tls-channel=main -device \
|
||||||
|
virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
|
34
tests/qemuxml2argvdata/qemuxml2argv-channel-spicevmc.xml
Normal file
34
tests/qemuxml2argvdata/qemuxml2argv-channel-spicevmc.xml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<domain type='qemu'>
|
||||||
|
<name>QEMUGuest1</name>
|
||||||
|
<uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
|
||||||
|
<memory>219136</memory>
|
||||||
|
<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='1'>
|
||||||
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x0a' function='0x0'/>
|
||||||
|
</controller>
|
||||||
|
<graphics type='spice' port='5903' tlsPort='5904' autoport='no' listen='127.0.0.1'>
|
||||||
|
<channel name='main' mode='secure'/>
|
||||||
|
</graphics>
|
||||||
|
<channel type='spicevmc'>
|
||||||
|
<target type='virtio' name='com.redhat.spice.0'/>
|
||||||
|
<address type='virtio-serial' controller='1' bus='0' port='3'/>
|
||||||
|
</channel>
|
||||||
|
<memballoon model='virtio'/>
|
||||||
|
</devices>
|
||||||
|
</domain>
|
@ -407,6 +407,9 @@ mymain(int argc, char **argv)
|
|||||||
QEMUD_CMD_FLAG_NODEFCONFIG, false);
|
QEMUD_CMD_FLAG_NODEFCONFIG, false);
|
||||||
DO_TEST("console-virtio", QEMUD_CMD_FLAG_DEVICE |
|
DO_TEST("console-virtio", QEMUD_CMD_FLAG_DEVICE |
|
||||||
QEMUD_CMD_FLAG_NODEFCONFIG, false);
|
QEMUD_CMD_FLAG_NODEFCONFIG, false);
|
||||||
|
DO_TEST("channel-spicevmc", QEMUD_CMD_FLAG_DEVICE |
|
||||||
|
QEMUD_CMD_FLAG_NODEFCONFIG | QEMUD_CMD_FLAG_SPICE |
|
||||||
|
QEMUD_CMD_FLAG_CHARDEV_SPICEVMC, false);
|
||||||
|
|
||||||
DO_TEST("smartcard-host",
|
DO_TEST("smartcard-host",
|
||||||
QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE |
|
QEMUD_CMD_FLAG_CHARDEV | QEMUD_CMD_FLAG_DEVICE |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user