diff options
-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 |