It's not desired to force users imagine path for a socket they
are not even supposed to connect to. On the other hand, we
already have a release where the qemu agent socket path is
exposed to XML, so we cannot silently drop it from there.
The new path is generated in form:
$LOCALSTATEDIR/lib/libvirt/qemu/$domain.agent
---
This makes the qemu agent to be generated at domain startup phase.
So until that, we generate XML without any path, e.g.:
<channel type='unix'>
<source mode='connect'/>
<target type='virtio' name='org.qemu.guest_agent.0'/>
<address type='virtio-serial' controller='0' bus='0'
port='1'/>
</channel>
The other possibility is to generate path during XML parse phase, however this
expose something we are lacking for years - callbacks to fill in default values
for not configured ones. The aim so to make libvirt accept this snippet as
valid qemu agent config:
<channel type='unix'>
<target type='virtio' name='org.qemu.guest_agent.0'/>
</channel>
src/conf/domain_conf.c | 37 ++++++++++++++++++++-----------------
src/qemu/qemu_process.c | 30 ++++++++++++++++++++++++++++--
2 files changed, 48 insertions(+), 19 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7a2b012..6245fec 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -6038,7 +6038,10 @@ virDomainChrSourceDefParseXML(virDomainChrSourceDefPtr def,
break;
case VIR_DOMAIN_CHR_TYPE_UNIX:
- if (path == NULL) {
+ /* path is not required in special case of qemu guest agent */
+ if (path == NULL &&
+ chr_def->targetType != VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO
&&
+ STRNEQ(chr_def->target.name, "org.qemu.guest_agent.0")) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing source path attribute for char
device"));
goto error;
@@ -6135,7 +6138,6 @@ virDomainChrDefParseXML(virCapsPtr caps,
char *type = NULL;
const char *nodeName;
virDomainChrDefPtr def;
- int remaining;
bool seenTarget = false;
if (!(def = virDomainChrDefNew()))
@@ -6159,29 +6161,28 @@ virDomainChrDefParseXML(virCapsPtr caps,
}
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(caps, vmdef, 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(caps, vmdef, def, cur) < 0) {
+ goto error;
}
+ break;
}
- cur = cur->next;
}
+ cur = cur->next;
}
if (!seenTarget &&
((def->targetType = virDomainChrDefaultTargetType(caps, vmdef,
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",
@@ -13307,10 +13308,12 @@ virDomainChrSourceDefFormat(virBufferPtr buf,
break;
case VIR_DOMAIN_CHR_TYPE_UNIX:
+
virBufferAsprintf(buf, " <source mode='%s'",
def->data.nix.listen ? "bind" :
"connect");
- virBufferEscapeString(buf, " path='%s'/>\n",
+ virBufferEscapeString(buf, " path='%s'",
def->data.nix.path);
+ virBufferAddLit(buf, "/>\n");
break;
}
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 4251c34..90f072d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2788,6 +2788,31 @@ qemuProcessPrepareMonitorChr(virQEMUDriverConfigPtr cfg,
return 0;
}
+static int
+qemuProcessPrepareAgentChr(virQEMUDriverConfigPtr cfg,
+ virDomainObjPtr vm)
+{
+ virDomainChrSourceDefPtr config = qemuFindAgentConfig(vm->def);
+ virDomainChrSourceDefPtr newConfing = qemuFindAgentConfig(vm->newDef);
+
+ if (!config)
+ return 0;
+
+ /* if user hasn't supplied any agent socket path, generate one,
+ * and store it in inactive config as well */
+ if ((config->type == VIR_DOMAIN_CHR_TYPE_UNIX) &&
+ !config->data.nix.path) {
+ if ((virAsprintf(&config->data.nix.path, "%s/%s.agent",
+ cfg->libDir, vm->def->name) < 0) ||
+ !(newConfing->data.nix.path = strdup(config->data.nix.path))) {
+ virReportOOMError();
+ return -1;
+ }
+ newConfing->data.nix.listen = config->data.nix.listen = true;
+ }
+
+ return 0;
+}
/*
* Precondition: vm must be locked, and a job must be active.
@@ -3772,8 +3797,9 @@ int qemuProcessStart(virConnectPtr conn,
goto cleanup;
}
- VIR_DEBUG("Preparing monitor state");
- if (qemuProcessPrepareMonitorChr(cfg, priv->monConfig, vm->def->name) <
0)
+ VIR_DEBUG("Preparing monitor and agent state");
+ if ((qemuProcessPrepareMonitorChr(cfg, priv->monConfig, vm->def->name) <
0) ||
+ (qemuProcessPrepareAgentChr(cfg, vm) < 0))
goto cleanup;
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_MONITOR_JSON))
--
1.8.0.2