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 -=|