From 329baff8ca13d8e5d6ca98d221d59cd2329cd19c Mon Sep 17 00:00:00 2001 From: Krutika Dhananjay Date: Tue, 24 Sep 2013 17:01:46 +0530 Subject: cli,glusterd: Implement 'volume status tasks' oVirt's Gluster Integration needs an inexpensive command that can be executed every 10 seconds to monitor async tasks and their parameters, for all volumes. The solution involves adding a 'tasks' sub-command to 'volume status' to fetch only the async task IDs, type and other relevant parameters. Only the originator glusterd participates in this command as all the information needed is available on all the nodes. This is to make the command suitable for being executed every 10 seconds. Change-Id: I1edc607baf29b001a5585079dec681d7c641b3d1 BUG: 1012346 Signed-off-by: Krutika Dhananjay Reviewed-on: http://review.gluster.org/6006 Tested-by: Gluster Build System Reviewed-by: Kaushal M --- cli/src/cli-cmd-parser.c | 19 ++++-- cli/src/cli-cmd-volume.c | 2 +- cli/src/cli-rpc-ops.c | 155 +++++++++++++++++++++++++++++++++-------------- cli/src/cli-xml-output.c | 31 +++++++++- cli/src/cli.h | 2 + 5 files changed, 156 insertions(+), 53 deletions(-) (limited to 'cli/src') diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 33a6c0104b..62f5c3723a 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2182,7 +2182,7 @@ cli_cmd_get_statusop (const char *arg) uint32_t ret = GF_CLI_STATUS_NONE; char *w = NULL; char *opwords[] = {"detail", "mem", "clients", "fd", - "inode", "callpool", NULL}; + "inode", "callpool", "tasks", NULL}; struct { char *opname; uint32_t opcode; @@ -2193,6 +2193,7 @@ cli_cmd_get_statusop (const char *arg) { "fd", GF_CLI_STATUS_FD }, { "inode", GF_CLI_STATUS_INODE }, { "callpool", GF_CLI_STATUS_CALLPOOL }, + { "tasks", GF_CLI_STATUS_TASKS }, { NULL } }; @@ -2307,8 +2308,9 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, if (!strcmp (words[3], "nfs")) { if (cmd == GF_CLI_STATUS_FD || - cmd == GF_CLI_STATUS_DETAIL) { - cli_err ("Detail/FD status not available" + cmd == GF_CLI_STATUS_DETAIL || + cmd == GF_CLI_STATUS_TASKS) { + cli_err ("Detail/FD/Tasks status not available" " for NFS Servers"); ret = -1; goto out; @@ -2317,14 +2319,21 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, } else if (!strcmp (words[3], "shd")){ if (cmd == GF_CLI_STATUS_FD || cmd == GF_CLI_STATUS_CLIENTS || - cmd == GF_CLI_STATUS_DETAIL) { - cli_err ("Detail/FD/Clients status not " + cmd == GF_CLI_STATUS_DETAIL || + cmd == GF_CLI_STATUS_TASKS) { + cli_err ("Detail/FD/Clients/Tasks status not " "available for Self-heal Daemons"); ret = -1; goto out; } cmd |= GF_CLI_STATUS_SHD; } else { + if (cmd == GF_CLI_STATUS_TASKS) { + cli_err ("Tasks status not available for " + "bricks"); + ret = -1; + goto out; + } cmd |= GF_CLI_STATUS_BRICK; ret = dict_set_str (dict, "brick", (char *)words[3]); } diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 040f610adc..56ad65ebb5 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1914,7 +1914,7 @@ struct cli_cmd volume_cmds[] = { "volume top operations"}, { "volume status [all | [nfs|shd|]]" - " [detail|clients|mem|inode|fd|callpool]", + " [detail|clients|mem|inode|fd|callpool|tasks]", cli_cmd_volume_status_cbk, "display status of all or specified volume(s)/brick"}, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index f9605c1049..5dddbb41bb 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -6299,43 +6299,57 @@ out: return; } - static void -cli_print_volume_tasks (dict_t *dict) { - int ret = -1; - int tasks = 0; - char *op = 0; - char *task_id_str = NULL; - int status = 0; - char key[1024] = {0,}; - int i = 0; +cli_print_volume_status_tasks (dict_t *dict) +{ + int ret = -1; + int i = 0; + int j = 0; + int count = 0; + int task_count = 0; + int status = 0; + char *op = NULL; + char *task_id_str = NULL; + char *volname = NULL; + char key[1024] = {0,}; + char task[1024] = {0,}; + char *brick = NULL; + char *src_brick = NULL; + char *dest_brick = NULL; - ret = dict_get_int32 (dict, "tasks", &tasks); + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + + ret = dict_get_int32 (dict, "tasks", &task_count); if (ret) { - gf_log ("cli", GF_LOG_ERROR, - "Failed to get tasks count"); + gf_log ("cli", GF_LOG_ERROR, "Failed to get tasks count"); return; } - if (tasks == 0) { + cli_out ("Task Status of Volume %s", volname); + cli_print_line (CLI_BRICK_STATUS_LINE_LEN); + + if (task_count == 0) { cli_out ("There are no active volume tasks"); + cli_out (" "); return; } - cli_out ("%15s%40s%15s", "Task", "ID", "Status"); - cli_out ("%15s%40s%15s", "----", "--", "------"); - for (i = 0; i < tasks; i++) { + for (i = 0; i < task_count; i++) { memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.type", i); ret = dict_get_str(dict, key, &op); if (ret) return; + cli_out ("%-20s : %-20s", "Task", op); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.id", i); ret = dict_get_str (dict, key, &task_id_str); if (ret) return; + cli_out ("%-20s : %-20s", "ID", task_id_str); memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "task%d.status", i); @@ -6343,22 +6357,63 @@ cli_print_volume_tasks (dict_t *dict) { if (ret) return; + snprintf (task, sizeof (task), "task%d", i); + /* Replace brick only has two states - In progress and Complete Ref: xlators/mgmt/glusterd/src/glusterd-replace-brick.c */ + if (!strcmp (op, "Replace brick")) { - if (status) { - status = GF_DEFRAG_STATUS_COMPLETE; - } else { - status = GF_DEFRAG_STATUS_STARTED; - } - } + if (status) + status = GF_DEFRAG_STATUS_COMPLETE; + else + status = GF_DEFRAG_STATUS_STARTED; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.src-brick", task); + ret = dict_get_str (dict, key, &src_brick); + if (ret) + goto out; + + cli_out ("%-20s : %-20s", "Source Brick", src_brick); - cli_out ("%15s%40s%15s", op, task_id_str, + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.dst-brick", task); + ret = dict_get_str (dict, key, &dest_brick); + if (ret) + goto out; + + cli_out ("%-20s : %-20s", "Destination Brick", + dest_brick); + + } else if (!strcmp (op, "Remove brick")) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.count", task); + ret = dict_get_int32 (dict, key, &count); + if (ret) + goto out; + + cli_out ("%-20s", "Removed bricks:"); + + for (j = 1; j <= count; j++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key),"%s.brick%d", + task, j); + ret = dict_get_str (dict, key, &brick); + if (ret) + goto out; + + cli_out ("%-20s", brick); + } + } + cli_out ("%-20s : %-20s", "Status", cli_vol_task_status_str[status]); + cli_out (" "); } +out: + return; } static int @@ -6462,23 +6517,6 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov, if ((cmd & GF_CLI_STATUS_NFS) || (cmd & GF_CLI_STATUS_SHD)) notbrick = _gf_true; - ret = dict_get_int32 (dict, "count", &count); - if (ret) - goto out; - if (count == 0) { - ret = -1; - goto out; - } - - ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); - if (ret) - goto out; - ret = dict_get_int32 (dict, "other-count", &other_count); - if (ret) - goto out; - - index_max = brick_index_max + other_count; - if (global_state->mode & GLUSTER_MODE_XML) { if (!local->all) { ret = cli_xml_output_vol_status_begin (local, @@ -6491,11 +6529,21 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov, goto out; } } - ret = cli_xml_output_vol_status (local, dict); - if (ret) { - gf_log ("cli", GF_LOG_ERROR, - "Error outputting to xml"); - goto out; + if (cmd & GF_CLI_STATUS_TASKS) { + ret = cli_xml_output_vol_status_tasks_detail (local, + dict); + if (ret) { + gf_log ("cli", GF_LOG_ERROR,"Error outputting " + "to xml"); + goto out; + } + } else { + ret = cli_xml_output_vol_status (local, dict); + if (ret) { + gf_log ("cli", GF_LOG_ERROR, + "Error outputting to xml"); + goto out; + } } if (!local->all) { @@ -6531,6 +6579,10 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov, cli_print_volume_status_callpool (dict, notbrick); goto cont; break; + case GF_CLI_STATUS_TASKS: + cli_print_volume_status_tasks (dict); + goto cont; + break; default: break; } @@ -6539,6 +6591,17 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov, if (ret) goto out; + ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max); + if (ret) + goto out; + + ret = dict_get_int32 (dict, "other-count", &other_count); + if (ret) + goto out; + + index_max = brick_index_max + other_count; + + cli_out ("Status of volume: %s", volname); if ((cmd & GF_CLI_STATUS_DETAIL) == 0) { @@ -6612,7 +6675,7 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov, cli_out (" "); if ((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE) - cli_print_volume_tasks (dict); + cli_print_volume_status_tasks (dict); cont: ret = rsp.op_ret; diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c index 6cc734a18e..cc021a34d6 100644 --- a/cli/src/cli-xml-output.c +++ b/cli/src/cli-xml-output.c @@ -1564,6 +1564,36 @@ out: gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); return ret; } + +int +cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict) +{ + int ret = -1; + char *volname = NULL; + + /**/ + ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volume"); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + ret = xmlTextWriterWriteFormatElement (local->writer, + (xmlChar *)"volName", "%s", + volname); + XML_RET_CHECK_AND_GOTO (ret, out); + + ret = cli_xml_output_vol_status_tasks (local, dict); + if (ret) + goto out; + + /* */ + ret = xmlTextWriterEndElement (local->writer); + XML_RET_CHECK_AND_GOTO (ret, out); + +out: + return ret; +} #endif int @@ -1683,7 +1713,6 @@ cli_xml_output_vol_status (cli_local_t *local, dict_t *dict) goto out; } break; - default: break; diff --git a/cli/src/cli.h b/cli/src/cli.h index 5a491eba7a..a36c1606f5 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -393,6 +393,8 @@ cli_xml_output_generic_volume (char *op, dict_t *dict, int op_ret, int op_errno, int cli_xml_output_vol_gsync (dict_t *dict, int op_ret, int op_errno, char *op_errstr); +int +cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict); char * is_server_debug_xlator (void *myframe); -- cgit