From 169c73f28dae61236de54889edcaa8236d91da59 Mon Sep 17 00:00:00 2001 From: Rajesh Amaravathi Date: Wed, 7 Dec 2011 20:51:03 +0530 Subject: cli: volume status enhancement * Support "gluster volume status (all)" option to display all volumes' status. * On option "detail" appended to "gluster volume status *", amount of storage free, total storage, and backend filesystem details like inode size, inode count, free inodes, fs type, device name of each brick is displayed. * One can also obtain [detailed]status of only one brick. * Format of the enhanced volume status command is: "gluster volume status [all|] [] [detail]" * Some generic functions have been added to common-utils: skipword get_nth_word These functions enable parsing and fetching of words in a sentence. glusterd_get_brick_root (in glusterd) These are self explanatory. Change-Id: I6f40c1e19810f8504cd3b1786207364053d82e28 BUG: 765464 Signed-off-by: Rajesh Amaravathi Reviewed-on: http://review.gluster.com/777 Tested-by: Gluster Build System Reviewed-by: Amar Tumballi --- cli/src/cli-cmd-parser.c | 71 ++++- cli/src/cli-cmd-volume.c | 166 +++++++++++- cli/src/cli-rpc-ops.c | 169 +++++++++--- cli/src/cli.h | 28 +- libglusterfs/src/common-utils.c | 49 ++++ libglusterfs/src/common-utils.h | 8 + rpc/rpc-lib/src/protocol-common.h | 1 + rpc/xdr/src/cli1-xdr.c | 11 + rpc/xdr/src/cli1-xdr.h | 14 + rpc/xdr/src/cli1-xdr.x | 13 + xlators/mgmt/glusterd/src/glusterd-handler.c | 28 +- xlators/mgmt/glusterd/src/glusterd-op-sm.c | 172 ++++++++---- xlators/mgmt/glusterd/src/glusterd-utils.c | 375 +++++++++++++++++++++++++-- xlators/mgmt/glusterd/src/glusterd-utils.h | 11 + 14 files changed, 992 insertions(+), 124 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index fa46fa06671..acbd960ba43 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1795,23 +1795,84 @@ out: return ret; } -int32_t +int cli_cmd_volume_status_parse (const char **words, int wordcount, - dict_t **options) + dict_t **options) { dict_t *dict = NULL; int ret = -1; + int cmd = 0; - GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; - GF_ASSERT(words[2]); + switch (wordcount) { + + case 2: + cmd = GF_CLI_STATUS_ALL; + ret = 0; + break; + + case 3: + if (!strcmp (words[2], "all")) { + + cmd = GF_CLI_STATUS_ALL; + ret = 0; + + } else if (!strcmp (words[2], "detail")) { + + cmd = GF_CLI_STATUS_ALL_DETAIL; + ret = 0; + + } else { + cmd = GF_CLI_STATUS_VOL; + ret = dict_set_str (dict, "volname", (char *)words[2]); + } + break; + + case 4: + if (!strcmp (words[2], "all") && + !strcmp (words[3], "detail")) { + + cmd = GF_CLI_STATUS_ALL_DETAIL; + ret = 0; + + } else if (!strcmp (words[3], "detail")) { + cmd = GF_CLI_STATUS_VOL_DETAIL; + ret = dict_set_str (dict, "volname", (char *)words[2]); + + } else { + + cmd = GF_CLI_STATUS_BRICK; + ret = dict_set_str (dict, "volname", (char *)words[2]); + if (ret) + goto out; + ret = dict_set_str (dict, "brick", (char *)words[3]); + } + break; + + case 5: + if (strcmp (words[4], "detail")) + goto out; + + cmd = GF_CLI_STATUS_BRICK_DETAIL; + ret = dict_set_str (dict, "volname", (char *)words[2]); + if (ret) + goto out; + ret = dict_set_str (dict, "brick", (char *)words[3]); + break; + + default: + goto out; + } + + if (ret) + goto out; - ret = dict_set_str (dict, "volname", (char *)words[2]); + ret = dict_set_int32 (dict, "cmd", cmd); if (ret) goto out; diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 009896d9ce4..38c16797ea1 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1344,39 +1344,177 @@ out: int cli_cmd_volume_status_cbk (struct cli_state *state, - struct cli_cmd_word *word, - const char **words, int wordcount) + 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; + uint32_t cmd = 0; - if (wordcount != 3) { + ret = cli_cmd_volume_status_parse (words, wordcount, &dict); + + if (ret) { cli_usage_out (word->pattern); goto out; } - proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME]; + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; + + if (!(cmd & GF_CLI_STATUS_ALL)) { + /* for one volume or brick */ + proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_VOLUME]; + } else { + /* volume status all or all detail */ + proc = &cli_rpc_prog->proctable[GLUSTER_CLI_STATUS_ALL]; + } + + if (!proc->fn) + goto out; frame = create_frame (THIS, THIS->ctx->pool); if (!frame) goto out; - ret = cli_cmd_volume_status_parse (words, wordcount, &dict); + ret = proc->fn (frame, THIS, dict); + + out: + if (dict) + dict_unref (dict); + return ret; +} + + +int +cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status) +{ + uint64_t free = -1; + uint64_t total = -1; + char key[1024] = {0}; + int ret = 0; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.free", i); + ret = dict_get_uint64 (dict, key, &free); if (ret) goto out; - if (proc->fn) - ret = proc->fn (frame, THIS, dict); + status->free = gf_uint64_2human_readable (free); + if (!status->free) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.total", i); + ret = dict_get_uint64 (dict, key, &total); + if (ret) + goto out; + + status->total = gf_uint64_2human_readable (total); + if (!status->total) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.device", i); + ret = dict_get_str (dict, key, &(status->device)); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.block_size", i); + ret = dict_get_uint64 (dict, key, &(status->block_size)); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.mnt_options", i); + ret = dict_get_str (dict, key, &(status->mount_options)); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.fs_name", i); + ret = dict_get_str (dict, key, &(status->fs_name)); + if (ret) + goto out; + + if (IS_EXT_FS(status->fs_name) || + !strcmp (status->fs_name, "xfs")) { + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.inode_size", i); + ret = dict_get_str (dict, key, &(status->inode_size)); + if (ret) + status->inode_size = NULL; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.total_inodes", i); + ret = dict_get_uint64 (dict, key, &(status->total_inodes)); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.free_inodes", i); + ret = dict_get_uint64 (dict, key, &(status->free_inodes)); + if (ret) + goto out; + + } else { + status->inode_size = NULL; + status->total_inodes = 0; + status->free_inodes = 0; + } out: return ret; } +void +cli_print_detailed_status (cli_volume_status_t *status) +{ + cli_out ("%-20s : %-20s", "Brick", status->brick); + cli_out ("%-20s : %-20d", "Port", status->port); + cli_out ("%-20s : %-20c", "Online", (status->online) ? 'Y' : 'N'); + cli_out ("%-20s : %-20s", "Pid", status->pid_str); + cli_out ("%-20s : %-20s", "File System", status->fs_name); + cli_out ("%-20s : %-20s", "Device", status->device); + + if (status->mount_options) { + cli_out ("%-20s : %-20s", "Mount Options", + status->mount_options); + } else { + cli_out ("%-20s : %-20s", "Mount Options", "N/A"); + } + + cli_out ("%-20s : %-20s", "Disk Space Free", status->free); + cli_out ("%-20s : %-20s", "Total Disk Space", status->total); + + if (status->inode_size) { + cli_out ("%-20s : %-20s", "Inode Size", + status->inode_size); + } else { + cli_out ("%-20s : %-20s", "Inode Size", "N/A"); + } + + if (status->total_inodes) { + cli_out ("%-20s : %-20ld", "Inode Count", + status->total_inodes); + } else { + cli_out ("%-20s : %-20s", "Inode Count", "N/A"); + } + + if (status->free_inodes) { + cli_out ("%-20s : %-20ld", "Free Inodes", + status->free_inodes); + } else { + cli_out ("%-20s : %-20s", "Free Inodes", "N/A"); + } +} int -cli_print_brick_status (char *brick, int port, int online, char *pid) +cli_print_brick_status (cli_volume_status_t *status) { int fieldlen = CLI_VOL_STATUS_BRICK_LEN; char buf[80] = {0,}; @@ -1385,22 +1523,24 @@ cli_print_brick_status (char *brick, int port, int online, char *pid) char *p = NULL; int num_tabs = 0; - bricklen = strlen (brick); - p = brick; + bricklen = strlen (status->brick); + p = status->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; + p = status->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%s", port, online?'Y':'N', pid); + cli_out ("%d\t%c\t%s", + status->port, status->online?'Y':'N', + status->pid_str); bricklen = 0; } } @@ -1597,7 +1737,7 @@ struct cli_cmd volume_cmds[] = { cli_cmd_volume_top_cbk, "volume top operations"}, - { "volume status ", + { "volume status [all|] [brick] [detail]", cli_cmd_volume_status_cbk, "display status of specified volume"}, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index f6ae1d94122..06c52dac186 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -3796,22 +3796,19 @@ out: static int gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, - int count, void *myframe) + int count, void *myframe) { - gf_cli_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 = -1; - char *pid_str = NULL; - char brick[8192] = {0,}; - char *volname = NULL; - + int ret = -1; + int i = 0; + int pid = -1; + uint32_t cmd = 0; + char key[1024] = {0,}; + char *hostname = NULL; + char *path = NULL; + char *volname = NULL; + dict_t *dict = NULL; + gf_cli_rsp rsp = {0,}; + cli_volume_status_t status = {0}; if (req->rpc_status == -1) goto out; @@ -3839,16 +3836,39 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, if (ret) goto out; + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; + + if ((cmd & GF_CLI_STATUS_ALL)) { + ((call_frame_t *)myframe)->local = dict; + ret = 0; + goto out; + } ret = dict_get_int32 (dict, "count", &count); if (ret) goto out; + if (count == 0) { + ret = -1; + goto out; + } + + status.brick = GF_CALLOC (1, PATH_MAX + 256, gf_common_mt_strdup); ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + + cli_out ("\nSTATUS OF VOLUME: %s", volname); + + if ((cmd & GF_CLI_STATUS_DETAIL) == 0) + cli_out ("BRICK\t\t\t\t\t\t\tPORT\tONLINE\tPID"); - 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++) { + + cli_print_line (CLI_BRICK_STATUS_LINE_LEN); + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.hostname", i); ret = dict_get_str (dict, key, &hostname); @@ -3861,15 +3881,19 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, if (ret) goto out; + memset (status.brick, 0, PATH_MAX + 255); + snprintf (status.brick, PATH_MAX + 255, "%s:%s", + hostname, path); + memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "brick%d.port", i); - ret = dict_get_int32 (dict, key, &port); + ret = dict_get_int32 (dict, key, &(status.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); + ret = dict_get_int32 (dict, key, &(status.online)); if (ret) goto out; @@ -3879,40 +3903,44 @@ gf_cli3_1_status_cbk (struct rpc_req *req, struct iovec *iov, if (ret) goto out; if (pid == -1) - ret = gf_asprintf (&pid_str, "%s", "N/A"); + ret = gf_asprintf (&(status.pid_str), "%s", "N/A"); else - ret = gf_asprintf (&pid_str, "%d", pid); + ret = gf_asprintf (&(status.pid_str), "%d", pid); if (ret == -1) goto out; - snprintf (brick, sizeof (brick) -1, "%s:%s", hostname, path); + if ((cmd & GF_CLI_STATUS_DETAIL)) { + ret = cli_get_detail_status (dict, i, &status); + if (ret) + goto out; + cli_print_detailed_status (&status); - cli_print_line (CLI_BRICK_STATUS_LINE_LEN); - cli_print_brick_status (brick, port, online, pid_str); - if (pid_str) - GF_FREE (pid_str); + } else { + cli_print_brick_status (&status); + } } ret = rsp.op_ret; out: + if (status.brick) + GF_FREE (status.brick); + cli_cmd_broadcast_response (ret); return ret; } int32_t gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this, - void *data) + void *data) { gf_cli_req req = {{0,}}; - int ret = 0; - dict_t *dict = NULL; + int ret = -1; + dict_t *dict = NULL; - if (!frame || !this || !data) { - ret = -1; + if (!frame || !this || !data) goto out; - } dict = data; @@ -3920,7 +3948,7 @@ gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this, &req.dict.dict_val, (size_t *)&req.dict.dict_len); if (ret < 0) { - gf_log (this->name, GF_LOG_ERROR, + gf_log ("cli", GF_LOG_ERROR, "failed to serialize the data"); goto out; @@ -3935,6 +3963,80 @@ gf_cli3_1_status_volume (call_frame_t *frame, xlator_t *this, return ret; } +int +gf_cli_status_volume_all (call_frame_t *frame, xlator_t *this, void *data) +{ + int i = 0; + int ret = -1; + int vol_count = -1; + uint32_t cmd = 0; + char key[1024] = {0}; + char *volname = NULL; + dict_t *vol_dict = NULL; + dict_t *dict = NULL; + + dict = (dict_t *)data; + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; + + ret = gf_cli3_1_status_volume (frame, this, data); + if (ret) + goto out; + + vol_dict = (dict_t *)(frame->local); + + ret = dict_get_int32 (vol_dict, "vol_count", &vol_count); + if (ret) { + cli_out ("Failed to get names of volumes"); + goto out; + } + + if (vol_count == 0) { + cli_out ("No volumes present"); + ret = 0; + goto out; + } + + /* remove the "all" flag in cmd */ + cmd &= ~GF_CLI_STATUS_ALL; + cmd |= GF_CLI_STATUS_VOL; + + for (i = 0; i < vol_count; i++) { + + dict = dict_new (); + if (!dict) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "vol%d", i); + ret = dict_get_str (vol_dict, key, &volname); + if (ret) + goto out; + + ret = dict_set_dynstr (dict, "volname", volname); + if (ret) + goto out; + + ret = dict_set_uint32 (dict, "cmd", cmd); + if (ret) + goto out; + + ret = gf_cli3_1_status_volume (frame, this, dict); + if (ret) + goto out; + + dict_unref (dict); + } + + out: + if (ret) + gf_log ("cli", GF_LOG_ERROR, "status all failed"); + if (ret && dict) + dict_unref (dict); + return ret; +} + static int gf_cli3_1_mount_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) @@ -4265,6 +4367,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_TOP_VOLUME] = {"TOP_VOLUME", gf_cli3_1_top_volume}, [GLUSTER_CLI_GETWD] = {"GETWD", gf_cli3_1_getwd}, [GLUSTER_CLI_STATUS_VOLUME] = {"STATUS_VOLUME", gf_cli3_1_status_volume}, + [GLUSTER_CLI_STATUS_ALL] = {"STATUS_ALL", gf_cli_status_volume_all}, [GLUSTER_CLI_MOUNT] = {"MOUNT", gf_cli3_1_mount}, [GLUSTER_CLI_UMOUNT] = {"UMOUNT", gf_cli3_1_umount}, [GLUSTER_CLI_HEAL_VOLUME] = {"HEAL_VOLUME", gf_cli3_1_heal_volume}, diff --git a/cli/src/cli.h b/cli/src/cli.h index 1d2e069735a..e091e7004a8 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -37,7 +37,7 @@ #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 +#define CLI_BRICK_STATUS_LINE_LEN 78 enum argp_option_keys { ARGP_DEBUG_KEY = 133, @@ -124,6 +124,24 @@ struct cli_local { dict_t *dict; }; +struct cli_volume_status { + int port; + int online; + uint64_t block_size; + uint64_t total_inodes; + uint64_t free_inodes; + char *brick; + char *pid_str; + char *fs_name; + char *free; + char *total; + char *mount_options; + char *device; + char *inode_size; +}; + +typedef struct cli_volume_status cli_volume_status_t; + typedef struct cli_local cli_local_t; typedef ssize_t (*cli_serialize_t) (struct iovec outmsg, void *args); @@ -236,7 +254,13 @@ cli_cmd_volume_status_parse (const char **words, int wordcount, dict_t **options); int -cli_print_brick_status (char *brick, int port, int online, char *pid); +cli_print_brick_status (cli_volume_status_t *status); + +void +cli_print_detailed_status (cli_volume_status_t *status); + +int +cli_get_detail_status (dict_t *dict, int i, cli_volume_status_t *status); void cli_print_line (int len); diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index 1d0fb822fc5..d22ebd2ef04 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -1607,6 +1607,55 @@ nwstrtail (char *str, char *pattern) return *pattern ? NULL : str; } +void +skipword (char **s) +{ + if (!*s) + return; + + skipwhite (s); + + while (!isspace(**s)) + (*s)++; +} + +char * +get_nth_word (const char *str, int n) +{ + char buf[4096] = {0}; + char *start = NULL; + char *word = NULL; + int i = 0; + int word_len = 0; + const char *end = NULL; + + if (!str) + goto out; + + snprintf (buf, sizeof (buf), "%s", str); + start = buf; + + for (i = 0; i < n-1; i++) + skipword (&start); + + skipwhite (&start); + end = strpbrk ((const char *)start, " \t\n\0"); + + if (!end) + goto out; + + word_len = abs (end - start); + + word = GF_CALLOC (1, word_len + 1, gf_common_mt_strdup); + if (!word) + goto out; + + strncpy (word, start, word_len); + *(word + word_len) = '\0'; + out: + return word; +} + /* RFC 1123 & 952 */ char valid_host_name (char *address, int length) diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index 4cb3843d980..6045cd3efe0 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -74,6 +74,11 @@ void trap (void); #define WIPE(statp) do { typeof(*statp) z = {0,}; if (statp) *statp = z; } while (0) +#define IS_EXT_FS(fs_name) \ + (!strcmp (fs_name, "ext2") || \ + !strcmp (fs_name, "ext3") || \ + !strcmp (fs_name, "ext4")) + enum _gf_boolean { _gf_false = 0, @@ -409,6 +414,9 @@ int get_checksum_for_path (char *path, uint32_t *checksum); char *strtail (char *str, const char *pattern); void skipwhite (char **s); char *nwstrtail (char *str, char *pattern); +void skip_word (char **str); +/* returns a new string with nth word of given string. n>=1 */ +char *get_nth_word (const char *str, int n); char valid_host_name (char *address, int length); char valid_ipv4_address (char *address, int length); diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 9b358f49730..fd7c89aadb8 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -148,6 +148,7 @@ enum gluster_cli_procnum { GLUSTER_CLI_TOP_VOLUME, GLUSTER_CLI_GETWD, GLUSTER_CLI_STATUS_VOLUME, + GLUSTER_CLI_STATUS_ALL, GLUSTER_CLI_MOUNT, GLUSTER_CLI_UMOUNT, GLUSTER_CLI_HEAL_VOLUME, diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c index b0ac0799a8d..56562ee3d00 100644 --- a/rpc/xdr/src/cli1-xdr.c +++ b/rpc/xdr/src/cli1-xdr.c @@ -176,6 +176,17 @@ xdr_gf1_cli_top_op (XDR *xdrs, gf1_cli_top_op *objp) return TRUE; } +bool_t +xdr_gf_cli_status_type (XDR *xdrs, gf_cli_status_type *objp) +{ + register int32_t *buf; + buf = NULL; + + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + return TRUE; +} + bool_t xdr_gf_cli_req (XDR *xdrs, gf_cli_req *objp) { diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index 1d0faa996b5..d5593977d97 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -160,6 +160,18 @@ enum gf1_cli_top_op { }; typedef enum gf1_cli_top_op gf1_cli_top_op; +enum gf_cli_status_type { + GF_CLI_STATUS_NONE = 0x0000, + GF_CLI_STATUS_VOL = 0x0100, + GF_CLI_STATUS_ALL = 0x0200, + GF_CLI_STATUS_BRICK = 0x0400, + GF_CLI_STATUS_DETAIL = 0x0800, + GF_CLI_STATUS_VOL_DETAIL = 0x0900, + GF_CLI_STATUS_ALL_DETAIL = 0x0A00, + GF_CLI_STATUS_BRICK_DETAIL = 0x0C00, +}; +typedef enum gf_cli_status_type gf_cli_status_type; + struct gf_cli_req { struct { u_int dict_len; @@ -298,6 +310,7 @@ extern bool_t xdr_gf1_cli_op_flags (XDR *, gf1_cli_op_flags*); extern bool_t xdr_gf1_cli_gsync_set (XDR *, gf1_cli_gsync_set*); extern bool_t xdr_gf1_cli_stats_op (XDR *, gf1_cli_stats_op*); extern bool_t xdr_gf1_cli_top_op (XDR *, gf1_cli_top_op*); +extern bool_t xdr_gf_cli_status_type (XDR *, gf_cli_status_type*); extern bool_t xdr_gf_cli_req (XDR *, gf_cli_req*); extern bool_t xdr_gf_cli_rsp (XDR *, gf_cli_rsp*); extern bool_t xdr_gf1_cli_probe_req (XDR *, gf1_cli_probe_req*); @@ -329,6 +342,7 @@ extern bool_t xdr_gf1_cli_op_flags (); extern bool_t xdr_gf1_cli_gsync_set (); extern bool_t xdr_gf1_cli_stats_op (); extern bool_t xdr_gf1_cli_top_op (); +extern bool_t xdr_gf_cli_status_type (); extern bool_t xdr_gf_cli_req (); extern bool_t xdr_gf_cli_rsp (); extern bool_t xdr_gf1_cli_probe_req (); diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 129f5f971ab..5697310ad7d 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -103,6 +103,19 @@ enum gf1_cli_top_op { GF_CLI_TOP_WRITE_PERF }; +/* The unconventional hex numbers help us perform + bit-wise operations which reduces complexity */ +enum gf_cli_status_type { + GF_CLI_STATUS_NONE = 0x0000, + GF_CLI_STATUS_VOL = 0x0100, + GF_CLI_STATUS_ALL = 0x0200, + GF_CLI_STATUS_BRICK = 0x0400, + GF_CLI_STATUS_DETAIL = 0x0800, + GF_CLI_STATUS_VOL_DETAIL = 0x0900, + GF_CLI_STATUS_ALL_DETAIL = 0x0A00, + GF_CLI_STATUS_BRICK_DETAIL = 0x0C00 +}; + struct gf_cli_req { opaque dict<>; } ; diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 664798ca376..7817e1dd653 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -2511,10 +2511,11 @@ int glusterd_handle_status_volume (rpcsvc_request_t *req) { int32_t ret = -1; + uint32_t cmd = 0; + dict_t *dict = NULL; + char *volname = 0; gf_cli_req cli_req = {{0,}}; - dict_t *dict = NULL; - glusterd_op_t cli_op = GD_OP_STATUS_VOLUME; - char *volname = 0; + glusterd_op_t cli_op = GD_OP_STATUS_VOLUME; GF_ASSERT (req); @@ -2530,7 +2531,7 @@ glusterd_handle_status_volume (rpcsvc_request_t *req) if (!dict) goto out; ret = dict_unserialize (cli_req.dict.dict_val, - cli_req.dict.dict_len, &dict); + cli_req.dict.dict_len, &dict); if (ret < 0) { gf_log (THIS->name, GF_LOG_ERROR, "failed to " "unserialize buffer"); @@ -2539,15 +2540,22 @@ glusterd_handle_status_volume (rpcsvc_request_t *req) } - ret = dict_get_str (dict, "volname", &volname); - if (ret) { - gf_log (THIS->name, GF_LOG_ERROR, "failed to get volname"); + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) goto out; - } - gf_log ("glusterd", GF_LOG_INFO, "Received status volume req " - "for volume %s", volname); + if (!(cmd & GF_CLI_STATUS_ALL)) { + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "failed to get volname"); + goto out; + } + gf_log (THIS->name, GF_LOG_INFO, + "Received status volume req " + "for volume %s", volname); + } ret = glusterd_op_begin (req, GD_OP_STATUS_VOLUME, dict); diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 8f2d55aaf3a..68a98b16b7b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -527,12 +527,16 @@ out: static int glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) { - int ret = -1; - gf_boolean_t exists = _gf_false; - char *volname = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - char msg[2048] = {0,}; + int ret = -1; + uint32_t cmd = 0; + char msg[2048] = {0,}; + char *volname = NULL; + char *brick = NULL; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_brickinfo_t *tmpbrickinfo = NULL; + glusterd_volinfo_t *volinfo = NULL; GF_ASSERT (dict); this = THIS; @@ -540,30 +544,63 @@ glusterd_op_stage_status_volume (dict_t *dict, char **op_errstr) priv = this->private; GF_ASSERT(priv); + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; + + if (cmd & GF_CLI_STATUS_ALL) + goto out; ret = dict_get_str (dict, "volname", &volname); if (ret) { - gf_log ("glusterd", GF_LOG_ERROR, "Unable to get volume name"); + gf_log (THIS->name, GF_LOG_ERROR, + "Unable to get volume name"); goto out; } - exists = glusterd_check_volume_exists (volname); - if (!exists) { + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { snprintf (msg, sizeof(msg), "Volume %s does not exist", volname); - gf_log ("glusterd", GF_LOG_ERROR, "%s", msg); - + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); *op_errstr = gf_strdup(msg); ret = -1; goto out; } + if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + + ret = glusterd_brickinfo_from_brick (brick, &brickinfo); + if (ret) + goto out; + + ret = glusterd_volume_brickinfo_get (NULL, + brickinfo->hostname, + brickinfo->path, + volinfo, + &tmpbrickinfo, + GF_PATH_COMPLETE); + + if (ret) { + snprintf (msg, sizeof(msg), "No brick %s in" + " volume %s", brick, volname); + gf_log (THIS->name, GF_LOG_ERROR, "%s", msg); + + *op_errstr = gf_strdup(msg); + ret = -1; + goto out; + } + } + ret = 0; out: if (ret && !(*op_errstr)) *op_errstr = gf_strdup ("Validation Failed for Status"); - gf_log ("glusterd", GF_LOG_DEBUG, "Returning: %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning: %d", ret); return ret; } @@ -1203,15 +1240,17 @@ static int glusterd_op_status_volume (dict_t *dict, char **op_errstr, dict_t *rsp_dict) { - int ret = -1; - char *volname = NULL; - int count = 0; - int brick_count = 0; - glusterd_volinfo_t *volinfo = NULL; - glusterd_brickinfo_t *brickinfo = NULL; - glusterd_conf_t *priv = NULL; - xlator_t *this = NULL; - int32_t brick_index = 0; + int ret = -1; + int brick_count = 0; + int32_t brick_index = 0; + uint32_t cmd = 0; + char *volname = NULL; + char *brick = NULL; + xlator_t *this = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_brickinfo_t *brickinfo = NULL; + glusterd_brickinfo_t *tmpbrickinfo = NULL; + glusterd_conf_t *priv = NULL; this = THIS; GF_ASSERT (this); @@ -1221,41 +1260,83 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr, GF_ASSERT (dict); - - ret = dict_get_str (dict, "volname", &volname); - if (!ret) { - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_ERROR, "Volume with name: %s " - "does not exist", volname); - goto out; - } - } + ret = dict_get_uint32 (dict, "cmd", &cmd); + if (ret) + goto out; if (!rsp_dict) { //this should happen only on source ret = 0; rsp_dict = glusterd_op_get_ctx (); + + if ((cmd & GF_CLI_STATUS_ALL)) { + ret = glusterd_get_all_volnames (rsp_dict); + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, + "failed to get all volume " + "names for status"); + } + } - if (volname) { - list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { - if (!uuid_compare (brickinfo->uuid, priv->uuid)) { - ret = glusterd_add_brick_to_dict (volinfo, - brickinfo, - rsp_dict, - brick_index); - count++; - brick_count = count; - } - brick_index++; + ret = dict_set_uint32 (rsp_dict, "cmd", cmd); + if (ret) + goto out; + + if (cmd & GF_CLI_STATUS_ALL) + goto out; + + ret = dict_get_str (dict, "volname", &volname); + if (ret) + goto out; + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "Volume with name: %s " + "does not exist", volname); + goto out; + } + + if ((cmd & GF_CLI_STATUS_BRICK) != 0) { + ret = dict_get_str (dict, "brick", &brick); + if (ret) + goto out; + ret = glusterd_brickinfo_from_brick (brick, &tmpbrickinfo); + if (ret) + goto out; + if (uuid_is_null (tmpbrickinfo->uuid) && + glusterd_resolve_brick (tmpbrickinfo)) + goto out; + } + + list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { + if (!uuid_compare (brickinfo->uuid, priv->uuid)) { + + if ((cmd & GF_CLI_STATUS_BRICK) != 0 && + (strcmp (tmpbrickinfo->path, + brickinfo->path) || + uuid_compare (tmpbrickinfo->uuid, + brickinfo->uuid))) + continue; + + glusterd_add_brick_to_dict (volinfo, brickinfo, + rsp_dict, brick_index); + + if (cmd & GF_CLI_STATUS_DETAIL) + glusterd_add_brick_detail_to_dict (volinfo, + brickinfo, + rsp_dict, + brick_index); + brick_count++; } + if (!(cmd & GF_CLI_STATUS_BRICK)) + brick_index++; } ret = dict_set_int32 (rsp_dict, "count", brick_count); out: - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); return ret; } @@ -2119,7 +2200,7 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) rsp_dict); if (status) { - gf_log ("", GF_LOG_ERROR, "Commit failed: %d", status); + gf_log (THIS->name, GF_LOG_ERROR, "Commit failed: %d", status); } ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, @@ -2131,7 +2212,8 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx) if (rsp_dict) dict_unref (rsp_dict); - gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + + gf_log (THIS->name, GF_LOG_DEBUG, "Returning with %d", ret); return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 2eaf4f4a2f4..b2d0bcdd7ad 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -58,6 +58,9 @@ #include #include #include +#include + + #ifdef GF_SOLARIS_HOST_OS #include #endif @@ -679,11 +682,11 @@ glusterd_brickinfo_from_brick (char *brick, GF_ASSERT (brickinfo); tmp_host = gf_strdup (brick); - if (tmp_host) - get_host_name (tmp_host, &hostname); + if (tmp_host && !get_host_name (tmp_host, &hostname)) + goto out; tmp_path = gf_strdup (brick); - if (tmp_path) - get_path_name (tmp_path, &path); + if (tmp_path && !get_path_name (tmp_path, &path)) + goto out; GF_ASSERT (hostname); GF_ASSERT (path); @@ -3084,21 +3087,331 @@ out: return -1; } +int +glusterd_get_brick_root (char *path, char **mount_point) +{ + char *ptr = NULL; + struct stat brickstat = {0}; + struct stat buf = {0}; + + if (!path) + goto err; + *mount_point = gf_strdup (path); + if (!*mount_point) + goto err; + if (stat (*mount_point, &brickstat)) + goto err; + + while ((ptr = strrchr (*mount_point, '/')) && + ptr != *mount_point) { + + *ptr = '\0'; + if (stat (*mount_point, &buf)) { + gf_log (THIS->name, GF_LOG_ERROR, "error in " + "stat: %s", strerror (errno)); + goto err; + } + + if (brickstat.st_dev != buf.st_dev) { + *ptr = '/'; + break; + } + } + + if (ptr == *mount_point) { + if (stat ("/", &buf)) { + gf_log (THIS->name, GF_LOG_ERROR, "error in " + "stat: %s", strerror (errno)); + goto err; + } + if (brickstat.st_dev == buf.st_dev) + strcpy (*mount_point, "/"); + } + + return 0; + + err: + if (*mount_point) + GF_FREE (*mount_point); + return -1; +} + +static int +glusterd_add_inode_size_to_dict (dict_t *dict, int count) +{ + int ret = -1; + int fd = -1; + char key[1024] = {0}; + char buffer[4096] = {0}; + char cmd_str[4096] = {0}; + char *inode_size = NULL; + char *device = NULL; + char *fs_name = NULL; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.device", count); + ret = dict_get_str (dict, key, &device); + if (ret) + goto out; + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.fs_name", count); + ret = dict_get_str (dict, key, &fs_name); + if (ret) + goto out; + + /* get inode size for xfs or ext2/3/4 */ + if (!strcmp (fs_name, "xfs")) { + + snprintf (cmd_str, sizeof (cmd_str), + "xfs_info %s | " + "grep isize | " + "cut -d ' ' -f 2- | " + "cut -d '=' -f 2 | " + "cut -d ' ' -f 1 " + "> /tmp/gf_status.txt ", + device); + + } else if (IS_EXT_FS(fs_name)) { + + snprintf (cmd_str, sizeof (cmd_str), + "tune2fs -l %s | " + "grep -i 'inode size' | " + "awk '{print $3}' " + "> /tmp/gf_status.txt ", + device); + + } else { + ret = 0; + gf_log (THIS->name, GF_LOG_INFO, "Skipped fetching " + "inode size for %s: FS type not recommended", + fs_name); + goto out; + } + + ret = runcmd ("/bin/sh", "-c", cmd_str, NULL); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "could not get inode " + "size for %s : %s package missing", fs_name, + ((strcmp (fs_name, "xfs")) ? + "e2fsprogs" : "xfsprogs")); + goto out; + } + + fd = open ("/tmp/gf_status.txt", O_RDONLY); + unlink ("/tmp/gf_status.txt"); + if (fd < 0) { + ret = -1; + goto out; + } + memset (buffer, 0, sizeof (buffer)); + ret = read (fd, buffer, sizeof (buffer)); + if (ret < 2) { + ret = -1; + goto out; + } + + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "brick%d.inode_size", count); + + inode_size = get_nth_word (buffer, 1); + if (!inode_size) { + ret = -1; + goto out; + } + + ret = dict_set_dynstr (dict, key, inode_size); + + out: + if (fd >= 0) + close (fd); + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, "failed to get inode size"); + return ret; +} + +static int +glusterd_add_brick_mount_details (glusterd_brickinfo_t *brickinfo, + dict_t *dict, int count) +{ + int ret = -1; + int fd = -1; + char key[1024] = {0}; + char base_key[1024] = {0}; + char buffer[4096] = {0}; + char cmd_str[1024] = {0}; + char *mnt_pt = NULL; + char *fs_name = NULL; + char *mnt_options = NULL; + char *device = NULL; + runner_t runner = {0}; + + snprintf (base_key, sizeof (base_key), "brick%d", count); + + ret = glusterd_get_brick_root (brickinfo->path, &mnt_pt); + if (ret) + goto out; + + /* get mount details of brick in back-end */ + snprintf (cmd_str, sizeof (cmd_str), " %s ", mnt_pt); + + runinit (&runner); + runner_add_args (&runner, "grep", cmd_str, "/etc/mtab", NULL); + runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); + + ret = runner_start (&runner); + if (ret) + goto out; + + if (!fgets (buffer, sizeof(buffer), + runner_chio (&runner, STDOUT_FILENO))) { + ret = -1; + goto out; + } + + runner_end (&runner); + + /* get device file */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.device", base_key); + + device = get_nth_word (buffer, 1); + if (!device) + goto out; + + ret = dict_set_dynstr (dict, key, device); + if (ret) + goto out; + + /* fs type */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.fs_name", base_key); + + fs_name = get_nth_word (buffer, 3); + if (!fs_name) + goto out; + + ret = dict_set_dynstr (dict, key, fs_name); + if (ret) + goto out; + + /* mount options */ + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.mnt_options", base_key); + + mnt_options = get_nth_word (buffer, 4); + if (!mnt_options) + goto out; + ret = dict_set_dynstr (dict, key, mnt_options); + + out: + if (mnt_pt) + GF_FREE (mnt_pt); + if (fd >= 0) + close (fd); + return ret; +} + +int +glusterd_add_brick_detail_to_dict (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + dict_t *dict, int count) +{ + int ret = -1; + uint64_t memtotal = 0; + uint64_t memfree = 0; + uint64_t inodes_total = 0; + uint64_t inodes_free = 0; + uint64_t block_size = 0; + char key[1024] = {0}; + char base_key[1024] = {0}; + struct statvfs brickstat = {0}; + + GF_ASSERT (volinfo); + GF_ASSERT (brickinfo); + GF_ASSERT (dict); + + snprintf (base_key, sizeof (base_key), "brick%d", count); + + ret = statvfs (brickinfo->path, &brickstat); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "statfs error: %s ", + strerror (errno)); + goto out; + } + + /* file system block size */ + block_size = brickstat.f_bsize; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.block_size", base_key); + ret = dict_set_uint64 (dict, key, block_size); + if (ret) + goto out; + + /* free space in brick */ + memfree = brickstat.f_bfree * brickstat.f_bsize; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.free", base_key); + ret = dict_set_uint64 (dict, key, memfree); + if (ret) + goto out; + + /* total space of brick */ + memtotal = brickstat.f_blocks * brickstat.f_bsize; + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.total", base_key); + ret = dict_set_uint64 (dict, key, memtotal); + if (ret) + goto out; + + /* inodes: total and free counts only for ext2/3/4 and xfs */ + inodes_total = brickstat.f_files; + if (inodes_total) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.total_inodes", base_key); + ret = dict_set_uint64 (dict, key, inodes_total); + if (ret) + goto out; + } + + inodes_free = brickstat.f_ffree; + if (inodes_free) { + memset (key, 0, sizeof (key)); + snprintf (key, sizeof (key), "%s.free_inodes", base_key); + ret = dict_set_uint64 (dict, key, inodes_free); + if (ret) + goto out; + } + + ret = glusterd_add_brick_mount_details (brickinfo, dict, count); + if (ret) + goto out; + + ret = glusterd_add_inode_size_to_dict (dict, count); + + out: + if (ret) + gf_log (THIS->name, GF_LOG_DEBUG, "Error adding brick" + " detail to dict: %s", strerror (errno)); + return ret; +} + int32_t glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, dict_t *dict, int32_t count) { - int ret = -1; - char key[8192] = {0,}; - char base_key[8192] = {0}; - char pidfile[PATH_MAX] = {0}; - char path[PATH_MAX] = {0}; - int32_t pid = -1; - int32_t brick_online = -1; - xlator_t *this = NULL; - glusterd_conf_t *priv = NULL; + int ret = -1; + int32_t pid = -1; + int32_t brick_online = -1; + char key[1024] = {0}; + char base_key[1024] = {0}; + char pidfile[PATH_MAX] = {0}; + char path[PATH_MAX] = {0}; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + GF_ASSERT (volinfo); GF_ASSERT (brickinfo); @@ -3111,6 +3424,7 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, snprintf (base_key, sizeof (base_key), "brick%d", count); snprintf (key, sizeof (key), "%s.hostname", base_key); + ret = dict_set_str (dict, key, brickinfo->hostname); if (ret) goto out; @@ -3142,13 +3456,42 @@ glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, memset (key, 0, sizeof (key)); snprintf (key, sizeof (key), "%s.status", base_key); ret = dict_set_int32 (dict, key, brick_online); - if (ret) - goto out; out: if (ret) - gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + gf_log (THIS->name, GF_LOG_DEBUG, "Returning %d", ret); + + return ret; +} + +int32_t +glusterd_get_all_volnames (dict_t *dict) +{ + int ret = -1; + int32_t vol_count = 0; + char key[256] = {0}; + glusterd_volinfo_t *entry = NULL; + glusterd_conf_t *priv = NULL; + priv = THIS->private; + GF_ASSERT (priv); + + list_for_each_entry (entry, &priv->volumes, vol_list) { + memset (key, sizeof (key), 0); + snprintf (key, sizeof (key), "vol%d", vol_count); + ret = dict_set_str (dict, key, entry->volname); + if (ret) + goto out; + + vol_count++; + } + + ret = dict_set_int32 (dict, "vol_count", vol_count); + + out: + if (ret) + gf_log (THIS->name, GF_LOG_ERROR, "failed to get all " + "volume names for status"); return ret; } diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index a34956b0c4a..0ce17450284 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -347,11 +347,22 @@ glusterd_recreate_bricks (glusterd_conf_t *conf); int32_t glusterd_handle_upgrade_downgrade (dict_t *options, glusterd_conf_t *conf); +int +glusterd_get_brick_root (char *path, char **mount_point); + +int +glusterd_add_brick_detail_to_dict (glusterd_volinfo_t *volinfo, + glusterd_brickinfo_t *brickinfo, + dict_t *dict, int32_t count); + int32_t glusterd_add_brick_to_dict (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo, dict_t *dict, int32_t count); +int32_t +glusterd_get_all_volnames (dict_t *dict); + gf_boolean_t glusterd_is_fuse_available (); -- cgit