summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c73
-rw-r--r--cli/src/cli-cmd-snapshot.c2
-rw-r--r--cli/src/cli-rpc-ops.c216
-rw-r--r--rpc/xdr/src/cli1-xdr.x6
-rw-r--r--tests/bugs/bug-1087203.t61
-rw-r--r--tests/bugs/bug-1112613.t49
-rwxr-xr-xtests/snapshot.rc66
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c211
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) {