diff --git a/src/vz/vz_driver.c b/src/vz/vz_driver.c index 343145510ab62aafb47c9c7e335aedcf21af0797..5f8e0c0ad54e8e41bf45affbcfbd998b9005d701 100644 --- a/src/vz/vz_driver.c +++ b/src/vz/vz_driver.c @@ -2545,6 +2545,7 @@ vzDomainMigratePerformStep(virDomainPtr domain, { int ret = -1; virDomainObjPtr dom = NULL; + vzDomObjPtr privdom; virURIPtr vzuri = NULL; vzConnPtr privconn = domain->conn->privateData; const char *miguri = NULL; @@ -2579,6 +2580,8 @@ vzDomainMigratePerformStep(virDomainPtr domain, if (vzDomainObjBeginJob(dom) < 0) goto cleanup; job = true; + privdom = dom->privateData; + privdom->job.hasProgress = true; if (vzEnsureDomainExists(dom) < 0) goto cleanup; @@ -2784,6 +2787,44 @@ vzDomainMigrateConfirm3Params(virDomainPtr domain ATTRIBUTE_UNUSED, return 0; } +static int +vzDomainGetJobInfoImpl(virDomainObjPtr dom, virDomainJobInfoPtr info) +{ + vzDomObjPtr privdom = dom->privateData; + vzDomainJobObjPtr job = &privdom->job; + + memset(info, 0, sizeof(*info)); + + if (!job->active || !job->hasProgress) + return 0; + + if (vzDomainJobUpdateTime(job) < 0) + return -1; + + info->type = VIR_DOMAIN_JOB_UNBOUNDED; + info->dataTotal = 100; + info->dataProcessed = job->progress; + info->dataRemaining = 100 - job->progress; + info->timeElapsed = job->elapsed; + + return 0; +} + +static int +vzDomainGetJobInfo(virDomainPtr domain, virDomainJobInfoPtr info) +{ + virDomainObjPtr dom; + int ret; + + if (!(dom = vzDomObjFromDomain(domain))) + return -1; + + ret = vzDomainGetJobInfoImpl(dom, info); + + virObjectUnlock(dom); + return ret; +} + static virHypervisorDriver vzHypervisorDriver = { .name = "vz", .connectOpen = vzConnectOpen, /* 0.10.0 */ @@ -2875,6 +2916,7 @@ static virHypervisorDriver vzHypervisorDriver = { .domainMigrateFinish3Params = vzDomainMigrateFinish3Params, /* 1.3.5 */ .domainMigrateConfirm3Params = vzDomainMigrateConfirm3Params, /* 1.3.5 */ .domainUpdateDeviceFlags = vzDomainUpdateDeviceFlags, /* 2.0.0 */ + .domainGetJobInfo = vzDomainGetJobInfo, /* 2.2.0 */ }; static virConnectDriver vzConnectDriver = { diff --git a/src/vz/vz_sdk.c b/src/vz/vz_sdk.c index 38254c05e2df1d91e0d62825cf66338bbb629b4d..f81b32007ba1db7651d56fad8ab2a949766e7275 100644 --- a/src/vz/vz_sdk.c +++ b/src/vz/vz_sdk.c @@ -2140,6 +2140,34 @@ prlsdkHandlePerfEvent(vzDriverPtr driver, virObjectUnlock(dom); } +static void +prlsdkHandleMigrationProgress(vzDriverPtr driver, + PRL_HANDLE event, + unsigned char *uuid) +{ + virDomainObjPtr dom = NULL; + vzDomObjPtr privdom = NULL; + PRL_UINT32 progress; + PRL_HANDLE param = PRL_INVALID_HANDLE; + PRL_RESULT pret; + + if (!(dom = virDomainObjListFindByUUID(driver->domains, uuid))) + return; + + pret = PrlEvent_GetParam(event, 0, ¶m); + prlsdkCheckRetGoto(pret, cleanup); + + pret = PrlEvtPrm_ToUint32(param, &progress); + prlsdkCheckRetGoto(pret, cleanup); + + privdom = dom->privateData; + privdom->job.progress = progress; + + cleanup: + PrlHandle_Free(param); + virObjectUnlock(dom); +} + static PRL_RESULT prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque) { @@ -2195,6 +2223,9 @@ prlsdkEventsHandler(PRL_HANDLE prlEvent, PRL_VOID_PTR opaque) case PET_DSP_EVT_DISP_CONNECTION_CLOSED: vzDestroyDriverConnection(); break; + case PET_DSP_EVT_VM_MIGRATE_PROGRESS_CHANGED: + prlsdkHandleMigrationProgress(driver, prlEvent, uuid); + break; default: VIR_DEBUG("Skipping event of type %d", prlEventType); } diff --git a/src/vz/vz_utils.c b/src/vz/vz_utils.c index 3aea7a55bd6ee8719e5ac1f6c9b20cfed6496ad5..312355d9b64ea936115bcb303078d718ffb91e71 100644 --- a/src/vz/vz_utils.c +++ b/src/vz/vz_utils.c @@ -588,7 +588,7 @@ vzDomObjAlloc(void) if (VIR_ALLOC(pdom) < 0) return NULL; - if (virCondInit(&pdom->jobCond) < 0) + if (virCondInit(&pdom->job.cond) < 0) goto error; pdom->stats = PRL_INVALID_HANDLE; @@ -611,7 +611,7 @@ vzDomObjFree(void* p) PrlHandle_Free(pdom->sdkdom); PrlHandle_Free(pdom->stats); - virCondDestroy(&pdom->jobCond); + virCondDestroy(&pdom->job.cond); VIR_FREE(pdom); }; @@ -628,12 +628,19 @@ vzDomainObjBeginJob(virDomainObjPtr dom) return -1; then = now + VZ_JOB_WAIT_TIME; - while (pdom->job) { - if (virCondWaitUntil(&pdom->jobCond, &dom->parent.lock, then) < 0) + while (pdom->job.active) { + if (virCondWaitUntil(&pdom->job.cond, &dom->parent.lock, then) < 0) goto error; } - pdom->job = true; + if (virTimeMillisNow(&now) < 0) + return -1; + + pdom->job.active = true; + pdom->job.started = now; + pdom->job.elapsed = 0; + pdom->job.progress = 0; + pdom->job.hasProgress = false; return 0; error: @@ -651,6 +658,27 @@ vzDomainObjEndJob(virDomainObjPtr dom) { vzDomObjPtr pdom = dom->privateData; - pdom->job = false; - virCondSignal(&pdom->jobCond); + pdom->job.active = false; + virCondSignal(&pdom->job.cond); +} + +int +vzDomainJobUpdateTime(vzDomainJobObjPtr job) +{ + unsigned long long now; + + if (!job->started) + return 0; + + if (virTimeMillisNow(&now) < 0) + return -1; + + if (now < job->started) { + VIR_WARN("Async job starts in the future"); + job->started = 0; + return 0; + } + + job->elapsed = now - job->started; + return 0; } diff --git a/src/vz/vz_utils.h b/src/vz/vz_utils.h index 3f6b62011f68de830ecadbc3ea9312b2bd7f3d5b..d033f943a2f3d8eacdae2f5efe34fa8523651b62 100644 --- a/src/vz/vz_utils.h +++ b/src/vz/vz_utils.h @@ -93,13 +93,24 @@ struct _vzConn { typedef struct _vzConn vzConn; typedef struct _vzConn *vzConnPtr; +struct _vzDomainJobObj { + virCond cond; + bool active; + /* when the job started, zeroed on time discontinuities */ + unsigned long long started; + unsigned long long elapsed; + bool hasProgress; + int progress; /* percents */ +}; + +typedef struct _vzDomainJobObj vzDomainJobObj; +typedef struct _vzDomainJobObj *vzDomainJobObjPtr; struct vzDomObj { int id; PRL_HANDLE sdkdom; PRL_HANDLE stats; - bool job; - virCond jobCond; + vzDomainJobObj job; }; typedef struct vzDomObj *vzDomObjPtr; @@ -146,3 +157,5 @@ int vzDomainObjBeginJob(virDomainObjPtr dom); void vzDomainObjEndJob(virDomainObjPtr dom); +int +vzDomainJobUpdateTime(vzDomainJobObjPtr job);