Some qemu guest-agent commands require so called
'supported level' to be set. In other words, GA needs
to be told which version of qemu is being used.
Moreover, guest-agent can't remember this information
during its restarts. But QEMU developers are trying
to learn guest-agent to remember it.
---
src/qemu/qemu_agent.c | 35 +++++++++++++++++++++++++++++++++++
src/qemu/qemu_agent.h | 2 ++
src/qemu/qemu_process.c | 45 ++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 79 insertions(+), 3 deletions(-)
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 9df5546..536724f 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -106,6 +106,16 @@ struct _qemuAgent {
/* If anything went wrong, this will be fed back
* the next monitor msg */
virError lastError;
+
+ /* Some guest-agent commands are available only
+ * after telling guest-agent what qemu version it
+ * deals with. However, currently guest-agent is not
+ * capable of remembering this information.
+ * Therefore we need to memorize it and set
+ * before such commands.
+ * XXX Remove this in the future
+ */
+ unsigned int version;
};
#if DEBUG_RAW_IO
@@ -1184,3 +1194,28 @@ cleanup:
virJSONValueFree(reply);
return ret;
}
+
+/*
+ * qemuAgentSetSupportedLevelCommand:
+ * @mon: Agent
+ * @version: QEMU version
+ *
+ * Let GA knows what qemu version it deals with.
+ * This enables/disables some functionality on
+ * one hand, but on the other GA should cope nicely
+ * after this.
+ *
+ * QEMU @version format:
+ * major * 1000 * 1000 + minor * 1000 + micro
+ * as returned by qemuCapsExtractVersionInfo().
+ *
+ * The minimum required by QEMU is 1.0.0, which
+ * makes @version MUST be >= 1000*1000
+ */
+void qemuAgentSetSupportedLevel(qemuAgentPtr mon,
+ unsigned int version)
+{
+ qemuAgentLock(mon);
+ mon->version = version;
+ qemuAgentUnlock(mon);
+}
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index df59ef7..2858207 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -69,4 +69,6 @@ int qemuAgentShutdown(qemuAgentPtr mon,
int qemuAgentFSFreeze(qemuAgentPtr mon);
int qemuAgentFSThaw(qemuAgentPtr mon);
+void qemuAgentSetSupportedLevel(qemuAgentPtr mon,
+ unsigned int version);
#endif /* __QEMU_AGENT_H__ */
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d22020b..a0b0159 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2825,6 +2825,7 @@ qemuProcessReconnect(void *opaque)
struct qemuDomainJobObj oldjob;
int state;
int reason;
+ unsigned int version;
memcpy(&oldjob, &data->oldjob, sizeof(oldjob));
@@ -2876,7 +2877,7 @@ qemuProcessReconnect(void *opaque)
*/
if (!priv->qemuCaps &&
qemuCapsExtractVersionInfo(obj->def->emulator, obj->def->os.arch,
- NULL,
+ &version,
&priv->qemuCaps) < 0)
goto error;
@@ -2925,6 +2926,18 @@ qemuProcessReconnect(void *opaque)
if (obj->def->id >= driver->nextvmid)
driver->nextvmid = obj->def->id + 1;
+ if (priv->agent) {
+ if (priv->agentError) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to set guest-supported-level"
+ " due to agent error"));
+ goto error;
+ }
+
+ VIR_DEBUG("Setting guest-supported-level to %u", version);
+ qemuAgentSetSupportedLevel(priv->agent, version);
+ }
+
endjob:
if (qemuDomainObjEndJob(driver, obj) == 0)
obj = NULL;
@@ -3083,6 +3096,7 @@ int qemuProcessStart(virConnectPtr conn,
virCommandPtr cmd = NULL;
struct qemuProcessHookData hookData;
unsigned long cur_balloon;
+ unsigned int version;
hookData.conn = conn;
hookData.vm = vm;
@@ -3212,7 +3226,7 @@ int qemuProcessStart(virConnectPtr conn,
qemuCapsFree(priv->qemuCaps);
priv->qemuCaps = NULL;
if (qemuCapsExtractVersionInfo(vm->def->emulator, vm->def->os.arch,
- NULL,
+ &version,
&priv->qemuCaps) < 0)
goto cleanup;
@@ -3432,6 +3446,18 @@ int qemuProcessStart(virConnectPtr conn,
priv->agentError = true;
}
+ if (priv->agent) {
+ if (priv->agentError) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to set guest-supported-level"
+ " due to agent error"));
+ goto cleanup;
+ }
+
+ VIR_DEBUG("Setting guest-supported-level to %u", version);
+ qemuAgentSetSupportedLevel(priv->agent, version);
+ }
+
VIR_DEBUG("Detecting VCPU PIDs");
if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
goto cleanup;
@@ -3782,6 +3808,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
bool running = true;
virDomainPausedReason reason;
virSecurityLabelPtr seclabel = NULL;
+ unsigned int version;
VIR_DEBUG("Beginning VM attach process");
@@ -3835,7 +3862,7 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
priv->qemuCaps = NULL;
if (qemuCapsExtractVersionInfo(vm->def->emulator,
vm->def->os.arch,
- NULL,
+ &version,
&priv->qemuCaps) < 0)
goto cleanup;
@@ -3901,6 +3928,18 @@ int qemuProcessAttach(virConnectPtr conn ATTRIBUTE_UNUSED,
priv->agentError = true;
}
+ if (priv->agent) {
+ if (priv->agentError) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to set guest-supported-level"
+ " due to agent error"));
+ goto cleanup;
+ }
+
+ VIR_DEBUG("Setting guest-supported-level to %u", version);
+ qemuAgentSetSupportedLevel(priv->agent, version);
+ }
+
VIR_DEBUG("Detecting VCPU PIDs");
if (qemuProcessDetectVcpuPIDs(driver, vm) < 0)
goto cleanup;
--
1.7.3.4