[sheepdog] [PATCH 1/2] collie: add command 'collie vdi rollback'

levin li levin108 at gmail.com
Thu Aug 30 07:59:54 CEST 2012


From: levin li <xingke.lwp at taobao.com>

With this command we can rollback a cloned VDI to any specified
snapshot, or easily reset to its parent VDI, the usage is easy.

To rollback to a specified snapshot:

$ collie vdi rollback -s 1 base_vdi clone_vdi

To reset to its parent:

$ collie vdi rollback clone_vdi

Signed-off-by: levin li <xingke.lwp at taobao.com>
---
 collie/vdi.c             |   88 ++++++++++++++++++++++++++++++++++++++++++++++
 include/internal_proto.h |    1 +
 2 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/collie/vdi.c b/collie/vdi.c
index 2e01091..77cdd80 100644
--- a/collie/vdi.c
+++ b/collie/vdi.c
@@ -752,6 +752,91 @@ static int vdi_delete(int argc, char **argv)
 	return EXIT_SUCCESS;
 }
 
+static int do_vdi_rollback(uint32_t vid, uint32_t snap_vid)
+{
+	int ret, fd;
+	struct sd_req hdr;
+	struct sd_rsp *rsp = (struct sd_rsp *)&hdr;
+	unsigned int rlen, wlen = sizeof(vid);
+
+	fd = connect_to(sdhost, sdport);
+	if (fd < 0) {
+		fprintf(stderr, "Failed to connect to %s:%d\n",
+			sdhost, sdport);
+		return SD_RES_NETWORK_ERROR;
+	}
+
+	sd_init_req(&hdr, SD_OP_ROLLBACK_VDI);
+	hdr.vdi.base_vdi_id = snap_vid;
+	hdr.data_length = wlen;
+	hdr.flags = SD_FLAG_CMD_WRITE;
+
+	ret = exec_req(fd, &hdr, &vid, &wlen, &rlen);
+	close(fd);
+
+	if (ret) {
+		fprintf(stderr, "Failed to connect to %s:%d\n",
+			sdhost, sdport);
+		return SD_RES_NETWORK_ERROR;
+	}
+
+	return rsp->result;
+}
+
+static int vdi_rollback(int argc, char **argv)
+{
+	int ret, has_dest;
+	char *vdiname;
+	char *snap_vdiname = NULL;
+	uint32_t vid, snap_vid = 0;
+	struct sheepdog_inode inode;
+
+	if (!vdi_cmd_data.snapshot_id && !vdi_cmd_data.snapshot_tag[0]) {
+		vdiname = argv[optind++];
+		has_dest = 0;
+	} else {
+		snap_vdiname = argv[optind++];
+		vdiname = argv[optind++];
+		has_dest = 1;
+	}
+
+	ret = find_vdi_name(vdiname, 0, "", &vid, 0);
+	if (ret != SD_RES_SUCCESS) {
+		fprintf(stderr, "Failed to read VDI %s\n", vdiname);
+		return EXIT_FAILURE;
+	}
+
+	if (has_dest) {
+		ret = find_vdi_name(snap_vdiname, vdi_cmd_data.snapshot_id,
+				    vdi_cmd_data.snapshot_tag, &snap_vid, 0);
+		if (ret != SD_RES_SUCCESS) {
+			fprintf(stderr, "Failed to read snapshot %s\n",
+				snap_vdiname);
+			return EXIT_FAILURE;
+		}
+	}
+
+	ret = sd_read_object(vid_to_vdi_oid(vid), &inode, sizeof(inode), 0);
+	if (ret != SD_RES_SUCCESS) {
+		fprintf(stderr, "Failed to read VDI object %s\n", vdiname);
+		return EXIT_FAILURE;
+	}
+
+	if (inode.snap_id != 1 || inode.parent_vdi_id == 0) {
+		fprintf(stderr, "Can not rollback a non-cloned VDI\n");
+		return EXIT_FAILURE;
+	}
+
+	if (!has_dest)
+		snap_vid = inode.parent_vdi_id;
+
+	ret = do_vdi_rollback(vid, snap_vid);
+	if (ret != SD_RES_SUCCESS)
+		return EXIT_FAILURE;
+
+	return EXIT_SUCCESS;
+}
+
 static int vdi_object(int argc, char **argv)
 {
 	char *vdiname = argv[optind];
@@ -1537,6 +1622,9 @@ static struct subcommand vdi_cmd[] = {
 	{"delete", "<vdiname>", "saph", "delete an image",
 	 NULL, SUBCMD_FLAG_NEED_THIRD_ARG,
 	 vdi_delete, vdi_options},
+	{"rollback", "<snapshot vdiname> <vdiname> ", "saph", "rollback to a snapshot",
+	 NULL, SUBCMD_FLAG_NEED_THIRD_ARG,
+	 vdi_rollback, vdi_options},
 	{"list", "[vdiname]", "aprh", "list images",
 	 NULL, 0, vdi_list, vdi_options},
 	{"tree", NULL, "aph", "show images in tree view format",
diff --git a/include/internal_proto.h b/include/internal_proto.h
index c1d116a..a8b3c69 100644
--- a/include/internal_proto.h
+++ b/include/internal_proto.h
@@ -65,6 +65,7 @@
 #define SD_OP_INFO_RECOVER 0xAA
 #define SD_OP_GET_VDI_COPIES 0xAB
 #define SD_OP_COMPLETE_RECOVERY 0xAC
+#define SD_OP_ROLLBACK_VDI   0xAD
 
 /* internal flags for hdr.flags, must be above 0x80 */
 #define SD_FLAG_CMD_RECOVERY 0x0080
-- 
1.7.1




More information about the sheepdog mailing list