[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC v2 8/8] Added support to handle QMP events
--- tools/libxl/libxl_dom_save.c | 71 ++++++++------------ tools/libxl/libxl_qmp.c | 150 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 170 insertions(+), 51 deletions(-) diff --git a/tools/libxl/libxl_dom_save.c b/tools/libxl/libxl_dom_save.c index ddfe2f8..d188dd2 100644 --- a/tools/libxl/libxl_dom_save.c +++ b/tools/libxl/libxl_dom_save.c @@ -432,63 +432,44 @@ static void mirror_qemu_disks(libxl__egc *egc, libxl__stream_write_state *sws, { int counter = 20; char* target; - bool job_is_ready = false; libxl__domain_save_state *dss = sws->dss; const uint32_t domid = dss->domid; STATE_AO_GC(dss->ao); - if (dss->mirror_qemu_disks) { + if (rc) + goto err; /* * If the -q was provided, the drive-mirror job is started. - * TODO: Move the following code as part of the domain_suspend * TODO: The port should be sent by the destination. - */ -start_mirror: - LOGD(DEBUG, domid, "Sleeping for a bit so that source can start NBD\n"); - sleep(30); - LOGD(DEBUG, domid, "Starting mirror-drive of device %s\n", - QEMU_DRIVE_MIRROR_DEVICE); - target = GCSPRINTF("nbd:%s:%s:exportname=%s", dss->hostname, - QEMU_DRIVE_MIRROR_PORT, QEMU_DRIVE_MIRROR_DEVICE); - rc = libxl__qmp_drive_mirror(gc, dss->domid, QEMU_DRIVE_MIRROR_DEVICE, + */ + start_mirror: + LOGD(DEBUG, domid, "Sleeping for a bit so that source can start NBD\n"); + sleep(30); + LOGD(DEBUG, domid, "Starting mirror-drive of device %s\n", + QEMU_DRIVE_MIRROR_DEVICE); + target = GCSPRINTF("nbd:%s:%s:exportname=%s", dss->hostname, + QEMU_DRIVE_MIRROR_PORT, QEMU_DRIVE_MIRROR_DEVICE); + rc = libxl__qmp_drive_mirror(gc, dss->domid, QEMU_DRIVE_MIRROR_DEVICE, target, "raw"); - if (!rc) { - LOGD(INFO, domid, "Drive mirror command returned successfully\n"); + if (!rc) { + LOGD(DEBUG, domid, "Drive mirror command returned successfully\n"); + }else{ + LOGD(ERROR, domid, "Sending drive mirror command failed\n"); + if(counter > 0){ + LOGD(INFO, domid, "Counter: %d. Sleeping for 10 sec and retry\n", counter); + sleep(10); + counter--; + goto start_mirror; }else{ - LOGD(ERROR, domid, "Sending drive mirror command failed\n"); - if(counter > 0){ - LOGD(INFO, domid, "Counter: %d. Sleeping for 10 sec and retry\n", counter); - sleep(10); - counter--; - goto start_mirror; - }else{ - goto cont; - } - } - - /* - * Query job status until it is ready - * TODO: This code is just an inefficient busy wait. QMP sends an - * TODO: asynchronous message when mirroring job is completed. Consider - * TODO: adding the capability to handle asynchronous QMP messages (already done?) - */ - while(!job_is_ready) { - LOGD(INFO, domid, "Checking for drive-mirror job"); - rc = libxl__qmp_query_block_jobs(gc, dss->domid, &job_is_ready); - if(rc){ - LOGD(ERROR, domid, "Checking block job failed\n"); - goto cont; - }else{ - LOGD(INFO, domid, "Checking block job succeeded\n"); - } - if(!job_is_ready){ - LOGD(INFO, domid, "Sleeping 5 sec\n"); - sleep(5); - } + goto err; } } -cont: + libxl__stream_write_start(egc, &sws->dss->sws); + return; + + err: + dss->callback(egc, dss, rc); } static void stream_done(libxl__egc *egc, diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c index fe6f076..5ef5fb1 100644 --- a/tools/libxl/libxl_qmp.c +++ b/tools/libxl/libxl_qmp.c @@ -59,6 +59,13 @@ typedef struct callback_id_pair { LIBXL_STAILQ_ENTRY(struct callback_id_pair) next; } callback_id_pair; +typedef struct handler_event_pair { + const char* event_type; + void *opaque; + qmp_request_context *context; + qmp_callback_t event_handler; +} event_handler_pair; + struct libxl__qmp_handler { struct sockaddr_un addr; int qmp_fd; @@ -66,6 +73,9 @@ struct libxl__qmp_handler { time_t timeout; /* wait_for_id will be used by the synchronous send function */ int wait_for_id; + /* wait_for_event_type is used to wait on QMP events */ + const char* wait_for_event_type; + event_handler_pair *hep; char buffer[QMP_RECEIVE_BUFFER_SIZE + 1]; libxl__yajl_ctx *yajl_ctx; @@ -287,6 +297,25 @@ static void qmp_handle_error_response(libxl__gc *gc, libxl__qmp_handler *qmp, libxl__json_object_get_string(resp)); } +static void qmp_handle_event(libxl__gc *gc, libxl__qmp_handler *qmp, + const libxl__json_object *event) +{ + const char* event_type = NULL; + const libxl__json_object *event_o = NULL; + event_o = libxl__json_map_get("event", event, JSON_ANY); + event_type = libxl__json_object_get_string(event_o); + int rc; + + if(qmp->wait_for_event_type && + !strcmp(event_type, qmp->wait_for_event_type)) { + rc = qmp->hep->event_handler(qmp, + libxl__json_map_get("data", event, JSON_ANY), + qmp->hep->opaque); + qmp->hep->context->rc = rc; + qmp->wait_for_event_type = NULL; + } +} + static int qmp_handle_response(libxl__gc *gc, libxl__qmp_handler *qmp, const libxl__json_object *resp) { @@ -325,6 +354,7 @@ static int qmp_handle_response(libxl__gc *gc, libxl__qmp_handler *qmp, qmp_handle_error_response(gc, qmp, resp); return -1; case LIBXL__QMP_MESSAGE_TYPE_EVENT: + qmp_handle_event(gc, qmp, resp); return 0; case LIBXL__QMP_MESSAGE_TYPE_INVALID: return -1; @@ -348,9 +378,7 @@ static libxl__qmp_handler *qmp_init_handler(libxl__gc *gc, uint32_t domid) qmp->ctx = CTX; qmp->domid = domid; - //TODO: Changed default timeout because drive-mirror command takes a long - //TODO: to return. Consider timeout to be passed as param. - qmp->timeout = 600; + qmp->timeout = 5; LIBXL_STAILQ_INIT(&qmp->callback_list); @@ -627,6 +655,31 @@ static void qmp_free_handler(libxl__qmp_handler *qmp) free(qmp); } +static int wait_for_event(libxl__qmp_handler *qmp, event_handler_pair *hep, + int timeout) +{ + int ret = 0; + GC_INIT(qmp->ctx); + qmp->timeout = timeout; + qmp_request_context context = { .rc = 0 }; + qmp->hep = hep; + qmp->wait_for_event_type = hep->event_type; + hep->context = &context; + + while (qmp->wait_for_event_type) { + if ((ret = qmp_next(gc, qmp)) < 0) { + break; + } + } + + if (!qmp->wait_for_event_type && ret == 0) { + ret = context.rc; + } + GC_FREE; + + return ret; +} + /* * QMP Parameters Helpers */ @@ -1072,10 +1125,82 @@ int libxl__qmp_nbd_server_add(libxl__gc *gc, int domid, const char *disk) return qmp_run_command(gc, domid, "nbd-server-add", args, NULL, NULL); } -int libxl__qmp_drive_mirror(libxl__gc *gc, int domid, const char* device, const char* target, const char* format) +static int block_job_ready_handler(libxl__qmp_handler *qmp, + const libxl__json_object *data, void *opaque){ + + GC_INIT(qmp->ctx); + int rc = -1; + + const char *type; + const char *device; + unsigned int len; + unsigned int offset; + unsigned int speed; + + const libxl__json_object *obj = NULL; + + obj = libxl__json_map_get("type", data, JSON_STRING); + if (!obj) { + LOGD(ERROR, qmp->domid, "Failed to retrieve job type."); + rc = ERROR_FAIL; + goto out; + } + type = libxl__json_object_get_string(obj); + + obj = libxl__json_map_get("device", data, JSON_STRING); + if (!obj) { + LOGD(ERROR, qmp->domid, "Failed to retrieve device."); + rc = ERROR_FAIL; + goto out; + } + device = libxl__json_object_get_string(obj); + + obj = libxl__json_map_get("len", data, JSON_INTEGER); + if (!obj) { + LOGD(ERROR, qmp->domid, "Failed to retrieve length."); + rc = ERROR_FAIL; + goto out; + } + len = libxl__json_object_get_integer(obj); + + obj = libxl__json_map_get("offset", data, JSON_INTEGER); + if (!obj) { + LOGD(ERROR, qmp->domid, "Failed to retrieve offset."); + rc = ERROR_FAIL; + goto out; + } + offset = libxl__json_object_get_integer(obj); + + obj = libxl__json_map_get("speed", data, JSON_INTEGER); + if (!obj) { + LOGD(ERROR, qmp->domid, "Failed to retrieve speed."); + rc = ERROR_FAIL; + goto out; + } + speed = libxl__json_object_get_integer(obj); + + LOGD(INFO, qmp->domid, "Block Job Ready: Details: Device: %s, Type: %s, Len: %u, Offset: %u, Speed %u\n", + device, type, len, offset, speed); + + rc = 0; +out: + GC_FREE; + return rc; +} + +int libxl__qmp_drive_mirror(libxl__gc *gc, int domid, const char* device, + const char* target, const char* format) { + libxl__qmp_handler *qmp = NULL; libxl__json_object *args = NULL; - //TODO: Allow method to receive "sync", "speed", "mode", "granurality", "buf-size" + int rc = 0; + /* TODO: Allow method to receive "sync", "speed", "mode", "granurality" + * "buf-size" + */ + qmp = libxl__qmp_initialize(gc, domid); + if (!qmp) + return -1; + qmp_parameters_add_string(gc, &args, "device", device); qmp_parameters_add_string(gc, &args, "target", target); qmp_parameters_add_string(gc, &args, "sync", "full"); @@ -1084,7 +1209,20 @@ int libxl__qmp_drive_mirror(libxl__gc *gc, int domid, const char* device, const qmp_parameters_add_integer(gc, &args, "granularity", 0); qmp_parameters_add_integer(gc, &args, "buf-size", 0); - return qmp_run_command(gc, domid, "drive-mirror", args, NULL, NULL); + rc = qmp_synchronous_send(qmp, "drive-mirror", args, + NULL, NULL, qmp->timeout); + + if ( !rc ) { + event_handler_pair hep = + { + .event_type = "BLOCK_JOB_READY", + .event_handler = block_job_ready_handler, + }; + + rc = wait_for_event(qmp, &hep, 600); + } + libxl__qmp_close(qmp); + return rc; } static int query_block_callback(libxl__qmp_handler *qmp, -- 2.3.2 (Apple Git-55) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |