[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH RFC v3 RESEND 02/12] Migration with Local Disks Mirroring: Added QMP commands used for mirroring disks



Migration with local disks mirroring uses the embedded NBD server in QEMU. A NBD
server is added in libxl during instance creation time in the destination (QMP
command: nbd_server_add). The drive mirror command (QMP: driver_mirror) is
executed on the source during 'instance save' to replicate the disk in the
destination. When the local disk migration option is used, the QEMU process in
the destination will be started with the "-incoming defer" option instead of
"-incoming fd". Once the disk and memory have been transferred to the
destination the QEMU process will be resumed using the migrate incoming command
(QMP command: migrate_incoming).

Signed-off-by: Bruno Alvisio <bruno.alvisio@xxxxxxxxx>
---
 tools/libxl/libxl_internal.h |  11 ++++
 tools/libxl/libxl_qmp.c      | 139 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index bfa95d8..4d7679e 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1830,6 +1830,17 @@ _hidden int libxl__qmp_nbd_server_add(libxl__gc *gc, int 
domid,
 /* Start replication */
 _hidden int libxl__qmp_start_replication(libxl__gc *gc, int domid,
                                          bool primary);
+/* Mirror drive */
+_hidden int libxl__qmp_drive_mirror(libxl__gc *gc, int domid,
+                                    const char* device, const char* target,
+                                    const char* format);
+/* Query block devices */
+_hidden int libxl__qmp_query_block(libxl__gc *gc, int domid,
+                                   char *device_names);
+/* Resume QEMU process started with -incoming defer option */
+_hidden int libxl__qmp_migrate_incoming(libxl__gc *gc, int domid,
+                                        const char* uri);
+
 /* Get replication error that occurs when the vm is running */
 _hidden int libxl__qmp_query_xen_replication_status(libxl__gc *gc, int domid);
 /* Do checkpoint */
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 0e993af..1a1a318 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1159,6 +1159,145 @@ int libxl__qmp_stop_replication(libxl__gc *gc, int 
domid, bool primary)
     return qmp_run_command(gc, domid, "xen-set-replication", args, NULL, NULL);
 }
 
+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.", 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;
+    int block_job_timeout = 3600;
+    int rc = 0;
+
+    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");
+    qmp_parameters_add_string(gc, &args, "format", format);
+    qmp_parameters_add_string(gc, &args, "mode", "existing");
+    qmp_parameters_add_integer(gc, &args, "granularity", 0);
+    qmp_parameters_add_integer(gc, &args, "buf-size", 0);
+
+    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, block_job_timeout);
+    }
+    libxl__qmp_close(qmp);
+    return rc;
+}
+
+static int query_block_callback(libxl__qmp_handler *qmp,
+                                const libxl__json_object *response,
+                                void *opaque)
+{
+    GC_INIT(qmp->ctx);
+    const libxl__json_object *blockinfo = NULL;
+    int i, rc = -1;
+
+    for (i = 0; (blockinfo = libxl__json_array_get(response, i)); i++) {
+        const libxl__json_object *d;
+        const char* device_name;
+        d = libxl__json_map_get("device", blockinfo, JSON_STRING);
+        if (!d)
+            goto out;
+
+        device_name = libxl__json_object_get_string(d);
+    }
+
+    rc = 0;
+out:
+    GC_FREE;
+    return rc;
+}
+
+int libxl__qmp_query_block(libxl__gc *gc, int domid, char *device_names)
+{
+    return qmp_run_command(gc, domid, "query-block", NULL, 
query_block_callback,
+                           device_names);
+}
+
+int libxl__qmp_migrate_incoming(libxl__gc *gc, int domid, const char* uri)
+{
+    libxl__json_object *args = NULL;
+
+    qmp_parameters_add_string(gc, &args, "uri", uri);
+
+    return qmp_run_command(gc, domid, "migrate-incoming", args, NULL, NULL);
+}
+
 int libxl__qmp_nbd_server_stop(libxl__gc *gc, int domid)
 {
     return qmp_run_command(gc, domid, "nbd-server-stop", NULL, NULL, NULL);
-- 
2.3.2 (Apple Git-55)


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.