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

[Xen-devel] [RFC PATCH 6/7] qmp: add qmp handlers to delete internal/external disk snapshot



Xl doesn't maintain domain snapshot info and has no idea of snapshot
info and related files after creation, so it doesn't supply domain
snapshot delete command. These qmp handlers won't be used by xl.

But for libvirt, it maintains domain snapshot info itself and supplies
snapshot delete commands, and so needs APIs from libxl to delete
internal/external disk snapshots. To libvirt, these qmp handlers
are userful.

Signed-off-by: Chunyan Liu <cyliu@xxxxxxxx>
---
 tools/libxl/libxl.h          |  17 +++++
 tools/libxl/libxl_internal.h |  28 ++++++++
 tools/libxl/libxl_qmp.c      | 158 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 203 insertions(+)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index d60f139..412a42f 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1730,6 +1730,23 @@ void libxl_psr_cat_info_list_free(libxl_psr_cat_info 
*list, int nr);
 #endif
 
 /* Domain snapshot related APIs */
+
+/* structure to retrieve qmp block job status */
+typedef struct libxl_block_job_info
+{
+     char *disk_vdev;
+     const char *type;
+     unsigned long speed;
+     /* The following fields provide an indication of block job progress.
+      * @current indicates the current position and will be between 0 and @end.
+      * @end is the final cursor position for this operation and represents
+      * completion.
+      * To approximate progress, divide @cur by @end.
+      */
+      unsigned long long current;
+      unsigned long long end;
+} libxl_block_job_info;
+
 int libxl_disk_snapshot_create(libxl_ctx *ctx, uint32_t domid,
                                libxl_disk_snapshot *snapshot, int nb);
 int libxl_disk_snapshot_revert(libxl_ctx *ctx, uint32_t domid,
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index f24e0af..a6456e8 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1739,6 +1739,34 @@ _hidden int libxl__qmp_cpu_add(libxl__gc *gc, int domid, 
int index);
 _hidden int libxl__qmp_disk_snapshot_transaction(libxl__gc *gc, int domid,
                                                 libxl_disk_snapshot *snapshot,
                                                 int nb);
+/* Delete a disk snapshot */
+_hidden int libxl__qmp_disk_snapshot_delete(libxl__gc *gc, int domid,
+                                           libxl_disk_snapshot *snapshot);
+/* shorten backing file chain. Merge base to top */
+_hidden int libxl__qmp_block_commit(libxl__gc *gc, uint32_t domid,
+                                    libxl_device_disk *disk,
+                                    const char *base, const char *top,
+                                    const char *backing_file,
+                                    unsigned long bandwidth);
+/* shorten backing file chain. Merge top to base */
+_hidden int libxl__qmp_block_stream(libxl__gc *gc, uint32_t domid,
+                                    libxl_device_disk *disk,
+                                    const char *base,
+                                    const char *backing_file,
+                                    unsigned long long bandwidth,
+                                    const char *error);
+/* query qmp block job status */
+_hidden int libxl__qmp_query_block_job(libxl__gc *gc, uint32_t domid,
+                                       libxl_device_disk *disk,
+                                       libxl_block_job_info *info);
+/* cancel a qmp block job */
+_hidden int libxl__qmp_block_job_cancel(libxl__gc *gc, uint32_t domid,
+                                        libxl_device_disk *disk,
+                                        bool force);
+
+/* complete a qmp block job */
+_hidden int libxl__qmp_block_job_complete(libxl__gc *gc, uint32_t domid,
+                                          libxl_device_disk *disk);
 /* close and free the QMP handler */
 _hidden void libxl__qmp_close(libxl__qmp_handler *qmp);
 /* remove the socket file, if the file has already been removed,
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 2216511..09cb628 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -1034,6 +1034,164 @@ int libxl__qmp_disk_snapshot_transaction(libxl__gc *gc, 
int domid,
     return qmp_run_command(gc, domid, "transaction", args, NULL, NULL);
 }
 
+int libxl__qmp_disk_snapshot_delete(libxl__gc *gc, int domid,
+                                   libxl_disk_snapshot *snapshot)
+{
+    libxl__json_object *args = NULL;
+
+    if (snapshot->type == LIBXL_DISK_SNAPSHOT_TYPE_EXTERNAL) {
+        LOG(ERROR, "QMP doesn't support deleting external disk snapshot");
+        return -1;
+    }
+
+    if (snapshot->type != LIBXL_DISK_SNAPSHOT_TYPE_INTERNAL) {
+        LOG(ERROR, "Invalid disk snapshot type");
+        return -1;
+    }
+
+    qmp_parameters_add_string(gc, &args, "device", snapshot->disk.vdev);
+    qmp_parameters_add_string(gc, &args, "name", snapshot->name);
+
+    return qmp_run_command(gc, domid, "blockdev-snapshot-delete-internal-sync",
+                           args, NULL, NULL);
+}
+
+/* send qmp 'block-commit' command
+ * .args_type  = "device:B,base:s?,top:s?,backing-file:s?,speed:o?"
+ * According to qemu document:
+ * If top == active image, the job will not be completed by itself,
+ * user needs to complete the job with the block-job-complete
+ * command after getting ready.
+ */
+int libxl__qmp_block_commit(libxl__gc *gc, uint32_t domid,
+                            libxl_device_disk *disk,
+                            const char *base, const char *top,
+                            const char *backing_file,
+                            unsigned long bandwidth)
+{
+    libxl__json_object *args = NULL;
+
+    qmp_parameters_add_string(gc, &args, "device", disk->vdev);
+    if (base != NULL)
+        qmp_parameters_add_string(gc, &args, "base", base);
+    if (top != NULL)
+        qmp_parameters_add_string(gc, &args, "top", top);
+    if (backing_file != NULL)
+        qmp_parameters_add_string(gc, &args, "backing-file", backing_file);
+    if (!bandwidth)
+        qmp_parameters_add_integer(gc, &args, "speed", bandwidth);
+
+    return qmp_run_command(gc, domid, "block-commit", args, NULL, NULL);
+}
+
+/* send qmp 'block-stream' command
+ * .args_type  = "device:B,base:s?,speed:o?,backing-file:s?,on-error:s?"
+ */
+int libxl__qmp_block_stream(libxl__gc *gc, uint32_t domid,
+                            libxl_device_disk *disk,
+                            const char *base,
+                            const char *backing_file,
+                            unsigned long long bandwidth,
+                            const char *error)
+{
+    libxl__json_object *args = NULL;
+
+    qmp_parameters_add_string(gc, &args, "device", disk->vdev);
+    if (base != NULL)
+        qmp_parameters_add_string(gc, &args, "base", base);
+    if (backing_file != NULL)
+        qmp_parameters_add_string(gc, &args, "backing-file", backing_file);
+    if (!bandwidth)
+        qmp_parameters_add_integer(gc, &args, "speed", bandwidth);
+    if (error != NULL)
+        qmp_parameters_add_string(gc, &args, "on-error", error);
+
+    return qmp_run_command(gc, domid, "block-stream", args, NULL, NULL);
+}
+
+/* send qmp 'block-job-cancel' command
+ *   .args_type  = "device:B,force:b?"
+ */
+int libxl__qmp_block_job_cancel(libxl__gc *gc, uint32_t domid,
+                                libxl_device_disk *disk,
+                                bool force)
+{
+    libxl__json_object *args = NULL;
+
+    qmp_parameters_add_string(gc, &args, "device", disk->vdev);
+    if (force)
+        qmp_parameters_add_bool(gc, &args, "force", force);
+
+    return qmp_run_command(gc, domid, "block-job-cancel", args, NULL, NULL);
+}
+
+/* send qmp 'block-job-complete' command
+ *   .args_type  = "device:B",
+ */
+int libxl__qmp_block_job_complete(libxl__gc *gc, uint32_t domid,
+                                  libxl_device_disk *disk)
+{
+    libxl__json_object *args = NULL;
+
+    qmp_parameters_add_string(gc, &args, "device", disk->vdev);
+
+    return qmp_run_command(gc, domid, "block-job-complete", args, NULL, NULL);
+}
+
+static int qmp_query_block_jobs_callback(libxl__qmp_handler *qmp,
+                                         const libxl__json_object *response,
+                                         void *opaque)
+{
+    /* export response for upper layer to handle */
+    libxl_block_job_info *info = opaque;
+    const libxl__json_object *obj = NULL;
+    int i;
+    bool found = false;
+
+    for (i = 0; (obj = libxl__json_array_get(response, i)); i++) {
+        const libxl__json_object *o = NULL;
+        const char *device;
+
+        if (!libxl__json_object_is_map(obj))
+            continue;
+        o = libxl__json_map_get("device", obj, JSON_STRING);
+        device = libxl__json_object_get_string(o);
+        if (!device || !strcmp(device, info->disk_vdev))
+            continue;
+
+        o = libxl__json_map_get("type", obj, JSON_STRING);
+        if (!o)
+            continue;
+        info->type = libxl__json_object_get_string(o);
+
+        o = libxl__json_map_get("speed", obj, JSON_INTEGER);
+        info->speed = libxl__json_object_get_integer(o);
+
+        o = libxl__json_map_get("offset", obj, JSON_INTEGER);
+        info->current = libxl__json_object_get_integer(o);
+
+        o = libxl__json_map_get("len", obj, JSON_INTEGER);
+        info->end = libxl__json_object_get_integer(o);
+
+        found = true;
+        break;
+    }
+
+    if (!found)
+        return -1;
+
+    return 0;
+}
+
+int libxl__qmp_query_block_job(libxl__gc *gc, uint32_t domid,
+                               libxl_device_disk *disk,
+                               libxl_block_job_info *info)
+{
+    info->disk_vdev = libxl__strdup(gc, disk->vdev);
+    return qmp_run_command(gc, domid, "query-block-jobs", NULL,
+                           &qmp_query_block_jobs_callback, info);
+}
+
 int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
                                const libxl_domain_config *guest_config)
 {
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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