diff mbox

[2/2] qemu_agent: Wait for events instead of agent response

Message ID d6a28d41ec8a98d8adcc2d40292461449eed874d.1339776203.git.mprivozn@redhat.com
State New
Headers show

Commit Message

Michal Prívozník June 15, 2012, 4:10 p.m. UTC
With latest changes to qemu-ga success on some commands is not reported
anymore, e.g. guest-shutdown or guest-suspend-*. However, errors are
still being reported. Therefore, we need to find different source of
indication if operation was successful. Events.
---
 src/qemu/qemu_agent.c   |   49 ++++++++++++++++++++++++++++++++++++++++++----
 src/qemu/qemu_agent.h   |    9 ++++++++
 src/qemu/qemu_process.c |    7 ++++++
 3 files changed, 60 insertions(+), 5 deletions(-)

Comments

Eric Blake June 15, 2012, 5:16 p.m. UTC | #1
On 06/15/2012 10:10 AM, Michal Privoznik wrote:
> With latest changes to qemu-ga success on some commands is not reported
> anymore, e.g. guest-shutdown or guest-suspend-*. However, errors are
> still being reported. Therefore, we need to find different source of
> indication if operation was successful. Events.
> ---
>  src/qemu/qemu_agent.c   |   49 ++++++++++++++++++++++++++++++++++++++++++----
>  src/qemu/qemu_agent.h   |    9 ++++++++
>  src/qemu/qemu_process.c |    7 ++++++
>  3 files changed, 60 insertions(+), 5 deletions(-)
> 

> @@ -1238,6 +1257,24 @@ error:
>      return NULL;
>  }
>  
> +void qemuAgentNotifyEvent(qemuAgentPtr mon,
> +                          qemuAgentEvent event)
> +{
> +    VIR_DEBUG("mon=%p event=%d", mon, event);
> +    if (mon->await_event == event) {
> +        VIR_DEBUG("Wakening up a tragedian");

s/Wakening/Waking/

ACK.
Michal Prívozník June 16, 2012, 7:51 a.m. UTC | #2
On 15.06.2012 19:16, Eric Blake wrote:
> On 06/15/2012 10:10 AM, Michal Privoznik wrote:
>> With latest changes to qemu-ga success on some commands is not reported
>> anymore, e.g. guest-shutdown or guest-suspend-*. However, errors are
>> still being reported. Therefore, we need to find different source of
>> indication if operation was successful. Events.
>> ---
>>  src/qemu/qemu_agent.c   |   49 ++++++++++++++++++++++++++++++++++++++++++----
>>  src/qemu/qemu_agent.h   |    9 ++++++++
>>  src/qemu/qemu_process.c |    7 ++++++
>>  3 files changed, 60 insertions(+), 5 deletions(-)
>>
> 
>> @@ -1238,6 +1257,24 @@ error:
>>      return NULL;
>>  }
>>  
>> +void qemuAgentNotifyEvent(qemuAgentPtr mon,
>> +                          qemuAgentEvent event)
>> +{
>> +    VIR_DEBUG("mon=%p event=%d", mon, event);
>> +    if (mon->await_event == event) {
>> +        VIR_DEBUG("Wakening up a tragedian");
> 
> s/Wakening/Waking/
> 
> ACK.
> 
> 

Fixed and pushed. Thanks.

Michal
diff mbox

Patch

diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index 36610c2..95aec67 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -107,6 +107,11 @@  struct _qemuAgent {
     /* If anything went wrong, this will be fed back
      * the next monitor msg */
     virError lastError;
+
+    /* Some guest agent commands don't return anything
+     * but fire up an event on qemu monitor instead.
+     * Take that as indication of successful completion */
+    qemuAgentEvent await_event;
 };
 
 #if DEBUG_RAW_IO
@@ -826,6 +831,13 @@  void qemuAgentClose(qemuAgentPtr mon)
         VIR_FORCE_CLOSE(mon->fd);
     }
 
+    /* If there is somebody waiting for a message
+     * wake him up. No message will arrive anyway. */
+    if (mon->msg && !mon->msg->finished) {
+        mon->msg->finished = 1;
+        virCondSignal(&mon->notify);
+    }
+
     if (qemuAgentUnref(mon) > 0)
         qemuAgentUnlock(mon);
 }
@@ -982,6 +994,7 @@  qemuAgentCommand(qemuAgentPtr mon,
     int ret = -1;
     qemuAgentMessage msg;
     char *cmdstr = NULL;
+    int await_event = mon->await_event;
 
     *reply = NULL;
 
@@ -1010,10 +1023,16 @@  qemuAgentCommand(qemuAgentPtr mon,
               ret, msg.rxObject);
 
     if (ret == 0) {
+        /* If we haven't obtained any reply but we wait for an
+         * event, then don't report this as error */
         if (!msg.rxObject) {
-            qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
-                            _("Missing monitor reply object"));
-            ret = -1;
+            if (await_event) {
+                VIR_DEBUG("Woken up by event %d", await_event);
+            } else {
+                qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                _("Missing monitor reply object"));
+                ret = -1;
+            }
         } else {
             *reply = msg.rxObject;
         }
@@ -1238,6 +1257,24 @@  error:
     return NULL;
 }
 
+void qemuAgentNotifyEvent(qemuAgentPtr mon,
+                          qemuAgentEvent event)
+{
+    VIR_DEBUG("mon=%p event=%d", mon, event);
+    if (mon->await_event == event) {
+        VIR_DEBUG("Wakening up a tragedian");
+        mon->await_event = QEMU_AGENT_EVENT_NONE;
+        /* somebody waiting for this event, wake him up. */
+        if (mon->msg && !mon->msg->finished) {
+            mon->msg->finished = 1;
+            virCondSignal(&mon->notify);
+        }
+    } else {
+        /* shouldn't happen but one never knows */
+        VIR_WARN("Received unexpected event %d", event);
+    }
+}
+
 VIR_ENUM_DECL(qemuAgentShutdownMode);
 
 VIR_ENUM_IMPL(qemuAgentShutdownMode,
@@ -1257,9 +1294,10 @@  int qemuAgentShutdown(qemuAgentPtr mon,
     if (!cmd)
         return -1;
 
+    mon->await_event = QEMU_AGENT_EVENT_SHUTDOWN;
     ret = qemuAgentCommand(mon, cmd, &reply);
 
-    if (ret == 0)
+    if (reply && ret == 0)
         ret = qemuAgentCheckError(cmd, reply);
 
     virJSONValueFree(cmd);
@@ -1362,9 +1400,10 @@  qemuAgentSuspend(qemuAgentPtr mon,
     if (!cmd)
         return -1;
 
+    mon->await_event = QEMU_AGENT_EVENT_SUSPEND;
     ret = qemuAgentCommand(mon, cmd, &reply);
 
-    if (ret == 0)
+    if (reply && ret == 0)
         ret = qemuAgentCheckError(cmd, reply);
 
     virJSONValueFree(cmd);
diff --git a/src/qemu/qemu_agent.h b/src/qemu/qemu_agent.h
index 98c23b0..0816d90 100644
--- a/src/qemu/qemu_agent.h
+++ b/src/qemu/qemu_agent.h
@@ -56,6 +56,15 @@  int qemuAgentUnref(qemuAgentPtr mon) ATTRIBUTE_RETURN_CHECK;
 void qemuAgentClose(qemuAgentPtr mon);
 
 typedef enum {
+    QEMU_AGENT_EVENT_NONE = 0,
+    QEMU_AGENT_EVENT_SHUTDOWN,
+    QEMU_AGENT_EVENT_SUSPEND
+} qemuAgentEvent;
+
+void qemuAgentNotifyEvent(qemuAgentPtr mon,
+                          qemuAgentEvent event);
+
+typedef enum {
     QEMU_AGENT_SHUTDOWN_POWERDOWN,
     QEMU_AGENT_SHUTDOWN_REBOOT,
     QEMU_AGENT_SHUTDOWN_HALT,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 2b47bf6..1df3637 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -665,6 +665,9 @@  qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                  vm->def->name);
     }
 
+    if (priv->agent)
+        qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SHUTDOWN);
+
     qemuProcessShutdownOrReboot(driver, vm);
 
 unlock:
@@ -1118,6 +1121,7 @@  qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     event = virDomainEventPMSuspendNewFromObj(vm);
 
     if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
+        qemuDomainObjPrivatePtr priv = vm->privateData;
         VIR_DEBUG("Transitioned guest %s to pmsuspended state due to "
                   "QMP suspend event", vm->def->name);
 
@@ -1128,6 +1132,9 @@  qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
             VIR_WARN("Unable to save status on vm %s after suspend event",
                      vm->def->name);
         }
+
+        if (priv->agent)
+            qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND);
     }
 
     virDomainObjUnlock(vm);