On Thu, Sep 18, 2008 at 12:45:07PM -0400, David Lively wrote: > Hi - > > We have some folks looking into the implementation of events (just VM > state transition events, for now) in libvirtd. I've been assuming that > events will be XML strings, something like: > > <event type="domain-state-transition" timestamp="xxxxx"> > <domain-id>22</domain-id> > <old-state>nostate</old-state> > <new-state>running</new-state> > </event> > > where the contents of the <event> element are determined by the event > type, and the attributes type and timestamp are required. > > Originally, I was thinking one would listen for events by registering > a callback, something like: > int virConnectAddEventHandler(virConnPtr conn, char **filter, > virEventHandler handler, void *arg) > where filter is either NULL, indicating interest in all events, or else > a NULL-terminated vector of event type names, allowing filtering by > event type. void handler(conn, const char *eventXML, arg) would be > called for each matching event. I think I'd prefer to have properly typed event callbacks for each type of event we're dealing with, and to register callbacks against the object being tracked. We also don't want to do transitions on all the states - eg transitions between nostate & running are happening many times a second - its not useful to track that IMHO. Against a virConnectPtr object I'd expect to be able to register to get an event upon - A new domain object coming into existance - A existing domain object going out of existance So, you could register a callback, call Rich's virConnectListAllDomains() once, and then rely on the callbacks from that point onwards to keep your list of domains up2date. So in case of listening for domains: enum { VIR_CONNECT_DOMAIN_EVENT_ADDED, VIR_CONNECT_DOMAIN_EVENT_REMOVED, }; typedef int (*virConnectDomainEventCallback)(virConnectPtr conn, virDomainPtr dom, int event, void *opaque); int virCOnnectDomainEventRegister(virConnectPtr conn, virConnectDomainEventCallback cb, void *opaque); There would eventually be equivalent API for virNetworkPtr objects and virStoragePoolPtr objects, to track addition & removal of them. Against a virDomainPtr object, I'd expect to be able to register to get an event upon the significant state transitions. If we exclude the transition between nonstate & running which just happens far to often to be practical to track, I don't see a need to filter the events further - just have the callback get all events against that domain object. enum { VIR_DOMAIN_EVENT_STARTED VIR_DOMAIN_EVENT_SUSPENDED VIR_DOMAIN_EVENT_RESUMED VIR_DOMAIN_EVENT_STOPPED VIR_DOMAIN_EVENT_SAVED, VIR_DOMAIN_EVENT_RESTORED, }; typedef int (*virDomainLifecycleEventCallback)(virDomainPtr dom, int event, void *opaque); virDomainLifecycleEventRegister(virDomainPtr dom, virDomainLifecycleEventCallback cb, void *opaque); > I'm a little concerned that a vector of event type names isn't really > adequate for specifying a filter. Does this need to be more general > (XPathString exprs??) IMHO, XML / xpath is rather overkill for getting lifecycle events. > But my larger concern is that an asynchronous callback mechanism (as > proposed above) assumes the presence of some thread / process from which > to make the callbacks. ???This works fine in the libvirtd context, but > not outside of it. For instance, we build a "client only" version of > libvirt with ONLY the remote driver, which currently doesn't require > pthreads at all. Introducing asynchronous callbacks into the API means > pthreads is now required for this. I wouldn't want to use threads for this - any application which is structured in such a way as to be able to make use of async events will have some kind of event loop implementation. We merely need to provoide a way to hook libvirt into that event loop. We already have the API defined for this - src/event.h, and have an demonstration impl that the daemon uses qemud/event.c. So we'd want to validate this src/event.h API contract by doing a proof-of concept impl with an external Glib event loop and if it proves sane, then make the event.h file part of the public API. Applications could either craft their event loop impl themselves, or we can provide some add-on pre-built helper libraries with common impls. eg, an optional libvirt-glib library which comes with a pre-built event impl for applications which use glib. Likewise a libvirt-qt helper. That'd cover pretty much all common GUI apps. This approach has been used very successfully by DBus to avoid tieing dbus to a specific event loop impl. > I'm not sure how much requiring this extra thread matters. If it does, > we could always define a synchronous delivery mechanism instead. For > instance, we could have a virDeliverEvents(conn) call to make the > callbacks for any outstanding events. Or we could just dispense with > callbacks altogether, and return a readable (pipe) fd from which the > client can read events. I don't like the idea of exposing an FD as I consider this to be internal impl details. Allowing apps to see it will constrain our abilty to change internals. So I prefer to have the applicaiton provide an event loop impl, which we can call into to register FDs or timeout as & when libvirt deems neccessary. Daniel -- |: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :| |: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :| -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list