On Thu, Jun 09, 2011 at 12:10:13PM -0500, Adam Litke wrote: > When an operation started by virDomainBlockPullAll completes (either with > success or with failure), raise an event to indicate the final status. This > allows an API user to avoid polling on virDomainBlockPullInfo if they would > prefer to use the event mechanism. > > * daemon/remote.c: Dispatch events to client > * include/libvirt/libvirt.h.in: Define event ID and callback signature > * src/conf/domain_event.c, src/conf/domain_event.h, > src/libvirt_private.syms: Extend API to handle the new event > * src/qemu/qemu_driver.c: Connect to the QEMU monitor event > for block_stream completion and emit a libvirt block pull event > * src/remote/remote_driver.c: Receive and dispatch events to application > * src/remote/remote_protocol.x: Wire protocol definition for the event > * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, > src/qemu/qemu_monitor_json.c: Watch for BLOCK_STREAM_COMPLETED event > from QEMU monitor > > Signed-off-by: Adam Litke <agl@xxxxxxxxxx> > diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c > index fabc1a5..90c2b32 100644 > --- a/src/conf/domain_event.c > +++ b/src/conf/domain_event.c > @@ -84,6 +84,10 @@ struct _virDomainEvent { > char *authScheme; > virDomainEventGraphicsSubjectPtr subject; > } graphics; > + struct { > + char *path; > + int status; > + } blockPull; > } data; > }; > > @@ -500,6 +504,11 @@ void virDomainEventFree(virDomainEventPtr event) > } > VIR_FREE(event->data.graphics.subject); > } > + break; > + > + case VIR_DOMAIN_EVENT_ID_BLOCK_PULL: > + VIR_FREE(event->data.blockPull.path); > + break; > } > > VIR_FREE(event->dom.name); > @@ -875,6 +884,40 @@ virDomainEventPtr virDomainEventGraphicsNewFromObj(virDomainObjPtr obj, > return ev; > } > > +static virDomainEventPtr > +virDomainEventBlockPullNew(int id, const char *name, unsigned char *uuid, > + const char *path, int status) > +{ > + virDomainEventPtr ev = > + virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_BLOCK_PULL, > + id, name, uuid); > + > + if (ev) { > + if (!(ev->data.blockPull.path = strdup(path))) { > + virDomainEventFree(ev); > + return NULL; You want a virReportOOMError() call there. > + } > + ev->data.blockPull.status = status; > + } > + > + return ev; > +} > + > +virDomainEventPtr virDomainEventBlockPullNewFromObj(virDomainObjPtr obj, > + const char *path, > + int status) > +{ > + return virDomainEventBlockPullNew(obj->def->id, obj->def->name, > + obj->def->uuid, path, status); > +} > + > +virDomainEventPtr virDomainEventBlockPullNewFromDom(virDomainPtr dom, > + const char *path, > + int status) > +{ > + return virDomainEventBlockPullNew(dom->id, dom->name, dom->uuid, > + path, status); > +} > > virDomainEventPtr virDomainEventControlErrorNewFromDom(virDomainPtr dom) > { > +static int > +qemuProcessHandleBlockPull(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > + virDomainObjPtr vm, > + const char *diskAlias, > + int status) > +{ > + struct qemud_driver *driver = qemu_driver; > + virDomainEventPtr blockPullEvent = NULL; > + const char *path; > + virDomainDiskDefPtr disk; > + > + virDomainObjLock(vm); > + disk = qemuProcessFindDomainDiskByAlias(vm, diskAlias); > + > + if (disk) > + path = disk->src; > + else > + path = ""; If we can't find the disk associated with the alias, then I think we should just discard the event rather than emitting one with a zero-length path. > + blockPullEvent = virDomainEventBlockPullNewFromObj(vm, path, status); > + > + virDomainObjUnlock(vm); > + qemuDriverLock(driver); > + qemuDomainEventQueue(driver, blockPullEvent); > + qemuDriverUnlock(driver); > + > + return 0; > +} Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :| -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list