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