[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 1/9] Introduce public API for domain async job handling



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    |   48 +++++++++++++++++++++++++++++++++++++++
 python/generator.py             |    1 +
 python/libvirt-override-api.xml |    5 ++++
 python/libvirt-override.c       |   37 ++++++++++++++++++++++++++++++
 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 f192fb1..5058bc0 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1756,6 +1756,54 @@ int virConnectCompareCPU(virConnectPtr conn,
                          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 */
+} virDomainJobType;
+
+typedef struct _virDomainJobInfo virDomainJobInfo;
+typedef virDomainJobInfo *virDomainJobInfoPtr;
+struct _virDomainJobInfo {
+    /* One of virDomainJobType */
+    int type;
+
+    /* Only for VIR_DOMAIN_JOB_BOUNDED */
+    int percentComplete;
+
+    /* Time is measured in seconds */
+    unsigned long long timeElapsed;
+    unsigned long long timeRemaining;
+
+    /* 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 4182219..a0a3f58 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 3d8f46c..efd21ef 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 d90a763..037dea1 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -2019,6 +2019,42 @@ libvirt_virConnectListDefinedInterfaces(PyObject *self ATTRIBUTE_UNUSED,
     return(py_retval);
 }
 
+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(13);
+    PyList_SetItem(py_retval, 0, libvirt_intWrap((int) info.type));
+    PyList_SetItem(py_retval, 1, libvirt_intWrap(info.percentComplete));
+    PyList_SetItem(py_retval, 2, libvirt_ulonglongWrap(info.timeElapsed));
+    PyList_SetItem(py_retval, 3, libvirt_ulonglongWrap(info.timeRemaining));
+    PyList_SetItem(py_retval, 4, libvirt_ulonglongWrap(info.dataTotal));
+    PyList_SetItem(py_retval, 5, libvirt_ulonglongWrap(info.dataProcessed));
+    PyList_SetItem(py_retval, 6, libvirt_ulonglongWrap(info.dataRemaining));
+    PyList_SetItem(py_retval, 7, libvirt_ulonglongWrap(info.memTotal));
+    PyList_SetItem(py_retval, 8, libvirt_ulonglongWrap(info.memProcessed));
+    PyList_SetItem(py_retval, 9, libvirt_ulonglongWrap(info.memRemaining));
+    PyList_SetItem(py_retval, 10, libvirt_ulonglongWrap(info.fileTotal));
+    PyList_SetItem(py_retval, 11, libvirt_ulonglongWrap(info.fileProcessed));
+    PyList_SetItem(py_retval, 12, libvirt_ulonglongWrap(info.fileRemaining));
+
+    return(py_retval);
+}
+
+
 /*******************************************
  * Helper functions to avoid importing modules
  * for every callback
@@ -2734,6 +2770,7 @@ static PyMethodDef libvirtMethods[] = {
     {(char *) "virSecretSetValue", libvirt_virSecretSetValue, METH_VARARGS, NULL},
     {(char *) "virConnectListInterfaces", libvirt_virConnectListInterfaces, METH_VARARGS, NULL},
     {(char *) "virConnectListDefinedInterfaces", libvirt_virConnectListDefinedInterfaces, 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);
-- 
1.6.6


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]