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

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to