diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 8870e4630a..8d4edfb163 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -3999,7 +3999,12 @@ qemu-kvm -net nic,model=? /dev/null
then libvirt can interact with a guest agent installed in the
guest, for actions such as guest shutdown or file system quiescing.
Since 0.7.7, guest agent interaction
- since 0.9.10
+ since 0.9.10 Moreover, since 1.0.5
+ it is possible to have source path auto generated for virtio unix channels.
+ This is very useful in case of a qemu guest agent, where users don't
+ usually care about the source path since it's libvirt who talks to
+ the guest agent. In case users want to utilize this feature, they should
+ leave <source>
element out.
spicevmc
Paravirtualized SPICE channel. The domain must also have a
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 24e347cd74..6f250313dd 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -1721,6 +1721,7 @@ fi
%if %{with_qemu}
%ghost %dir %attr(0700, root, root) %{_localstatedir}/run/libvirt/qemu/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/
+%dir %attr{0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/lib/libvirt/qemu/channel/target/
%dir %attr(0750, %{qemu_user}, %{qemu_group}) %{_localstatedir}/cache/libvirt/qemu/
%endif
%if %{with_lxc}
diff --git a/src/Makefile.am b/src/Makefile.am
index cd098dbf5f..299b8fd0dc 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2157,6 +2157,7 @@ if WITH_SANLOCK
endif
if WITH_QEMU
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu"
+ $(MKDIR_P) "$(DESTDIR)$(localstatedir)/lib/libvirt/qemu/channel/target"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/run/libvirt/qemu"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/cache/libvirt/qemu"
$(MKDIR_P) "$(DESTDIR)$(localstatedir)/log/libvirt/qemu"
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a8b5dfd655..608870f157 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6634,7 +6634,9 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
break;
case VIR_DOMAIN_CHR_TYPE_UNIX:
- if (path == NULL) {
+ /* path can be auto generated */
+ if (!path &&
+ chr_def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source path attribute for char device"));
goto error;
@@ -6729,7 +6731,6 @@ virDomainChrDefParseXML(xmlXPathContextPtr ctxt,
char *type = NULL;
const char *nodeName;
virDomainChrDefPtr def;
- int remaining;
bool seenTarget = false;
if (!(def = virDomainChrDefNew()))
@@ -6753,29 +6754,26 @@ virDomainChrDefParseXML(xmlXPathContextPtr ctxt,
}
cur = node->children;
- remaining = virDomainChrSourceDefParseXML(&def->source, cur, flags,
- def, ctxt,
- vmSeclabels, nvmSeclabels);
- if (remaining < 0)
- goto error;
- if (remaining) {
- while (cur != NULL) {
- if (cur->type == XML_ELEMENT_NODE) {
- if (xmlStrEqual(cur->name, BAD_CAST "target")) {
- seenTarget = true;
- if (virDomainChrDefParseTargetXML(def, cur) < 0) {
- goto error;
- }
+ while (cur != NULL) {
+ if (cur->type == XML_ELEMENT_NODE) {
+ if (xmlStrEqual(cur->name, BAD_CAST "target")) {
+ seenTarget = true;
+ if (virDomainChrDefParseTargetXML(def, cur) < 0) {
+ goto error;
}
}
- cur = cur->next;
}
+ cur = cur->next;
}
if (!seenTarget &&
((def->targetType = virDomainChrDefaultTargetType(def->deviceType)) < 0))
goto cleanup;
+ if (virDomainChrSourceDefParseXML(&def->source, node->children, flags, def,
+ ctxt, vmSeclabels, nvmSeclabels) < 0)
+ goto error;
+
if (def->source.type == VIR_DOMAIN_CHR_TYPE_SPICEVMC) {
if (def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
@@ -14288,8 +14286,8 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
case VIR_DOMAIN_CHR_TYPE_UNIX:
virBufferAsprintf(buf, " data.nix.listen ? "bind" : "connect");
- virBufferEscapeString(buf, " path='%s'/>\n",
- def->data.nix.path);
+ virBufferEscapeString(buf, " path='%s'", def->data.nix.path);
+ virBufferAddLit(buf, "/>\n");
break;
}
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 62c3382031..1ea2bcd76e 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -792,6 +792,22 @@ qemuDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
(def->os.arch == VIR_ARCH_S390 || def->os.arch == VIR_ARCH_S390X))
dev->data.controller->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_NONE;
+ /* auto generate unix socket path */
+ if (dev->type == VIR_DOMAIN_DEVICE_CHR &&
+ dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
+ dev->data.chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
+ dev->data.chr->source.type == VIR_DOMAIN_CHR_TYPE_UNIX &&
+ !dev->data.chr->source.data.nix.path &&
+ (driver && (cfg = virQEMUDriverGetConfig(driver)))) {
+
+ if (virAsprintf(&dev->data.chr->source.data.nix.path,
+ "%s/channel/target/%s.%s",
+ cfg->libDir, def->name,
+ dev->data.chr->target.name) < 0)
+ goto no_memory;
+ dev->data.chr->source.data.nix.listen = true;
+ }
+
ret = 0;
cleanup: