summaryrefslogtreecommitdiff
path: root/daemon/remote.c
diff options
context:
space:
mode:
authorJovanka Gulicoska <jovanka.gulicoska@gmail.com>2016-06-15 20:35:45 +0200
committerCole Robinson <crobinso@redhat.com>2016-06-16 12:22:11 -0400
commit22fb4374dad02232d212b16d9977fc8af6313532 (patch)
treefd3cc2b2e734d9b7b591a87bf84f5afc5b3938db /daemon/remote.c
parentedc1a27a5af66314dd04f15749aac687c072bed1 (diff)
downloadlibvirt-22fb4374dad02232d212b16d9977fc8af6313532.tar.gz
remote: implement storage lifecycle event APIs
Diffstat (limited to 'daemon/remote.c')
-rw-r--r--daemon/remote.c206
1 files changed, 204 insertions, 2 deletions
diff --git a/daemon/remote.c b/daemon/remote.c
index b2a420bc00..4e2aff87b4 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -181,6 +181,32 @@ remoteRelayNetworkEventCheckACL(virNetServerClientPtr client,
return ret;
}
+static bool
+remoteRelayStoragePoolEventCheckACL(virNetServerClientPtr client,
+ virConnectPtr conn,
+ virStoragePoolPtr pool)
+{
+ virStoragePoolDef def;
+ virIdentityPtr identity = NULL;
+ bool ret = false;
+
+ /* For now, we just create a virStoragePoolDef with enough contents to
+ * satisfy what viraccessdriverpolkit.c references. This is a bit
+ * fragile, but I don't know of anything better. */
+ def.name = pool->name;
+ memcpy(def.uuid, pool->uuid, VIR_UUID_BUFLEN);
+
+ if (!(identity = virNetServerClientGetIdentity(client)))
+ goto cleanup;
+ if (virIdentitySetCurrent(identity) < 0)
+ goto cleanup;
+ ret = virConnectStoragePoolEventRegisterAnyCheckACL(conn, &def);
+
+ cleanup:
+ ignore_value(virIdentitySetCurrent(NULL));
+ virObjectUnref(identity);
+ return ret;
+}
static bool
remoteRelayDomainQemuMonitorEventCheckACL(virNetServerClientPtr client,
@@ -1236,6 +1262,44 @@ static virConnectNetworkEventGenericCallback networkEventCallbacks[] = {
verify(ARRAY_CARDINALITY(networkEventCallbacks) == VIR_NETWORK_EVENT_ID_LAST);
+static int
+remoteRelayStoragePoolEventLifecycle(virConnectPtr conn,
+ virStoragePoolPtr pool,
+ int event,
+ int detail,
+ void *opaque)
+{
+ daemonClientEventCallbackPtr callback = opaque;
+ remote_storage_pool_event_lifecycle_msg data;
+
+ if (callback->callbackID < 0 ||
+ !remoteRelayStoragePoolEventCheckACL(callback->client, conn, pool))
+ return -1;
+
+ VIR_DEBUG("Relaying storage pool lifecycle event %d, detail %d, callback %d",
+ event, detail, callback->callbackID);
+
+ /* build return data */
+ memset(&data, 0, sizeof(data));
+ make_nonnull_storage_pool(&data.pool, pool);
+ data.callbackID = callback->callbackID;
+ data.event = event;
+ data.detail = detail;
+
+ remoteDispatchObjectEventSend(callback->client, remoteProgram,
+ REMOTE_PROC_STORAGE_POOL_EVENT_LIFECYCLE,
+ (xdrproc_t)xdr_remote_storage_pool_event_lifecycle_msg,
+ &data);
+
+ return 0;
+}
+
+static virConnectStoragePoolEventGenericCallback storageEventCallbacks[] = {
+ VIR_STORAGE_POOL_EVENT_CALLBACK(remoteRelayStoragePoolEventLifecycle),
+};
+
+verify(ARRAY_CARDINALITY(storageEventCallbacks) == VIR_STORAGE_POOL_EVENT_ID_LAST);
+
static void
remoteRelayDomainQemuMonitorEvent(virConnectPtr conn,
virDomainPtr dom,
@@ -1343,6 +1407,21 @@ void remoteClientFreeFunc(void *data)
}
VIR_FREE(priv->networkEventCallbacks);
+ for (i = 0; i < priv->nstorageEventCallbacks; i++) {
+ int callbackID = priv->storageEventCallbacks[i]->callbackID;
+ if (callbackID < 0) {
+ VIR_WARN("unexpected incomplete storage pool callback %zu", i);
+ continue;
+ }
+ VIR_DEBUG("Deregistering remote storage pool event relay %d",
+ callbackID);
+ priv->storageEventCallbacks[i]->callbackID = -1;
+ if (virConnectStoragePoolEventDeregisterAny(priv->conn,
+ callbackID) < 0)
+ VIR_WARN("unexpected storage pool event deregister failure");
+ }
+ VIR_FREE(priv->storageEventCallbacks);
+
for (i = 0; i < priv->nqemuEventCallbacks; i++) {
int callbackID = priv->qemuEventCallbacks[i]->callbackID;
if (callbackID < 0) {
@@ -3528,8 +3607,10 @@ remoteDispatchConnectDomainEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED
* to our array, but on OOM append failure, we'd have to then hope
* deregister works to undo our register. So instead we append an
* incomplete callback to our array, then register, then fix up
- * our callback; but since VIR_APPEND_ELEMENT clears 'callback' on
- * success, we use 'ref' to save a copy of the pointer. */
+ * our callback; or you can use VIR_APPEND_ELEMENT_COPY to avoid
+ * clearing 'callback' and having to juggle the pointer
+ * between 'ref' and 'callback'.
+ */
if (VIR_ALLOC(callback) < 0)
goto cleanup;
callback->client = client;
@@ -5434,6 +5515,127 @@ remoteDispatchConnectNetworkEventDeregisterAny(virNetServerPtr server ATTRIBUTE_
return rv;
}
+static int
+remoteDispatchConnectStoragePoolEventRegisterAny(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED,
+ remote_connect_storage_pool_event_register_any_args *args,
+ remote_connect_storage_pool_event_register_any_ret *ret)
+{
+ int callbackID;
+ int rv = -1;
+ daemonClientEventCallbackPtr callback = NULL;
+ daemonClientEventCallbackPtr ref;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+ virStoragePoolPtr pool = NULL;
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ virMutexLock(&priv->lock);
+
+ if (args->pool &&
+ !(pool = get_nonnull_storage_pool(priv->conn, *args->pool)))
+ goto cleanup;
+
+ if (args->eventID >= VIR_STORAGE_POOL_EVENT_ID_LAST || args->eventID < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unsupported storage pool event ID %d"), args->eventID);
+ goto cleanup;
+ }
+
+ /* If we call register first, we could append a complete callback
+ * to our array, but on OOM append failure, we'd have to then hope
+ * deregister works to undo our register. So instead we append an
+ * incomplete callback to our array, then register, then fix up
+ * our callback; but since VIR_APPEND_ELEMENT clears 'callback' on
+ * success, we use 'ref' to save a copy of the pointer. */
+ if (VIR_ALLOC(callback) < 0)
+ goto cleanup;
+ callback->client = client;
+ callback->eventID = args->eventID;
+ callback->callbackID = -1;
+ ref = callback;
+ if (VIR_APPEND_ELEMENT(priv->storageEventCallbacks,
+ priv->nstorageEventCallbacks,
+ callback) < 0)
+ goto cleanup;
+
+ if ((callbackID = virConnectStoragePoolEventRegisterAny(priv->conn,
+ pool,
+ args->eventID,
+ storageEventCallbacks[args->eventID],
+ ref,
+ remoteEventCallbackFree)) < 0) {
+ VIR_SHRINK_N(priv->storageEventCallbacks,
+ priv->nstorageEventCallbacks, 1);
+ callback = ref;
+ goto cleanup;
+ }
+
+ ref->callbackID = callbackID;
+ ret->callbackID = callbackID;
+
+ rv = 0;
+
+ cleanup:
+ VIR_FREE(callback);
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ virObjectUnref(pool);
+ virMutexUnlock(&priv->lock);
+ return rv;
+}
+
+static int
+remoteDispatchConnectStoragePoolEventDeregisterAny(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr ATTRIBUTE_UNUSED,
+ remote_connect_storage_pool_event_deregister_any_args *args)
+{
+ int rv = -1;
+ size_t i;
+ struct daemonClientPrivate *priv =
+ virNetServerClientGetPrivateData(client);
+
+ if (!priv->conn) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+ goto cleanup;
+ }
+
+ virMutexLock(&priv->lock);
+
+ for (i = 0; i < priv->nstorageEventCallbacks; i++) {
+ if (priv->storageEventCallbacks[i]->callbackID == args->callbackID)
+ break;
+ }
+ if (i == priv->nstorageEventCallbacks) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("storage pool event callback %d not registered"),
+ args->callbackID);
+ goto cleanup;
+ }
+
+ if (virConnectStoragePoolEventDeregisterAny(priv->conn, args->callbackID) < 0)
+ goto cleanup;
+
+ VIR_DELETE_ELEMENT(priv->storageEventCallbacks, i,
+ priv->nstorageEventCallbacks);
+
+ rv = 0;
+
+ cleanup:
+ if (rv < 0)
+ virNetMessageSaveError(rerr);
+ virMutexUnlock(&priv->lock);
+ return rv;
+}
+
static int
qemuDispatchConnectDomainMonitorEventRegister(virNetServerPtr server ATTRIBUTE_UNUSED,