This patch allows the following to be specified in a QEmu domain:
<channel type='unix'>
<source mode='bind' path='/tmp/vmchannel'/>
<target type='vmchannel' deviceid='0200'/>
</channel>
* docs/schemas/domain.rng src/conf/domain_conf.[ch]: extend the domain schema
and parsing/serialization for the new construct
QEmu support adds the following on the qemu command line:
-vmchannel di:0200,unix:/tmp/vmchannel,server,nowait
* src/qemu/qemu_conf.c: Add -vmchannel argument output
* tests/qemuxml2(argv|xml)test.c: Add test for vmchannel <channel> syntax
---
docs/schemas/domain.rng | 13 ++++++++-
src/conf/domain_conf.c | 30 +++++++++++++++++++-
src/conf/domain_conf.h | 2 +
src/qemu/qemu_conf.c | 18 ++++++++++++
.../qemuxml2argv-channel-vmchannel.args | 1 +
.../qemuxml2argv-channel-vmchannel.xml | 26 +++++++++++++++++
tests/qemuxml2argvtest.c | 1 +
tests/qemuxml2xmltest.c | 2 +
8 files changed, 91 insertions(+), 2 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.xml
diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index b75f17e..39a19ae 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -1059,12 +1059,23 @@
<attribute name="port"/>
</element>
</define>
+ <define name="vmchannelTarget">
+ <element name="target">
+ <attribute name="type">
+ <value>vmchannel</value>
+ </attribute>
+ <attribute name="deviceid"/>
+ </element>
+ </define>
<define name="channel">
<element name="channel">
<ref name="qemucdevSrcType"/>
<interleave>
<ref name="qemucdevSrcDef"/>
- <ref name="guestfwdTarget"/>
+ <choice>
+ <ref name="guestfwdTarget"/>
+ <ref name="vmchannelTarget"/>
+ </choice>
</interleave>
</element>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 918a5d7..c02b959 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -130,6 +130,7 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
VIR_ENUM_IMPL(virDomainChrTarget, VIR_DOMAIN_CHR_TARGET_TYPE_LAST,
"null",
+ "vmchannel",
"monitor",
"parallel",
"serial",
@@ -1349,6 +1350,7 @@ virDomainChrDefParseXML(virConnectPtr conn,
const char *targetType = NULL;
const char *addrStr = NULL;
const char *portStr = NULL;
+ const char *deviceidStr = NULL;
virDomainChrDefPtr def;
if (VIR_ALLOC(def) < 0) {
@@ -1504,6 +1506,26 @@ virDomainChrDefParseXML(virConnectPtr conn,
virSocketSetPort(def->target.addr, port);
break;
+ case VIR_DOMAIN_CHR_TARGET_TYPE_VMCHANNEL:
+ deviceidStr = virXMLPropString(cur, "deviceid");
+
+ if (deviceidStr == NULL) {
+ virDomainReportError(conn, VIR_ERR_INVALID_DOMAIN,
+ _("vmchannel channel does not "
+ "define a device id"));
+ goto error;
+ }
+
+ unsigned int deviceid;
+ if (virStrToLong_ui(deviceidStr, NULL, 16, &deviceid) < 0) {
+ virDomainReportError(conn, VIR_ERR_INVALID_DOMAIN,
+ _("Invalid device id: %s"),
+ deviceidStr);
+ goto error;
+ }
+ def->target.deviceid = deviceid;
+ break;
+
default:
virDomainReportError(conn, VIR_ERR_XML_ERROR,
_("unexpected target type type %u"),
@@ -1514,7 +1536,6 @@ virDomainChrDefParseXML(virConnectPtr conn,
cur = cur->next;
}
-
switch (def->type) {
case VIR_DOMAIN_CHR_TYPE_NULL:
/* Nada */
@@ -1641,6 +1662,7 @@ cleanup:
VIR_FREE(targetType);
VIR_FREE(addrStr);
VIR_FREE(portStr);
+ VIR_FREE(deviceidStr);
return def;
@@ -4125,6 +4147,7 @@ virDomainChrDefFormat(virConnectPtr conn,
switch (def->targetType) {
/* channel types are in a common channel element */
case VIR_DOMAIN_CHR_TARGET_TYPE_GUESTFWD:
+ case VIR_DOMAIN_CHR_TARGET_TYPE_VMCHANNEL:
elementName = "channel";
break;
@@ -4237,6 +4260,11 @@ virDomainChrDefFormat(virConnectPtr conn,
addr, port);
break;
+ case VIR_DOMAIN_CHR_TARGET_TYPE_VMCHANNEL:
+ virBufferVSprintf(buf, " <target type='vmchannel'
deviceid='%.4X'/>\n",
+ def->target.deviceid);
+ break;
+
case VIR_DOMAIN_CHR_TARGET_TYPE_PARALLEL:
case VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL:
case VIR_DOMAIN_CHR_TARGET_TYPE_CONSOLE:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fadf43f..1549a01 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -214,6 +214,7 @@ virNetHasValidPciAddr(virDomainNetDefPtr def)
enum virDomainChrTargetType {
VIR_DOMAIN_CHR_TARGET_TYPE_NULL = 0,
+ VIR_DOMAIN_CHR_TARGET_TYPE_VMCHANNEL,
VIR_DOMAIN_CHR_TARGET_TYPE_MONITOR,
VIR_DOMAIN_CHR_TARGET_TYPE_PARALLEL,
VIR_DOMAIN_CHR_TARGET_TYPE_SERIAL,
@@ -252,6 +253,7 @@ struct _virDomainChrDef {
union {
int port; /* parallel, serial, console */
virSocketAddrPtr addr; /* guestfwd */
+ unsigned int deviceid; /* PCI device id for vmchannel */
} target;
int type;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index fa54974..5ee0477 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -2197,6 +2197,24 @@ int qemudBuildCommandLine(virConnectPtr conn,
ADD_ARG_LIT("-net");
ADD_ARG(virBufferContentAndReset(&buf));
+ break;
+
+ case VIR_DOMAIN_CHR_TARGET_TYPE_VMCHANNEL:
+ if (!(qemuCmdFlags & QEMUD_CMD_FLAG_VMCHANNEL)) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_NO_SUPPORT,
+ _("vmchannel requires QEMU to support -vmchannel"));
+ goto error;
+ }
+
+ virBufferVSprintf(&buf, "di:%.4X,",
channel->target.deviceid);
+
+ qemudBuildCommandLineChrDevStr(channel, &buf);
+ if (virBufferError(&buf))
+ goto error;
+
+ ADD_ARG_LIT("-vmchannel");
+ ADD_ARG(virBufferContentAndReset(&buf));
+ break;
}
}
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.args
b/tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.args
new file mode 100644
index 0000000..aa946d4
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.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 -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda
/dev/HostVG/QEMUGuest1 -net none -serial none -parallel none -vmchannel
di:0200,unix:/tmp/vmchannel,server,nowait -usb
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.xml
b/tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.xml
new file mode 100644
index 0000000..ce4943d
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-vmchannel.xml
@@ -0,0 +1,26 @@
+<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'/>
+ </disk>
+ <channel type='unix'>
+ <source mode='bind' path='/tmp/vmchannel'/>
+ <target type='vmchannel' deviceid='0200'/>
+ </channel>
+ </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index c948379..c2809c7 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -270,6 +270,7 @@ mymain(int argc, char **argv)
DO_TEST("console-compat", 0);
DO_TEST("channel-guestfwd", QEMUD_CMD_FLAG_CHARDEV);
+ DO_TEST("channel-vmchannel", QEMUD_CMD_FLAG_VMCHANNEL);
DO_TEST("sound", 0);
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 25ef2ce..54c3e2d 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -129,7 +129,9 @@ mymain(int argc, char **argv)
DO_TEST("serial-many");
DO_TEST("parallel-tcp");
DO_TEST("console-compat");
+
DO_TEST("channel-guestfwd");
+ DO_TEST("channel-vmchannel");
DO_TEST("hostdev-usb-product");
DO_TEST("hostdev-usb-address");
--
1.6.2.5