qemu: monitor: Add infrastructure for 'query-jobs'

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
This commit is contained in:
Peter Krempa 2018-12-04 17:58:38 +01:00
parent 93de886b10
commit ed56851f1b
9 changed files with 290 additions and 0 deletions

View 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);
}

View 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);

View 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;
}

View 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)

View File

@ -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"
}

View File

@ -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>

View File

@ -0,0 +1 @@
{ "return": [] }

View 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);