From nobody Fri Dec 19 17:40:28 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1561391887; cv=none; d=zoho.com; s=zohoarc; b=A+qCG/yEZH8x4GWEVdC7kh+2yz1B2FcqY2qC1OduSgsNQ4KZmWKMWgFtI9sU5ko93teAZ4IAOvI6IU4lBm8UvKsDIUPFZ8MhRcj9WPBVXVPngLSAz0CKE2/fgMiQF+G7jTuqB0uSR4szBQbR7esuvR1YbzFHUKSaGd/VYvTZ60k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1561391887; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=3sV8vOgUbI3B12ieZgXhimktz4PXAinyJQOPHJOCT3g=; b=ILoH+Gche0yemmHoxOFN3I9guiKLxGpeShB4mOjA7aXjyjsR1jHtI9Q7XcR6YVnCDfhCA2ii+/jJ5p7pePMD9+33ldswj5Ka45s4Gpw6ZDd5+Gsh67IeNB2PlPcUn1VuS0rcv4LhS608otnO+ezoGMSM5EtuxMOelsJeu6D8lnE= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1561391887348461.73927688674394; Mon, 24 Jun 2019 08:58:07 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B08663688B; Mon, 24 Jun 2019 15:58:05 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 87A9B1001B07; Mon, 24 Jun 2019 15:58:05 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 45D2A206D2; Mon, 24 Jun 2019 15:58:05 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x5OFt5Kf014642 for ; Mon, 24 Jun 2019 11:55:05 -0400 Received: by smtp.corp.redhat.com (Postfix) id 797D81001B05; Mon, 24 Jun 2019 15:55:05 +0000 (UTC) Received: from angien.brq.redhat.com (unknown [10.43.2.229]) by smtp.corp.redhat.com (Postfix) with ESMTP id 034261001B04 for ; Mon, 24 Jun 2019 15:55:04 +0000 (UTC) From: Peter Krempa To: libvir-list@redhat.com Date: Mon, 24 Jun 2019 17:54:54 +0200 Message-Id: <5bbac8937df2711e643f0970738441789b3bac94.1561391499.git.pkrempa@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 7/9] qemu: monitor: Add infrastructure for 'query-jobs' X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 24 Jun 2019 15:58:06 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Signed-off-by: Peter Krempa Reviewed-by: J=C3=A1n Tomko --- src/qemu/qemu_monitor.c | 23 +++++ src/qemu/qemu_monitor.h | 49 +++++++++++ src/qemu/qemu_monitor_json.c | 79 +++++++++++++++++ src/qemu/qemu_monitor_json.h | 6 ++ .../query-jobs-create.json | 20 +++++ .../query-jobs-create.result | 11 +++ .../qemumonitorjsondata/query-jobs-empty.json | 1 + .../query-jobs-empty.result | 0 tests/qemumonitorjsontest.c | 85 +++++++++++++++++++ 9 files changed, 274 insertions(+) create mode 100644 tests/qemumonitorjsondata/query-jobs-create.json create mode 100644 tests/qemumonitorjsondata/query-jobs-create.result create mode 100644 tests/qemumonitorjsondata/query-jobs-empty.json create mode 100644 tests/qemumonitorjsondata/query-jobs-empty.result diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 3cd037fdba..c9dbc67f53 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4584,3 +4584,26 @@ qemuMonitorDeleteBitmap(qemuMonitorPtr mon, return qemuMonitorJSONDeleteBitmap(mon, node, bitmap); } + + +void +qemuMonitorJobInfoFree(qemuMonitorJobInfoPtr job) +{ + if (!job) + return; + + VIR_FREE(job->id); + VIR_FREE(job->error); + VIR_FREE(job); +} + + +int +qemuMonitorGetJobInfo(qemuMonitorPtr mon, + qemuMonitorJobInfoPtr **jobs, + size_t *njobs) +{ + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONGetJobInfo(mon, jobs, njobs); +} diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index e3a3c212fd..4cbe185c5c 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -117,6 +117,48 @@ struct _qemuMonitorRdmaGidStatus { }; +typedef enum { + QEMU_MONITOR_JOB_TYPE_UNKNOWN, /* internal value, not exposed by qemu = */ + QEMU_MONITOR_JOB_TYPE_COMMIT, + QEMU_MONITOR_JOB_TYPE_STREAM, + QEMU_MONITOR_JOB_TYPE_MIRROR, + QEMU_MONITOR_JOB_TYPE_BACKUP, + QEMU_MONITOR_JOB_TYPE_CREATE, + QEMU_MONITOR_JOB_TYPE_LAST +} qemuMonitorJobType; + +VIR_ENUM_DECL(qemuMonitorJob); + +typedef enum { + QEMU_MONITOR_JOB_STATUS_UNKNOWN, /* internal value, not exposed by qem= u */ + QEMU_MONITOR_JOB_STATUS_CREATED, + QEMU_MONITOR_JOB_STATUS_RUNNING, + QEMU_MONITOR_JOB_STATUS_PAUSED, + QEMU_MONITOR_JOB_STATUS_READY, + QEMU_MONITOR_JOB_STATUS_STANDBY, + QEMU_MONITOR_JOB_STATUS_WAITING, + QEMU_MONITOR_JOB_STATUS_PENDING, + QEMU_MONITOR_JOB_STATUS_ABORTING, + QEMU_MONITOR_JOB_STATUS_CONCLUDED, + QEMU_MONITOR_JOB_STATUS_UNDEFINED, /* the job states below should not = be visible outside of qemu */ + QEMU_MONITOR_JOB_STATUS_NULL, + QEMU_MONITOR_JOB_STATUS_LAST +} qemuMonitorJobStatus; + +VIR_ENUM_DECL(qemuMonitorJobStatus); + +typedef struct _qemuMonitorJobInfo qemuMonitorJobInfo; +typedef qemuMonitorJobInfo *qemuMonitorJobInfoPtr; +struct _qemuMonitorJobInfo { + char *id; + qemuMonitorJobType type; + qemuMonitorJobStatus status; + char *error; + long long progressCurrent; + long long progressTotal; +}; + + char *qemuMonitorGuestPanicEventInfoFormatMsg(qemuMonitorEventPanicInfoPtr= info); void qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfoPtr info); void qemuMonitorEventRdmaGidStatusFree(qemuMonitorRdmaGidStatusPtr info); @@ -1278,3 +1320,10 @@ struct _qemuMonitorCurrentMachineInfo { int qemuMonitorGetCurrentMachineInfo(qemuMonitorPtr mon, qemuMonitorCurrentMachineInfoPtr info= ); +void qemuMonitorJobInfoFree(qemuMonitorJobInfoPtr job); + +VIR_DEFINE_AUTOPTR_FUNC(qemuMonitorJobInfo, qemuMonitorJobInfoFree); + +int qemuMonitorGetJobInfo(qemuMonitorPtr mon, + qemuMonitorJobInfoPtr **jobs, + size_t *njobs); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 33ee026fe1..68780a5a4f 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -56,6 +56,14 @@ VIR_LOG_INIT("qemu.qemu_monitor_json"); #define LINE_ENDING "\r\n" +VIR_ENUM_IMPL(qemuMonitorJob, + QEMU_MONITOR_JOB_TYPE_LAST, + "", "commit", "stream", "mirror", "backup", "create"); +VIR_ENUM_IMPL(qemuMonitorJobStatus, + QEMU_MONITOR_JOB_STATUS_LAST, + "", "created", "running", "paused", "ready", "standby", "wai= ting", + "pending", "aborting", "concluded", "undefined", "null"); + static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValue= Ptr data); static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr= data); static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValu= ePtr data); @@ -9038,3 +9046,74 @@ qemuMonitorJSONDeleteBitmap(qemuMonitorPtr mon, virJSONValueFree(reply); return ret; } + + +static qemuMonitorJobInfoPtr +qemuMonitorJSONGetJobInfoOne(virJSONValuePtr data) +{ + const char *id =3D virJSONValueObjectGetString(data, "id"); + const char *type =3D virJSONValueObjectGetString(data, "type"); + const char *status =3D virJSONValueObjectGetString(data, "status"); + const char *errmsg =3D virJSONValueObjectGetString(data, "error"); + int tmp; + VIR_AUTOPTR(qemuMonitorJobInfo) job =3D NULL; + qemuMonitorJobInfoPtr ret =3D NULL; + + if (!data) + return NULL; + + if (VIR_ALLOC(job) < 0) + return NULL; + + if ((tmp =3D qemuMonitorJobTypeFromString(type)) < 0) + tmp =3D QEMU_MONITOR_JOB_TYPE_UNKNOWN; + + job->type =3D tmp; + + if ((tmp =3D qemuMonitorJobStatusTypeFromString(status)) < 0) + tmp =3D QEMU_MONITOR_JOB_STATUS_UNKNOWN; + + job->status =3D tmp; + + if (VIR_STRDUP(job->id, id) < 0 || + VIR_STRDUP(job->error, errmsg) < 0) + return NULL; + + VIR_STEAL_PTR(ret, job); + return ret; +} + + +int +qemuMonitorJSONGetJobInfo(qemuMonitorPtr mon, + qemuMonitorJobInfoPtr **jobs, + size_t *njobs) +{ + virJSONValuePtr data; + VIR_AUTOPTR(virJSONValue) cmd =3D NULL; + VIR_AUTOPTR(virJSONValue) reply =3D NULL; + size_t i; + + if (!(cmd =3D qemuMonitorJSONMakeCommand("query-jobs", NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0) + return -1; + + data =3D virJSONValueObjectGetArray(reply, "return"); + + for (i =3D 0; i < virJSONValueArraySize(data); i++) { + qemuMonitorJobInfoPtr job =3D NULL; + + if (!(job =3D qemuMonitorJSONGetJobInfoOne(virJSONValueArrayGet(da= ta, i)))) + return -1; + + if (VIR_APPEND_ELEMENT(*jobs, *njobs, job) < 0) + return -1; + } + + return 0; +} diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index c2b47e6129..a50d4d7b23 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -319,6 +319,12 @@ int qemuMonitorJSONBlockJobCancel(qemuMonitorPtr mon, const char *jobname) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int +qemuMonitorJSONGetJobInfo(qemuMonitorPtr mon, + qemuMonitorJobInfoPtr **jobs, + size_t *njobs); + + int qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon, const char *jobname, unsigned long long speed) diff --git a/tests/qemumonitorjsondata/query-jobs-create.json b/tests/qemum= onitorjsondata/query-jobs-create.json new file mode 100644 index 0000000000..fbc7c4b15d --- /dev/null +++ b/tests/qemumonitorjsondata/query-jobs-create.json @@ -0,0 +1,20 @@ +{ + "return": [ + { + "current-progress": 1, + "status": "concluded", + "total-progress": 1, + "type": "create", + "id": "createjob-fail", + "error": "Image size must be a multiple of 512 bytes" + }, + { + "current-progress": 1, + "status": "concluded", + "total-progress": 1, + "type": "create", + "id": "createjob" + } + ], + "id": "libvirt-24" +} diff --git a/tests/qemumonitorjsondata/query-jobs-create.result b/tests/qem= umonitorjsondata/query-jobs-create.result new file mode 100644 index 0000000000..a43282fe67 --- /dev/null +++ b/tests/qemumonitorjsondata/query-jobs-create.result @@ -0,0 +1,11 @@ +[job] +id=3Dcreatejob-fail +type=3Dcreate +status=3Dconcluded +error=3DImage size must be a multiple of 512 bytes + +[job] +id=3Dcreatejob +type=3Dcreate +status=3Dconcluded +error=3D diff --git a/tests/qemumonitorjsondata/query-jobs-empty.json b/tests/qemumo= nitorjsondata/query-jobs-empty.json new file mode 100644 index 0000000000..c1ede999e5 --- /dev/null +++ b/tests/qemumonitorjsondata/query-jobs-empty.json @@ -0,0 +1 @@ +{ "return": [] } diff --git a/tests/qemumonitorjsondata/query-jobs-empty.result b/tests/qemu= monitorjsondata/query-jobs-empty.result new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 798b7beca3..171a7cc104 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -2925,6 +2925,79 @@ testQAPISchemaValidate(const void *opaque) } +static void +testQueryJobsPrintJob(virBufferPtr buf, + qemuMonitorJobInfoPtr job) +{ + virBufferAddLit(buf, "[job]\n"); + virBufferAsprintf(buf, "id=3D%s\n", NULLSTR(job->id)); + virBufferAsprintf(buf, "type=3D%s\n", NULLSTR(qemuMonitorJobTypeToStri= ng(job->type))); + virBufferAsprintf(buf, "status=3D%s\n", NULLSTR(qemuMonitorJobStatusTy= peToString(job->status))); + virBufferAsprintf(buf, "error=3D%s\n", NULLSTR(job->error)); + virBufferAddLit(buf, "\n"); +} + + +struct testQueryJobsData { + const char *name; + virDomainXMLOptionPtr xmlopt; +}; + + +static int +testQueryJobs(const void *opaque) +{ + const struct testQueryJobsData *data =3D opaque; + qemuMonitorTestPtr test =3D qemuMonitorTestNewSimple(data->xmlopt); + VIR_AUTOFREE(char *) filenameJSON =3D NULL; + VIR_AUTOFREE(char *) fileJSON =3D NULL; + VIR_AUTOFREE(char *) filenameResult =3D NULL; + VIR_AUTOFREE(char *) actual =3D NULL; + qemuMonitorJobInfoPtr *jobs =3D NULL; + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + size_t njobs =3D 0; + size_t i; + int ret =3D -1; + + if (virAsprintf(&filenameJSON, + abs_srcdir "/qemumonitorjsondata/query-jobs-%s.json", + data->name) < 0 || + virAsprintf(&filenameResult, + abs_srcdir "/qemumonitorjsondata/query-jobs-%s.result", + data->name) < 0) + goto cleanup; + + if (virTestLoadFile(filenameJSON, &fileJSON) < 0) + goto cleanup; + + if (qemuMonitorTestAddItem(test, "query-jobs", fileJSON) < 0) + goto cleanup; + + if (qemuMonitorJSONGetJobInfo(qemuMonitorTestGetMonitor(test), + &jobs, &njobs) < 0) + goto cleanup; + + for (i =3D 0; i < njobs; i++) + testQueryJobsPrintJob(&buf, jobs[i]); + + virBufferTrim(&buf, "\n", -1); + + if (virBufferCheckError(&buf) < 0) + goto cleanup; + + actual =3D virBufferContentAndReset(&buf); + + if (virTestCompareToFile(actual, filenameResult) < 0) + goto cleanup; + + ret =3D 0; + + cleanup: + qemuMonitorTestFree(test); + return ret; +} + + static int mymain(void) { @@ -3199,6 +3272,18 @@ mymain(void) #undef DO_TEST_QAPI_VALIDATE +#define DO_TEST_QUERY_JOBS(name) \ + do { \ + struct testQueryJobsData data =3D { name, driver.xmlopt}; \ + if (virTestRun("query-jobs-" name, testQueryJobs, &data) < 0) \ + ret =3D -1; \ + } while (0) + + DO_TEST_QUERY_JOBS("empty"); + DO_TEST_QUERY_JOBS("create"); + +#undef DO_TEST_QUERY_JOBS + cleanup: VIR_FREE(metaschemastr); virJSONValueFree(metaschema); --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list