]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: monitor: Add infrastructure for 'query-jobs'
authorPeter Krempa <pkrempa@redhat.com>
Tue, 4 Dec 2018 16:58:38 +0000 (17:58 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Thu, 18 Jul 2019 15:59:33 +0000 (17:59 +0200)
Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
tests/qemumonitorjsondata/query-jobs-create.json [new file with mode: 0644]
tests/qemumonitorjsondata/query-jobs-create.result [new file with mode: 0644]
tests/qemumonitorjsondata/query-jobs-empty.json [new file with mode: 0644]
tests/qemumonitorjsondata/query-jobs-empty.result [new file with mode: 0644]
tests/qemumonitorjsontest.c

index f174b81ba0b53e967db18d47891ab684c0e6ee37..70e864fa6770fa2580b4d63106e484179d2aba19 100644 (file)
@@ -4585,3 +4585,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);
+}
index e6e99ad0bce7557c43145767f59f11f5287a2c9e..3e9bb4a2893f3b0bbd508bcf0f1ae12259d4ed04 100644 (file)
@@ -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 qemu */
+    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);
@@ -1279,3 +1321,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);
index 404d32e921fed8f2794d8a40f16ece346d00f577..a1cb553109bb6b869708689fb62366838b5e4847 100644 (file)
@@ -56,6 +56,30 @@ 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",
+              "waiting",
+              "pending",
+              "aborting",
+              "concluded",
+              "undefined",
+              "null");
+
 static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr data);
 static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data);
 static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data);
@@ -9044,3 +9068,74 @@ qemuMonitorJSONDeleteBitmap(qemuMonitorPtr mon,
     virJSONValueFree(reply);
     return ret;
 }
+
+
+static qemuMonitorJobInfoPtr
+qemuMonitorJSONGetJobInfoOne(virJSONValuePtr data)
+{
+    const char *id = virJSONValueObjectGetString(data, "id");
+    const char *type = virJSONValueObjectGetString(data, "type");
+    const char *status = virJSONValueObjectGetString(data, "status");
+    const char *errmsg = virJSONValueObjectGetString(data, "error");
+    int tmp;
+    VIR_AUTOPTR(qemuMonitorJobInfo) job = NULL;
+    qemuMonitorJobInfoPtr ret = NULL;
+
+    if (!data)
+        return NULL;
+
+    if (VIR_ALLOC(job) < 0)
+        return NULL;
+
+    if ((tmp = qemuMonitorJobTypeFromString(type)) < 0)
+        tmp = QEMU_MONITOR_JOB_TYPE_UNKNOWN;
+
+    job->type = tmp;
+
+    if ((tmp = qemuMonitorJobStatusTypeFromString(status)) < 0)
+        tmp = QEMU_MONITOR_JOB_STATUS_UNKNOWN;
+
+    job->status = 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 = NULL;
+    VIR_AUTOPTR(virJSONValue) reply = NULL;
+    size_t i;
+
+    if (!(cmd = 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 = virJSONValueObjectGetArray(reply, "return");
+
+    for (i = 0; i < virJSONValueArraySize(data); i++) {
+        qemuMonitorJobInfoPtr job = NULL;
+
+        if (!(job = qemuMonitorJSONGetJobInfoOne(virJSONValueArrayGet(data, i))))
+            return -1;
+
+        if (VIR_APPEND_ELEMENT(*jobs, *njobs, job) < 0)
+            return -1;
+    }
+
+    return 0;
+}
index 28a5d826562b7f4115751d42ff835c589214bf4d..89eb554f1d1c54941540028dffac616772f9d3bb 100644 (file)
@@ -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/qemumonitorjsondata/query-jobs-create.json
new file mode 100644 (file)
index 0000000..fbc7c4b
--- /dev/null
@@ -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/qemumonitorjsondata/query-jobs-create.result
new file mode 100644 (file)
index 0000000..a43282f
--- /dev/null
@@ -0,0 +1,11 @@
+[job]
+id=createjob-fail
+type=create
+status=concluded
+error=Image size must be a multiple of 512 bytes
+
+[job]
+id=createjob
+type=create
+status=concluded
+error=<null>
diff --git a/tests/qemumonitorjsondata/query-jobs-empty.json b/tests/qemumonitorjsondata/query-jobs-empty.json
new file mode 100644 (file)
index 0000000..c1ede99
--- /dev/null
@@ -0,0 +1 @@
+{ "return": [] }
diff --git a/tests/qemumonitorjsondata/query-jobs-empty.result b/tests/qemumonitorjsondata/query-jobs-empty.result
new file mode 100644 (file)
index 0000000..e69de29
index 93abc3d964246f56934fc63dd1124561a6599ea6..8eb9d2e01bbfe1e374b299225de7a35e57b7bebe 100644 (file)
@@ -2925,6 +2925,79 @@ testQAPISchemaValidate(const void *opaque)
 }
 
 
+static void
+testQueryJobsPrintJob(virBufferPtr buf,
+                      qemuMonitorJobInfoPtr job)
+{
+    virBufferAddLit(buf, "[job]\n");
+    virBufferAsprintf(buf, "id=%s\n", NULLSTR(job->id));
+    virBufferAsprintf(buf, "type=%s\n", NULLSTR(qemuMonitorJobTypeToString(job->type)));
+    virBufferAsprintf(buf, "status=%s\n", NULLSTR(qemuMonitorJobStatusTypeToString(job->status)));
+    virBufferAsprintf(buf, "error=%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 = opaque;
+    qemuMonitorTestPtr test = qemuMonitorTestNewSimple(data->xmlopt);
+    VIR_AUTOFREE(char *) filenameJSON = NULL;
+    VIR_AUTOFREE(char *) fileJSON = NULL;
+    VIR_AUTOFREE(char *) filenameResult = NULL;
+    VIR_AUTOFREE(char *) actual = NULL;
+    qemuMonitorJobInfoPtr *jobs = NULL;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    size_t njobs = 0;
+    size_t i;
+    int ret = -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 = 0; i < njobs; i++)
+        testQueryJobsPrintJob(&buf, jobs[i]);
+
+    virBufferTrim(&buf, "\n", -1);
+
+    if (virBufferCheckError(&buf) < 0)
+        goto cleanup;
+
+    actual = virBufferContentAndReset(&buf);
+
+    if (virTestCompareToFile(actual, filenameResult) < 0)
+        goto cleanup;
+
+    ret = 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 = { name, driver.xmlopt}; \
+        if (virTestRun("query-jobs-" name, testQueryJobs, &data) < 0) \
+            ret = -1; \
+    } while (0)
+
+    DO_TEST_QUERY_JOBS("empty");
+    DO_TEST_QUERY_JOBS("create");
+
+#undef DO_TEST_QUERY_JOBS
+
  cleanup:
     VIR_FREE(metaschemastr);
     virJSONValueFree(metaschema);