summaryrefslogtreecommitdiffstats
path: root/cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src')
-rw-r--r--cli/src/cli-cmd-parser.c72
-rw-r--r--cli/src/cli-cmd-volume.c25
-rw-r--r--cli/src/cli-rpc-ops.c110
-rw-r--r--cli/src/cli.h4
4 files changed, 180 insertions, 31 deletions
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 <VOLNAME>",
+ { "volume heal <VOLNAME> [{full | info {healed | heal-failed | split-brain}}]",
cli_cmd_volume_heal_cbk,
- "Start healing of volume specified by <VOLNAME>"},
+ "self-heal commands on volume specified by <VOLNAME>"},
{"volume statedump <VOLNAME> [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
@@ -259,6 +259,10 @@ 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);
void