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