From c36c95a79c2f73f35727c6f8cba0586714663fd9 Mon Sep 17 00:00:00 2001 From: Sachin Pandit Date: Mon, 17 Mar 2014 07:22:03 +0530 Subject: snapshot/config : snapshot config changes. Syntax : gluster snapshot config [volname] [snap-max-hard-limit ] [snap-max-soft-limit ] 1)If volume name is not specified, then the value is set system wide. 2)If volume name is specified, then the value is set to that particular volume. *NOTE : snap-max-soft-limit cannot be specified to individual volumes. case 1) When system limit is greater than volume limit. Sample output : Snapshot System Configuration: snap-max-hard-limit : 200 snap-max-soft-limit : 50% Snapshot Volume Configuration: Volume : vol2 snap-max-hard-limit : 100 Effective snap-max-hard-limit : 100 Effective snap-max-soft-limit : 50 (50%) Volume : vol1 snap-max-hard-limit : 150 Effective snap-max-hard-limit : 150 Effective snap-max-soft-limit : 75 (50%) case 2) When system limit is lesser than volume limit. Sample output : Snapshot System Configuration: snap-max-hard-limit : 50 snap-max-soft-limit : 50% Snapshot Volume Configuration: Volume : vol2 snap-max-hard-limit : 100 Effective snap-max-hard-limit : 50 Effective snap-max-soft-limit : 25 (50%) Volume : vol1 snap-max-hard-limit : 150 Effective snap-max-hard-limit : 50 Effective snap-max-soft-limit : 25 (50%) Change-Id: I97b5daefec7205bb9ab7b5b51d38f504cc5ee940 BUG: 1075034 Signed-off-by: Sachin Pandit Reviewed-on: http://review.gluster.org/7303 Reviewed-by: Rajesh Joseph Tested-by: Rajesh Joseph --- cli/src/cli-cmd-parser.c | 340 ++++++++++++++++++++++++++++------------------- 1 file changed, 205 insertions(+), 135 deletions(-) (limited to 'cli/src/cli-cmd-parser.c') diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index d25bf45a3..6232f6301 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -31,20 +31,33 @@ struct snap_config_opt_vals_ snap_confopt_vals[] = { {.op_name = "snap-max-hard-limit", .question = "Changing snapshot-max-hard-limit " - "will lead deletion of snapshots " + "will lead to deletion of snapshots " "if they exceed the new limit.\n" "Do you want to continue?" }, {.op_name = "snap-max-soft-limit", .question = "Changing snapshot-max-soft-limit " - "will lead deletion of snapshots " + "will lead to deletion of snapshots " "if they exceed the new limit.\n" "Do you want to continue?" }, + {.op_name = "both", + .question = "Changing snapshot-max-hard-limit & " + "snapshot-max-soft-limit will lead to " + "deletion of snapshots if they exceed " + "the new limit.\nDo you want to continue?" + }, {.op_name = NULL, } }; +enum cli_snap_config_set_types { + GF_SNAP_CONFIG_SET_HARD = 0, + GF_SNAP_CONFIG_SET_SOFT = 1, + GF_SNAP_CONFIG_SET_BOTH = 2, +}; +typedef enum cli_snap_config_set_types cli_snap_config_set_types; + static const char * id_sel (void *wcon) { @@ -182,7 +195,8 @@ cli_cmd_volume_create_parse (const char **words, int wordcount, dict_t **options char *invalid_volnames[] = {"volume", "type", "subvolumes", "option", "end-volume", "all", "volume_not_in_ring", - "description", NULL}; + "description", "force", "snap-max-hard-limit", + "snap-max-soft-limit", NULL}; char *w = NULL; int op_count = 0; int32_t replica_count = 1; @@ -3097,135 +3111,7 @@ out : return ret; } -/* function cli_snap_config_parse - return value: -1 on failure - 1 if user cancels the operation - 0 on success -*/ -int32_t -cli_snap_config_parse (const char **words, int wordcount, dict_t *options, - struct cli_state *state) -{ - char *volname = NULL; - int ret = -1; - int i = -1; - char *key = NULL; - char *value = NULL; - uint64_t limit = 0; - gf1_cli_snapshot type = GF_SNAP_OPTION_TYPE_NONE; - gf_answer_t answer = GF_ANSWER_NO; - struct snap_config_opt_vals_ *conf_vals = NULL; - gf_boolean_t op_match = _gf_true; - - GF_ASSERT (words); - GF_ASSERT (options); - GF_ASSERT (state); - - if ((wordcount != 3) && (wordcount != 5)) { - gf_log ("", GF_LOG_ERROR, - "Invalid wordcount(%d)", wordcount); - goto out; - } - - volname = (char *)words[2]; - - GF_ASSERT (volname); - - type = GF_SNAP_OPTION_TYPE_CONFIG; - ret = dict_set_int32 (options, "type", type); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Failed to set type."); - goto out; - } - - ret = dict_set_str (options, "volname", volname); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Failed to set volname."); - goto out; - } - - /* snapshot config [snap-max-hard-limit - * | snap-max-soft-limit ] */ - - if (wordcount > 3) { - key = (char *) words[3]; - value = (char *) words[4]; - } else { - ret = dict_set_int32 (options, "config-command", - GF_SNAP_CONFIG_DISPLAY); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set config-command"); - ret = -1; - goto out; - } - } - - if (key) { - /* Check options in snap_confopt_vals for invalid keys */ - for (conf_vals = snap_confopt_vals; conf_vals->op_name; - conf_vals++) { - op_match = _gf_true; - for (i = 0; conf_vals->op_name[i] && key[i]; i++) { - if (conf_vals->op_name[i] == key[i] || - (conf_vals->op_name[i] == '-' && - key[i] == '_')) - continue; - op_match = _gf_false; - break; - } - - if (op_match) - break; - } - - if (!op_match) { - gf_log ("", GF_LOG_ERROR, "Invalid key"); - ret = -1; - goto out; - } - - ret = dict_set_str (options, "config-key", conf_vals->op_name); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set config-key"); - goto out; - } - } - - if (value) { - ret = dict_set_int32 (options, "config-command", - GF_SNAP_CONFIG_TYPE_SET); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Unable to set config-command"); - ret = -1; - goto out; - } - - limit = (uint64_t) atoll (value); - ret = dict_set_uint64 (options, conf_vals->op_name, limit); - if (ret) { - gf_log ("", GF_LOG_ERROR, - "Failed to set %s.", key); - goto out; - } - - /* Ask question only for a set op */ - if (conf_vals->question) { - answer = cli_cmd_get_confirmation (state, - conf_vals->question); - if (GF_ANSWER_NO == answer) { - ret = 1; - gf_log ("", GF_LOG_DEBUG, "User cancelled " - "snapshot config operation"); - goto out; - } - } - } -out: - return ret; -} /* snapshot restore * @arg-0, dict : Request Dictionary to be sent to server side. @@ -3386,6 +3272,181 @@ out : return ret; } + +int32_t +cli_snap_config_limit_parse (const char **words, dict_t *dict, + unsigned int wordcount, unsigned int index, + char *key) +{ + int ret = -1; + int limit = 0; + + GF_ASSERT (words); + GF_ASSERT (dict); + GF_ASSERT (key); + + if (index >= wordcount) { + ret = -1; + cli_err ("Please provide a value for %s.",key); + gf_log ("cli", GF_LOG_ERROR, "Value not provided for %s", key); + goto out; + } + + limit = strtol (words[index], NULL, 0); + if (limit <= 0) { + ret = -1; + cli_err ("%s should be greater than 0.", key); + goto out; + } + + ret = dict_set_int32 (dict, key, limit); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Could not set " + "%s in dictionary", key); + goto out; + } + +out : + return ret; +} + +/* function cli_snap_config_parse + * Config Syntax : gluster snapshot config [volname] + * [snap-max-hard-limit ] + * [snap-max-soft-limit ] + * + return value: <0 on failure + 1 if user cancels the operation + 0 on success + + NOTE : snap-max-soft-limit can only be set for system. +*/ +int32_t +cli_snap_config_parse (const char **words, int wordcount, dict_t *dict, + unsigned int cmdi, struct cli_state *state) +{ + int ret = -1; + gf_answer_t answer = GF_ANSWER_NO; + gf_boolean_t vol_presence = _gf_false; + struct snap_config_opt_vals_ *conf_vals = NULL; + int8_t hard_limit = 0; + int8_t soft_limit = 0; + int8_t config_type = -1; + const char *question = NULL; + + GF_ASSERT (words); + GF_ASSERT (dict); + GF_ASSERT (state); + + if ((wordcount < 2) || (wordcount > 7)) { + gf_log ("cli", GF_LOG_ERROR, + "Invalid wordcount(%d)", wordcount); + goto out; + } + + if (wordcount == 2) { + config_type = GF_SNAP_CONFIG_DISPLAY; + ret = 0; + goto set; + } + + /* Check whether the 3rd word is volname */ + if (strcmp (words[cmdi], "snap-max-hard-limit") != 0 + && strcmp (words[cmdi], "snap-max-soft-limit") != 0) { + ret = dict_set_str (dict, "volname", (char *)words[cmdi]); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to set volname"); + goto out; + } + cmdi++; + vol_presence = _gf_true; + + if (cmdi == wordcount) { + config_type = GF_SNAP_CONFIG_DISPLAY; + ret = 0; + goto set; + } + } + + config_type = GF_SNAP_CONFIG_TYPE_SET; + + if (strcmp (words[cmdi], "snap-max-hard-limit") == 0) { + ret = cli_snap_config_limit_parse (words, dict, wordcount, + ++cmdi, "snap-max-hard-limit"); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to parse snap " + "config hard limit"); + goto out; + } + hard_limit = 1; + + if (++cmdi == wordcount) { + ret = 0; + goto set; + } + } + + if (strcmp (words[cmdi], "snap-max-soft-limit") == 0) { + if (vol_presence == 1) { + ret = -1; + cli_err ("Soft limit cannot be set to individual " + "volumes."); + gf_log ("cli", GF_LOG_ERROR, "Soft limit cannot be " + "set to volumes"); + goto out; + } + + ret = cli_snap_config_limit_parse (words, dict, wordcount, + ++cmdi, "snap-max-soft-limit"); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to parse snap " + "config soft limit"); + goto out; + } + + if (++cmdi != wordcount) { + ret = -1; + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); + goto out; + } + soft_limit = 1; + } else { + ret = -1; + gf_log ("cli", GF_LOG_ERROR, "Invalid Syntax"); + goto out; + } + ret = 0; /* Success */ + +set: + ret = dict_set_int32 (dict, "config-command", config_type); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to set " + "config-command"); + goto out; + } + + if (config_type == GF_SNAP_CONFIG_TYPE_SET) { + conf_vals = snap_confopt_vals; + if (hard_limit && soft_limit) { + question = conf_vals[GF_SNAP_CONFIG_SET_BOTH].question; + } else if (soft_limit) { + question = conf_vals[GF_SNAP_CONFIG_SET_SOFT].question; + } else if (hard_limit) { + question = conf_vals[GF_SNAP_CONFIG_SET_HARD].question; + } + + answer = cli_cmd_get_confirmation (state, question); + if (GF_ANSWER_NO == answer) { + ret = 1; + gf_log ("cli", GF_LOG_DEBUG, "User cancelled " + "snapshot config operation"); + } + } + +out: + return ret; +} + int validate_snapname (const char *snapname, char **opwords) { int ret = -1; @@ -3461,7 +3522,7 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, if (type != GF_SNAP_OPTION_TYPE_CONFIG) { ret = dict_set_int32 (dict, "hold_snap_locks", _gf_true); if (ret) { - gf_log ("", GF_LOG_ERROR, + gf_log ("cli", GF_LOG_ERROR, "Unable to set hold-snap-locks value as _gf_true"); goto out; } @@ -3552,16 +3613,25 @@ cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options, case GF_SNAP_OPTION_TYPE_CONFIG: { - /* snapshot config [snap-max-hard-limit | - * snap-max-soft-limit ] */ + /* snapshot config [volname] [snap-max-hard-limit ] + * [snap-max-soft-limit ] */ ret = cli_snap_config_parse (words, wordcount, dict, - state); + cmdi, state); if (ret) { if (ret < 0) gf_log ("cli", GF_LOG_ERROR, "config command parsing failed."); goto out; } + + ret = dict_set_int32 (dict, "type", + GF_SNAP_OPTION_TYPE_CONFIG); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to set " + "config type"); + ret = -1; + goto out; + } break; } case GF_SNAP_OPTION_TYPE_STATUS: -- cgit