On Thu, Feb 18, 2010 at 03:56:07PM +0000, Daniel P. Berrange wrote: > Introduce a new public API that provides a way to get progress > info on currently running jobs on a virDomainpPtr. APIs that > are initially within scope of this idea are > > virDomainMigrate > virDomainMigrateToURI > virDomainSave > virDomainRestore > virDomainCoreDump > > These all take a potentially long time and benefit from monitoring. > The virDomainJobInfo struct allows for various pieces of information > to be reported > > - Percentage completion > - Time > - Overall data > - Guest memory data > - Guest disk/file data > > * include/libvirt/libvirt.h.in: Add virDomainGetJobInfo > * python/generator.py, python/libvirt-override-api.xml, > python/libvirt-override.c: Override for virDomainGetJobInfo API > * python/typewrappers.c, python/typewrappers.h: Introduce wrapper > for unsigned long long type > --- > include/libvirt/libvirt.h.in | 49 +++++++++++++++++++++++++++++++++++++++ > python/generator.py | 1 + > python/libvirt-override-api.xml | 5 ++++ > python/libvirt-override.c | 36 ++++++++++++++++++++++++++++ > python/typewrappers.c | 8 ++++++ > python/typewrappers.h | 1 + > 6 files changed, 100 insertions(+), 0 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index 260505e..51c0844 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -1787,6 +1787,55 @@ char *virConnectBaselineCPU(virConnectPtr conn, > unsigned int ncpus, > unsigned int flags); > > +typedef enum { > + VIR_DOMAIN_JOB_NONE = 0, /* No job is active */ > + VIR_DOMAIN_JOB_BOUNDED = 1, /* Job with a finite completion time */ > + VIR_DOMAIN_JOB_UNBOUNDED = 2, /* Job without a finite completion time */ > + VIR_DOMAIN_JOB_COMPLETED = 3, /* Job has finished, but isn't cleaned up */ > + VIR_DOMAIN_JOB_FAILED = 4, /* Job hit error, but isn't cleaned up */ 5 disapeared ? > + VIR_DOMAIN_JOB_CANCELLED = 6, /* Job was aborted, but isn't cleaned up */ > +} virDomainJobType; > + > +typedef struct _virDomainJobInfo virDomainJobInfo; > +typedef virDomainJobInfo *virDomainJobInfoPtr; > +struct _virDomainJobInfo { > + /* One of virDomainJobType */ > + int type; > + > + /* Time is measured in seconds */ > + unsigned long long timeElapsed; /* Always set */ > + unsigned long long timeRemaining; /* Only for VIR_DOMAIN_JOB_BOUNDED */ > + > + /* Data is measured in bytes unless otherwise specified > + * and is measuring the job as a whole > + * > + * For VIR_DOMAIN_JOB_UNBOUNDED, dataTotal may be less > + * than the final sum of dataProcessed + dataRemaining > + * in the event that the hypervisor has to repeat some > + * data eg due to dirtied pages during migration > + * > + * For VIR_DOMAIN_JOB_BOUNDED, dataTotal shall always > + * equal sum of dataProcessed + dataRemaining > + */ > + unsigned long long dataTotal; > + unsigned long long dataProcessed; > + unsigned long long dataRemaining; > + > + /* As above, but only tracking guest memory progress */ > + unsigned long long memTotal; > + unsigned long long memProcessed; > + unsigned long long memRemaining; > + > + /* As above, but only tracking guest disk file progress */ > + unsigned long long fileTotal; > + unsigned long long fileProcessed; > + unsigned long long fileRemaining; > +}; I wonder if we should not somehow provide an unit for the items being measured. Maybe we don't want bytes in the future > +int virDomainGetJobInfo(virDomainPtr dom, > + virDomainJobInfoPtr info); > + > + > #ifdef __cplusplus > } > #endif > diff --git a/python/generator.py b/python/generator.py > index 24eaf50..f7625fd 100755 > --- a/python/generator.py > +++ b/python/generator.py > @@ -271,6 +271,7 @@ skip_impl = ( > 'virConnGetLastError', > 'virGetLastError', > 'virDomainGetInfo', > + 'virDomainGetJobInfo', > 'virNodeGetInfo', > 'virDomainGetUUID', > 'virDomainGetUUIDString', > diff --git a/python/libvirt-override-api.xml b/python/libvirt-override-api.xml > index 76a6fd5..1260c0c 100644 > --- a/python/libvirt-override-api.xml > +++ b/python/libvirt-override-api.xml > @@ -48,6 +48,11 @@ > <return type='int *' info='the list of information or None in case of error'/> > <arg name='domain' type='virDomainPtr' info='a domain object'/> > </function> > + <function name='virDomainGetJobInfo' file='python'> > + <info>Extract information about an active job being processed for a domain.</info> > + <return type='int *' info='the list of information or None in case of error'/> > + <arg name='domain' type='virDomainPtr' info='a domain object'/> > + </function> > <function name='virNodeGetInfo' file='python'> > <info>Extract hardware information about the Node.</info> > <return type='int *' info='the list of information or None in case of error'/> > diff --git a/python/libvirt-override.c b/python/libvirt-override.c > index 2447ad7..e27bce6 100644 > --- a/python/libvirt-override.c > +++ b/python/libvirt-override.c > @@ -2072,6 +2072,41 @@ libvirt_virConnectBaselineCPU(PyObject *self ATTRIBUTE_UNUSED, > } > > > +static PyObject * > +libvirt_virDomainGetJobInfo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) { > + PyObject *py_retval; > + int c_retval; > + virDomainPtr domain; > + PyObject *pyobj_domain; > + virDomainJobInfo info; > + > + if (!PyArg_ParseTuple(args, (char *)"O:virDomainGetJobInfo", &pyobj_domain)) > + return(NULL); > + domain = (virDomainPtr) PyvirDomain_Get(pyobj_domain); > + > + LIBVIRT_BEGIN_ALLOW_THREADS; > + c_retval = virDomainGetJobInfo(domain, &info); > + LIBVIRT_END_ALLOW_THREADS; > + if (c_retval < 0) > + return VIR_PY_NONE; > + py_retval = PyList_New(12); > + PyList_SetItem(py_retval, 0, libvirt_intWrap((int) info.type)); > + PyList_SetItem(py_retval, 1, libvirt_ulonglongWrap(info.timeElapsed)); > + PyList_SetItem(py_retval, 2, libvirt_ulonglongWrap(info.timeRemaining)); > + PyList_SetItem(py_retval, 3, libvirt_ulonglongWrap(info.dataTotal)); > + PyList_SetItem(py_retval, 4, libvirt_ulonglongWrap(info.dataProcessed)); > + PyList_SetItem(py_retval, 5, libvirt_ulonglongWrap(info.dataRemaining)); > + PyList_SetItem(py_retval, 6, libvirt_ulonglongWrap(info.memTotal)); > + PyList_SetItem(py_retval, 7, libvirt_ulonglongWrap(info.memProcessed)); > + PyList_SetItem(py_retval, 8, libvirt_ulonglongWrap(info.memRemaining)); > + PyList_SetItem(py_retval, 9, libvirt_ulonglongWrap(info.fileTotal)); > + PyList_SetItem(py_retval, 10, libvirt_ulonglongWrap(info.fileProcessed)); > + PyList_SetItem(py_retval, 11, libvirt_ulonglongWrap(info.fileRemaining)); > + > + return(py_retval); > +} > + > + > /******************************************* > * Helper functions to avoid importing modules > * for every callback > @@ -2788,6 +2823,7 @@ static PyMethodDef libvirtMethods[] = { > {(char *) "virConnectListInterfaces", libvirt_virConnectListInterfaces, METH_VARARGS, NULL}, > {(char *) "virConnectListDefinedInterfaces", libvirt_virConnectListDefinedInterfaces, METH_VARARGS, NULL}, > {(char *) "virConnectBaselineCPU", libvirt_virConnectBaselineCPU, METH_VARARGS, NULL}, > + {(char *) "virDomainGetJobInfo", libvirt_virDomainGetJobInfo, METH_VARARGS, NULL}, > {NULL, NULL, 0, NULL} > }; > > diff --git a/python/typewrappers.c b/python/typewrappers.c > index 9ba99de..b33822c 100644 > --- a/python/typewrappers.c > +++ b/python/typewrappers.c > @@ -49,6 +49,14 @@ libvirt_longlongWrap(long long val) > } > > PyObject * > +libvirt_ulonglongWrap(unsigned long long val) > +{ > + PyObject *ret; > + ret = PyLong_FromUnsignedLongLong(val); > + return (ret); > +} > + > +PyObject * > libvirt_charPtrWrap(char *str) > { > PyObject *ret; > diff --git a/python/typewrappers.h b/python/typewrappers.h > index 61f7249..dadcdd4 100644 > --- a/python/typewrappers.h > +++ b/python/typewrappers.h > @@ -138,6 +138,7 @@ PyObject * libvirt_intWrap(int val); > PyObject * libvirt_longWrap(long val); > PyObject * libvirt_ulongWrap(unsigned long val); > PyObject * libvirt_longlongWrap(long long val); > +PyObject * libvirt_ulonglongWrap(unsigned long long val); > PyObject * libvirt_charPtrWrap(char *str); > PyObject * libvirt_constcharPtrWrap(const char *str); > PyObject * libvirt_charPtrConstWrap(const char *str); The unit is more a question, I don't see an use right now, but it sounds like it can make the API more flexible if we want to use it for "something else" Basically looks fine ACK, Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list