|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC] tools/libxl: add disk snapshot support
add internal disk snapshot support through qemu qmp, including create,
delete and list.
Signed-off-by: Bamvor Jian Zhang <bjzhang@xxxxxxxx>
---
tools/libxl/libxl.c | 29 ++++++++++
tools/libxl/libxl.h | 9 +++
tools/libxl/libxl_internal.h | 15 +++++
tools/libxl/libxl_qmp.c | 132 +++++++++++++++++++++++++++++++++++++++++++
tools/libxl/libxl_types.idl | 12 ++++
tools/libxl/xl.h | 3 +
tools/libxl/xl_cmdimpl.c | 114 +++++++++++++++++++++++++++++++++++++
tools/libxl/xl_cmdtable.c | 18 ++++++
8 files changed, 332 insertions(+)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 30b0b06..76b4c65 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -5661,6 +5661,35 @@ int libxl_fd_set_cloexec(libxl_ctx *ctx, int fd, int
cloexec)
int libxl_fd_set_nonblock(libxl_ctx *ctx, int fd, int nonblock)
{ return fd_set_flags(ctx,fd, F_GETFL,F_SETFL,"FL", O_NONBLOCK, nonblock); }
+int libxl__disk_snapshot_create(libxl_ctx *ctx, int domid,
+ libxl_snapshot *snapshot)
+{
+ int rc;
+ GC_INIT(ctx);
+ rc = libxl__qmp_disk_snapshot_internal(gc, domid, snapshot);
+ GC_FREE;
+ return rc;
+}
+
+int libxl__disk_snapshot_delete(libxl_ctx *ctx, int domid,
+ libxl_snapshot *snapshot)
+{
+ int rc;
+ GC_INIT(ctx);
+ rc = libxl__qmp_disk_snapshot_delete_internal(gc, domid, snapshot);
+ GC_FREE;
+ return rc;
+}
+
+int libxl__disk_snapshot_list(libxl_ctx *ctx, int domid,
+ libxl_snapshot **snapshotp)
+{
+ GC_INIT(ctx);
+ libxl__qmp_disk_snapshot_list_internal(gc, domid, snapshotp);
+ GC_FREE;
+ return 0;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index b2c3015..5139a01 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1151,6 +1151,15 @@ int libxl_flask_getenforce(libxl_ctx *ctx);
int libxl_flask_setenforce(libxl_ctx *ctx, int mode);
int libxl_flask_loadpolicy(libxl_ctx *ctx, void *policy, uint32_t size);
+/* disk snapshot api
+ * support create, delete and list for internal snapshot of a single disk
+ */
+int libxl__disk_snapshot_create(libxl_ctx *ctx, int domid,
+ libxl_snapshot *snapshot);
+int libxl__disk_snapshot_delete(libxl_ctx *ctx, int domid,
+ libxl_snapshot *snapshot);
+int libxl__disk_snapshot_list(libxl_ctx *ctx, int domid,
+ libxl_snapshot **snapshotp);
/* misc */
/* Each of these sets or clears the flag according to whether the
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index c2b73c4..ab73a1d 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1585,6 +1585,21 @@ _hidden int libxl__qmp_set_global_dirty_log(libxl__gc
*gc, int domid, bool enabl
_hidden int libxl__qmp_insert_cdrom(libxl__gc *gc, int domid, const
libxl_device_disk *disk);
/* Add a virtual CPU */
_hidden int libxl__qmp_cpu_add(libxl__gc *gc, int domid, int index);
+/* disk internal snapshot */
+int libxl__qmp_disk_snapshot_internal(libxl__gc *gc, int domid,
+ libxl_snapshot *snapshot);
+/* caller should ensure that the id and name at lease exist one and only exist
+ * one. */
+int libxl__qmp_disk_snapshot_delete_internal(libxl__gc *gc, int domid,
+ libxl_snapshot *snapshot);
+int libxl__qmp_disk_snapshot_list_internal(libxl__gc *gc, int domid,
+ libxl_snapshot **snapshotp);
+/* tranaction operation for disk snapshot: support internal and external
+ * snapshot */
+int libxl__qmp_disk_snapshot_transaction(libxl__gc *gc, int domid,
+ libxl_snapshot *snapshot, int nb);
+/* run and get qmp result */
+int libxl__qmp_test(libxl__gc *gc, int domid, const char* command);
/* 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 8433e42..5f7cbf4 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -939,6 +939,138 @@ int libxl__qmp_cpu_add(libxl__gc *gc, int domid, int idx)
return qmp_run_command(gc, domid, "cpu-add", args, NULL, NULL);
}
+int libxl__qmp_disk_snapshot_transaction(libxl__gc *gc, int domid,
+ libxl_snapshot *snapshot, int nb)
+{
+ libxl__json_object *args = NULL;
+ libxl__json_object *types = NULL;
+ libxl__json_object **type = NULL;
+ libxl__json_object **device = NULL;
+ int i;
+
+ type = (libxl__json_object**)calloc(nb, sizeof(libxl__json_object*));
+ device = (libxl__json_object**)calloc(nb, sizeof(libxl__json_object*));
+ types = libxl__json_object_alloc(gc, JSON_ARRAY);
+ for ( i = 0; i < nb; i++ ) {
+ qmp_parameters_add_string(gc, &type[i], "type",
+ "blockdev-snapshot-internal-sync");
+ qmp_parameters_add_string(gc, &device[i], "device",
snapshot[i].device);
+ qmp_parameters_add_string(gc, &device[i], "name", snapshot[i].name);
+ qmp_parameters_common_add(gc, &type[i], "data", device[i]);
+ flexarray_append(types->u.array, (void*)type[i]);
+ }
+ qmp_parameters_common_add(gc, &args, "actions", types);
+ return qmp_run_command(gc, domid, "transaction", args, NULL, NULL);
+}
+
+int libxl__qmp_disk_snapshot_internal(libxl__gc *gc, int domid,
+ libxl_snapshot *snapshot)
+{
+ return libxl__qmp_disk_snapshot_transaction(gc, domid, snapshot, 1);
+}
+
+static int qmp_disk_snapshot_list_internal_callback(libxl__qmp_handler *qmp,
+ const libxl__json_object
*response,
+ void *opaque)
+{
+ const libxl__json_object *obj = NULL;
+ const libxl__json_object *label = NULL;
+ const libxl__json_object *insert_dev = NULL;
+ const libxl__json_object *image = NULL;
+ const libxl__json_object *snapshot_array = NULL;
+ const libxl__json_object *snapshot_node = NULL;
+ int i = 0;
+ int j = 0;
+ libxl_snapshot **snapshotp = (libxl_snapshot**)opaque;
+ char *device = strdup((*snapshotp)[0].device);
+ libxl_snapshot *snapshot;
+ int count;
+
+ for (i = 0; (obj = libxl__json_array_get(response, i)); i++) {
+ if (!libxl__json_object_is_map(obj))
+ continue;
+
+ label = libxl__json_map_get("device", obj, JSON_STRING);
+ if ( strcmp(libxl__json_object_get_string(label), device) )
+ continue;
+
+ insert_dev = libxl__json_map_get("inserted", obj, JSON_MAP);
+ if ( insert_dev == NULL ) {
+ goto not_found;
+ }
+
+ image = libxl__json_map_get("image", insert_dev, JSON_MAP);
+ if ( image == NULL ) {
+ goto not_found;
+ }
+
+ snapshot_array = libxl__json_map_get("snapshots", image, JSON_ARRAY);
+ if ( snapshot_array == NULL ) {
+ goto not_found;
+ }
+
+ count = libxl__json_object_get_array(snapshot_array)->count;
+ *snapshotp = realloc(*snapshotp, sizeof(libxl_snapshot)*(count + 1));
+ memset(*snapshotp, 0, sizeof(libxl_snapshot)*(count + 1));
+ for ( j = 0; j < count; j++ ) {
+ snapshot_node = libxl__json_array_get(snapshot_array, j);
+ snapshot = &(*snapshotp)[j];
+ snapshot->device = strdup(device);
+ label = libxl__json_map_get("id", snapshot_node, JSON_STRING);
+ snapshot->id = strdup(libxl__json_object_get_string(label));
+ label = libxl__json_map_get("name", snapshot_node, JSON_STRING);
+ snapshot->name = strdup(libxl__json_object_get_string(label));
+ label = libxl__json_map_get("vm-state-size", snapshot_node,
+ JSON_INTEGER);
+ snapshot->vm_state_size = libxl__json_object_get_integer(label);
+ label = libxl__json_map_get("date-sec", snapshot_node,
+ JSON_INTEGER);
+ snapshot->date_sec = libxl__json_object_get_integer(label);
+ label = libxl__json_map_get("date-nsec", snapshot_node,
+ JSON_INTEGER);
+ snapshot->date_nsec = libxl__json_object_get_integer(label);
+ label = libxl__json_map_get("vm-clock-sec", snapshot_node,
+ JSON_INTEGER);
+ snapshot->vm_clock_sec = libxl__json_object_get_integer(label);
+ label = libxl__json_map_get("vm-clock-nsec", snapshot_node,
+ JSON_INTEGER);
+ snapshot->vm_clock_nsec = libxl__json_object_get_integer(label);
+ }
+ goto found;
+ }
+not_found:
+ free((*snapshotp)[0].device);
+ (*snapshotp)[0].device = NULL;
+found:
+ free(device);
+ return 0;
+}
+
+int libxl__qmp_disk_snapshot_delete_internal(libxl__gc *gc, int domid,
+ libxl_snapshot *snapshot)
+{
+ libxl__json_object *args = NULL;
+
+ qmp_parameters_add_string(gc, &args, "device", snapshot->device);
+ if (snapshot->id)
+ qmp_parameters_add_string(gc, &args, "id", snapshot->id);
+ else if (snapshot->name)
+ qmp_parameters_add_string(gc, &args, "name", snapshot->name);
+ else
+ return -1;
+
+ return qmp_run_command(gc, domid, "blockdev-snapshot-delete-internal-sync",
+ args, NULL, NULL);
+}
+
+
+int libxl__qmp_disk_snapshot_list_internal(libxl__gc *gc, int domid,
+ libxl_snapshot **snapshotp)
+{
+ return qmp_run_command(gc, domid, "query-block", NULL,
+ qmp_disk_snapshot_list_internal_callback,
snapshotp);
+}
+
int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
const libxl_domain_config *guest_config)
{
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 612645c..ca4bf36 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -598,3 +598,15 @@ libxl_event = Struct("event",[
])),
("domain_create_console_available", Struct(None, [])),
]))])
+
+libxl_snapshot = Struct("snapshot",[
+ ("device", string),
+ ("name", string),
+ ("id", string),
+ ("vm_state_size", uint64),
+ ("date_sec", uint64),
+ ("date_nsec", uint64),
+ ("vm_clock_sec", uint64),
+ ("vm_clock_nsec", uint64),
+ ])
+
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 10a2e66..d3894c0 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -110,6 +110,9 @@ int main_loadpolicy(int argc, char **argv);
int main_remus(int argc, char **argv);
#endif
int main_devd(int argc, char **argv);
+int main_disk_snapshot_create(int argc, char **argv);
+int main_disk_snapshot_delete(int argc, char **argv);
+int main_disk_snapshot_list(int argc, char **argv);
void help(const char *command);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 8389468..215270e 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -7381,6 +7381,120 @@ out:
return ret;
}
+int main_disk_snapshot_create(int argc, char **argv) {
+ uint32_t domid;
+ int opt;
+ int rc = 0;
+ libxl_snapshot snapshot;
+ struct timeval timeval;
+
+ memset(&snapshot, 0, sizeof(libxl_snapshot));
+ SWITCH_FOREACH_OPT(opt, "n:", NULL, "disk-snapshot-create", 2) {
+ case 'n':
+ snapshot.name = strdup(optarg);
+ break;
+ }
+
+ if ( !snapshot.name ) {
+ snapshot.name = (char*)malloc(sizeof(time_t) * 8 + 1);
+ gettimeofday(&timeval, NULL);
+ sprintf(snapshot.name, "%ld", timeval.tv_sec);
+ }
+
+ if ( argc - optind != 2 ) {
+ fprintf(stderr, "no domain name and disk, exit!!!\n");
+ return -1;
+ }
+ domid = find_domain(argv[optind++]);
+ snapshot.device = strdup(argv[optind++]);
+ rc = libxl__disk_snapshot_create(ctx, domid, &snapshot);
+ libxl_snapshot_dispose(&snapshot);
+
+ return rc;
+}
+
+int main_disk_snapshot_delete(int argc, char **argv) {
+ uint32_t domid;
+ int opt;
+ int rc = 0;
+ libxl_snapshot snapshot;
+
+ memset(&snapshot, 0, sizeof(libxl_snapshot));
+ SWITCH_FOREACH_OPT(opt, "i:n:", NULL, "disk-snapshot-delete", 2) {
+ case 'i':
+ snapshot.id = strdup(optarg);
+ break;
+ case 'n':
+ snapshot.name = strdup(optarg);
+ break;
+ }
+
+ if ( snapshot.id == NULL && snapshot.name == NULL ) {
+ fprintf(stderr, "should provide id or name for deleting\n");
+ return -1;
+ }
+ domid = find_domain(argv[optind++]);
+ snapshot.device = strdup(argv[optind++]);
+ rc = libxl__disk_snapshot_delete(ctx, domid, &snapshot);
+ libxl_snapshot_dispose(&snapshot);
+
+ return rc;
+}
+
+int main_disk_snapshot_list(int argc, char **argv) {
+ uint32_t domid;
+ int opt;
+ libxl_snapshot *snapshot;
+ int rc = 0;
+ int i = 0;
+ struct tm *tm;
+ time_t time;
+
+ SWITCH_FOREACH_OPT(opt, "", NULL, "disk-snapshot-list", 2) {
+ /* No options */
+ }
+
+ snapshot = (libxl_snapshot*)malloc(sizeof(libxl_snapshot));
+ memset(snapshot, 0, sizeof(libxl_snapshot));
+ domid = find_domain(argv[optind++]);
+ snapshot[0].device = strdup(argv[optind++]);
+
+ rc = libxl__disk_snapshot_list(ctx, domid, &snapshot);
+ if (snapshot[0].device == NULL ) {
+ fprintf(stderr, "snapshot on this device does not exist\n");
+ rc = -1;
+ goto error;
+ }
+ if (snapshot[0].name == NULL && snapshot[0].id == NULL ) {
+ fprintf(stderr, "no this device: %s\n", snapshot[0].device);
+ rc = -1;
+ goto error;
+ }
+ printf("Snapshot list:\n");
+ printf("ID TAG VM SIZE DATE"
+ " VM CLOCK\n");
+ while(snapshot[i].name != NULL && snapshot[i].id != NULL ) {
+ printf("%-10s", snapshot[i].id);
+ printf("%-20s", snapshot[i].name);
+ printf("%7lu", snapshot[i].vm_state_size);
+ time = (time_t)snapshot[i].date_sec;
+ tm = gmtime(&time);
+ printf(" %04d-%02d-%02d %02d:%02d:%02d", tm->tm_year + 1900,
tm->tm_mon + 1,
+ tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
+ printf(" %02lu:%02lu:%02lu.%03lu\n", snapshot[i].vm_clock_sec / 3600,
+ snapshot[i].vm_clock_sec / 60, snapshot[i].vm_clock_sec % 60,
+ snapshot[i].vm_clock_nsec / 1000000);
+ libxl_snapshot_dispose(&snapshot[i]);
+ i++;
+ }
+ goto exit;
+error:
+ libxl_snapshot_dispose(&snapshot[0]);
+exit:
+ free(snapshot);
+ return rc;
+}
+
/*
* Local variables:
* mode: C
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index e8ab93a..930da22 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -497,6 +497,24 @@ struct cmd_spec cmd_table[] = {
"[options]",
"-F Run in the foreground",
},
+ { "disk-snapshot-create",
+ &main_disk_snapshot_create, 0, 1,
+ "Do domain disk snapshot create",
+ "[-n] <Domain>",
+ " -n name snapshot name. if ignore, use second
from Epoch",
+ },
+ { "disk-snapshot-delete",
+ &main_disk_snapshot_delete, 0, 1,
+ "Do domain disk snapshot delete",
+ "[-n|-i] <Domain> <device>",
+ " -n name snapshot name\n"
+ " -i id snapshot id",
+ },
+ { "disk-snapshot-list",
+ &main_disk_snapshot_list, 0, 1,
+ "Do domain disk snapshot list",
+ "<Domain> <device>",
+ },
};
int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
--
1.8.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |