From 0143a2ef653d0f7a337c8220f127655dadbca942 Mon Sep 17 00:00:00 2001 From: Vijay Bellur Date: Thu, 18 Aug 2011 23:19:22 +0530 Subject: mgmt/glusterd, cli: Introduce gluster volume status Change-Id: Iea835b9e448e736016da2e44e3c9bfff93f2fa78 BUG: 3439 Reviewed-on: http://review.gluster.com/259 Tested-by: Gluster Build System Reviewed-by: Anand Avati --- cli/src/cli-cmd-parser.c | 34 +++++++++++++ cli/src/cli-cmd-volume.c | 72 +++++++++++++++++++++++++++ cli/src/cli-rpc-ops.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++- cli/src/cli.c | 11 ++++ cli/src/cli.h | 13 +++++ 5 files changed, 256 insertions(+), 1 deletion(-) (limited to 'cli') diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index a442b3aee..9f35cc47e 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1646,3 +1646,37 @@ out: dict_destroy (dict); return ret; } + +int32_t +cli_cmd_volume_status_parse (const char **words, int wordcount, + dict_t **options) +{ + dict_t *dict = NULL; + int ret = -1; + + GF_ASSERT (words); + GF_ASSERT (options); + + + GF_ASSERT ((strncmp(words[0], "volume", 6) == 0)); + GF_ASSERT ((strncmp(words[1], "status", 5) == 0)); + + + dict = dict_new (); + if (!dict) + goto out; + + GF_ASSERT(words[2]); + + ret = dict_set_str (dict, "volname", (char *)words[2]); + if (ret) + goto out; + + *options = dict; + + out: + if (ret && dict) + dict_destroy (dict); + + return ret; +} diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index ab7f1ddc7..b61eb31c0 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1211,6 +1211,74 @@ cli_cmd_log_level_cbk (struct cli_state *state, struct cli_cmd_word *word, return ret; } +int +cli_cmd_volume_status_cbk (struct cli_state *state, + struct cli_cmd_word *word, + const char **words, int wordcount) +{ + int ret = -1; + rpc_clnt_procedure_t *proc = NULL; + call_frame_t *frame = NULL; + dict_t *dict = NULL; + int parse_error = 0; + + if (wordcount != 3) { + cli_usage_out (word->pattern); + parse_error = 1; + goto out; + } + + proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME]; + + frame = create_frame (THIS, THIS->ctx->pool); + if (!frame) + goto out; + + ret = cli_cmd_volume_status_parse (words, wordcount, &dict); + if (ret) + goto out; + + if (proc->fn) + ret = proc->fn (frame, THIS, dict); + + out: + return ret; +} + + +int +cli_print_brick_status (char *brick, int port, int online, int pid) +{ + int fieldlen = CLI_VOL_STATUS_BRICK_LEN; + char buf[80] = {0,}; + int bricklen = 0; + int i = 0; + char *p = NULL; + int num_tabs = 0; + + bricklen = strlen (brick); + p = brick; + while (bricklen > 0) { + if (bricklen > fieldlen) { + i++; + strncpy (buf, p, fieldlen); + buf[strlen(buf) + 1] = '\0'; + cli_out ("%s", buf); + p = brick + i * fieldlen; + bricklen -= fieldlen; + } else { + num_tabs = (fieldlen - bricklen) / CLI_TAB_LENGTH + 1; + printf ("%s", p); + while (num_tabs-- != 0) + printf ("\t"); + cli_out ("%d\t%c\t%d", port, online?'Y':'N', pid); + bricklen = 0; + } + } + + return 0; +} + struct cli_cmd volume_cmds[] = { { "volume info [all|]", cli_cmd_volume_info_cbk, @@ -1309,6 +1377,10 @@ struct cli_cmd volume_cmds[] = { cli_cmd_log_level_cbk, "log level for translator"}, + { "volume status ", + cli_cmd_volume_status_cbk, + "display status of specified volume"}, + { NULL, NULL, NULL } }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index b6fbf3f05..498cdbf74 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -3562,6 +3562,130 @@ out: return ret; } +static int +gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + gf1_cli_status_volume_rsp rsp = {0,}; + int ret = -1; + dict_t *dict = NULL; + char *hostname = NULL; + char *path = NULL; + int i = 0; + int port = 0; + int online = 0; + char key[1024] = {0,}; + int pid = 0; + char brick[8192] = {0,}; + char *volname = NULL; + + + if (req->rpc_status == -1) + goto out; + + ret = gf_xdr_to_cli_status_volume_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("cli", GF_LOG_ERROR, "Volume status response error"); + goto out; + } + + gf_log ("cli", GF_LOG_DEBUG, "Received response to status cmd"); + + if (rsp.op_ret && strcmp (rsp.op_errstr, "")) + cli_out ("%s", rsp.op_errstr); + else if (rsp.op_ret) + cli_out ("Unable to obtain volume status information."); + + dict = dict_new (); + if (!dict) + goto out; + + ret = dict_unserialize (rsp.dict.dict_val, + rsp.dict.dict_len, + &dict); + if (ret) + goto out; + + + ret = dict_get_int32 (dict, "count", &count); + if (ret) + goto out; + + ret = dict_get_str (dict, "volname", &volname); + + cli_out ("Brick status for volume: %s", volname); + cli_out ("Brick\t\t\t\t\t\t\tPort\tOnline\tPID"); + for (i = 0; i < count; i++) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.hostname", i); + ret = dict_get_str (dict, key, &hostname); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.path", i); + ret = dict_get_str (dict, key, &path); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.port", i); + ret = dict_get_int32 (dict, key, &port); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.status", i); + ret = dict_get_int32 (dict, key, &online); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.pid", i); + ret = dict_get_int32 (dict, key, &pid); + + snprintf (brick, sizeof (brick) -1, "%s:%s", hostname, path); + + cli_print_line (CLI_BRICK_STATUS_LINE_LEN); + cli_print_brick_status (brick, port, online, pid); + } + + ret = rsp.op_ret; + + out: + cli_cmd_broadcast_response (ret); + return ret; +} + +int32_t +gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this, + void *data) +{ + gf1_cli_status_volume_req req = {0,}; + int ret = 0; + dict_t *dict = NULL; + + if (!frame || !this || !data) { + ret = -1; + goto out; + } + + dict = data; + + ret = dict_get_str (dict, "volname", &req.volname); + if (ret) + goto out; + + ret = cli_cmd_submit (&req, frame, cli_rpc_prog, + GLUSTER_CLI_STATUS_VOLUME, NULL, + gf_xdr_from_cli_status_volume_req, + this, gf_cli3_1_status_cbk, + (xdrproc_t)xdr_gf1_cli_status_volume_req); + + out: + gf_log ("cli", GF_LOG_DEBUG, "Returning: %d", ret); + return ret; +} struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_NULL] = {"NULL", NULL }, @@ -3593,7 +3717,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_QUOTA] = {"QUOTA", gf_cli3_1_quota}, [GLUSTER_CLI_TOP_VOLUME] = {"TOP_VOLUME", gf_cli3_1_top_volume}, [GLUSTER_CLI_LOG_LEVEL] = {"VOLUME_LOGLEVEL", gf_cli3_1_log_level}, - [GLUSTER_CLI_GETWD] = {"GETWD", gf_cli3_1_getwd} + [GLUSTER_CLI_GETWD] = {"GETWD", gf_cli3_1_getwd}, + [GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", gf_cli3_1_status_volume}, }; struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli.c b/cli/src/cli.c index 1703c0ca6..eec14d6fa 100644 --- a/cli/src/cli.c +++ b/cli/src/cli.c @@ -698,3 +698,14 @@ out: return ret; } + +void +cli_print_line (int len) +{ + GF_ASSERT (len > 0); + + while (len--) + printf ("-"); + + printf ("\n"); +} diff --git a/cli/src/cli.h b/cli/src/cli.h index 91fca102e..55d0d89f1 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -34,6 +34,9 @@ #define CLI_DEFAULT_CONN_TIMEOUT 120 #define CLI_DEFAULT_CMD_TIMEOUT 120 #define DEFAULT_CLI_LOG_FILE_DIRECTORY DATADIR "/log/glusterfs" +#define CLI_VOL_STATUS_BRICK_LEN 55 +#define CLI_TAB_LENGTH 8 +#define CLI_BRICK_STATUS_LINE_LEN 75 enum argp_option_keys { ARGP_DEBUG_KEY = 133, @@ -248,4 +251,14 @@ cli_cmd_volume_top_parse (const char **words, int wordcount, int32_t cli_cmd_log_level_parse (const char **words, int wordcount, dict_t **options); + +int32_t +cli_cmd_volume_status_parse (const char **words, int wordcount, + dict_t **options); + +int +cli_print_brick_status (char *brick, int port, int online, int pid); + +void +cli_print_line (int len); #endif /* __CLI_H__ */ -- cgit