From 35c6ca05d8ee0e1be1b67ac64d32c21b195aaeea Mon Sep 17 00:00:00 2001 From: Sachin Pandit Date: Mon, 23 Jun 2014 09:35:52 +0530 Subject: 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 *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: 1112613 Signed-off-by: Sachin Pandit Reviewed-on: http://review.gluster.org/8162 Reviewed-by: Atin Mukherjee Tested-by: Gluster Build System Reviewed-by: Avra Sengupta Reviewed-by: Raghavendra Bhat Reviewed-by: Kaushal M --- xlators/mgmt/glusterd/src/glusterd-snapshot.c | 211 +++++++++++++++++++++++--- 1 file changed, 186 insertions(+), 25 deletions(-) (limited to 'xlators') diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index b40d7abc408..2f9f68e97e1 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -3123,15 +3123,10 @@ glusterd_snapshot_get_vol_snapnames (dict_t *dict, glusterd_volinfo_t *volinfo) list_for_each_entry_safe (snap_vol, tmp_vol, &volinfo->snap_volumes, snapvol_list) { snapcount++; - snapname = gf_strdup (snap_vol->snapshot->snapname); - if (!snapname) { - gf_log (this->name, GF_LOG_ERROR, - "strdup failed"); - ret = -1; - goto out; - } snprintf (key, sizeof (key), "snapname%d", snapcount); - ret = dict_set_dynstr (dict, key, snapname); + + ret = dict_set_dynstr_with_alloc (dict, key, + snap_vol->snapshot->snapname); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to " "set %s", key); @@ -4472,23 +4467,104 @@ out: return ret; } -/* This is a snapshot remove handler function. This function will be - * executed in the originator node. This function is responsible for - * calling mgmt v3 framework to do the actual remove on all the bricks - * - * @param req RPC request object - * @param op gluster operation - * @param dict dictionary containing snapshot remove request - * @param err_str In case of an err this string should be populated - * @param len length of err_str buffer - * - * @return Negative value on Failure and 0 in success - */ -int -glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op, - dict_t *dict, char *err_str, size_t len) +int32_t +glusterd_handle_snapshot_delete_vol (dict_t *dict, char *err_str, int len) { - int ret = -1; + int32_t ret = -1; + int32_t i = 0; + glusterd_volinfo_t *snap_volinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_volinfo_t *temp_volinfo = NULL; + char key[PATH_MAX] = ""; + xlator_t *this = NULL; + char *volname = NULL; + + this = THIS; + GF_ASSERT (this); + GF_ASSERT (dict); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get " + "volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + snprintf (err_str, len, "Volume (%s) does not exist", volname); + gf_log (this->name, GF_LOG_ERROR, "Failed to get volinfo of " + "volume %s", volname); + goto out; + } + + ret = glusterd_snapshot_get_vol_snapnames (dict, volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to get snapshot list for volume %s", volname); + goto out; + } + + ret = 0; +out: + return ret; +} + +int32_t +glusterd_handle_snapshot_delete_all (dict_t *dict) +{ + int32_t ret = -1; + int32_t i = 0; + char key[PATH_MAX] = ""; + glusterd_conf_t *priv = NULL; + glusterd_snap_t *snap = NULL; + glusterd_snap_t *tmp_snap = NULL; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + + GF_ASSERT (dict); + + list_for_each_entry_safe (snap, tmp_snap, &priv->snapshots, snap_list) { + /* indexing from 1 to n, to keep it uniform with other code + * paths + */ + i++; + ret = snprintf (key, sizeof (key), "snapname%d", i); + if (ret < 0) { + goto out; + } + + ret = dict_set_dynstr_with_alloc (dict, key, snap->snapname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Could not save " + "snap name"); + goto out; + } + } + + ret = dict_set_int32 (dict, "snapcount", i); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Could not save snapcount"); + goto out; + } + + ret = 0; + +out: + return ret; +} + +int32_t +glusterd_handle_snapshot_delete_type_snap (rpcsvc_request_t *req, + glusterd_op_t op, + dict_t *dict, char *err_str, + size_t len) +{ + int32_t ret = -1; int64_t volcount = 0; char *snapname = NULL; char *volname = NULL; @@ -4499,6 +4575,7 @@ glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op, xlator_t *this = NULL; this = THIS; + GF_ASSERT (this); GF_ASSERT (req); GF_ASSERT (dict); @@ -4553,6 +4630,90 @@ glusterd_handle_snapshot_remove (rpcsvc_request_t *req, glusterd_op_t op, } ret = 0; + +out : + return ret; +} + +/* This is a snapshot remove handler function. This function will be + * executed in the originator node. This function is responsible for + * calling mgmt v3 framework to do the actual remove on all the bricks + * + * @param req RPC request object + * @param op gluster operation + * @param dict dictionary containing snapshot remove request + * @param err_str In case of an err this string should be populated + * @param len length of err_str buffer + * + * @return Negative value on Failure and 0 in success + */ +int +glusterd_handle_snapshot_delete (rpcsvc_request_t *req, glusterd_op_t op, + dict_t *dict, char *err_str, size_t len) +{ + int ret = -1; + xlator_t *this = NULL; + int32_t delete_cmd = -1; + + this = THIS; + + GF_ASSERT (this); + + GF_ASSERT (req); + GF_ASSERT (dict); + GF_ASSERT (err_str); + + ret = dict_get_int32 (dict, "delete-cmd", &delete_cmd); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get delete-cmd"); + goto out; + } + + switch (delete_cmd) { + case GF_SNAP_DELETE_TYPE_SNAP: + ret = glusterd_handle_snapshot_delete_type_snap (req, op, dict, + err_str, len); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to handle " + "snapshot delete for type SNAP"); + goto out; + } + break; + + case GF_SNAP_DELETE_TYPE_ALL: + ret = glusterd_handle_snapshot_delete_all (dict); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to handle " + "snapshot delete for type ALL"); + goto out; + } + break; + + case GF_SNAP_DELETE_TYPE_VOL: + ret = glusterd_handle_snapshot_delete_vol (dict, err_str, len); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to handle " + "snapshot delete for type VOL"); + goto out; + } + break; + + default: + gf_log (this->name, GF_LOG_ERROR, "Wrong snapshot delete type"); + break; + } + + if ( ret == 0 && (delete_cmd == GF_SNAP_DELETE_TYPE_ALL || + delete_cmd == GF_SNAP_DELETE_TYPE_VOL)) { + ret = glusterd_op_send_cli_response (op, 0, 0, req, dict, + err_str); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to send cli " + "response"); + goto out; + } + } + ret = 0; out: return ret; } @@ -7343,7 +7504,7 @@ glusterd_handle_snapshot_fn (rpcsvc_request_t *req) } break; case GF_SNAP_OPTION_TYPE_DELETE: - ret = glusterd_handle_snapshot_remove (req, cli_op, dict, + ret = glusterd_handle_snapshot_delete (req, cli_op, dict, err_str, sizeof (err_str)); if (ret) { -- cgit