diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 260505ef47..62044158b4 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 */
+ VIR_DOMAIN_JOB_CANCELLED = 5, /* 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 mill-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;
+};
+
+int virDomainGetJobInfo(virDomainPtr dom,
+ virDomainJobInfoPtr info);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/python/generator.py b/python/generator.py
index 24eaf502d4..f7625fd3b4 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 76a6fd5fce..1260c0cbc6 100644
--- a/python/libvirt-override-api.xml
+++ b/python/libvirt-override-api.xml
@@ -48,6 +48,11 @@
+
+ Extract information about an active job being processed for a domain.
+
+
+
Extract hardware information about the Node.
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 2447ad7052..e27bce6730 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 9ba99de0db..b33822c212 100644
--- a/python/typewrappers.c
+++ b/python/typewrappers.c
@@ -48,6 +48,14 @@ libvirt_longlongWrap(long long val)
return (ret);
}
+PyObject *
+libvirt_ulonglongWrap(unsigned long long val)
+{
+ PyObject *ret;
+ ret = PyLong_FromUnsignedLongLong(val);
+ return (ret);
+}
+
PyObject *
libvirt_charPtrWrap(char *str)
{
diff --git a/python/typewrappers.h b/python/typewrappers.h
index 61f72490be..dadcdd4518 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);