diff options
-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 | ||||
-rw-r--r-- | rpc/xdr/src/cli1-xdr.x | 6 | ||||
-rw-r--r-- | tests/bugs/bug-1087203.t | 61 | ||||
-rw-r--r-- | tests/bugs/bug-1112613.t | 49 | ||||
-rwxr-xr-x | tests/snapshot.rc | 66 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 211 |
8 files changed, 588 insertions, 96 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 85a916e380..a0b873d235 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -3424,7 +3424,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; } @@ -3475,7 +3475,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; } @@ -3636,34 +3636,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; } @@ -4002,7 +4039,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 1fb4e5e634..07d04595b0 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 6728c9c4e6..187fcc1bee 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; @@ -8818,7 +8900,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"); @@ -8852,6 +8934,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) { @@ -9005,6 +9204,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: diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 3a9841934c..f7bfcf469d 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -172,6 +172,12 @@ enum gf1_cli_snapshot_status { GF_SNAP_STATUS_TYPE_VOL }; +enum gf1_cli_snapshot_delete { + GF_SNAP_DELETE_TYPE_ALL = 0, + GF_SNAP_DELETE_TYPE_SNAP = 1, + GF_SNAP_DELETE_TYPE_VOL = 2 +}; + struct gf_cli_req { opaque dict<>; }; diff --git a/tests/bugs/bug-1087203.t b/tests/bugs/bug-1087203.t index 585ecf440a..e41d601fb6 100644 --- a/tests/bugs/bug-1087203.t +++ b/tests/bugs/bug-1087203.t @@ -5,50 +5,12 @@ . $(dirname $0)/../snapshot.rc . $(dirname $0)/../cluster.rc -function config_validate () -{ - local var=$1 - $CLI_1 snapshot config | grep "^$var" | sed 's/.*: //' -} - -function snap_create () -{ - local limit=$1; - local i=0 - while [ $i -lt $limit ] - do - $CLI_1 snapshot create snap$i ${V0} - i=$[$i+1] - done -} - -function snap_delete () -{ - local limit=$1; - local i=0 - while [ $i -lt $limit ] - do - $CLI_1 snapshot delete snap$i - i=$[$i+1] - done -} - -function get_snap_count () -{ - $CLI_1 snapshot list | wc -l -} - function get_volume_info () { local var=$1 $CLI_1 volume info $V0 | grep "^$var" | sed 's/.*: //' } -function is_snapshot_present () -{ - $CLI_1 snapshot list -} - cleanup; TEST verify_lvm_version @@ -94,7 +56,7 @@ TEST $CLI_1 snapshot config $V0 snap-max-hard-limit 10 # Validating auto-delete feature # Make sure auto-delete is disabled by default -EXPECT 'disable' config_validate 'auto-delete' +EXPECT 'disable' snap_config CLI_1 'auto-delete' # Test for invalid value for auto-delete TEST ! $CLI_1 snapshot config auto-delete test @@ -103,36 +65,39 @@ TEST $CLI_1 snapshot config snap-max-hard-limit 6 TEST $CLI_1 snapshot config snap-max-soft-limit 50 # Create 4 snapshots -TEST snap_create 4; +snap_index=1 +snap_count=4 +TEST snap_create CLI_1 $V0 $snap_index $snap_count # If auto-delete is disabled then oldest snapshot # should not be deleted automatically. -EXPECT '4' get_snap_count; +EXPECT '4' get_snap_count CLI_1; -TEST snap_delete 4; +TEST snap_delete CLI_1 $snap_index $snap_count; # After all those 4 snaps are deleted, There will not be any snaps present -EXPECT 'No snapshots present' is_snapshot_present; +EXPECT '0' get_snap_count CLI_1; TEST $CLI_1 snapshot config auto-delete enable + # auto-delete is already enabled, Hence expect a failure. TEST ! $CLI_1 snapshot config auto-delete on # Testing other boolean values with auto-delete TEST $CLI_1 snapshot config auto-delete off -EXPECT 'off' config_validate 'auto-delete' +EXPECT 'off' snap_config CLI_1 'auto-delete' TEST $CLI_1 snapshot config auto-delete true -EXPECT 'true' config_validate 'auto-delete' +EXPECT 'true' snap_config CLI_1 'auto-delete' # Try to create 4 snaps again, As auto-delete is enabled # oldest snap should be deleted and snapcount should be 3 -TEST snap_create 4; -EXPECT '3' get_snap_count; +TEST snap_create CLI_1 $V0 $snap_index $snap_count; +EXPECT '3' get_snap_count CLI_1; TEST $CLI_1 snapshot config auto-delete disable -EXPECT 'disable' config_validate 'auto-delete' +EXPECT 'disable' snap_config CLI_1 'auto-delete' cleanup; diff --git a/tests/bugs/bug-1112613.t b/tests/bugs/bug-1112613.t new file mode 100644 index 0000000000..17302eaa42 --- /dev/null +++ b/tests/bugs/bug-1112613.t @@ -0,0 +1,49 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc +. $(dirname $0)/../snapshot.rc +. $(dirname $0)/../cluster.rc + +cleanup; + +V1="patchy2" + +TEST verify_lvm_version; +TEST launch_cluster 2 +TEST setup_lvm 2 + +TEST $CLI_1 peer probe $H2 +EXPECT_WITHIN $PROBE_TIMEOUT 1 peer_count + +TEST $CLI_1 volume create $V0 $H1:$L1 +TEST $CLI_1 volume start $V0 +TEST $CLI_1 volume create $V1 $H2:$L2 +TEST $CLI_1 volume start $V1 + +# Create 3 snapshots for volume $V0 +snap_count=3 +snap_index=1 +TEST snap_create CLI_1 $V0 $snap_index $snap_count; + +# Create 3 snapshots for volume $V1 +snap_count=4 +snap_index=11 +TEST snap_create CLI_1 $V1 $snap_index $snap_count; + +EXPECT '3' get_snap_count CLI_1 $V0; +EXPECT '4' get_snap_count CLI_1 $V1; +EXPECT '7' get_snap_count CLI_1 + +TEST $CLI_1 snapshot delete volume $V0 +EXPECT '0' get_snap_count CLI_1 $V0; +EXPECT '4' get_snap_count CLI_1 $V1; +EXPECT '4' get_snap_count CLI_1 + +TEST $CLI_1 snapshot delete all +EXPECT '0' get_snap_count CLI_1 $V0; +EXPECT '0' get_snap_count CLI_1 $V1; +EXPECT '0' get_snap_count CLI_1 + +cleanup; + diff --git a/tests/snapshot.rc b/tests/snapshot.rc index a208fa3d41..408b5a72a0 100755 --- a/tests/snapshot.rc +++ b/tests/snapshot.rc @@ -318,3 +318,69 @@ function volume_exists() { return 0 fi } + +# arg-1 : From which node the command should be trigerred +# Ex : $CLI_1, $CLI_2, etc. +# arg-2 : Volume name +# arg-3 : Starting index for the snapname "snap$i" +# arg-4 : Number of snapshots to be taken +function snap_create() +{ + eval local cli_index=\$$1 + local volname=$2 + local i=$3 + local limit=$[$i + $4] + + while [ $i -lt $limit ] + do + $cli_index snapshot create snap$i $volname + i=$[$i+1] + done +} + +# arg-1 : From which node the command should be trigerred +# Ex : $CLI_1. $CLI_2, etc. +# arg-2 : Volume name. +function get_snap_count() +{ + eval local cli_index=\$$1 + local volname=$2 + + + if [ -z "$2" ] + then + $cli_index snapshot list | grep -v "No snapshots present"\ + | wc -l + else + $cli_index snapshot list $volname\ + | grep -v "No snapshots present"\ + | wc -l + fi +} + +# arg-1 : From which node the command should be trigerred +# Ex : $CLI_1, $CLI_2, etc. +# arg-2 : Starting index for the snapname "snap$i" +# arg-3 : Number of snapshots to be deleted. +function snap_delete() +{ + eval local cli_index=\$$1 + local i=$2 + local limit=$[$i + $3] + + while [ $i -lt $limit ] + do + $cli_index snapshot delete snap$i + i=$[$i+1] + done +} + +# arg-1 : From which node the command should be triggered +# Ex : $CLI_1, $CLI_2, etc. +# arg-2 : key value +function snap_config() +{ + eval local cli_index=\$$1 + local var=$2 + $cli_index snapshot config | grep "^$var" | sed 's/.*: //' +} diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index b40d7abc40..2f9f68e97e 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) { |