This code changes the daemaon to: use the pulic def of virEventRegisterImpl Add functionality to dispatch events to connected remote drivers qemud.c | 28 ++++++++--- qemud.h | 14 +++++ remote.c | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 193 insertions(+), 7 deletions(-)
diff --git a/qemud/qemud.c b/qemud/qemud.c index 9da27d2..3020d81 100644 --- a/qemud/qemud.c +++ b/qemud/qemud.c @@ -723,12 +723,12 @@ static struct qemud_server *qemudInitialize(int sigread) { server->sigread = sigread; - __virEventRegisterImpl(virEventAddHandleImpl, - virEventUpdateHandleImpl, - virEventRemoveHandleImpl, - virEventAddTimeoutImpl, - virEventUpdateTimeoutImpl, - virEventRemoveTimeoutImpl); + virEventRegisterImpl(virEventAddHandleImpl, + virEventUpdateHandleImpl, + virEventRemoveHandleImpl, + virEventAddTimeoutImpl, + virEventUpdateTimeoutImpl, + virEventRemoveTimeoutImpl); virStateInitialize(); @@ -1105,7 +1105,12 @@ static int qemudDispatchServer(struct qemud_server *server, struct qemud_socket client->auth = sock->auth; memcpy (&client->addr, &addr, sizeof addr); client->addrlen = addrlen; + client->server = server; + if(VIR_ALLOC(client->domainEventCallbacks)<0) { + qemudLog(QEMUD_ERR, _("Error allocating domainEventCallbacks: %s"), strerror(errno)); + goto cleanup; + } #if HAVE_POLKIT /* Only do policy checks for non-root - allow root user through with no checks, as a fail-safe - root can easily @@ -1199,6 +1204,15 @@ static void qemudDispatchClientFailure(struct qemud_server *server, struct qemud virEventRemoveHandleImpl(client->fd); + /* Deregister event delivery callback */ + if(client->conn) { + qemudDebug("Deregistering to relay remote events"); + virConnectDomainEventDeregister(client->conn, remoteRelayDomainEvent); + } + + /* Free domain callback list */ + __virDomainEventCallbackListFree(client->domainEventCallbacks); + if (client->conn) virConnectClose(client->conn); @@ -1503,7 +1517,7 @@ static int qemudClientWrite(struct qemud_server *server, } -static void qemudDispatchClientWrite(struct qemud_server *server, struct qemud_client *client) { +void qemudDispatchClientWrite(struct qemud_server *server, struct qemud_client *client) { switch (client->mode) { case QEMUD_MODE_TX_PACKET: { if (qemudClientWrite(server, client) < 0) diff --git a/qemud/qemud.h b/qemud/qemud.h index 91cb939..2fb3ca9 100644 --- a/qemud/qemud.h +++ b/qemud/qemud.h @@ -132,6 +132,12 @@ struct qemud_client { */ virConnectPtr conn; + /* This is the list of remote callbacks registered */ + virDomainEventCallbackListPtr domainEventCallbacks; + + /* back-pointer to our server */ + struct qemud_server *server; + struct qemud_client *next; }; @@ -179,8 +185,16 @@ void qemudLog(int priority, const char *fmt, ...) void remoteDispatchClientRequest (struct qemud_server *server, struct qemud_client *client); +void qemudDispatchClientWrite(struct qemud_server *server, + struct qemud_client *client); + #if HAVE_POLKIT int qemudGetSocketIdentity(int fd, uid_t *uid, pid_t *pid); #endif +int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int event, + void *opaque); + #endif diff --git a/qemud/remote.c b/qemud/remote.c index 72e064e..eeed5fd 100644 --- a/qemud/remote.c +++ b/qemud/remote.c @@ -75,6 +75,13 @@ typedef int (*dispatch_fn) (struct qemud_server *server, char *args, char *ret); +/* Prototypes */ +static void +remoteDispatchDomainEventSend (struct qemud_client *client, + virDomainPtr dom, + virDomainEventType event, + virDomainEventCallbackPtr callback); + /* This function gets called from qemud when it detects an incoming * remote protocol message. At this point, client->buffer contains * the full call message (including length word which we skip). @@ -405,6 +412,24 @@ remoteDispatchError (struct qemud_client *client, remoteDispatchSendError (client, req, VIR_ERR_RPC, msg); } +int remoteRelayDomainEvent (virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + int event, + void *opaque) +{ + int i; + struct qemud_client *c = opaque; + REMOTE_DEBUG("Relaying domain event %d", event); + + if(c && c->domainEventCallbacks) { + for(i=0; i < c->domainEventCallbacks->count; i++) { + remoteDispatchDomainEventSend (c, dom, event, + c->domainEventCallbacks->callbacks[i]); + qemudDispatchClientWrite(c->server,c); + } + } + return 0; +} /*----- Functions. -----*/ @@ -3620,6 +3645,139 @@ remoteDispatchStorageVolLookupByPath (struct qemud_server *server ATTRIBUTE_UNUS } +/************************** + * Async Events + **************************/ +static int remoteDispatchDomainEvent (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client ATTRIBUTE_UNUSED, + remote_message_header *req ATTRIBUTE_UNUSED, + void *args ATTRIBUTE_UNUSED, + remote_domain_event_ret *ret ATTRIBUTE_UNUSED) +{ + /* This call gets dispatched from a client call. + * This does not make sense, as this should not be intiated + * from the client side in generated code. + */ + return -1; +} + +/*************************** + * Register / deregister events + ***************************/ +static int remoteDispatchDomainEventsRegister (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client, + remote_message_header *req ATTRIBUTE_UNUSED, + remote_domain_events_register_args *args ATTRIBUTE_UNUSED, + void *ret ATTRIBUTE_UNUSED) +{ + CHECK_CONN(client); + + if( __virDomainEventCallbackListAdd(client->conn, client->domainEventCallbacks, + (virConnectDomainEventCallback)args->callback, + (void *)args->user_data) < 0 ) { + REMOTE_DEBUG("%s","Error adding event callback"); + return -1; + } + + /* Register event delivery callback + * This is redundant if already registered for this client + */ + REMOTE_DEBUG("%s","Registering to relay remote events"); + virConnectDomainEventRegister(client->conn, remoteRelayDomainEvent, client); + + return 0; +} + +static int remoteDispatchDomainEventsDeregister (struct qemud_server *server ATTRIBUTE_UNUSED, + struct qemud_client *client, + remote_message_header *req ATTRIBUTE_UNUSED, + remote_domain_events_deregister_args *args ATTRIBUTE_UNUSED, + void *ret ATTRIBUTE_UNUSED) +{ + CHECK_CONN(client); + + if( __virDomainEventCallbackListRemove(client->conn, client->domainEventCallbacks, + (virConnectDomainEventCallback)args->callback) < 0 ) { + REMOTE_DEBUG("%s","WARNING: Could not remove event callback from list"); + } + + /* Deregister event delivery callback */ + REMOTE_DEBUG("%s","Deregistering to relay remote events"); + virConnectDomainEventDeregister(client->conn, remoteRelayDomainEvent); + + return 0; +} + +static void +remoteDispatchDomainEventSend (struct qemud_client *client, + virDomainPtr dom, + virDomainEventType event, + virDomainEventCallbackPtr callback) +{ + remote_message_header rep; + XDR xdr; + int len; + remote_domain_event_ret data; + + if(!client) { + remoteDispatchError (client, NULL, "%s", _("Invalid Client")); + return; + } + + rep.prog = REMOTE_PROGRAM; + rep.vers = REMOTE_PROTOCOL_VERSION; + rep.proc = REMOTE_PROC_DOMAIN_EVENT; + rep.direction = REMOTE_MESSAGE; + rep.serial = 1; + rep.status = REMOTE_OK; + + /* Serialise the return header and event. */ + xdrmem_create (&xdr, client->buffer, sizeof client->buffer, XDR_ENCODE); + + len = 0; /* We'll come back and write this later. */ + if (!xdr_int (&xdr, &len)) { + remoteDispatchError (client, NULL, "%s", _("xdr_int failed (1)")); + xdr_destroy (&xdr); + return; + } + + if (!xdr_remote_message_header (&xdr, &rep)) { + xdr_destroy (&xdr); + return; + } + + /* build return data */ + make_nonnull_domain (&data.dom, dom); + data.event = (int) event; + data.callback = (unsigned long) callback->cb; + data.user_data = (unsigned long) callback->opaque; + + if (!xdr_remote_domain_event_ret(&xdr, &data)) { + remoteDispatchError (client, NULL, "%s", _("serialise return struct")); + xdr_destroy (&xdr); + return; + } + + len = xdr_getpos (&xdr); + if (xdr_setpos (&xdr, 0) == 0) { + remoteDispatchError (client, NULL, "%s", _("xdr_setpos failed")); + xdr_destroy (&xdr); + return; + } + + if (!xdr_int (&xdr, &len)) { + remoteDispatchError (client, NULL, "%s", _("xdr_int failed (2)")); + xdr_destroy (&xdr); + return; + } + + xdr_destroy (&xdr); + + /* Send it. */ + client->mode = QEMUD_MODE_TX_PACKET; + client->bufferLength = len; + client->bufferOffset = 0; +} /*----- Helpers. -----*/ /* get_nonnull_domain and get_nonnull_network turn an on-wire
-- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list