At least Xen supports backend drivers in another domain (aka "driver
domain"). This patch introduces XML config option for such setting as
'domain' attribute of 'source' element. Verification its content is left
for the driver.
In the future same option will be needed for USB devices (hostdev
objects), but for now libxl doesn't have support for PVUSB.
Signed-off-by: Marek Marczykowski-Górecki <marmarek(a)invisiblethingslab.com>
---
Changes in v2:
- describe in docs/formatdomain.html.in
- enforce empty domain tag (only 'name' attribute allowed)
Changes in v3:
- change <domain name='xx'/> element to domain='' attribute of
source
element - this is more logical place
- grammar of docs
docs/formatdomain.html.in | 29 +++++++++++++++++++++++++++--
docs/schemas/domaincommon.rng | 20 ++++++++++++++++++++
src/conf/domain_conf.c | 33 +++++++++++++++++++++++++++++----
src/conf/domain_conf.h | 1 +
src/util/virstoragefile.c | 4 +++-
src/util/virstoragefile.h | 1 +
6 files changed, 81 insertions(+), 7 deletions(-)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index c5ad6f4..38c42d5 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1907,13 +1907,17 @@
<span class="since">since 0.0.3</span></dt>
<dd>
The <code>file</code> attribute specifies the fully-qualified
- path to the file holding the disk.
+ path to the file holding the disk. The optional
+ <code>domain</code> attribute allows specifying a backend
domain
+ (aka driver domain) where the file is stored.
</dd>
<dt><code>type='block'</code>
<span class="since">since 0.0.3</span></dt>
<dd>
The <code>dev</code> attribute specifies the path to the
- host device to serve as the disk.
+ host device to serve as the disk. The optional
+ <code>domain</code> attribute allows specifying a backend
domain
+ (aka driver domain) for the device.
</dd>
<dt><code>type='dir'</code>
<span class="since">since 0.7.5</span></dt>
@@ -4336,6 +4340,27 @@ qemu-kvm -net nic,model=? /dev/null
element is unspecified is to have the link state <code>up</code>.
<span class="since">Since 0.9.5</span>
</p>
+ <h5><a name="elementDomain">Setting up a network backend in a
driver domain</a></h5>
+<pre>
+ ...
+ <devices>
+ ...
+ <interface type='bridge'>
+ <source bridge='br0'
<b>domain='netvm'</b>/>
+ </interface>
+ ...
+ </devices>
+ ...</pre>
+
+ <p>
+ The optional <code>domain</code> attribute allows specifying a backend
+ domain (aka driver domain) for the device. Use the <code>name</code>
attribute
+ to specify its name. You can use it to create a direct network link between
+ domains (so data will not go through host system). Use with type
'ethernet'
+ to create plain network link, or with 'bridge' to connect to some bridge
+ inside the driver domain.
+ <span class="since">Since 1.0.7 (Xen only)</span>
+ </p>
<h5><a name="ipconfig">IP configuration</a></h5>
<pre>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index d467dce..a4321f1 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1340,6 +1340,11 @@
<attribute name="file">
<ref name="absFilePath"/>
</attribute>
+ <optional>
+ <attribute name="domain">
+ <ref name="domainName"/>
+ </attribute>
+ </optional>
</optional>
<optional>
<ref name="storageStartupPolicy"/>
@@ -1365,6 +1370,11 @@
</attribute>
</optional>
<optional>
+ <attribute name="domain">
+ <ref name="domainName"/>
+ </attribute>
+ </optional>
+ <optional>
<ref name="storageStartupPolicy"/>
</optional>
<optional>
@@ -2040,6 +2050,11 @@
<attribute name="bridge">
<ref name="deviceName"/>
</attribute>
+ <optional>
+ <attribute name="domain">
+ <ref name="domainName"/>
+ </attribute>
+ </optional>
<empty/>
</element>
</optional>
@@ -2059,6 +2074,11 @@
<attribute name="dev">
<ref name="deviceName"/>
</attribute>
+ <optional>
+ <attribute name="domain">
+ <ref name="domainName"/>
+ </attribute>
+ </optional>
<empty/>
</element>
</optional>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4251b13..17b699a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1442,6 +1442,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
VIR_FREE(def->backend.vhost);
VIR_FREE(def->virtPortProfile);
VIR_FREE(def->script);
+ VIR_FREE(def->domain_name);
VIR_FREE(def->ifname);
VIR_FREE(def->ifname_guest);
VIR_FREE(def->ifname_guest_actual);
@@ -5520,9 +5521,11 @@ virDomainDiskSourceParse(xmlNodePtr node,
switch ((virStorageType)src->type) {
case VIR_STORAGE_TYPE_FILE:
src->path = virXMLPropString(node, "file");
+ src->domain_name = virXMLPropString(node, "domain");
break;
case VIR_STORAGE_TYPE_BLOCK:
src->path = virXMLPropString(node, "dev");
+ src->domain_name = virXMLPropString(node, "domain");
break;
case VIR_STORAGE_TYPE_DIR:
src->path = virXMLPropString(node, "dir");
@@ -7369,6 +7372,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
char *vhostuser_path = NULL;
char *vhostuser_type = NULL;
char *trustGuestRxFilters = NULL;
+ char *domain_name = NULL;
virNWFilterHashTablePtr filterparams = NULL;
virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node;
@@ -7423,12 +7427,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
def->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
xmlStrEqual(cur->name, BAD_CAST "source")) {
bridge = virXMLPropString(cur, "bridge");
+ domain_name = virXMLPropString(cur, "domain");
} else if (!dev &&
(def->type == VIR_DOMAIN_NET_TYPE_ETHERNET ||
def->type == VIR_DOMAIN_NET_TYPE_DIRECT) &&
xmlStrEqual(cur->name, BAD_CAST "source")) {
dev = virXMLPropString(cur, "dev");
mode = virXMLPropString(cur, "mode");
+ domain_name = virXMLPropString(cur, "domain");
} else if (!vhostuser_path && !vhostuser_mode &&
!vhostuser_type
&& def->type == VIR_DOMAIN_NET_TYPE_VHOSTUSER
&&
xmlStrEqual(cur->name, BAD_CAST "source")) {
@@ -7802,6 +7808,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
def->script = script;
script = NULL;
}
+ if (domain_name != NULL) {
+ def->domain_name = domain_name;
+ domain_name = NULL;
+ }
if (ifname != NULL) {
def->ifname = ifname;
ifname = NULL;
@@ -8061,6 +8071,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(addrtype);
VIR_FREE(trustGuestRxFilters);
VIR_FREE(ips);
+ VIR_FREE(domain_name);
virNWFilterHashTableFree(filterparams);
return def;
@@ -16544,6 +16555,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf,
virBufferAddLit(buf, "<source");
virBufferEscapeString(buf, " file='%s'", src->path);
virBufferEscapeString(buf, " startupPolicy='%s'",
startupPolicy);
+ virBufferEscapeString(buf, " domain='%s'",
src->domain_name);
virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels,
src->seclabels, flags,
@@ -16554,6 +16566,7 @@ virDomainDiskSourceFormatInternal(virBufferPtr buf,
virBufferAddLit(buf, "<source");
virBufferEscapeString(buf, " dev='%s'", src->path);
virBufferEscapeString(buf, " startupPolicy='%s'",
startupPolicy);
+ virBufferEscapeString(buf, " domain='%s'",
src->domain_name);
virDomainDiskSourceDefFormatSeclabel(buf, src->nseclabels,
src->seclabels, flags,
@@ -17713,8 +17726,14 @@ virDomainNetDefFormat(virBufferPtr buf,
break;
case VIR_DOMAIN_NET_TYPE_ETHERNET:
- virBufferEscapeString(buf, "<source dev='%s'/>\n",
- def->data.ethernet.dev);
+ if (def->data.ethernet.dev || def->domain_name) {
+ virBufferAddLit(buf, "<source");
+ virBufferEscapeString(buf, " dev='%s'",
+ def->data.ethernet.dev);
+ virBufferEscapeString(buf, " domain='%s'",
+ def->domain_name);
+ virBufferAddLit(buf, "/>\n");
+ }
break;
case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
@@ -17730,8 +17749,14 @@ virDomainNetDefFormat(virBufferPtr buf,
break;
case VIR_DOMAIN_NET_TYPE_BRIDGE:
- virBufferEscapeString(buf, "<source
bridge='%s'/>\n",
- def->data.bridge.brname);
+ if (def->data.bridge.brname || def->domain_name) {
+ virBufferAddLit(buf, "<source");
+ virBufferEscapeString(buf, " bridge='%s'",
+ def->data.bridge.brname);
+ virBufferEscapeString(buf, " domain='%s'",
+ def->domain_name);
+ virBufferAddLit(buf, "/>\n");
+ }
break;
case VIR_DOMAIN_NET_TYPE_SERVER:
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 93f2314..28c6920 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -995,6 +995,7 @@ struct _virDomainNetDef {
unsigned long sndbuf;
} tune;
char *script;
+ char *domain_name; /* backend domain name */
char *ifname;
char *ifname_guest;
char *ifname_guest_actual;
diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
index 8d3d1f5..c2703b7 100644
--- a/src/util/virstoragefile.c
+++ b/src/util/virstoragefile.c
@@ -1835,7 +1835,8 @@ virStorageSourceCopy(const virStorageSource *src,
VIR_STRDUP(ret->backingStoreRaw, src->backingStoreRaw) < 0 ||
VIR_STRDUP(ret->snapshot, src->snapshot) < 0 ||
VIR_STRDUP(ret->configFile, src->configFile) < 0 ||
- VIR_STRDUP(ret->compat, src->compat) < 0)
+ VIR_STRDUP(ret->compat, src->compat) < 0 ||
+ VIR_STRDUP(ret->domain_name, src->domain_name))
goto error;
if (src->nhosts) {
@@ -2023,6 +2024,7 @@ virStorageSourceClear(virStorageSourcePtr def)
VIR_FREE(def->path);
VIR_FREE(def->volume);
+ VIR_FREE(def->domain_name);
virStorageSourcePoolDefFree(def->srcpool);
VIR_FREE(def->driverName);
virBitmapFree(def->features);
diff --git a/src/util/virstoragefile.h b/src/util/virstoragefile.h
index b4c3808..a3c7e1e 100644
--- a/src/util/virstoragefile.h
+++ b/src/util/virstoragefile.h
@@ -241,6 +241,7 @@ struct _virStorageSource {
char *snapshot; /* for storage systems supporting internal snapshots */
char *configFile; /* some storage systems use config file as part of
the source definition */
+ char *domain_name; /* name of domain holding backing storage file/dev */
size_t nhosts;
virStorageNetHostDefPtr hosts;
virStorageSourcePoolDefPtr srcpool;
--
1.8.3.1