diff options
author | Sachin Pandit <spandit@redhat.com> | 2014-06-11 09:03:16 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2014-06-13 02:12:29 -0700 |
commit | 10cd2bc38e1f0a1297d59c0791a85ed9d01c93ff (patch) | |
tree | e7230795e97b668c04011fa018597aae0619ef10 | |
parent | 6ba178fd9ebf9fc98415c30bcd338a68ee5eb601 (diff) |
glusterd/snapshot : Provide enable/disable option for snapshot auto-delete feature.
This patch provides an interface to enable or disable
the auto-delete feature.
Syntax : gluster snapshot config auto-delete <enable/disable>
DETAILS :
1) When auto-delete feature is disabled, If the the soft-limit is
reached then user is given a warning about exceeding soft-limit
along with successful snapshot creation message (oldest snapshot is
not deleted). And upon reaching hard-limit further snapshot creation
is not allowed.
Example :
------------------------------------------------------------------
|Case - 1: Upon reaching soft-limit
|
|Snapshot create : snap successfully created.
|Warning : soft-limit of volume (vol) is reached. Snapshot creation
|is not possible once hard-limit is reached.
|
|-----------------------------------------------------
|Case - 2: Upon reaching hard-limit
|
|Snapshot create : snap creation failed.
|Error : hard-limit of volume (vol) is reached, Hence it is not
|possible to take further snapshots. Please delete few snapshots
|of the volume (vol) before taking another snapshot.
------------------------------------------------------------------
2) When auto-delete feature is enabled, then as soon as the soft-limit
is reached the oldest snapshot is deleted for every successful snapshot
creation (same as existing method), With this it is made sure that
number of snapshot created is not more than snap-max-hard-limit.
Change-Id: Ie3ca64bbd2c763371f541cd2e378314e73b695b4
BUG: 1105415
Signed-off-by: Sachin Pandit <spandit@redhat.com>
Reviewed-on: http://review.gluster.org/8017
Tested-by: Justin Clift <justin@gluster.org>
Reviewed-by: Rajesh Joseph <rjoseph@redhat.com>
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Tested-by: Krishnan Parthasarathi <kparthas@redhat.com>
Reviewed-by: Raghavendra Bhat <raghavendra@redhat.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r-- | cli/src/cli-cmd-parser.c | 57 | ||||
-rw-r--r-- | cli/src/cli-cmd-snapshot.c | 4 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 37 | ||||
-rw-r--r-- | tests/bugs/bug-1087203.t | 127 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 134 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 107 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 4 |
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 |