qemu: Add support for domain cleanup callbacks

Add support for registering cleanup callbacks to be run when a domain
transitions to shutoff state.
This commit is contained in:
Jiri Denemark 2012-03-16 07:52:26 +01:00
parent 9f71368d06
commit bf9f0a9726
3 changed files with 90 additions and 0 deletions

View File

@ -232,6 +232,7 @@ static void qemuDomainObjPrivateFree(void *data)
VIR_ERROR(_("Unexpected QEMU agent still active during domain deletion")); VIR_ERROR(_("Unexpected QEMU agent still active during domain deletion"));
qemuAgentClose(priv->agent); qemuAgentClose(priv->agent);
} }
VIR_FREE(priv->cleanupCallbacks);
VIR_FREE(priv); VIR_FREE(priv);
} }
@ -1769,3 +1770,75 @@ qemuDomainCheckDiskPresence(struct qemud_driver *driver,
cleanup: cleanup:
return ret; return ret;
} }
/*
* The vm must be locked when any of the following cleanup functions is
* called.
*/
int
qemuDomainCleanupAdd(virDomainObjPtr vm,
qemuDomainCleanupCallback cb)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int i;
VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb);
for (i = 0; i < priv->ncleanupCallbacks; i++) {
if (priv->cleanupCallbacks[i] == cb)
return 0;
}
if (VIR_RESIZE_N(priv->cleanupCallbacks,
priv->ncleanupCallbacks_max,
priv->ncleanupCallbacks, 1) < 0) {
virReportOOMError();
return -1;
}
priv->cleanupCallbacks[priv->ncleanupCallbacks++] = cb;
return 0;
}
void
qemuDomainCleanupRemove(virDomainObjPtr vm,
qemuDomainCleanupCallback cb)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int i;
VIR_DEBUG("vm=%s, cb=%p", vm->def->name, cb);
for (i = 0; i < priv->ncleanupCallbacks; i++) {
if (priv->cleanupCallbacks[i] == cb) {
memmove(priv->cleanupCallbacks + i,
priv->cleanupCallbacks + i + 1,
priv->ncleanupCallbacks - i - 1);
priv->ncleanupCallbacks--;
}
}
VIR_SHRINK_N(priv->cleanupCallbacks,
priv->ncleanupCallbacks_max,
priv->ncleanupCallbacks_max - priv->ncleanupCallbacks);
}
void
qemuDomainCleanupRun(struct qemud_driver *driver,
virDomainObjPtr vm)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
int i;
VIR_DEBUG("driver=%p, vm=%s", driver, vm->def->name);
/* run cleanup callbacks in reverse order */
for (i = priv->ncleanupCallbacks - 1; i >= 0; i--) {
if (priv->cleanupCallbacks[i])
priv->cleanupCallbacks[i](driver, vm);
}
VIR_FREE(priv->cleanupCallbacks);
priv->ncleanupCallbacks = 0;
priv->ncleanupCallbacks_max = 0;
}

View File

@ -101,6 +101,9 @@ struct qemuDomainJobObj {
typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet; typedef struct _qemuDomainPCIAddressSet qemuDomainPCIAddressSet;
typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr; typedef qemuDomainPCIAddressSet *qemuDomainPCIAddressSetPtr;
typedef void (*qemuDomainCleanupCallback)(struct qemud_driver *driver,
virDomainObjPtr vm);
typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate; typedef struct _qemuDomainObjPrivate qemuDomainObjPrivate;
typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr; typedef qemuDomainObjPrivate *qemuDomainObjPrivatePtr;
struct _qemuDomainObjPrivate { struct _qemuDomainObjPrivate {
@ -137,6 +140,10 @@ struct _qemuDomainObjPrivate {
char *origname; char *origname;
virConsolesPtr cons; virConsolesPtr cons;
qemuDomainCleanupCallback *cleanupCallbacks;
size_t ncleanupCallbacks;
size_t ncleanupCallbacks_max;
}; };
struct qemuDomainWatchdogEvent struct qemuDomainWatchdogEvent
@ -314,4 +321,12 @@ bool qemuDomainJobAllowed(qemuDomainObjPrivatePtr priv,
int qemuDomainCheckDiskPresence(struct qemud_driver *driver, int qemuDomainCheckDiskPresence(struct qemud_driver *driver,
virDomainObjPtr vm, virDomainObjPtr vm,
bool start_with_state); bool start_with_state);
int qemuDomainCleanupAdd(virDomainObjPtr vm,
qemuDomainCleanupCallback cb);
void qemuDomainCleanupRemove(virDomainObjPtr vm,
qemuDomainCleanupCallback cb);
void qemuDomainCleanupRun(struct qemud_driver *driver,
virDomainObjPtr vm);
#endif /* __QEMU_DOMAIN_H__ */ #endif /* __QEMU_DOMAIN_H__ */

View File

@ -3803,6 +3803,8 @@ void qemuProcessStop(struct qemud_driver *driver,
/* shut it off for sure */ /* shut it off for sure */
ignore_value(qemuProcessKill(driver, vm, VIR_QEMU_PROCESS_KILL_FORCE)); ignore_value(qemuProcessKill(driver, vm, VIR_QEMU_PROCESS_KILL_FORCE));
qemuDomainCleanupRun(driver, vm);
/* Stop autodestroy in case guest is restarted */ /* Stop autodestroy in case guest is restarted */
qemuProcessAutoDestroyRemove(driver, vm); qemuProcessAutoDestroyRemove(driver, vm);