mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-20 07:59:00 +00:00
qemu: Add connection close callbacks
Add support for registering arbitrary callback to be called for a domain when a connection gets closed.
This commit is contained in:
parent
4f061ea641
commit
791273603e
@ -56,6 +56,11 @@
|
||||
|
||||
#define VIR_FROM_THIS VIR_FROM_QEMU
|
||||
|
||||
struct _qemuDriverCloseDef {
|
||||
virConnectPtr conn;
|
||||
qemuDriverCloseCallback cb;
|
||||
};
|
||||
|
||||
void qemuDriverLock(struct qemud_driver *driver)
|
||||
{
|
||||
virMutexLock(&driver->lock);
|
||||
@ -490,3 +495,170 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
|
||||
virConfFree (conf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
qemuDriverCloseCallbackFree(void *payload,
|
||||
const void *name ATTRIBUTE_UNUSED)
|
||||
{
|
||||
VIR_FREE(payload);
|
||||
}
|
||||
|
||||
int
|
||||
qemuDriverCloseCallbackInit(struct qemud_driver *driver)
|
||||
{
|
||||
driver->closeCallbacks = virHashCreate(5, qemuDriverCloseCallbackFree);
|
||||
if (!driver->closeCallbacks)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
qemuDriverCloseCallbackShutdown(struct qemud_driver *driver)
|
||||
{
|
||||
virHashFree(driver->closeCallbacks);
|
||||
}
|
||||
|
||||
int
|
||||
qemuDriverCloseCallbackSet(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
virConnectPtr conn,
|
||||
qemuDriverCloseCallback cb)
|
||||
{
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
qemuDriverCloseDefPtr closeDef;
|
||||
|
||||
virUUIDFormat(vm->def->uuid, uuidstr);
|
||||
VIR_DEBUG("vm=%s, uuid=%s, conn=%p, cb=%p",
|
||||
vm->def->name, uuidstr, conn, cb);
|
||||
|
||||
closeDef = virHashLookup(driver->closeCallbacks, uuidstr);
|
||||
if (closeDef) {
|
||||
if (closeDef->conn != conn) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Close callback for domain %s already registered"
|
||||
" with another connection %p"),
|
||||
vm->def->name, closeDef->conn);
|
||||
return -1;
|
||||
}
|
||||
if (closeDef->cb && closeDef->cb != cb) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Another close callback is already defined for"
|
||||
" domain %s"), vm->def->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
closeDef->cb = cb;
|
||||
} else {
|
||||
if (VIR_ALLOC(closeDef) < 0) {
|
||||
virReportOOMError();
|
||||
return -1;
|
||||
}
|
||||
|
||||
closeDef->conn = conn;
|
||||
closeDef->cb = cb;
|
||||
if (virHashAddEntry(driver->closeCallbacks, uuidstr, closeDef) < 0) {
|
||||
VIR_FREE(closeDef);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
qemuDriverCloseCallbackUnset(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
qemuDriverCloseCallback cb)
|
||||
{
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
qemuDriverCloseDefPtr closeDef;
|
||||
|
||||
virUUIDFormat(vm->def->uuid, uuidstr);
|
||||
VIR_DEBUG("vm=%s, uuid=%s, cb=%p",
|
||||
vm->def->name, uuidstr, cb);
|
||||
|
||||
closeDef = virHashLookup(driver->closeCallbacks, uuidstr);
|
||||
if (!closeDef)
|
||||
return -1;
|
||||
|
||||
if (closeDef->cb && closeDef->cb != cb) {
|
||||
qemuReportError(VIR_ERR_INTERNAL_ERROR,
|
||||
_("Trying to remove mismatching close callback for"
|
||||
" domain %s"), vm->def->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return virHashRemoveEntry(driver->closeCallbacks, uuidstr);
|
||||
}
|
||||
|
||||
qemuDriverCloseCallback
|
||||
qemuDriverCloseCallbackGet(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
virConnectPtr conn)
|
||||
{
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
qemuDriverCloseDefPtr closeDef;
|
||||
qemuDriverCloseCallback cb = NULL;
|
||||
|
||||
virUUIDFormat(vm->def->uuid, uuidstr);
|
||||
VIR_DEBUG("vm=%s, uuid=%s, conn=%p",
|
||||
vm->def->name, uuidstr, conn);
|
||||
|
||||
closeDef = virHashLookup(driver->closeCallbacks, uuidstr);
|
||||
if (closeDef && (!conn || closeDef->conn == conn))
|
||||
cb = closeDef->cb;
|
||||
|
||||
VIR_DEBUG("cb=%p", cb);
|
||||
return cb;
|
||||
}
|
||||
|
||||
struct qemuDriverCloseCallbackData {
|
||||
struct qemud_driver *driver;
|
||||
virConnectPtr conn;
|
||||
};
|
||||
|
||||
static void
|
||||
qemuDriverCloseCallbackRun(void *payload,
|
||||
const void *name,
|
||||
void *opaque)
|
||||
{
|
||||
struct qemuDriverCloseCallbackData *data = opaque;
|
||||
qemuDriverCloseDefPtr closeDef = payload;
|
||||
const char *uuidstr = name;
|
||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||
virDomainObjPtr dom;
|
||||
|
||||
VIR_DEBUG("conn=%p, thisconn=%p, uuid=%s, cb=%p",
|
||||
closeDef->conn, data->conn, uuidstr, closeDef->cb);
|
||||
|
||||
if (data->conn != closeDef->conn || !closeDef->cb)
|
||||
return;
|
||||
|
||||
if (virUUIDParse(uuidstr, uuid) < 0) {
|
||||
VIR_WARN("Failed to parse %s", uuidstr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(dom = virDomainFindByUUID(&data->driver->domains, uuid))) {
|
||||
VIR_DEBUG("No domain object with UUID %s", uuidstr);
|
||||
return;
|
||||
}
|
||||
|
||||
dom = closeDef->cb(data->driver, dom, data->conn);
|
||||
if (dom)
|
||||
virDomainObjUnlock(dom);
|
||||
|
||||
virHashRemoveEntry(data->driver->closeCallbacks, uuidstr);
|
||||
}
|
||||
|
||||
void
|
||||
qemuDriverCloseCallbackRunAll(struct qemud_driver *driver,
|
||||
virConnectPtr conn)
|
||||
{
|
||||
struct qemuDriverCloseCallbackData data = {
|
||||
driver, conn
|
||||
};
|
||||
VIR_DEBUG("conn=%p", conn);
|
||||
|
||||
virHashForEach(driver->closeCallbacks, qemuDriverCloseCallbackRun, &data);
|
||||
}
|
||||
|
@ -46,6 +46,8 @@
|
||||
|
||||
# define QEMUD_CPUMASK_LEN CPU_SETSIZE
|
||||
|
||||
typedef struct _qemuDriverCloseDef qemuDriverCloseDef;
|
||||
typedef qemuDriverCloseDef *qemuDriverCloseDefPtr;
|
||||
|
||||
/* Main driver state */
|
||||
struct qemud_driver {
|
||||
@ -144,6 +146,13 @@ struct qemud_driver {
|
||||
* when the virConnectPtr is closed*/
|
||||
virHashTablePtr autodestroy;
|
||||
|
||||
/* Mapping of 'char *uuidstr' -> qemuDriverCloseDefPtr of domains
|
||||
* which want a specific cleanup to be done when a connection is
|
||||
* closed. Such cleanup may be to automatically destroy the
|
||||
* domain or abort a particular job running on it.
|
||||
*/
|
||||
virHashTablePtr closeCallbacks;
|
||||
|
||||
int keepAliveInterval;
|
||||
unsigned int keepAliveCount;
|
||||
};
|
||||
@ -180,4 +189,22 @@ struct qemuDomainDiskInfo {
|
||||
int io_status;
|
||||
};
|
||||
|
||||
typedef virDomainObjPtr (*qemuDriverCloseCallback)(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
virConnectPtr conn);
|
||||
int qemuDriverCloseCallbackInit(struct qemud_driver *driver);
|
||||
void qemuDriverCloseCallbackShutdown(struct qemud_driver *driver);
|
||||
int qemuDriverCloseCallbackSet(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
virConnectPtr conn,
|
||||
qemuDriverCloseCallback cb);
|
||||
int qemuDriverCloseCallbackUnset(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
qemuDriverCloseCallback cb);
|
||||
qemuDriverCloseCallback qemuDriverCloseCallbackGet(struct qemud_driver *driver,
|
||||
virDomainObjPtr vm,
|
||||
virConnectPtr conn);
|
||||
void qemuDriverCloseCallbackRunAll(struct qemud_driver *driver,
|
||||
virConnectPtr conn);
|
||||
|
||||
#endif /* __QEMUD_CONF_H */
|
||||
|
@ -662,6 +662,9 @@ qemudStartup(int privileged) {
|
||||
if (qemuProcessAutoDestroyInit(qemu_driver) < 0)
|
||||
goto error;
|
||||
|
||||
if (qemuDriverCloseCallbackInit(qemu_driver) < 0)
|
||||
goto error;
|
||||
|
||||
/* Get all the running persistent or transient configs first */
|
||||
if (virDomainLoadAllConfigs(qemu_driver->caps,
|
||||
&qemu_driver->domains,
|
||||
@ -801,6 +804,7 @@ qemudShutdown(void) {
|
||||
virSysinfoDefFree(qemu_driver->hostsysinfo);
|
||||
|
||||
qemuProcessAutoDestroyShutdown(qemu_driver);
|
||||
qemuDriverCloseCallbackShutdown(qemu_driver);
|
||||
|
||||
VIR_FREE(qemu_driver->configDir);
|
||||
VIR_FREE(qemu_driver->autostartDir);
|
||||
@ -922,6 +926,7 @@ static int qemudClose(virConnectPtr conn) {
|
||||
virDomainEventStateDeregisterConn(conn,
|
||||
driver->domainEventState);
|
||||
qemuProcessAutoDestroyRun(driver, conn);
|
||||
qemuDriverCloseCallbackRunAll(driver, conn);
|
||||
qemuDriverUnlock(driver);
|
||||
|
||||
conn->privateData = NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user