From 7d575e09e258098e689445901480915052a548c1 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Wed, 3 Feb 2010 11:31:45 +0000 Subject: [PATCH] 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 | 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(+) 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);