[sheepdog] [PATCH v3 11/12] collie: implement "collie cluster snapshot" subcommand
Kai Zhang
kyle at zelin.io
Tue May 14 09:51:56 CEST 2013
Command example:
collie cluster snapshot save /localpath
collie cluster snapshot list /localpath
collie cluster snapshot load /localpath
Signed-off-by: Kai Zhang <kyle at zelin.io>
---
collie/cluster.c | 132 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 126 insertions(+), 6 deletions(-)
diff --git a/collie/cluster.c b/collie/cluster.c
index fa2e131..9a0cf6a 100644
--- a/collie/cluster.c
+++ b/collie/cluster.c
@@ -15,14 +15,15 @@
#include <sys/time.h>
#include "collie.h"
+#include "farm/farm.h"
static struct sd_option cluster_options[] = {
{'b', "store", true, "specify backend store"},
{'c', "copies", true, "specify the default data redundancy (number of copies)"},
{'m', "mode", true, "mode (safe, quorum, unsafe)"},
{'f', "force", false, "do not prompt for confirmation"},
- {'R', "restore", true, "restore the cluster"},
- {'l', "list", false, "list the user epoch information"},
+ {'e', "epoch", true, "specify epoch to be loaded to new cluster."
+ " default is to load the last epoch"},
{ 0, NULL, false, NULL },
};
@@ -223,6 +224,110 @@ static int cluster_shutdown(int argc, char **argv)
return EXIT_SUCCESS;
}
+static void print_list(void *buf, unsigned len)
+{
+ struct snap_log *log_buf = (struct snap_log *)buf;
+ unsigned nr = len / sizeof(struct snap_log), i;
+
+ printf("Index\t\tSnapshot Time\n");
+ for (i = 0; i < nr; i++, log_buf++) {
+ time_t *t = (time_t *)&log_buf->time;
+ printf("%d\t\t", log_buf->epoch);
+ printf("%s", ctime(t));
+ }
+}
+
+static int list_snapshot(int argc, char **argv)
+{
+ char *path = argv[optind++];
+ void *buf = NULL;
+ int log_nr;
+ int ret = EXIT_SYSFAIL;
+
+ if (farm_init(path) != SD_RES_SUCCESS)
+ goto out;
+
+ buf = snap_log_read(&log_nr);
+ if (!buf)
+ goto out;
+
+ print_list(buf, log_nr * sizeof(struct snap_log));
+ ret = EXIT_SUCCESS;
+out:
+ if (ret)
+ sd_eprintf("fail to list snapshot");
+ free(buf);
+ return ret;
+}
+
+static void fill_obj_tree(uint32_t vid, const char *name, const char *tag,
+ uint32_t snapid, uint32_t flags,
+ const struct sd_inode *i, void *data)
+{
+ uint64_t vdi_oid = vid_to_vdi_oid(vid);
+
+ /* ignore active vdi */
+ if (!i->snap_ctime)
+ return;
+
+ obj_tree_insert(vdi_oid, VDI, i->nr_copies);
+
+ for (int idx = 0; idx < MAX_DATA_OBJS; idx++) {
+ if (i->data_vdi_id[idx]) {
+ uint64_t oid = vid_to_data_oid(i->data_vdi_id[idx],
+ idx);
+ obj_tree_insert(oid, OBJECT, i->nr_copies);
+ }
+ }
+}
+
+static int save_snapshot(int argc, char **argv)
+{
+ char *path = argv[optind++];
+ int ret = EXIT_SYSFAIL;
+
+ sd_dprintf("saving cluster snapshop to path: %s", path);
+
+ if (parse_vdi(fill_obj_tree, SD_INODE_SIZE, NULL) != SD_RES_SUCCESS)
+ goto out;
+
+ if (farm_init(path) != SD_RES_SUCCESS)
+ goto out;
+
+ if (farm_save_snapshot() != SD_RES_SUCCESS)
+ goto out;
+
+ ret = EXIT_SUCCESS;
+out:
+ if (ret)
+ sd_eprintf("fail to save snapshot to path: %s", path);
+ free_obj_tree();
+ return ret;
+}
+
+static int load_snapshot(int argc, char **argv)
+{
+ char *path = argv[optind++];
+ int ret = EXIT_SYSFAIL;
+
+ sd_dprintf("loading cluster snapshot from path: %s", path);
+
+ if (farm_init(path) != SD_RES_SUCCESS)
+ goto out;
+
+ if (cluster_format(0, NULL) != SD_RES_SUCCESS)
+ goto out;
+
+ if (farm_load_snapshot(cluster_cmd_data.epoch) != SD_RES_SUCCESS)
+ goto out;
+
+ ret = EXIT_SUCCESS;
+out:
+ if (ret)
+ sd_eprintf("fail to load snapshot");
+ return ret;
+}
+
#define RECOVER_PRINT \
"Caution! Please try starting all the cluster nodes normally before\n" \
"running this command.\n\n" \
@@ -315,6 +420,21 @@ static int cluster_recover(int argc, char **argv)
return do_generic_subcommand(cluster_recover_cmd, argc, argv);
}
+/* Subcommand list of snapshot */
+static struct subcommand cluster_snapshot_cmd[] = {
+ {"save", NULL, "eh", "save snapshot to localpath",
+ NULL, 0, save_snapshot, cluster_options},
+ {"list", NULL, "eh", "list snapshot of localpath",
+ NULL, 0, list_snapshot, NULL},
+ {"load", NULL, "eh", "list snapshot of localpath",
+ NULL, 0, load_snapshot, NULL}
+};
+
+static int cluster_snapshot(int argc, char **argv)
+{
+ return do_generic_subcommand(cluster_snapshot_cmd, argc, argv);
+}
+
static struct subcommand cluster_cmd[] = {
{"info", NULL, "aprh", "show cluster information",
NULL, SUBCMD_FLAG_NEED_NODELIST, cluster_info, cluster_options},
@@ -322,6 +442,9 @@ static struct subcommand cluster_cmd[] = {
NULL, 0, cluster_format, cluster_options},
{"shutdown", NULL, "aph", "stop Sheepdog",
NULL, 0, cluster_shutdown, cluster_options},
+ {"snapshot", "<path>", "aeph", "snapshot/restore the cluster",
+ cluster_snapshot_cmd, SUBCMD_FLAG_NEED_ARG,
+ cluster_snapshot, cluster_options},
{"recover", NULL, "afph",
"See 'collie cluster recover' for more information\n",
cluster_recover_cmd, SUBCMD_FLAG_NEED_ARG,
@@ -369,7 +492,7 @@ static int cluster_parser(int ch, char *opt)
case 'f':
cluster_cmd_data.force = true;
break;
- case 'R':
+ case 'e':
cluster_cmd_data.epoch = strtol(opt, &p, 10);
if (opt == p) {
fprintf(stderr, "The epoch must be an integer\n");
@@ -380,9 +503,6 @@ static int cluster_parser(int ch, char *opt)
exit(EXIT_FAILURE);
}
break;
- case 'l':
- cluster_cmd_data.list = true;
- break;
}
return 0;
--
1.7.1
More information about the sheepdog
mailing list