diff options
author | Sachin Pandit <spandit@redhat.com> | 2014-06-23 09:35:52 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-09-23 02:01:04 -0700 |
commit | c5aa277ec26cd7cf4109bc8854af50a254edbbd9 (patch) | |
tree | ecb9237e41389075052c5c36ca2f2c958e1092c8 /cli | |
parent | cde7cf45c49a59a688788abc0358c482e30f4018 (diff) |
feature/snapshot : Interface to delete all snapshots belonging to a system as-well-as to a particular volume
Problem :
With the current design we can only delete a single snapshot.
And the deletion of volume which contains snapshot is not allowed.
Because of that user might be forced to delete all the snapshots
manually before he is allowed to delete a volume.
Solution:
Following is the interface with which user can delete
all the snapshots of a system or belonging to a particular volume.
Syntax : gluster snapshot delete all
*To delete all the snapshots present in a system
Syntax : gluster snapshot delete volume <volname>
*To deletes all the snapshot present in a volume specified.
========================================================================
Sample Output:
Case 1 : Deleting a single snapshot.
[root@snapshot-24 glusterfs]# gluster snapshot delete snap1
Deleting snap will erase all the information about the snap. Do you still want to continue? (y/n) y
snapshot delete: snap1: snap removed successfully
-----------------------------------------------------------------
Case 2 : Deleting all the snapshots in a Volume.
[root@snapshot-24 glusterfs]# gluster snapshot delete volume vol1
Volume (vol1) contains 9 snapshot(s).
Do you still want to continue and delete them? (y/n) y
snapshot delete: snap2: snap removed successfully
snapshot delete: snap3: snap removed successfully
snapshot delete: snap4: snap removed successfully
snapshot delete: snap5: snap removed successfully
.
.
.
-----------------------------------------------------------------
Case 3 : Deleting all the snapshots in a system.
[root@snapshot-24 glusterfs]# gluster snapshot delete all
System contains 4 snapshot(s).
Do you still want to continue and delete them? (y/n) y
snapshot delete: snap7: snap removed successfully
snapshot delete: snap8: snap removed successfully
snapshot delete: snap9: snap removed successfully
snapshot delete: snap10: snap removed successfully
========================================================================
Change-Id: Ifec8e128ab2011cbbba208376b9c92cfbe7d8d71
BUG: 1145083
Signed-off-by: Sachin Pandit <spandit@redhat.com>
Reviewed-on: http://review.gluster.org/8162
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Avra Sengupta <asengupt@redhat.com>
Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
Reviewed-by: Kaushal M <kaushal@redhat.com>
Signed-off-by: Sachin Pandit <spandit@redhat.com>
Reviewed-on: http://review.gluster.org/8798
Reviewed-by: Vijaikumar Mallikarjuna <vmallika@redhat.com>
Diffstat (limited to 'cli')
-rw-r--r-- | cli/src/cli-cmd-parser.c | 73 | ||||
-rw-r--r-- | cli/src/cli-cmd-snapshot.c | 2 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 216 |
3 files changed, 268 insertions, 23 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index b4dc3fe49bd..4811293dbb8 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -3422,7 +3422,7 @@ cli_snap_info_parse (dict_t *dict, const char **words, int wordcount) GF_ASSERT (dict); if (wordcount > 4 || wordcount < cmdi) { - gf_log ("", GF_LOG_ERROR, "Invalid syntax"); + gf_log ("cli", GF_LOG_ERROR, "Invalid syntax"); goto out; } @@ -3473,7 +3473,7 @@ cli_snap_info_parse (dict_t *dict, const char **words, int wordcount) ret = dict_set_str (dict, "volname", (char *)words[wordcount - 1]); if (ret) { - gf_log ("", GF_LOG_ERROR, "Count not save " + gf_log ("cli", GF_LOG_ERROR, "Could not save " "volume name %s", words[wordcount - 1]); goto out; } @@ -3634,34 +3634,71 @@ cli_snap_delete_parse (dict_t *dict, const char **words, int wordcount, int ret = -1; const char *question = NULL; + int32_t cmd = -1; + unsigned int cmdi = 2; gf_answer_t answer = GF_ANSWER_NO; - question = "Deleting snap will erase all the information about " - "the snap. Do you still want to continue?"; - GF_ASSERT (words); GF_ASSERT (dict); - if (wordcount != 3) { + if (wordcount > 4 || wordcount <= cmdi) { gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } - ret = dict_set_str (dict, "snapname", (char *)words[2]); - if (ret) { - gf_log ("cli", GF_LOG_ERROR, "Unable to save snapname %s", - words[2]); - goto out; + question = "Deleting snap will erase all the information about " + "the snap. Do you still want to continue?"; + + if (strcmp (words [cmdi], "all") == 0) { + ret = 0; + cmd = GF_SNAP_DELETE_TYPE_ALL; + } else if (strcmp (words [cmdi], "volume") == 0) { + if (++cmdi == wordcount) { + ret = -1; + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); + goto out; + } + + ret = dict_set_str (dict, "volname", + (char *)words[cmdi]); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not save " + "volume name %s", words[wordcount - 1]); + goto out; + } + cmd = GF_SNAP_DELETE_TYPE_VOL; + } else { + ret = dict_set_str (dict, "snapname", (char *)words[cmdi]); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to save " + "snapname %s", words[2]); + goto out; + } + cmd = GF_SNAP_DELETE_TYPE_SNAP; } - answer = cli_cmd_get_confirmation (state, question); - if (GF_ANSWER_NO == answer) { - ret = 1; - gf_log ("cli", GF_LOG_DEBUG, "User cancelled " - "snapshot delete operation for snap %s", - (char *)words[2]); + if ((cmdi + 1) != wordcount) { + ret = -1; + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); goto out; } + + if (cmd == GF_SNAP_DELETE_TYPE_SNAP) { + answer = cli_cmd_get_confirmation (state, question); + if (GF_ANSWER_NO == answer) { + ret = 1; + gf_log ("cli", GF_LOG_DEBUG, "User cancelled " + "snapshot delete operation for snap %s", + (char *)words[2]); + goto out; + } + } + + ret = dict_set_int32 (dict, "delete-cmd", cmd); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not save " + "type of snapshot delete"); + } out: return ret; } @@ -4000,7 +4037,7 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, "activate", "deactivate", "list", "status", "config", "info", NULL}; char *invalid_snapnames[] = {"description", "force", - "volume", NULL}; + "volume", "all", NULL}; GF_ASSERT (words); GF_ASSERT (options); diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c index 1fb4e5e634c..07d04595b06 100644 --- a/cli/src/cli-cmd-snapshot.c +++ b/cli/src/cli-cmd-snapshot.c @@ -108,7 +108,7 @@ struct cli_cmd snapshot_cmds[] = { cli_cmd_snapshot_cbk, "Snapshot Config." }, - {"snapshot delete <snapname>", + {"snapshot delete (all | snapname | volume <volname>)", cli_cmd_snapshot_cbk, "Snapshot Delete." }, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index a240f376f7f..268f5434a75 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -7721,11 +7721,14 @@ out: } int32_t -cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict) +cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict, call_frame_t *frame) { - int32_t ret = -1; - char *snap_name = NULL; + int32_t ret = -1; + char *snap_name = NULL; + int32_t delete_cmd = -1; + cli_local_t *local = NULL; + GF_ASSERT (frame); GF_ASSERT (rsp); GF_ASSERT (dict); @@ -7737,6 +7740,31 @@ cli_snapshot_remove_reply (gf_cli_rsp *rsp, dict_t *dict) goto out; } + ret = dict_get_int32 (dict, "delete-cmd", &delete_cmd); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not get delete-cmd"); + goto out; + } + + if (delete_cmd == GF_SNAP_DELETE_TYPE_ALL || + delete_cmd == GF_SNAP_DELETE_TYPE_VOL) { + local = ((call_frame_t *) frame) -> local; + if (!local) { + ret = -1; + gf_log ("cli", GF_LOG_ERROR, "frame->local is NULL"); + goto out; + } + + /* During first call back of snapshot delete of type + * ALL and VOL, We will get the snapcount and snapnames. + * Hence to make the subsequent rpc calls for individual + * snapshot delete, We need to save it in local dictionary. + */ + dict_copy (dict, local->dict); + ret = 0; + goto out; + } + ret = dict_get_str (dict, "snapname", &snap_name); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname"); @@ -8455,6 +8483,60 @@ out: return ret; } +int32_t +cli_populate_req_dict_for_delete (dict_t *snap_dict, dict_t *dict, size_t index) +{ + int32_t ret = -1; + char key[PATH_MAX] = ""; + char *buffer = NULL; + int type = 0; + int snapcount = 0; + + GF_ASSERT (snap_dict); + GF_ASSERT (dict); + + ret = dict_set_int32 (snap_dict, "delete-cmd", + GF_SNAP_DELETE_TYPE_SNAP); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not save command " + "type in snap dictionary"); + goto out; + } + + ret = snprintf (key, sizeof (key), "snapname%lu", index); + if (ret < 0) { + goto out; + } + + ret = dict_get_str (dict, key, &buffer); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to get snapname"); + goto out; + } + + ret = dict_set_dynstr_with_alloc (snap_dict, "snapname", buffer); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to save snapname"); + goto out; + } + + ret = dict_set_int32 (snap_dict, "type", GF_SNAP_OPTION_TYPE_DELETE); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to save command type"); + goto out; + } + + ret = dict_set_dynstr_with_alloc (snap_dict, "cmd-str", + "snapshot delete"); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "Could not save command string as delete"); + goto out; + } +out: + return ret; +} + int cli_populate_req_dict_for_status (dict_t *snap_dict, dict_t *dict, int index) { int ret = -1; @@ -8820,7 +8902,7 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov, break; case GF_SNAP_OPTION_TYPE_DELETE: - ret = cli_snapshot_remove_reply (&rsp, dict); + ret = cli_snapshot_remove_reply (&rsp, dict, frame); if (ret) { gf_log ("cli", GF_LOG_ERROR, "Failed to delete snap"); @@ -8854,6 +8936,123 @@ out: } int32_t +gf_cli_snapshot_for_delete (call_frame_t *frame, xlator_t *this, + void *data) +{ + gf_cli_req req = {{0,}}; + dict_t *options = NULL; + int32_t ret = -1; + int32_t cmd = -1; + cli_local_t *local = NULL; + dict_t *snap_dict = NULL; + int32_t snapcount = 0; + int i = 0; + char question[PATH_MAX] = ""; + char *volname = NULL; + gf_answer_t answer = GF_ANSWER_NO; + + GF_VALIDATE_OR_GOTO ("cli", frame, out); + GF_VALIDATE_OR_GOTO ("cli", frame->local, out); + GF_VALIDATE_OR_GOTO ("cli", this, out); + GF_VALIDATE_OR_GOTO ("cli", data, out); + + local = frame->local; + + options = data; + + ret = dict_get_int32 (local->dict, "delete-cmd", &cmd); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to get " + "delete-cmd"); + goto out; + } + + /* No need multiple RPCs for individual snapshot delete*/ + if (cmd == GF_SNAP_DELETE_TYPE_SNAP) { + ret = 0; + goto out; + } + + ret = dict_get_int32 (local->dict, "snapcount", + &snapcount); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not get " + "snapcount"); + goto out; + } + + if (snapcount == 0) { + cli_out ("No snapshots present"); + goto out; + } + + if (cmd == GF_SNAP_DELETE_TYPE_ALL) { + snprintf (question, sizeof (question), "System contains %d " + "snapshot(s).\nDo you still " + "want to continue and delete them? ", + snapcount); + } else { + ret = dict_get_str (local->dict, "volname", &volname); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to fetch " + "volname from local dictionary"); + goto out; + } + + snprintf (question, sizeof (question), "Volume (%s) contains " + "%d snapshot(s).\nDo you still want to " + "continue and delete them? ", volname, + snapcount); + } + + answer = cli_cmd_get_confirmation (global_state, question); + if (GF_ANSWER_NO == answer) { + ret = 0; + gf_log ("cli", GF_LOG_DEBUG, "User cancelled " + "snapshot delete operation for snap delete"); + goto out; + } + + for (i = 1 ; i <= snapcount ; i++) { + ret = -1; + + snap_dict = dict_new(); + if (!snap_dict) + goto out; + + ret = cli_populate_req_dict_for_delete (snap_dict, + local->dict, i); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not " + "populate snap request dictionary"); + goto out; + } + + ret = cli_to_glusterd (&req, frame, + gf_cli_snapshot_cbk, + (xdrproc_t) xdr_gf_cli_req, snap_dict, + GLUSTER_CLI_SNAP, this, cli_rpc_prog, + NULL); + if (ret) { + /* Fail the operation if deleting one of the + * snapshots is failed + */ + gf_log ("cli", GF_LOG_ERROR, "cli_to_glusterd " + "for snapshot delete failed"); + goto out; + } + dict_unref (snap_dict); + snap_dict = NULL; + } + +out: + if (snap_dict) + dict_unref (snap_dict); + + return ret; +} + +int32_t gf_cli_snapshot_for_status (call_frame_t *frame, xlator_t *this, void *data) { @@ -9007,6 +9206,15 @@ gf_cli_snapshot (call_frame_t *frame, xlator_t *this, } } + if (GF_SNAP_OPTION_TYPE_DELETE == type) { + ret = gf_cli_snapshot_for_delete (frame, this, data); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "cli to glusterd " + "for snapshot delete command failed"); + goto out; + } + } + ret = 0; out: |