diff --git a/src/libxl/libxl_domain.c b/src/libxl/libxl_domain.c index c86dbbd8ec..5b01db8198 100644 --- a/src/libxl/libxl_domain.c +++ b/src/libxl/libxl_domain.c @@ -74,6 +74,9 @@ libxlDomainObjInitJob(libxlDomainObjPrivatePtr priv) if (virCondInit(&priv->job.cond) < 0) return -1; + if (VIR_ALLOC(priv->job.current) < 0) + return -1; + return 0; } @@ -90,6 +93,7 @@ static void libxlDomainObjFreeJob(libxlDomainObjPrivatePtr priv) { ignore_value(virCondDestroy(&priv->job.cond)); + VIR_FREE(priv->job.current); } /* Give up waiting for mutex after 30 seconds */ @@ -131,6 +135,8 @@ libxlDomainObjBeginJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED, VIR_DEBUG("Starting job: %s", libxlDomainJobTypeToString(job)); priv->job.active = job; priv->job.owner = virThreadSelfID(); + priv->job.started = now; + priv->job.current->type = VIR_DOMAIN_JOB_UNBOUNDED; return 0; @@ -179,6 +185,27 @@ libxlDomainObjEndJob(libxlDriverPrivatePtr driver ATTRIBUTE_UNUSED, return virObjectUnref(obj); } +int +libxlDomainJobUpdateTime(struct libxlDomainJobObj *job) +{ + virDomainJobInfoPtr jobInfo = job->current; + unsigned long long now; + + if (!job->started) + return 0; + + if (virTimeMillisNow(&now) < 0) + return -1; + + if (now < job->started) { + job->started = 0; + return 0; + } + + jobInfo->timeElapsed = now - job->started; + return 0; +} + static void * libxlDomainObjPrivateAlloc(void) { diff --git a/src/libxl/libxl_domain.h b/src/libxl/libxl_domain.h index 44b3e0bc41..1c1eba3800 100644 --- a/src/libxl/libxl_domain.h +++ b/src/libxl/libxl_domain.h @@ -53,6 +53,8 @@ struct libxlDomainJobObj { virCond cond; /* Use to coordinate jobs */ enum libxlDomainJob active; /* Currently running job */ int owner; /* Thread which set current job */ + unsigned long long started; /* When the job started */ + virDomainJobInfoPtr current; /* Statistics for the current job */ }; typedef struct _libxlDomainObjPrivate libxlDomainObjPrivate; @@ -88,6 +90,10 @@ libxlDomainObjEndJob(libxlDriverPrivatePtr driver, virDomainObjPtr obj) ATTRIBUTE_RETURN_CHECK; +int +libxlDomainJobUpdateTime(struct libxlDomainJobObj *job) + ATTRIBUTE_RETURN_CHECK; + void libxlDomainEventQueue(libxlDriverPrivatePtr driver, virObjectEventPtr event); diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index a42647a5ef..67fc60cd52 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -4840,6 +4840,44 @@ libxlDomainMemoryStats(virDomainPtr dom, #undef LIBXL_SET_MEMSTAT +static int +libxlDomainGetJobInfo(virDomainPtr dom, + virDomainJobInfoPtr info) +{ + libxlDomainObjPrivatePtr priv; + virDomainObjPtr vm; + int ret = -1; + + if (!(vm = libxlDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainGetJobInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + priv = vm->privateData; + if (!priv->job.active) { + memset(info, 0, sizeof(*info)); + info->type = VIR_DOMAIN_JOB_NONE; + ret = 0; + goto cleanup; + } + + /* In libxl we don't have an estimated completion time + * thus we always set to unbounded and update time + * for the active job. */ + if (libxlDomainJobUpdateTime(&priv->job) < 0) + goto cleanup; + + memcpy(info, priv->job.current, sizeof(virDomainJobInfo)); + ret = 0; + + cleanup: + if (vm) + virObjectUnlock(vm); + return ret; +} + + static int libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID, virConnectDomainEventGenericCallback callback, @@ -5433,6 +5471,7 @@ static virHypervisorDriver libxlHypervisorDriver = { #endif .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */ .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */ + .domainGetJobInfo = libxlDomainGetJobInfo, /* 1.3.1 */ .domainMemoryStats = libxlDomainMemoryStats, /* 1.3.0 */ .domainGetCPUStats = libxlDomainGetCPUStats, /* 1.3.0 */ .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */