From 81ab6622d403558cd6f31efeb535fe886d3beeaa Mon Sep 17 00:00:00 2001 From: Pranith Kumar K Date: Thu, 16 Feb 2012 21:30:47 +0530 Subject: cluster/afr: Add commands to see self-heald ops Change-Id: Id92d3276e65a6c0fe61ab328b58b3954ae116c74 BUG: 763820 Signed-off-by: Pranith Kumar K Reviewed-on: http://review.gluster.com/2775 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur --- cli/src/cli-cmd-parser.c | 72 +++++++++++++++++++++++++++++++ cli/src/cli-cmd-volume.c | 25 +++++------ cli/src/cli-rpc-ops.c | 110 +++++++++++++++++++++++++++++++++++++++-------- cli/src/cli.h | 4 ++ 4 files changed, 180 insertions(+), 31 deletions(-) (limited to 'cli') diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 703a06e84a3..00c2f3618e6 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2108,3 +2108,75 @@ out: return ret; } + +int +cli_cmd_volume_heal_options_parse (const char **words, int wordcount, + dict_t **options) +{ + int ret = 0; + dict_t *dict = NULL; + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_set_str (dict, "volname", (char *) words[2]); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "failed to set volname"); + goto out; + } + + if (wordcount == 3) { + ret = dict_set_int32 (dict, "heal-op", GF_AFR_OP_HEAL_INDEX); + goto done; + } + + if (wordcount == 4) { + if (!strcmp (words[3], "full")) { + ret = dict_set_int32 (dict, "heal-op", + GF_AFR_OP_HEAL_FULL); + goto done; + } else if (!strcmp (words[3], "info")) { + ret = dict_set_int32 (dict, "heal-op", + GF_AFR_OP_INDEX_SUMMARY); + goto done; + } else { + ret = -1; + goto out; + } + } + if (wordcount == 5) { + if (strcmp (words[3], "info")) { + ret = -1; + goto out; + } + if (!strcmp (words[4], "healed")) { + ret = dict_set_int32 (dict, "heal-op", + GF_AFR_OP_HEALED_FILES); + goto done; + } + if (!strcmp (words[4], "heal-failed")) { + ret = dict_set_int32 (dict, "heal-op", + GF_AFR_OP_HEAL_FAILED_FILES); + goto done; + } + if (!strcmp (words[4], "split-brain")) { + ret = dict_set_int32 (dict, "heal-op", + GF_AFR_OP_SPLIT_BRAIN_FILES); + goto done; + } + ret = -1; + goto out; + } + ret = -1; + goto out; +done: + *options = dict; +out: + if (ret && dict) { + dict_unref (dict); + *options = NULL; + } + + return ret; +} diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 37b41c81e80..0906f3387ce 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1560,32 +1560,29 @@ cli_cmd_volume_heal_cbk (struct cli_state *state, struct cli_cmd_word *word, call_frame_t *frame = NULL; int sent = 0; int parse_error = 0; - dict_t *dict = NULL; + dict_t *options = NULL; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; - if (wordcount != 3) { + if (wordcount < 3) { cli_usage_out (word->pattern); - parse_error = 1; + parse_error = 1; goto out; } - dict = dict_new (); - if (!dict) - goto out; - - ret = dict_set_str (dict, "volname", (char *) words[2]); + ret = cli_cmd_volume_heal_options_parse (words, wordcount, &options); if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, "failed to set volname"); + cli_usage_out (word->pattern); + parse_error = 1; goto out; } proc = &cli_rpc_prog->proctable[GLUSTER_CLI_HEAL_VOLUME]; if (proc->fn) { - ret = proc->fn (frame, THIS, dict); + ret = proc->fn (frame, THIS, options); } out: @@ -1595,8 +1592,8 @@ out: cli_out ("Volume heal failed"); } - if (dict) - dict_unref (dict); + if (options) + dict_unref (options); return ret; } @@ -1826,9 +1823,9 @@ struct cli_cmd volume_cmds[] = { cli_cmd_volume_status_cbk, "display status of all or specified volume(s)/brick"}, - { "volume heal ", + { "volume heal [{full | info {healed | heal-failed | split-brain}}]", cli_cmd_volume_heal_cbk, - "Start healing of volume specified by "}, + "self-heal commands on volume specified by "}, {"volume statedump [nfs] [all|mem|iobuf|callpool|priv|fd|" "inode|history]...", diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index d1888415cef..9537c977d12 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -5320,6 +5320,38 @@ gf_cli3_1_umount (call_frame_t *frame, xlator_t *this, void *data) return ret; } +void +cmd_heal_volume_brick_out (dict_t *dict, int brick) +{ + uint64_t num_entries = 0; + int ret = 0; + char key[256] = {0}; + char *hostname = NULL; + char *path = NULL; + uint64_t i = 0; + + snprintf (key, sizeof (key), "%d-hostname", brick); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + snprintf (key, sizeof (key), "%d-path", brick); + ret = dict_get_str (dict, key, &path); + if (ret) + goto out; + snprintf (key, sizeof (key), "%d-count", brick); + ret = dict_get_uint64 (dict, key, &num_entries); + cli_out ("\nEntries on %s:%s %"PRIu64, hostname, path, num_entries); + for (i = 0; i < num_entries; i++) { + snprintf (key, sizeof (key), "%d-%"PRIu64, brick, i); + ret = dict_get_str (dict, key, &path); + if (ret) + continue; + cli_out (path); + } +out: + return; +} + int gf_cli3_1_heal_volume_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) @@ -5329,7 +5361,11 @@ gf_cli3_1_heal_volume_cbk (struct rpc_req *req, struct iovec *iov, cli_local_t *local = NULL; char *volname = NULL; call_frame_t *frame = NULL; + dict_t *input_dict = NULL; dict_t *dict = NULL; + int brick_count = 0; + int i = 0; + gf_xl_afr_op_t heal_op = GF_AFR_OP_INVALID; if (-1 == req->rpc_status) { goto out; @@ -5348,21 +5384,24 @@ gf_cli3_1_heal_volume_cbk (struct rpc_req *req, struct iovec *iov, frame->local = NULL; } - if (local) - dict = local->dict; - -#if (HAVE_LIB_XML) - if (global_state->mode & GLUSTER_MODE_XML) { - ret = cli_xml_output_dict ("volHeal", dict, rsp.op_ret, - rsp.op_errno, rsp.op_errstr); - if (ret) - gf_log ("cli", GF_LOG_ERROR, - "Error outputting to xml"); - goto out; - } -#endif - - ret = dict_get_str (dict, "volname", &volname); + if (local) { + input_dict = local->dict; + ret = dict_get_int32 (input_dict, "heal-op", + (int32_t*)&heal_op); + } + +//#if (HAVE_LIB_XML) +// if (global_state->mode & GLUSTER_MODE_XML) { +// ret = cli_xml_output_dict ("volHeal", dict, rsp.op_ret, +// rsp.op_errno, rsp.op_errstr); +// if (ret) +// gf_log ("cli", GF_LOG_ERROR, +// "Error outputting to xml"); +// goto out; +// } +//#endif + + ret = dict_get_str (input_dict, "volname", &volname); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, "failed to get volname"); goto out; @@ -5376,14 +5415,51 @@ gf_cli3_1_heal_volume_cbk (struct rpc_req *req, struct iovec *iov, cli_out ("Starting heal on volume %s has been %s", volname, (rsp.op_ret) ? "unsuccessful": "successful"); + if (rsp.op_ret) { + ret = rsp.op_ret; + goto out; + } + + if ((heal_op == GF_AFR_OP_HEAL_FULL) || + (heal_op == GF_AFR_OP_HEAL_INDEX)) { + ret = 0; + goto out; + } + 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 ("", GF_LOG_ERROR, + "Unable to allocate memory"); + goto out; + } else { + dict->extra_stdfree = rsp.dict.dict_val; + } + ret = dict_get_int32 (dict, "count", &brick_count); + if (ret) + goto out; + + if (!brick_count) { + cli_out ("All bricks of volume %s are down.", volname); + goto out; + } + + for (i = 0; i < brick_count; i++) + cmd_heal_volume_brick_out (dict, i); ret = rsp.op_ret; out: cli_cmd_broadcast_response (ret); if (local) cli_local_wipe (local); - if (rsp.dict.dict_val) - free (rsp.dict.dict_val); if (rsp.op_errstr) free (rsp.op_errstr); if (dict) diff --git a/cli/src/cli.h b/cli/src/cli.h index 74e1423f5db..1f78da1fba0 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -258,6 +258,10 @@ int32_t cli_cmd_volume_status_parse (const char **words, int wordcount, dict_t **options); +int +cli_cmd_volume_heal_options_parse (const char **words, int wordcount, + dict_t **options); + int cli_print_brick_status (cli_volume_status_t *status); -- cgit