mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
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:
parent
93de886b10
commit
ed56851f1b
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
20
tests/qemumonitorjsondata/query-jobs-create.json
Normal file
20
tests/qemumonitorjsondata/query-jobs-create.json
Normal 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"
|
||||
}
|
11
tests/qemumonitorjsondata/query-jobs-create.result
Normal file
11
tests/qemumonitorjsondata/query-jobs-create.result
Normal 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>
|
1
tests/qemumonitorjsondata/query-jobs-empty.json
Normal file
1
tests/qemumonitorjsondata/query-jobs-empty.json
Normal file
@ -0,0 +1 @@
|
||||
{ "return": [] }
|
0
tests/qemumonitorjsondata/query-jobs-empty.result
Normal file
0
tests/qemumonitorjsondata/query-jobs-empty.result
Normal 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);
|
||||
|
Loading…
Reference in New Issue
Block a user