[Libvir] RFC: Updated async job public API

Daniel P. Berrange berrange at redhat.com
Wed Feb 20 19:33:42 UTC 2008


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




More information about the libvir-list mailing list