summaryrefslogtreecommitdiffstats
path: root/cli
diff options
context:
space:
mode:
authorRajesh Amaravathi <rajesh@redhat.com>2011-12-07 20:51:03 +0530
committerVijay Bellur <vijay@gluster.com>2012-01-12 01:58:26 -0800
commit169c73f28dae61236de54889edcaa8236d91da59 (patch)
treea4d74fc14c9198cbc78633a844480ab6c4ffdda3 /cli
parent4e40a7e48757feedc959c7982acf05c73f739a15 (diff)
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|<vol>] [<brick>] [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 <rajesh@redhat.com> Reviewed-on: http://review.gluster.com/777 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Amar Tumballi <amar@gluster.com>
Diffstat (limited to 'cli')
-rw-r--r--cli/src/cli-cmd-parser.c71
-rw-r--r--cli/src/cli-cmd-volume.c166
-rw-r--r--cli/src/cli-rpc-ops.c169
-rw-r--r--cli/src/cli.h28
4 files changed, 381 insertions, 53 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 <VOLNAME>",
+ { "volume status [all|<VOLNAME>] [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);