[PATCH v3 0/5] Implement some job related APIs for test driver

v3: - Fix virDomainGetJobStats when use completed flags - Introduce testDomainSetDummyData - Add and refine some tests Luke Yue (5): test_driver: Implement virDomainGetJobInfo test_driver: Implement virDomainGetJobStats test_driver: Implement virDomainAbortJob test_driver: Introduce testDomainSetDummyData virshtest: add test for domjobinfo and domjobabort src/test/test_driver.c | 274 +++++++++++++++++++++++++++++++++++++++++ tests/virshtest.c | 89 +++++++++++++ 2 files changed, 363 insertions(+) -- 2.32.0

Signed-off-by: Luke Yue <lukedyue@gmail.com> --- src/test/test_driver.c | 89 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index b096d49ac6..ae6422c955 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -380,6 +380,10 @@ struct _testDomainObjPrivate { /* used by get/set time APIs */ long long seconds; unsigned int nseconds; + + /* used by Job Info APIs */ + unsigned int jobState; + unsigned int jobOperation; }; @@ -396,6 +400,9 @@ testDomainObjPrivateAlloc(void *opaque) priv->seconds = 627319920; priv->nseconds = 0; + priv->jobState = VIR_DOMAIN_JOB_NONE; + priv->jobOperation = VIR_DOMAIN_JOB_OPERATION_UNKNOWN; + return priv; } @@ -2674,6 +2681,87 @@ testDomainGetOSType(virDomainPtr dom G_GNUC_UNUSED) return ret; } +static int +testDomainGetJobInfoImpl(virDomainObj *dom, + virDomainJobInfoPtr info) +{ + testDomainObjPrivate *priv = dom->privateData; + + memset(info, 0, sizeof(*info)); + + info->type = priv->jobState; + + switch (priv->jobState) { + case VIR_DOMAIN_JOB_NONE: + break; + + case VIR_DOMAIN_JOB_BOUNDED: + info->dataTotal = 30 * 1024; + info->dataProcessed = 10 * 1024; + info->dataRemaining = 20 * 1024; + info->timeRemaining = 6000; + info->timeElapsed = 4000; + info->memTotal = 3 * 1024 * 1024; + info->memProcessed = 1024 * 1024; + info->memRemaining = 2 * 1024 * 1024; + info->fileTotal = 2 * 1024 * 1024; + info->fileProcessed = 1024 * 1024 / 2; + info->fileRemaining = 3 * 1024 * 1024 / 2; + break; + + case VIR_DOMAIN_JOB_UNBOUNDED: + info->dataTotal = 30 * 1024; + info->dataProcessed = 10 * 1024; + info->dataRemaining = 20 * 1024; + info->timeElapsed = 4000; + info->memTotal = 3 * 1024 * 1024; + info->memProcessed = 1024 * 1024; + info->memRemaining = 2 * 1024 * 1024; + info->fileTotal = 2 * 1024 * 1024; + info->fileProcessed = 1024 * 1024 / 2; + info->fileRemaining = 3 * 1024 * 1024 / 2; + break; + + case VIR_DOMAIN_JOB_COMPLETED: + info->timeElapsed = 10000; + info->dataTotal = 30 * 1024; + info->dataProcessed = 30 * 1024; + info->memTotal = 3 * 1024 * 1024; + info->memProcessed = 3 * 1024 * 1024; + info->fileTotal = 2 * 1024 * 1024; + info->fileProcessed = 2 * 1024 * 1024; + break; + + case VIR_DOMAIN_JOB_FAILED: + break; + + case VIR_DOMAIN_JOB_CANCELLED: + break; + } + + return 0; +} + +static int +testDomainGetJobInfo(virDomainPtr dom, + virDomainJobInfoPtr info) +{ + virDomainObj *vm; + int ret = -1; + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) + goto cleanup; + + ret = testDomainGetJobInfoImpl(vm, info); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + static int testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED, @@ -9576,6 +9664,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainMemoryPeek = testDomainMemoryPeek, /* 5.4.0 */ .domainGetBlockInfo = testDomainGetBlockInfo, /* 5.7.0 */ .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */ + .domainGetJobInfo = testDomainGetJobInfo, /* 7.7.0 */ .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */ .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */ -- 2.32.0

Signed-off-by: Luke Yue <lukedyue@gmail.com> --- src/test/test_driver.c | 135 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 131 insertions(+), 4 deletions(-) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index ae6422c955..9899976966 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -384,6 +384,8 @@ struct _testDomainObjPrivate { /* used by Job Info APIs */ unsigned int jobState; unsigned int jobOperation; + bool hasCompletedJob; + unsigned int jobCompleted; }; @@ -402,6 +404,8 @@ testDomainObjPrivateAlloc(void *opaque) priv->jobState = VIR_DOMAIN_JOB_NONE; priv->jobOperation = VIR_DOMAIN_JOB_OPERATION_UNKNOWN; + priv->hasCompletedJob = true; + priv->jobCompleted = VIR_DOMAIN_JOB_OPERATION_START; return priv; } @@ -2683,15 +2687,24 @@ testDomainGetOSType(virDomainPtr dom G_GNUC_UNUSED) static int testDomainGetJobInfoImpl(virDomainObj *dom, - virDomainJobInfoPtr info) + virDomainJobInfoPtr info, + bool completed) { testDomainObjPrivate *priv = dom->privateData; memset(info, 0, sizeof(*info)); - info->type = priv->jobState; + if (completed) { + if (priv->hasCompletedJob) { + info->type = VIR_DOMAIN_JOB_COMPLETED; + } else { + info->type = VIR_DOMAIN_JOB_NONE; + } + } else { + info->type = priv->jobState; + } - switch (priv->jobState) { + switch (info->type) { case VIR_DOMAIN_JOB_NONE: break; @@ -2755,13 +2768,126 @@ testDomainGetJobInfo(virDomainPtr dom, if (virDomainObjCheckActive(vm) < 0) goto cleanup; - ret = testDomainGetJobInfoImpl(vm, info); + ret = testDomainGetJobInfoImpl(vm, info, false); cleanup: virDomainObjEndAPI(&vm); return ret; } +static int +testDomainJobInfoToParams(testDomainObjPrivate *priv, + virDomainJobInfoPtr info, + int *type, + bool completed, + virTypedParameterPtr *params, + int *nparams) +{ + virTypedParameterPtr par = NULL; + int maxpar = 0; + int npar = 0; + unsigned int operation = VIR_DOMAIN_JOB_OPERATION_UNKNOWN; + + if (completed) { + operation = priv->jobCompleted; + } else { + operation = priv->jobOperation; + } + + if (virTypedParamsAddInt(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_OPERATION, + operation) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_DATA_TOTAL, + info->dataTotal) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_DATA_PROCESSED, + info->dataProcessed) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_DATA_REMAINING, + info->dataRemaining) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_TIME_ELAPSED, + info->timeElapsed) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_TIME_REMAINING, + info->timeRemaining) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_MEMORY_TOTAL, + info->memTotal) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_MEMORY_PROCESSED, + info->memProcessed) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_MEMORY_REMAINING, + info->memRemaining) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_DISK_TOTAL, + info->fileTotal) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_DISK_PROCESSED, + info->fileProcessed) < 0 || + virTypedParamsAddULLong(&par, &npar, &maxpar, + VIR_DOMAIN_JOB_DISK_REMAINING, + info->fileRemaining) < 0) + goto error; + + *type = info->type; + *params = par; + *nparams = npar; + return 0; + + error: + virTypedParamsFree(par, npar); + return -1; +} + +static int +testDomainGetJobStats(virDomainPtr domain, + int *type, + virTypedParameterPtr *params, + int *nparams, + unsigned int flags) +{ + virDomainJobInfo jobInfo; + virDomainObj *dom; + testDomainObjPrivate *priv; + bool completed = flags & VIR_DOMAIN_JOB_STATS_COMPLETED; + int ret = -1; + + virCheckFlags(VIR_DOMAIN_JOB_STATS_COMPLETED | + VIR_DOMAIN_JOB_STATS_KEEP_COMPLETED, -1); + + if (!(dom = testDomObjFromDomain(domain))) + return -1; + + priv = dom->privateData; + + if (testDomainGetJobInfoImpl(dom, &jobInfo, completed) < 0) + goto cleanup; + + if (jobInfo.type == VIR_DOMAIN_JOB_NONE) { + *type = VIR_DOMAIN_JOB_NONE; + *params = NULL; + *nparams = 0; + ret = 0; + goto cleanup; + } + + ret = testDomainJobInfoToParams(priv, &jobInfo, type, + completed, params, nparams); + + if (completed && ret == 0 && + !(flags & VIR_DOMAIN_JOB_STATS_KEEP_COMPLETED)) { + priv->hasCompletedJob = false; + priv->jobCompleted = VIR_DOMAIN_JOB_OPERATION_UNKNOWN; + } + + cleanup: + virDomainObjEndAPI(&dom); + + return ret; +} static int testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED, @@ -9665,6 +9791,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainGetBlockInfo = testDomainGetBlockInfo, /* 5.7.0 */ .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */ .domainGetJobInfo = testDomainGetJobInfo, /* 7.7.0 */ + .domainGetJobStats = testDomainGetJobStats, /* 7.7.0 */ .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */ .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */ -- 2.32.0

As we are using jobState to store dummy job type, so just change it to VIR_DOMAIN_JOB_CANCELLED when try to abort a job. Signed-off-by: Luke Yue <lukedyue@gmail.com> --- src/test/test_driver.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 9899976966..35350edda9 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -2889,6 +2889,34 @@ testDomainGetJobStats(virDomainPtr domain, return ret; } +static int +testDomainAbortJob(virDomainPtr dom) +{ + virDomainObj *vm; + int ret = -1; + testDomainObjPrivate *priv; + + if (!(vm = testDomObjFromDomain(dom))) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) + goto cleanup; + + priv = vm->privateData; + + if (priv->jobState == VIR_DOMAIN_JOB_NONE) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("no job is active on the domain")); + } else { + priv->jobState = VIR_DOMAIN_JOB_CANCELLED; + ret = 0; + } + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + static int testDomainGetLaunchSecurityInfo(virDomainPtr domain G_GNUC_UNUSED, virTypedParameterPtr *params G_GNUC_UNUSED, @@ -9792,6 +9820,7 @@ static virHypervisorDriver testHypervisorDriver = { .domainSetLifecycleAction = testDomainSetLifecycleAction, /* 5.7.0 */ .domainGetJobInfo = testDomainGetJobInfo, /* 7.7.0 */ .domainGetJobStats = testDomainGetJobStats, /* 7.7.0 */ + .domainAbortJob = testDomainAbortJob, /* 7.7.0 */ .domainSnapshotNum = testDomainSnapshotNum, /* 1.1.4 */ .domainSnapshotListNames = testDomainSnapshotListNames, /* 1.1.4 */ -- 2.32.0

We can't adjust all info of a domain in XML and it's hard to adjust some with current API coverage, so use this function to set some dummy data to specific domains, thus we can get different results in virsh tests. Currently, only domain fc5's priv->jobState and priv->jobOperation are being changed, in order to test virDomainGetJobInfo and virDomainGetJobStats (domjobinfo in virsh). Signed-off-by: Luke Yue <lukedyue@gmail.com> --- src/test/test_driver.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 35350edda9..372de8ba53 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -663,6 +663,32 @@ testDomObjFromDomain(virDomainPtr domain) return vm; } +/** + * We can't adjust all info of a domain in XML and it's hard to + * adjust some with current API coverage, so use this function to + * set some dummy data to specific domains, thus we can get different + * results in virshtest. + */ +static int +testDomainSetDummyData(virDomainObj *obj) +{ + virDomainDef *def; + testDomainObjPrivate *priv; + + priv = obj->privateData; + + if (!(def = virDomainObjGetOneDef(obj, VIR_DOMAIN_AFFECT_LIVE))) + return -1; + + if (STREQ(def->name, "fc5")) { + /* For testing domjobinfo */ + priv->jobState = VIR_DOMAIN_JOB_BOUNDED; + priv->jobOperation = VIR_DOMAIN_JOB_OPERATION_BACKUP; + } + + return 0; +} + static char * testDomainGenerateIfname(virDomainDef *domdef) { @@ -1055,6 +1081,9 @@ testParseDomains(testDriver *privconn, testDomainObjCheckTaint(obj); + if (testDomainSetDummyData(obj) < 0) + VIR_DEBUG("Failed to set dummy data"); + virDomainObjEndAPI(&obj); } -- 2.32.0

In testCompareDomJobInfoByName, we should get different jobinfo for fc4 and fc5, as we set different jobinfo value for fc5 in testDomainSetDummyData. And when use "--completed --keep-completed" flags, the completed job info should be preserved, with only "--completed" flag, the completed job info should be deleted, so should get none next time. In testCompareDomJobAbortByName, domjobabort should set type to cancelled and preserve the operation. Signed-off-by: Luke Yue <lukedyue@gmail.com> --- tests/virshtest.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/tests/virshtest.c b/tests/virshtest.c index 751e8ffc49..4e2efcb69a 100644 --- a/tests/virshtest.c +++ b/tests/virshtest.c @@ -291,6 +291,87 @@ static int testCompareDomControlInfoByName(const void *data G_GNUC_UNUSED) return testCompareOutputLit(exp, NULL, argv); } +static int testCompareDomJobInfoByName(const void *data G_GNUC_UNUSED) +{ + const char *const argv[] = { VIRSH_CUSTOM, "domjobinfo fc4;\ + domjobinfo fc5;\ + domjobinfo fc5 --completed --keep-completed;\ + domjobinfo fc5 --completed;\ + domjobinfo fc5 --completed", NULL }; + const char *exp = "\ +Job type: None \n\ +\n\ +Job type: Bounded \n\ +Operation: Backup \n\ +Time elapsed: 4000 ms\n\ +Time remaining: 6000 ms\n\ +Data processed: 10.000 KiB\n\ +Data remaining: 20.000 KiB\n\ +Data total: 30.000 KiB\n\ +Memory processed: 1.000 MiB\n\ +Memory remaining: 2.000 MiB\n\ +Memory total: 3.000 MiB\n\ +File processed: 512.000 KiB\n\ +File remaining: 1.500 MiB\n\ +File total: 2.000 MiB\n\ +\n\ +Job type: Completed \n\ +Operation: Start \n\ +Time elapsed: 10000 ms\n\ +Data processed: 30.000 KiB\n\ +Data remaining: 0.000 B\n\ +Data total: 30.000 KiB\n\ +Memory processed: 3.000 MiB\n\ +Memory remaining: 0.000 B\n\ +Memory total: 3.000 MiB\n\ +File processed: 2.000 MiB\n\ +File remaining: 0.000 B\n\ +File total: 2.000 MiB\n\ +\n\ +Job type: Completed \n\ +Operation: Start \n\ +Time elapsed: 10000 ms\n\ +Data processed: 30.000 KiB\n\ +Data remaining: 0.000 B\n\ +Data total: 30.000 KiB\n\ +Memory processed: 3.000 MiB\n\ +Memory remaining: 0.000 B\n\ +Memory total: 3.000 MiB\n\ +File processed: 2.000 MiB\n\ +File remaining: 0.000 B\n\ +File total: 2.000 MiB\n\ +\n\ +Job type: None \n\ +\n"; + return testCompareOutputLit(exp, NULL, argv); +} + +static int testCompareDomJobAbortByName(const void *data G_GNUC_UNUSED) +{ + const char *const argv[] = { VIRSH_CUSTOM, "domjobinfo fc5;\ + domjobabort fc5; domjobinfo fc5", NULL }; + const char *exp = "\ +Job type: Bounded \n\ +Operation: Backup \n\ +Time elapsed: 4000 ms\n\ +Time remaining: 6000 ms\n\ +Data processed: 10.000 KiB\n\ +Data remaining: 20.000 KiB\n\ +Data total: 30.000 KiB\n\ +Memory processed: 1.000 MiB\n\ +Memory remaining: 2.000 MiB\n\ +Memory total: 3.000 MiB\n\ +File processed: 512.000 KiB\n\ +File remaining: 1.500 MiB\n\ +File total: 2.000 MiB\n\ +\n\ +\n\ +Job type: Cancelled \n\ +Operation: Backup \n\ +\n"; + return testCompareOutputLit(exp, NULL, argv); +} + struct testInfo { const char *const *argv; const char *result; @@ -383,6 +464,14 @@ mymain(void) testCompareDomControlInfoByName, NULL) != 0) ret = -1; + if (virTestRun("virsh domjobinfo (by name)", + testCompareDomJobInfoByName, NULL) != 0) + ret = -1; + + if (virTestRun("virsh domjobabort (by name)", + testCompareDomJobAbortByName, NULL) != 0) + ret = -1; + /* It's a bit awkward listing result before argument, but that's a * limitation of C99 vararg macros. */ # define DO_TEST(i, result, ...) \ -- 2.32.0

On Wed, 2021-08-18 at 22:17 +0800, Luke Yue wrote:
v3: - Fix virDomainGetJobStats when use completed flags - Introduce testDomainSetDummyData - Add and refine some tests
Luke Yue (5): test_driver: Implement virDomainGetJobInfo test_driver: Implement virDomainGetJobStats test_driver: Implement virDomainAbortJob test_driver: Introduce testDomainSetDummyData virshtest: add test for domjobinfo and domjobabort
src/test/test_driver.c | 274 +++++++++++++++++++++++++++++++++++++++++ tests/virshtest.c | 89 +++++++++++++ 2 files changed, 363 insertions(+)
polite ping
participants (1)
-
Luke Yue