mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-20 11:35:19 +00:00
qemu_agent: Wait for events instead of agent response
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. (cherry picked from commit d97a234c62d272eb140c836cb93d750a4dec3354)
This commit is contained in:
parent
4cb2da8cd4
commit
e8603e5f73
@ -107,6 +107,11 @@ struct _qemuAgent {
|
|||||||
/* If anything went wrong, this will be fed back
|
/* If anything went wrong, this will be fed back
|
||||||
* the next monitor msg */
|
* the next monitor msg */
|
||||||
virError lastError;
|
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
|
#if DEBUG_RAW_IO
|
||||||
@ -825,6 +830,13 @@ void qemuAgentClose(qemuAgentPtr mon)
|
|||||||
VIR_FORCE_CLOSE(mon->fd);
|
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)
|
if (qemuAgentUnref(mon) > 0)
|
||||||
qemuAgentUnlock(mon);
|
qemuAgentUnlock(mon);
|
||||||
}
|
}
|
||||||
@ -981,6 +993,7 @@ qemuAgentCommand(qemuAgentPtr mon,
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
qemuAgentMessage msg;
|
qemuAgentMessage msg;
|
||||||
char *cmdstr = NULL;
|
char *cmdstr = NULL;
|
||||||
|
int await_event = mon->await_event;
|
||||||
|
|
||||||
*reply = NULL;
|
*reply = NULL;
|
||||||
|
|
||||||
@ -1009,10 +1022,16 @@ qemuAgentCommand(qemuAgentPtr mon,
|
|||||||
ret, msg.rxObject);
|
ret, msg.rxObject);
|
||||||
|
|
||||||
if (ret == 0) {
|
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) {
|
if (!msg.rxObject) {
|
||||||
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
if (await_event) {
|
||||||
_("Missing monitor reply object"));
|
VIR_DEBUG("Woken up by event %d", await_event);
|
||||||
ret = -1;
|
} else {
|
||||||
|
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
||||||
|
_("Missing monitor reply object"));
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
*reply = msg.rxObject;
|
*reply = msg.rxObject;
|
||||||
}
|
}
|
||||||
@ -1237,6 +1256,24 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qemuAgentNotifyEvent(qemuAgentPtr mon,
|
||||||
|
qemuAgentEvent event)
|
||||||
|
{
|
||||||
|
VIR_DEBUG("mon=%p event=%d", mon, event);
|
||||||
|
if (mon->await_event == event) {
|
||||||
|
VIR_DEBUG("Waking 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_DECL(qemuAgentShutdownMode);
|
||||||
|
|
||||||
VIR_ENUM_IMPL(qemuAgentShutdownMode,
|
VIR_ENUM_IMPL(qemuAgentShutdownMode,
|
||||||
@ -1256,9 +1293,10 @@ int qemuAgentShutdown(qemuAgentPtr mon,
|
|||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
mon->await_event = QEMU_AGENT_EVENT_SHUTDOWN;
|
||||||
ret = qemuAgentCommand(mon, cmd, &reply);
|
ret = qemuAgentCommand(mon, cmd, &reply);
|
||||||
|
|
||||||
if (ret == 0)
|
if (reply && ret == 0)
|
||||||
ret = qemuAgentCheckError(cmd, reply);
|
ret = qemuAgentCheckError(cmd, reply);
|
||||||
|
|
||||||
virJSONValueFree(cmd);
|
virJSONValueFree(cmd);
|
||||||
@ -1361,9 +1399,10 @@ qemuAgentSuspend(qemuAgentPtr mon,
|
|||||||
if (!cmd)
|
if (!cmd)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
mon->await_event = QEMU_AGENT_EVENT_SUSPEND;
|
||||||
ret = qemuAgentCommand(mon, cmd, &reply);
|
ret = qemuAgentCommand(mon, cmd, &reply);
|
||||||
|
|
||||||
if (ret == 0)
|
if (reply && ret == 0)
|
||||||
ret = qemuAgentCheckError(cmd, reply);
|
ret = qemuAgentCheckError(cmd, reply);
|
||||||
|
|
||||||
virJSONValueFree(cmd);
|
virJSONValueFree(cmd);
|
||||||
|
@ -55,6 +55,15 @@ int qemuAgentUnref(qemuAgentPtr mon) ATTRIBUTE_RETURN_CHECK;
|
|||||||
|
|
||||||
void qemuAgentClose(qemuAgentPtr mon);
|
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 {
|
typedef enum {
|
||||||
QEMU_AGENT_SHUTDOWN_POWERDOWN,
|
QEMU_AGENT_SHUTDOWN_POWERDOWN,
|
||||||
QEMU_AGENT_SHUTDOWN_REBOOT,
|
QEMU_AGENT_SHUTDOWN_REBOOT,
|
||||||
|
@ -663,6 +663,9 @@ qemuProcessHandleShutdown(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
vm->def->name);
|
vm->def->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->agent)
|
||||||
|
qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SHUTDOWN);
|
||||||
|
|
||||||
qemuProcessShutdownOrReboot(driver, vm);
|
qemuProcessShutdownOrReboot(driver, vm);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
@ -1116,6 +1119,7 @@ qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
event = virDomainEventPMSuspendNewFromObj(vm);
|
event = virDomainEventPMSuspendNewFromObj(vm);
|
||||||
|
|
||||||
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
|
if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
|
||||||
|
qemuDomainObjPrivatePtr priv = vm->privateData;
|
||||||
VIR_DEBUG("Transitioned guest %s to pmsuspended state due to "
|
VIR_DEBUG("Transitioned guest %s to pmsuspended state due to "
|
||||||
"QMP suspend event", vm->def->name);
|
"QMP suspend event", vm->def->name);
|
||||||
|
|
||||||
@ -1126,6 +1130,9 @@ qemuProcessHandlePMSuspend(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
|
|||||||
VIR_WARN("Unable to save status on vm %s after suspend event",
|
VIR_WARN("Unable to save status on vm %s after suspend event",
|
||||||
vm->def->name);
|
vm->def->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->agent)
|
||||||
|
qemuAgentNotifyEvent(priv->agent, QEMU_AGENT_EVENT_SUSPEND);
|
||||||
}
|
}
|
||||||
|
|
||||||
virDomainObjUnlock(vm);
|
virDomainObjUnlock(vm);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user