diff options
author | Gaurav Kumar Garg <ggarg@redhat.com> | 2015-03-10 15:04:59 +0530 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2015-03-18 18:34:07 -0700 |
commit | d236b01a8bf68b83c76ea1cfa8351833e19695f7 (patch) | |
tree | ee088fec3111b70dbf90c2af7fa7b43d6e97e019 /cli | |
parent | 7c4461329bba38b72536ee71a8172bc861ddf890 (diff) |
cli/glusterd: cli command implementation for bitrot features
CLI command for bitrot features.
volume bitrot <volname> enable|disable
Above command will enable/disable bitrot feature for particular volume.
BUG: 1170075
Change-Id: Ie84002ef7f479a285688fdae99c7afa3e91b8b99
Signed-off-by: Gaurav Kumar Garg <ggarg@redhat.com>
Signed-off-by: Anand nekkunti <anekkunt@redhat.com>
Signed-off-by: Dominic P Geevarghese <dgeevarg@redhat.com>
Reviewed-on: http://review.gluster.org/9866
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'cli')
-rw-r--r-- | cli/src/cli-cmd-parser.c | 219 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 64 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 118 | ||||
-rw-r--r-- | cli/src/cli.h | 3 |
4 files changed, 403 insertions, 1 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 83a9fbd7e7d..5520c9e46b1 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -4765,3 +4765,222 @@ out: return ret; } + +int +cli_cmd_validate_volume (char *volname) +{ + int i = 0; + int ret = -1; + + + if (volname[0] == '-') + return ret; + + if (!strcmp (volname, "all")) { + cli_err ("\"all\" cannot be the name of a volume."); + return ret; + } + + if (strchr (volname, '/')) { + cli_err ("Volume name should not contain \"/\" character."); + return ret; + } + + if (strlen (volname) > GD_VOLUME_NAME_MAX) { + cli_err ("Volname can not exceed %d characters.", + GD_VOLUME_NAME_MAX); + return ret; + } + + for (i = 0; i < strlen (volname); i++) + if (!isalnum (volname[i]) && (volname[i] != '_') && + (volname[i] != '-')) { + cli_err ("Volume name should not contain \"%c\"" + " character.\nVolume names can only" + "contain alphanumeric, '-' and '_' " + "characters.", volname[i]); + return ret; + } + + ret = 0; + + return ret; +} + +int32_t +cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **options) +{ + int32_t ret = -1; + char *w = NULL; + char *volname = NULL; + char *opwords[] = {"enable", "disable", + "scrub-throttle", + "scrub-frequency", + "scrub"}; + char *scrub_throt_values[] = {"frozen", "lazy", "normal", + "aggressive"}; + char *scrub_freq_values[] = {"daily", "weekly", + "biweekly", "monthly"}; + char *scrub_values[] = {"pause", "resume"}; + dict_t *dict = NULL; + gf_bitrot_type type = GF_BITROT_OPTION_TYPE_NONE; + + GF_ASSERT (words); + GF_ASSERT (options); + + dict = dict_new (); + if (!dict) + goto out; + + if (wordcount < 4 || wordcount > 5) { + gf_log ("", GF_LOG_ERROR, "Invalid syntax"); + goto out; + } + + volname = (char *)words[2]; + if (!volname) { + ret = -1; + goto out; + } + + ret = cli_cmd_validate_volume (volname); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Failed to validate volume name"); + goto out; + } + + ret = dict_set_str (dict, "volname", volname); + if (ret) { + cli_out ("Failed to set volume name in dictionary "); + goto out; + } + + w = str_getunamb (words[3], opwords); + if (!w) { + cli_out ("Invalid bit rot option : %s", words[3]); + ret = -1; + goto out; + } + + if (strcmp (w, "enable") == 0) { + if (wordcount == 4) { + type = GF_BITROT_OPTION_TYPE_ENABLE; + ret = 0; + goto set_type; + } else { + ret = -1; + goto out; + } + } + + if (strcmp (w, "disable") == 0) { + if (wordcount == 4) { + type = GF_BITROT_OPTION_TYPE_DISABLE; + ret = 0; + goto set_type; + } else { + ret = -1; + goto out; + } + } + + if (!strcmp (w, "scrub-throttle")) { + if (!words[4]) { + cli_err ("Missing scrub-throttle value for bitrot " + "option"); + ret = -1; + goto out; + } else { + w = str_getunamb (words[4], scrub_throt_values); + if (!w) { + cli_err ("Invalid scrub-throttle option for " + "bitrot"); + ret = -1; + goto out; + } else { + type = GF_BITROT_OPTION_TYPE_SCRUB_THROTTLE; + ret = dict_set_str (dict, + "scrub-throttle-value", + (char *) words[4]); + if (ret) { + cli_out ("Failed to set scrub-throttle " + "value in the dict"); + goto out; + } + goto set_type; + } + } + } + + if (!strcmp (words[3], "scrub-frequency")) { + if (!words[4]) { + cli_err ("Missing scrub-frequency value"); + ret = -1; + goto out; + } else { + w = str_getunamb (words[4], scrub_freq_values); + if (!w) { + cli_err ("Invalid frequency option for bitrot"); + ret = -1; + goto out; + } else { + type = GF_BITROT_OPTION_TYPE_SCRUB_FREQ; + ret = dict_set_str (dict, + "scrub-frequency-value", + (char *) words[4]); + if (ret) { + cli_out ("Failed to set dict for " + "bitrot"); + goto out; + } + goto set_type; + } + } + } + + if (!strcmp (words[3], "scrub")) { + if (!words[4]) { + cli_err ("Missing scrub value for bitrot option"); + ret = -1; + goto out; + } else { + w = str_getunamb (words[4], scrub_values); + if (!w) { + cli_err ("Invalid scrub option for bitrot"); + ret = -1; + goto out; + } else { + type = GF_BITROT_OPTION_TYPE_SCRUB; + ret = dict_set_str (dict, "scrub-value", + (char *) words[4]); + if (ret) { + cli_out ("Failed to set dict for " + "bitrot"); + goto out; + } + goto set_type; + } + } + } else { + cli_err ("Invalid option %s for bitrot. Please enter valid " + "bitrot option", words[3]); + ret = -1; + goto out; + } + +set_type: + ret = dict_set_int32 (dict, "type", type); + if (ret < 0) + goto out; + + *options = dict; + +out: + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "Unable to parse bitrot command"); + if (dict) + dict_destroy (dict); + } + + return ret; +} diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 5632a9798bb..6c950da4e97 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1300,6 +1300,58 @@ out: } int +cli_cmd_bitrot_cbk (struct cli_state *state, struct cli_cmd_word *word, + const char **words, int wordcount) +{ + + int ret = -1; + int parse_err = 0; + call_frame_t *frame = NULL; + dict_t *options = NULL; + cli_local_t *local = NULL; + rpc_clnt_procedure_t *proc = NULL; + int sent = 0; + + ret = cli_cmd_bitrot_parse (words, wordcount, &options); + if (ret < 0) { + cli_usage_out (word->pattern); + parse_err = 1; + goto out; + } + + frame = create_frame (THIS, THIS->ctx->pool); + if (!frame) { + ret = -1; + goto out; + } + + proc = &cli_rpc_prog->proctable[GLUSTER_CLI_BITROT]; + if (proc == NULL) { + ret = -1; + goto out; + } + + CLI_LOCAL_INIT (local, words, frame, options); + + if (proc->fn) { + ret = proc->fn (frame, THIS, options); + } + +out: + if (ret) { + cli_cmd_sent_status_get (&sent); + if ((sent == 0) && (parse_err == 0)) + cli_err ("Bit rot command failed. Please check the cli " + "logs for more details"); + + } + + CLI_STACK_DESTROY (frame); + + return ret; +} + +int cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word, const char **words, int wordcount) { @@ -2492,7 +2544,17 @@ struct cli_cmd volume_cmds[] = { }, {"volume get <VOLNAME> <key|all>", cli_cmd_volume_getopt_cbk, - "Get the value of the all options or given option for volume <VOLNAME>"}, + "Get the value of the all options or given option for volume <VOLNAME>" + }, + { "volume bitrot <volname> {enable|disable} |\n" + "volume bitrot <volname> {scrub-throttle frozen|lazy|normal" + "|aggressive} |\n" + "volume bitrot <volname> {scrub-frequency daily|weekly|biweekly" + "|monthly} |\n" + "volume bitrot <volname> {scrub pause|resume}", + cli_cmd_bitrot_cbk, + "Bitrot translator specific operations." + }, { NULL, NULL, NULL } }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 928df1e7082..6e66e377ed5 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -9804,6 +9804,123 @@ out: } +int +gf_cli_bitrot_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + int ret = -1; + gf_cli_rsp rsp = {0, }; + dict_t *dict = NULL; + call_frame_t *frame = NULL; + + if (req->rpc_status == -1) { + ret = -1; + goto out; + } + + frame = myframe; + + ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); + if (ret < 0) { + gf_log (frame->this->name, GF_LOG_ERROR, + "Failed to decode xdr response"); + goto out; + } + + if (rsp.op_ret) { + ret = -1; + if (global_state->mode & GLUSTER_MODE_XML) + goto xml_output; + + if (strcmp (rsp.op_errstr, "")) + cli_err ("Bitrot command failed : %s", rsp.op_errstr); + else + cli_err ("Bitrot command : failed"); + + goto out; + } + + if (rsp.dict.dict_len) { + /* Unserialize the dictionary */ + dict = dict_new (); + + if (!dict) { + ret = -1; + goto out; + } + + ret = dict_unserialize (rsp.dict.dict_val, + rsp.dict.dict_len, + &dict); + + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "failed to unserialize " + "req-buffer to dictionary"); + goto out; + } + } + + gf_log ("cli", GF_LOG_DEBUG, "Received resp to bit rot command"); + +xml_output: + if (global_state->mode & GLUSTER_MODE_XML) { + ret = cli_xml_output_vol_profile (dict, rsp.op_ret, + rsp.op_errno, + rsp.op_errstr); + if (ret) + gf_log ("cli", GF_LOG_ERROR, + "Error outputting to xml"); + goto out; + } + + if (!rsp.op_ret) + cli_out ("volume bitrot: success"); + + ret = rsp.op_ret; + +out: + if (dict) + dict_unref (dict); + + free (rsp.dict.dict_val); + free (rsp.op_errstr); + + cli_cmd_broadcast_response (ret); + + return ret; + +} + +int32_t +gf_cli_bitrot (call_frame_t *frame, xlator_t *this, void *data) +{ + gf_cli_req req = { {0,} }; + dict_t *options = NULL; + int ret = -1; + + if (!frame || !this || !data) + goto out; + + options = data; + + ret = cli_to_glusterd (&req, frame, gf_cli_bitrot_cbk, + (xdrproc_t) xdr_gf_cli_req, options, + GLUSTER_CLI_BITROT, this, cli_rpc_prog, + NULL); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, "cli_to_glusterd for " + "bitrot failed"); + goto out; + } + +out: + gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + + GF_FREE (req.dict.dict_val); + + return ret; +} + struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_NULL] = {"NULL", NULL }, [GLUSTER_CLI_PROBE] = {"PROBE_QUERY", gf_cli_probe}, @@ -9848,6 +9965,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_BARRIER_VOLUME] = {"BARRIER VOLUME", gf_cli_barrier_volume}, [GLUSTER_CLI_GANESHA] = {"GANESHA", gf_cli_ganesha}, [GLUSTER_CLI_GET_VOL_OPT] = {"GET_VOL_OPT", gf_cli_get_vol_opt}, + [GLUSTER_CLI_BITROT] = {"BITROT", gf_cli_bitrot} }; struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli.h b/cli/src/cli.h index ad286ef5f85..ed2bc4aba8a 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -238,6 +238,9 @@ int32_t cli_cmd_quota_parse (const char **words, int wordcount, dict_t **opt); int32_t +cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **opt); + +int32_t cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options, char **op_errstr); int32_t |