summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c57
-rw-r--r--cli/src/cli-cmd-snapshot.c4
-rw-r--r--cli/src/cli-rpc-ops.c37
-rw-r--r--tests/bugs/bug-1087203.t127
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c134
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.h1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c107
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h4
8 files changed, 422 insertions, 49 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index 7c6e3176dc6..d855dbf8a0a 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -197,7 +197,8 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options
"end-volume", "all", "volume_not_in_ring",
"description", "force",
"snap-max-hard-limit",
- "snap-max-soft-limit", NULL};
+ "snap-max-soft-limit", "auto-delete",
+ NULL};
char *w = NULL;
int op_count = 0;
int32_t replica_count = 1;
@@ -3612,6 +3613,7 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *dict,
int8_t config_type = -1;
const char *question = NULL;
unsigned int cmdi = 2;
+ int8_t auto_delete = -1;
/* cmdi is command index, here cmdi is "2" (gluster snapshot config)*/
GF_ASSERT (words);
@@ -3630,9 +3632,11 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *dict,
goto set;
}
+ /* auto-delete cannot be a volume name */
/* Check whether the 3rd word is volname */
if (strcmp (words[cmdi], "snap-max-hard-limit") != 0
- && strcmp (words[cmdi], "snap-max-soft-limit") != 0) {
+ && strcmp (words[cmdi], "snap-max-soft-limit") != 0
+ && strcmp (words[cmdi], "auto-delete") != 0) {
ret = dict_set_str (dict, "volname", (char *)words[cmdi]);
if (ret) {
gf_log ("cli", GF_LOG_ERROR, "Failed to set volname");
@@ -3690,7 +3694,52 @@ cli_snap_config_parse (const char **words, int wordcount, dict_t *dict,
goto out;
}
soft_limit = 1;
- } else {
+ goto set;
+ }
+
+ if (hard_limit != 1 && (strcmp(words[cmdi], "auto-delete") == 0)) {
+ if (vol_presence == 1) {
+ ret = -1;
+ cli_err ("As of now, auto-delete option cannot be set "
+ "to volumes");
+ gf_log ("cli", GF_LOG_ERROR, "auto-delete option "
+ "cannot be set to volumes");
+ goto out;
+ }
+
+ if (++cmdi >= wordcount) {
+ ret = -1;
+ gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax");
+ goto out;
+ }
+
+ if ((strcmp (words[cmdi], "enable") == 0) ||
+ (strcmp (words[cmdi], "disable") == 0)) {
+ ret = dict_set_str (dict, "auto-delete",
+ (char *)words[cmdi]);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set "
+ "value of auto-delete in request "
+ "dictionary");
+ goto out;
+ }
+ auto_delete = 1;
+ } else {
+ ret = -1;
+ cli_err ("Please enter a valid value (enable/disable) "
+ "for auto-delete");
+ gf_log ("cli", GF_LOG_ERROR, "Invalid value for "
+ "auto-delete");
+ goto out;
+ }
+
+ if (++cmdi != wordcount) {
+ ret = -1;
+ gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax");
+ goto out;
+ }
+ }
+ else {
ret = -1;
gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax");
goto out;
@@ -3705,7 +3754,7 @@ set:
goto out;
}
- if (config_type == GF_SNAP_CONFIG_TYPE_SET) {
+ if (config_type == GF_SNAP_CONFIG_TYPE_SET && auto_delete != 1) {
conf_vals = snap_confopt_vals;
if (hard_limit && soft_limit) {
question = conf_vals[GF_SNAP_CONFIG_SET_BOTH].question;
diff --git a/cli/src/cli-cmd-snapshot.c b/cli/src/cli-cmd-snapshot.c
index 45fa5673f7a..1fb4e5e634c 100644
--- a/cli/src/cli-cmd-snapshot.c
+++ b/cli/src/cli-cmd-snapshot.c
@@ -102,7 +102,9 @@ struct cli_cmd snapshot_cmds[] = {
cli_cmd_snapshot_cbk,
"Snapshot List."
},
- {"snapshot config [volname] [snap-max-hard-limit <count>] [snap-max-soft-limit <percent>]",
+ {"snapshot config [volname] ([snap-max-hard-limit <count>] "
+ "[snap-max-soft-limit <percent>]) "
+ "| ([auto-delete <enable|disable>])",
cli_cmd_snapshot_cbk,
"Snapshot Config."
},
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index b998fff3f4c..348fbe4e2e5 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -7682,6 +7682,7 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
uint64_t soft_limit = 0;
uint64_t i = 0;
uint64_t voldisplaycount = 0;
+ char *auto_delete = NULL;
GF_ASSERT (dict);
GF_ASSERT (rsp);
@@ -7711,8 +7712,11 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
/* Ignore the error, as the key specified is optional */
ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit);
+ ret = dict_get_str (dict, "auto-delete", &auto_delete);
+
if (!hard_limit && !soft_limit
- && config_command != GF_SNAP_CONFIG_DISPLAY) {
+ && config_command != GF_SNAP_CONFIG_DISPLAY
+ && !auto_delete) {
ret = -1;
gf_log(THIS->name, GF_LOG_ERROR,
"Could not fetch config-key");
@@ -7733,6 +7737,10 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
cli_out ("snapshot config: %s "
"for snap-max-soft-limit set successfully",
volname);
+ } else if (auto_delete) {
+ cli_out ("snapshot config: %s "
+ "auto-delete successfully %sd",
+ volname, auto_delete);
}
break;
@@ -7756,9 +7764,11 @@ cli_snapshot_config_display (dict_t *dict, gf_cli_rsp *rsp)
ret = -1;
goto out;
}
- cli_out ("snap-max-soft-limit : %"PRIu64"%%\n",
+ cli_out ("snap-max-soft-limit : %"PRIu64"%%",
soft_limit);
+ cli_out ("auto-delete : %s\n", auto_delete);
+
cli_out ("Snapshot Volume Configuration:");
ret = dict_get_uint64 (dict, "voldisplaycount",
@@ -8501,6 +8511,8 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,
int32_t type = 0;
call_frame_t *frame = NULL;
gf_boolean_t snap_driven = _gf_false;
+ int8_t soft_limit_flag = -1;
+ char *volname = NULL;
if (req->rpc_status == -1) {
ret = -1;
@@ -8550,8 +8562,29 @@ gf_cli_snapshot_cbk (struct rpc_req *req, struct iovec *iov,
"Failed to get snap name");
goto out;
}
+
+ /* TODO : Instead of using volname1 directly use
+ * volname$i in loop once snapshot of multiple
+ * volumes are supported
+ */
+ ret = dict_get_str (dict, "volname1", &volname);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR,
+ "Failed to get volume name");
+ goto out;
+ }
+
cli_out ("snapshot create: success: Snap %s created "
"successfully", snap_name);
+
+ ret = dict_get_int8 (dict, "soft-limit-reach",
+ &soft_limit_flag);
+ if (soft_limit_flag == 1) {
+ cli_out ("Warning: Soft-limit of volume (%s) is "
+ "reached. Snapshot creation is not possible "
+ "once hard-limit is reached.", volname);
+ }
+ ret = 0;
break;
case GF_SNAP_OPTION_TYPE_RESTORE:
diff --git a/tests/bugs/bug-1087203.t b/tests/bugs/bug-1087203.t
index acbb826013d..8926274dac7 100644
--- a/tests/bugs/bug-1087203.t
+++ b/tests/bugs/bug-1087203.t
@@ -2,45 +2,128 @@
. $(dirname $0)/../include.rc
. $(dirname $0)/../volume.rc
+. $(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 glusterd;
-TEST $CLI volume info;
+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 volume create $V0 replica 2 $H0:$B0/${V0}-{0,1};
-EXPECT "$V0" volinfo_field $V0 'Volume Name';
-EXPECT 'Created' volinfo_field $V0 'Status';
+TEST $CLI_1 volume create $V0 $H1:$L1 $H2:$L2
+EXPECT "$V0" get_volume_info 'Volume Name';
+EXPECT 'Created' get_volume_info 'Status';
-TEST $CLI volume start $V0
-EXPECT 'Started' volinfo_field $V0 'Status';
+TEST $CLI_1 volume start $V0
+EXPECT 'Started' get_volume_info 'Status';
# Setting system limit
-TEST $CLI snapshot config snap-max-hard-limit 100
+TEST $CLI_1 snapshot config snap-max-hard-limit 100
# Volume limit cannot exceed system limit, as limit is set to 100,
# this should fail.
-TEST ! $CLI snapshot config $V0 snap-max-hard-limit 101
+TEST ! $CLI_1 snapshot config $V0 snap-max-hard-limit 101
# Following are the invalid cases
-TEST ! $CLI snapshot config $V0 snap-max-hard-limit a10
-TEST ! $CLI snapshot config snap-max-hard-limit 10a
-TEST ! $CLI snapshot config snap-max-hard-limit 10%
-TEST ! $CLI snapshot config snap-max-soft-limit 50%1
-TEST ! $CLI snapshot config snap-max-soft-limit 0111
-TEST ! $CLI snapshot config snap-max-hard-limit OXA
-TEST ! $CLI snapshot config snap-max-hard-limit 11.11
-TEST ! $CLI snapshot config snap-max-soft-limit 50%
-TEST ! $CLI snapshot config snap-max-hard-limit -100
-TEST ! $CLI snapshot config snap-max-soft-limit -90
+TEST ! $CLI_1 snapshot config $V0 snap-max-hard-limit a10
+TEST ! $CLI_1 snapshot config snap-max-hard-limit 10a
+TEST ! $CLI_1 snapshot config snap-max-hard-limit 10%
+TEST ! $CLI_1 snapshot config snap-max-soft-limit 50%1
+TEST ! $CLI_1 snapshot config snap-max-soft-limit 0111
+TEST ! $CLI_1 snapshot config snap-max-hard-limit OXA
+TEST ! $CLI_1 snapshot config snap-max-hard-limit 11.11
+TEST ! $CLI_1 snapshot config snap-max-soft-limit 50%
+TEST ! $CLI_1 snapshot config snap-max-hard-limit -100
+TEST ! $CLI_1 snapshot config snap-max-soft-limit -90
# Soft limit cannot be assigned to volume
-TEST ! $CLI snapshot config $V0 snap-max-soft-limit 10
+TEST ! $CLI_1 snapshot config $V0 snap-max-soft-limit 10
# Valid case
-TEST $CLI snapshot config snap-max-soft-limit 50
-TEST $CLI snapshot config $V0 snap-max-hard-limit 10
+TEST $CLI_1 snapshot config snap-max-soft-limit 50
+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'
+
+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;
+
+# If auto-delete is disabled then oldest snapshot
+# should not be deleted automatically.
+EXPECT '4' get_snap_count;
+
+TEST snap_delete 4;
+
+# After all those 4 snaps are deleted, There will not be any snaps present
+EXPECT 'No snapshots present' is_snapshot_present;
+
+TEST $CLI_1 snapshot config auto-delete enable
+# auto-delete is already enabled, Hence expect a failure.
+TEST ! $CLI_1 snapshot config auto-delete enable
+EXPECT 'enable' config_validate '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 $CLI_1 snapshot config auto-delete disable
+EXPECT 'disable' config_validate 'auto-delete'
cleanup;
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
index 456f23abe4b..af4cf171aff 100644
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
@@ -203,7 +203,7 @@ out:
int
snap_max_limits_display_commit (dict_t *rsp_dict, char *volname,
- char *op_errstr)
+ char *op_errstr, int len)
{
char err_str[PATH_MAX] = "";
char buf[PATH_MAX] = "";
@@ -217,6 +217,7 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname,
xlator_t *this = NULL;
uint64_t opt_hard_max = 0;
uint64_t opt_soft_max = 0;
+ char *auto_delete = NULL;
this = THIS;
@@ -312,8 +313,8 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname,
/* For one volume */
ret = glusterd_volinfo_find (volname, &volinfo);
if (ret) {
- snprintf (err_str, PATH_MAX, "Failed to get the"
- " volinfo for volume %s", volname);
+ snprintf (err_str, PATH_MAX, "Volume (%s) does not "
+ "exist", volname);
goto out;
}
@@ -392,10 +393,30 @@ snap_max_limits_display_commit (dict_t *rsp_dict, char *volname,
goto out;
}
+ ret = dict_get_str (conf->opts,
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ &auto_delete);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "%s from options",
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE);
+ goto out;
+ }
+
+ ret = dict_set_dynstr_with_alloc (rsp_dict,
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ auto_delete);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set "
+ "%s in response dictionary",
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE);
+ goto out;
+ }
+
ret = 0;
out:
if (ret) {
- op_errstr = gf_strdup (err_str);
+ strncpy (op_errstr, err_str, len);
gf_log (this->name, GF_LOG_ERROR, "%s", err_str);
}
return ret;
@@ -1056,6 +1077,8 @@ glusterd_snapshot_config_prevalidate (dict_t *dict, char **op_errstr)
uint64_t soft_limit = 0;
gf_loglevel_t loglevel = GF_LOG_ERROR;
uint64_t max_limit = GLUSTERD_SNAPS_MAX_HARD_LIMIT;
+ char *req_auto_delete = NULL;
+ char *cur_auto_delete = NULL;
this = THIS;
@@ -1078,6 +1101,9 @@ glusterd_snapshot_config_prevalidate (dict_t *dict, char **op_errstr)
ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit);
+ ret = dict_get_str (dict, GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ &req_auto_delete);
+
ret = dict_get_str (dict, "volname", &volname);
if (volname) {
@@ -1115,6 +1141,24 @@ glusterd_snapshot_config_prevalidate (dict_t *dict, char **op_errstr)
}
break;
}
+
+ if (req_auto_delete) {
+ ret = dict_get_str (conf->opts,
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ &cur_auto_delete);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "get auto-delete value from options");
+ goto out;
+ }
+
+ if (strcmp (req_auto_delete, cur_auto_delete) == 0) {
+ ret = -1;
+ snprintf (err_str, PATH_MAX, "auto-delete "
+ "is already %sd", req_auto_delete);
+ goto out;
+ }
+ }
default:
break;
}
@@ -1185,13 +1229,14 @@ glusterd_handle_snapshot_config (rpcsvc_request_t *req, glusterd_op_t op,
case GF_SNAP_CONFIG_DISPLAY:
/* Reading data from local node only */
ret = snap_max_limits_display_commit (dict, volname,
- err_str);
+ err_str, len);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
"snap-max-limit "
"display commit failed.");
goto out;
}
+
/* If everything is successful then send the response
* back to cli
*/
@@ -1325,7 +1370,6 @@ glusterd_snap_create_pre_val_use_rsp_dict (dict_t *dst, dict_t *src)
brick_online = 0;
}
}
-
ret = 0;
out:
@@ -1638,11 +1682,13 @@ glusterd_snapshot_create_prevalidate (dict_t *dict, char **op_errstr,
effective_max_limit = opt_hard_max;
if (volinfo->snap_count >= effective_max_limit) {
+ ret = -1;
snprintf (err_str, sizeof (err_str),
"The number of existing snaps has reached "
- "the effective maximum limit of %"PRIu64" ,"
- "for the volume %s", effective_max_limit,
- volname);
+ "the effective maximum limit of %"PRIu64", "
+ "for the volume (%s). Please delete few "
+ "snapshots before taking further snapshots.",
+ effective_max_limit, volname);
loglevel = GF_LOG_WARNING;
goto out;
}
@@ -5133,6 +5179,17 @@ glusterd_snapshot_create_commit (dict_t *dict, char **op_errstr,
goto out;
}
+ if (is_origin_glusterd (dict)) {
+ ret = glusterd_is_snap_soft_limit_reached (origin_vol,
+ rsp_dict);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "check soft limit exceeded or not, "
+ "for volume %s ", origin_vol->volname);
+ goto out;
+ }
+ }
+
snap_vol = glusterd_do_snap_vol (origin_vol, snap, dict,
rsp_dict, i);
if (!snap_vol) {
@@ -5285,6 +5342,7 @@ glusterd_snapshot_config_commit (dict_t *dict, char **op_errstr,
uint64_t hard_limit = 0;
uint64_t soft_limit = 0;
char *next_version = NULL;
+ char *auto_delete = NULL;
this = THIS;
@@ -5312,6 +5370,9 @@ glusterd_snapshot_config_commit (dict_t *dict, char **op_errstr,
ret = dict_get_uint64 (dict, "snap-max-soft-limit", &soft_limit);
+ ret = dict_get_str (dict, GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ &auto_delete);
+
switch (config_command) {
case GF_SNAP_CONFIG_TYPE_SET:
if (hard_limit) {
@@ -5359,6 +5420,32 @@ glusterd_snapshot_config_commit (dict_t *dict, char **op_errstr,
goto out;
}
}
+
+ if (auto_delete) {
+ ret = glusterd_get_next_global_opt_version_str
+ (conf->opts, &next_version);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "get next global opt-version");
+ goto out;
+ }
+
+ ret = dict_set_dynstr_with_alloc (conf->opts,
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ auto_delete);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Could not "
+ "save auto-delete value in conf->opts");
+ goto out;
+ }
+
+ ret = glusterd_store_options (this, conf->opts);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "store options");
+ goto out;
+ }
+ }
break;
default:
@@ -6096,19 +6183,19 @@ glusterd_handle_snap_limit (dict_t *dict, dict_t *rsp_dict)
goto out;
}
- /* The minimum of the 2 limits i.e system wide limit and
- volume wide limit will be considered
- */
-
ret = dict_get_uint64 (priv->opts,
GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT,
&opt_max_hard);
if (ret) {
gf_log (this->name, GF_LOG_ERROR, "Failed to get "
- "%s", GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT);
+ "%s from opts dictionary",
+ GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT);
goto out;
}
+ /* The minimum of the 2 limits i.e system wide limit and
+ volume wide limit will be considered
+ */
if (volinfo->snap_max_hard_limit < opt_max_hard)
effective_max_limit = volinfo->snap_max_hard_limit;
else
@@ -6170,6 +6257,7 @@ glusterd_snapshot_create_postvalidate (dict_t *dict, int32_t op_ret,
int32_t cleanup = 0;
glusterd_snap_t *snap = NULL;
char *snapname = NULL;
+ char *auto_delete = NULL;
this = THIS;
@@ -6188,9 +6276,14 @@ glusterd_snapshot_create_postvalidate (dict_t *dict, int32_t op_ret,
if (ret) {
gf_log (this->name, GF_LOG_WARNING, "cleanup "
"operation failed");
- goto out;
}
}
+ /* Irrespective of status of cleanup its better
+ * to return from this function. As the functions
+ * following this block is not required to be
+ * executed in case of failure scenario.
+ */
+ goto out;
}
ret = dict_get_str (dict, "snapname", &snapname);
@@ -6224,8 +6317,17 @@ glusterd_snapshot_create_postvalidate (dict_t *dict, int32_t op_ret,
goto out;
}
+ ret = dict_get_str (priv->opts, GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ &auto_delete);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "the value of auto-delete from options");
+ goto out;
+ }
+
//ignore the errors of autodelete
- ret = glusterd_handle_snap_limit (dict, rsp_dict);
+ if (strcmp (auto_delete, "enable") == 0)
+ ret = glusterd_handle_snap_limit (dict, rsp_dict);
ret = 0;
out:
diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h
index dd5c6ec0dd7..ba3662bc7b2 100644
--- a/xlators/mgmt/glusterd/src/glusterd-store.h
+++ b/xlators/mgmt/glusterd/src/glusterd-store.h
@@ -69,6 +69,7 @@ typedef enum glusterd_store_ver_ac_{
#define GLUSTERD_STORE_KEY_SNAP_STATUS "status"
#define GLUSTERD_STORE_KEY_SNAP_RESTORED "snap-restored"
#define GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT "snap-max-hard-limit"
+#define GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE "auto-delete"
#define GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT "snap-max-soft-limit"
#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname"
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index d79ff249535..776278ff6c3 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -10612,6 +10612,7 @@ glusterd_snap_create_use_rsp_dict (dict_t *dst, dict_t *src)
int32_t src_missed_snap_count = -1;
int32_t dst_missed_snap_count = -1;
xlator_t *this = NULL;
+ int8_t soft_limit_flag = -1;
this = THIS;
GF_ASSERT (this);
@@ -10629,6 +10630,18 @@ glusterd_snap_create_use_rsp_dict (dict_t *dst, dict_t *src)
goto out;
}
+ /* set in dst dictionary soft-limit-reach only if soft-limit-reach
+ * is present src dictionary */
+ ret = dict_get_int8 (src, "soft-limit-reach", &soft_limit_flag);
+ if (!ret) {
+ ret = dict_set_int8 (dst, "soft-limit-reach", soft_limit_flag);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to set "
+ "soft_limit_flag");
+ goto out;
+ }
+ }
+
ret = dict_get_int32 (src, "missed_snap_count",
&src_missed_snap_count);
if (ret) {
@@ -13433,10 +13446,11 @@ out:
int32_t
glusterd_check_and_set_config_limit (glusterd_conf_t *priv)
{
- int32_t ret = -1;
- xlator_t *this = NULL;
- uint64_t hard_limit = 0;
- uint64_t soft_limit = 0;
+ int32_t ret = -1;
+ xlator_t *this = NULL;
+ uint64_t hard_limit = 0;
+ uint64_t soft_limit = 0;
+ char *auto_delete = NULL;
GF_ASSERT (priv);
this = THIS;
@@ -13472,6 +13486,21 @@ glusterd_check_and_set_config_limit (glusterd_conf_t *priv)
goto out;
}
}
+
+ ret = dict_get_str (priv->opts,
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ &auto_delete);
+ if (ret) {
+ ret = dict_set_dynstr_with_alloc (priv->opts, "auto-delete",
+ "disable");
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to store "
+ "auto-delete value as disabled during "
+ "glusterd init");
+ goto out;
+ }
+ }
+
ret = glusterd_store_options (this, priv->opts);
if (ret) {
gf_log (this->name, GF_LOG_ERROR,
@@ -13481,3 +13510,73 @@ glusterd_check_and_set_config_limit (glusterd_conf_t *priv)
out:
return ret;
}
+
+int32_t
+glusterd_is_snap_soft_limit_reached (glusterd_volinfo_t *volinfo, dict_t *dict)
+{
+ int32_t ret = -1;
+ uint64_t opt_max_hard = 0;
+ uint64_t opt_max_soft = 0;
+ uint64_t limit = 0;
+ char *auto_delete = NULL;
+ uint64_t effective_max_limit = 0;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+
+ GF_ASSERT (volinfo);
+ GF_ASSERT (dict);
+
+ this = THIS;
+ GF_ASSERT (this);
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = dict_get_uint64 (priv->opts,
+ GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT,
+ &opt_max_hard);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "%s", GLUSTERD_STORE_KEY_SNAP_MAX_HARD_LIMIT);
+ goto out;
+ }
+
+ if (volinfo->snap_max_hard_limit < opt_max_hard)
+ effective_max_limit = volinfo->snap_max_hard_limit;
+ else
+ effective_max_limit = opt_max_hard;
+
+ ret = dict_get_uint64 (priv->opts,
+ GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT,
+ &opt_max_soft);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "%s from opts dictionary",
+ GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT);
+ goto out;
+ }
+
+ ret = dict_get_str (priv->opts,
+ GLUSTERD_STORE_KEY_SNAP_AUTO_DELETE,
+ &auto_delete);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to get "
+ "auto-delete from options dictionary");
+ goto out;
+ }
+
+ limit = (opt_max_soft * effective_max_limit)/100;
+
+ if (volinfo->snap_count >= limit &&
+ (strcmp (auto_delete, "enable") != 0)) {
+ ret = dict_set_int8 (dict, "soft-limit-reach",
+ _gf_true);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR, "Failed to "
+ "set soft limit exceed flag in "
+ "response dictionary");
+ }
+ goto out;
+ }
+out :
+ return ret;
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index 2d7c4269d34..9e0400cf86a 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -893,5 +893,9 @@ glusterd_restart_snapds (glusterd_conf_t *priv);
int32_t
glusterd_check_and_set_config_limit (glusterd_conf_t *priv);
+
+int32_t
+glusterd_is_snap_soft_limit_reached (glusterd_volinfo_t *volinfo,
+ dict_t *dict);
/* End snapd functions */
#endif