A little over a month ago I proposed an API extension for enabling long operations to be done as asynchronous background jobs. http://www.redhat.com/archives/libvir-list/2008-January/msg00040.html While the proof of concept definitely worked, having played around & thought about it a little more I feel we can do better than that initial proposal. Some things I didn't like about it: - Complicated reference counting. This was because jobs may or may not be tied to a virDomainPtr object depending on whether the job was a creation attempt, or an operation on an existing object. - Complicated app code because they now had to track both Job & Domain objects together. - Added too many new APIs - this was a consequence of needing the separate top level virJob object, adding lots of XXXJob variants for APIs. - Complicated internal drivers due to the separate Job object. So to try and address this I've come up with an alternative, simpler design for this. The key idea is to get rid of the top level 'Job' object and make use of the 'flags' field present in (almost) all the APIs which need to have async behaviour. First of all, for the couple of APIs which don't have 'flags' we add new variants taking a 'flags' parameter. For each API needing to allow async operation, we define a flag for this eg, virDomainCreateXML -> VIR_DOMAIN_CREATE_XML_ASYNC virDomainRestore -> VIR_DOMAIN_RESTORE_ASYNC virStoragePoolBuild -> VIR_STORAGE_POOL_BUILD_ASYNC If the flag is omitted, current semantics are unchanged, so existing apps are not impacted. If you pass the appropriate XXX_ASYNC flag, then you cannot assume that the operation is complete upon returning from the call. To check completion status you ask for the virJobInfo data. This can be done with whichever of these APIs matches: virDomainGetJobInfo(virDomainPtr dom, virJobInfoPtr job) virStoragePoolGetJobInfo(virStoragePoolPtr vol, virJobInfoPtr job) virStorageVolGetJobInfo(virStorageVolPtr vol, virJobInfoPtr job) Finally, you can cancel an operation: virDomainCancelJob(virDomainPtr dom); virStoragePoolCancelJob(virStoragePoolPtr pool); virStorageVolCancelJob(virStorageVolPtr vol); If you passed the XXX_ASYNC flag, it is forbidden to call any APIs on the object other than the XXXCancelJob() or XXXGetJobInfo() methods, until the job is complete. This was true of the previous proof of concept I did but I didn't spell it out at the time. I've not done the intenral driver impl of this proposal yet, but it will be easier/clearer than the previous impl, and the virsh changes will be much less intrusive since we're merely passing a flag instead of calling a completely separate API. The patch below illustrates the proposed public API - note how its only adding a handful of new entry points - 3 virDomain methods needed an extra flags parameter - all the storage APIs were written to take flags already Dan. diff -r 3b8d18bc4d3e include/libvirt/libvirt.h.in --- a/include/libvirt/libvirt.h.in Wed Feb 20 12:20:50 2008 -0500 +++ b/include/libvirt/libvirt.h.in Wed Feb 20 14:14:09 2008 -0500 @@ -408,6 +408,62 @@ char * virConnectGetCap unsigned long long virNodeGetFreeMemory (virConnectPtr conn); + + +/* + * Asynchronous background jobs + */ + +/** + * virJobType; + * + * A job may have a finite bounded progress, or may be + * unbounded. + */ +typedef enum { + VIR_JOB_BOUNDED = 0, /* finite, 0-> 100 completion */ + VIR_JOB_UNBOUNDED = 1, /* unknown completion percent */ +} virJobType; + + +/** + * virJobState; + * + * A job may be in one of several states + */ +typedef enum { + VIR_JOB_RUNNING = 0, /* Still active */ + VIR_JOB_COMPLETE = 1, /* Completed successfully */ + VIR_JOB_FAILED = 2, /* Failed to complete see virJobGetError */ + VIR_JOB_CANCELLED = 3, /* User requested cancellation */ +} virJobState; + +/** + * virJobInfoPtr: + * + * a virJobInfo is a structure filled by virJobGetInfo() and extracting + * runtime informations for a given active Job + */ + +typedef struct _virJobInfo virJobInfo; + +struct _virJobInfo { + int type; /* One of virJobType constants */ + int state; /* One of virJobState constants */ + unsigned int runningTime; /* Actual running time in seconds */ + unsigned int remainingTime;/* Estimated remaining time in seconds */ + int percentComplete; /* Completion progress 0 -> 100, if VIR_JOB_BOUNDED */ +}; + +/** + * virJobInfoPtr: + * + * a virJobInfoPtr is a pointer to a virJobInfo structure. + */ + +typedef virJobInfo *virJobInfoPtr; + + /* * Gather list of running domains */ @@ -447,6 +503,11 @@ int virDomainDestroy (virDomainPtr dom int virDomainDestroy (virDomainPtr domain); int virDomainFree (virDomainPtr domain); + +int virDomainGetJobInfo (virDomainPtr dom, + virJobInfoPtr info); +int virDomainCancelJob (virDomainPtr dom); + /* * Domain suspend/resume */ @@ -458,8 +519,14 @@ int virDomainResume (virDomainPtr dom */ int virDomainSave (virDomainPtr domain, const char *to); +int virDomainSaveFlags (virDomainPtr domain, + const char *to, + unsigned int flags); int virDomainRestore (virConnectPtr conn, const char *from); +int virDomainRestoreFlags (virConnectPtr conn, + const char *from, + unsigned int flags); /* * Domain core dump @@ -535,6 +602,8 @@ int virConnectListDefinedDomains (virC char **const names, int maxnames); int virDomainCreate (virDomainPtr domain); +int virDomainCreateFlags (virDomainPtr domain, + unsigned int flags); int virDomainGetAutostart (virDomainPtr domain, int *autostart); @@ -897,6 +966,11 @@ int virStoragePoolRefresh (virStorage int virStoragePoolRefresh (virStoragePoolPtr pool, unsigned int flags); +int virStoragePoolGetJobInfo (virStoragePoolPtr pool, + virJobInfoPtr info); +int virStoragePoolCancelJob (virStoragePoolPtr pool); + + /* * StoragePool information */ @@ -955,6 +1029,10 @@ char * virStorageVolGetXMLDesc (virSt char * virStorageVolGetPath (virStorageVolPtr vol); +int virStorageVolGetJobInfo (virStoragePoolPtr pool, + virJobInfoPtr info); +int virStorageVolCancelJob (virStoragePoolPtr pool); + #ifdef __cplusplus } #endif . -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 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