summaryrefslogtreecommitdiffstats
path: root/cli
diff options
context:
space:
mode:
authorSamikshan Bairagya <samikshan@gmail.com>2016-07-07 20:33:02 +0530
committerAtin Mukherjee <amukherj@redhat.com>2016-08-26 08:23:37 -0700
commit4a3454753f6e4ddc309c8d1cb11a6e4e432c1da6 (patch)
tree1bfb4258035063b2b2678a9e2e898234b5199b1e /cli
parent7d3de1aed87ad9cd519cbc05e744f086760620c4 (diff)
glusterd/cli: cli to get local state representation from glusterd
Currently there is no existing CLI that can be used to get the local state representation of the cluster as maintained in glusterd in a readable as well as parseable format. The CLI added has the following usage: # gluster get-state [daemon] [odir <path/to/output/dir>] [file <filename>] This would dump data points that reflect the local state representation of the cluster as maintained in glusterd (no other daemons are supported as of now) to a file inside the specified output directory. The default output directory and filename is /var/run/gluster and glusterd_state_<timestamp> respectively. The option for specifying the daemon name leaves room to add support for other daemons in the future. Following are the data points captured as of now to represent the state from the local glusterd pov: * Peer: - Primary hostname - uuid - state - connection status - List of hostnames * Volumes: - name, id, transport type, status - counts: bricks, snap, subvol, stripe, arbiter, disperse, redundancy - snapd status - quorum status - tiering related information - rebalance status - replace bricks status - snapshots * Bricks: - Path, hostname (for all bricks these info will be shown) - port, rdma port, status, mount options, filesystem type and signed in status for bricks running locally. * Services: - name, online status for initialised services * Others: - Base port, last allocated port - op-version - MYUUID Change-Id: I4a45cc5407ab92d8afdbbd2098ece851f7e3d618 BUG: 1353156 Signed-off-by: Samikshan Bairagya <samikshan@gmail.com> Reviewed-on: http://review.gluster.org/14873 Reviewed-by: Avra Sengupta <asengupt@redhat.com> Smoke: Gluster Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Diffstat (limited to 'cli')
-rw-r--r--cli/src/cli-cmd-global.c57
-rw-r--r--cli/src/cli-cmd-parser.c114
-rw-r--r--cli/src/cli-rpc-ops.c135
-rw-r--r--cli/src/cli-xml-output.c26
-rw-r--r--cli/src/cli.h5
5 files changed, 290 insertions, 47 deletions
diff --git a/cli/src/cli-cmd-global.c b/cli/src/cli-cmd-global.c
index 53ee0ab2517..f4544da367c 100644
--- a/cli/src/cli-cmd-global.c
+++ b/cli/src/cli-cmd-global.c
@@ -34,7 +34,9 @@ cli_cmd_global_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
const char **words, int wordcount);
int cli_cmd_ganesha_cbk (struct cli_state *state, struct cli_cmd_word *word,
const char **words, int wordcount);
-
+int
+cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount);
struct cli_cmd global_cmds[] = {
{ "global help",
@@ -45,6 +47,10 @@ struct cli_cmd global_cmds[] = {
cli_cmd_ganesha_cbk,
"Enable/disable NFS-Ganesha support",
},
+ { "get-state [<daemon>] [odir </path/to/output/dir/>] [file <filename>]",
+ cli_cmd_get_state_cbk,
+ "Get local state representation of mentioned daemon",
+ },
{NULL, NULL, NULL}
};
@@ -133,3 +139,52 @@ out:
return ret;
}
+int
+cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
+ const char **words, int wordcount)
+{
+ int sent = 0;
+ int parse_error = 0;
+ int ret = -1;
+ rpc_clnt_procedure_t *proc = NULL;
+ call_frame_t *frame = NULL;
+ dict_t *options = NULL;
+ cli_local_t *local = NULL;
+ char *op_errstr = NULL;
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+
+ ret = cli_cmd_get_state_parse (state, words, wordcount, &options,
+ &op_errstr);
+
+ if (ret) {
+ if (op_errstr) {
+ cli_err ("%s", op_errstr);
+ cli_usage_out (word->pattern);
+ GF_FREE (op_errstr);
+ } else
+ cli_usage_out (word->pattern);
+
+ parse_error = 1;
+ goto out;
+ }
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_STATE];
+ if (proc->fn)
+ ret = proc->fn (frame, THIS, options);
+out:
+ if (ret) {
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Getting daemon state failed");
+ }
+
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+}
+
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index b83275bbfd7..20dcda5619e 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -931,6 +931,120 @@ out:
}
int32_t
+cli_cmd_get_state_parse (struct cli_state *state,
+ const char **words, int wordcount,
+ dict_t **options, char **op_errstr)
+{
+ dict_t *dict = NULL;
+ int ret = -1;
+ uint32_t cmd = 0;
+ char *odir = NULL;
+ char *filename = NULL;
+ char *daemon_name = NULL;
+ int count = 0;
+
+ GF_VALIDATE_OR_GOTO ("cli", options, out);
+ GF_VALIDATE_OR_GOTO ("cli", words, out);
+
+ dict = dict_new ();
+ if (!dict)
+ goto out;
+
+ if (wordcount < 1 || wordcount > 6) {
+ *op_errstr = gf_strdup ("Problem parsing arguments."
+ " Check usage.");
+ goto out;
+ }
+
+ if (wordcount >= 1) {
+ gf_asprintf (&daemon_name, "%s", "glusterd");
+
+ for (count = 1; count < wordcount; count++) {
+ if (strcmp (words[count], "odir") == 0 ||
+ strcmp (words[count], "file") == 0) {
+ if (strcmp (words[count], "odir") == 0) {
+ if (++count < wordcount) {
+ odir = (char *) words[count];
+ continue;
+ } else {
+ ret = -1;
+ goto out;
+ }
+ } else if (strcmp (words[count], "file") == 0) {
+ if (++count < wordcount) {
+ filename = (char *) words[count];
+ continue;
+ } else {
+ ret = -1;
+ goto out;
+ }
+ }
+ } else {
+ if (count > 1) {
+ *op_errstr = gf_strdup ("Problem "
+ "parsing arguments. "
+ "Check usage.");
+ ret = -1;
+ goto out;
+
+ }
+ if (strcmp (words[count], "glusterd") == 0) {
+ continue;
+ } else {
+ *op_errstr = gf_strdup ("glusterd is "
+ "the only supported daemon.");
+ ret = -1;
+ goto out;
+ }
+ }
+ }
+
+ ret = dict_set_str (dict, "daemon", daemon_name);
+ if (ret) {
+ *op_errstr = gf_strdup ("Command failed. Please check "
+ " log file for more details.");
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Setting daemon name to dictionary failed");
+ goto out;
+ }
+
+ if (odir) {
+ ret = dict_set_str (dict, "odir", odir);
+ if (ret) {
+ *op_errstr = gf_strdup ("Command failed. Please"
+ " check log file for"
+ " more details.");
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Setting output directory to"
+ "dictionary failed");
+ goto out;
+ }
+ }
+
+ if (filename) {
+ ret = dict_set_str (dict, "filename", filename);
+ if (ret) {
+ *op_errstr = gf_strdup ("Command failed. Please"
+ " check log file for"
+ " more details.");
+ gf_log (THIS->name, GF_LOG_ERROR,
+ "Setting filename to dictionary failed");
+ goto out;
+ }
+ }
+ }
+
+ out:
+ if (dict)
+ *options = dict;
+
+ if (ret && dict)
+ dict_unref (dict);
+
+ return ret;
+}
+
+int32_t
cli_cmd_inode_quota_parse (const char **words, int wordcount, dict_t **options)
{
dict_t *dict = NULL;
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index 441f4247c45..a8a26c820dd 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -55,17 +55,6 @@ int32_t
gf_cli_remove_brick (call_frame_t *frame, xlator_t *this,
void *data);
-char *cli_vol_type_str[] = {"Distribute",
- "Stripe",
- "Replicate",
- "Striped-Replicate",
- "Disperse",
- "Tier",
- "Distributed-Stripe",
- "Distributed-Replicate",
- "Distributed-Striped-Replicate",
- "Distributed-Disperse",
- };
char *cli_vol_status_str[] = {"Created",
"Started",
@@ -503,6 +492,73 @@ out:
return ret;
}
+int
+gf_cli_get_state_cbk (struct rpc_req *req, struct iovec *iov,
+ int count, void *myframe)
+{
+ gf_cli_rsp rsp = {0,};
+ int ret = -1;
+ dict_t *dict = NULL;
+ char *daemon_name = NULL;
+ char *ofilepath = NULL;
+
+ GF_VALIDATE_OR_GOTO ("cli", myframe, out);
+
+ if (-1 == req->rpc_status) {
+ goto out;
+ }
+ ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);
+ if (ret < 0) {
+ gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR,
+ "Failed to decode xdr response");
+ 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)
+ goto out;
+
+ if (rsp.op_ret) {
+ if (strcmp (rsp.op_errstr, ""))
+ cli_err ("Failed to get daemon state: %s", rsp.op_errstr);
+ else
+ cli_err ("Failed to get daemon state. Check glusterd"
+ " log file for more details");
+ } else {
+ ret = dict_get_str (dict, "daemon", &daemon_name);
+ if (ret)
+ gf_log ("cli", GF_LOG_ERROR, "Couldn't get daemon name");
+
+ ret = dict_get_str (dict, "ofilepath", &ofilepath);
+ if (ret)
+ gf_log ("cli", GF_LOG_ERROR, "Couldn't get filepath");
+
+ if (daemon_name && ofilepath)
+ cli_out ("%s state dumped to %s",
+ daemon_name, ofilepath);
+ }
+
+ ret = rsp.op_ret;
+
+out:
+ free (rsp.dict.dict_val);
+ free (rsp.op_errstr);
+
+ if (dict)
+ dict_unref (dict);
+
+ cli_cmd_broadcast_response (ret);
+
+ return ret;
+}
+
void
cli_out_options ( char *substr, char *optstr, char *valstr)
{
@@ -725,13 +781,11 @@ gf_cli_print_tier_info (dict_t *dict, int i, int brick_count)
vol_type = hot_type;
hot_dist_count = (hot_replica_count ?
hot_replica_count : 1);
- if ((hot_type != GF_CLUSTER_TYPE_TIER) &&
- (hot_type > 0) &&
- (hot_dist_count < hot_brick_count))
- vol_type = hot_type + GF_CLUSTER_TYPE_MAX - 1;
+ vol_type = get_vol_type (hot_type, hot_dist_count, hot_brick_count);
cli_out ("Hot Tier Type : %s",
- cli_vol_type_str[vol_type]);
+ vol_type_str[vol_type]);
+
gf_cli_print_number_of_bricks (hot_type,
hot_brick_count, hot_dist_count, 0,
hot_replica_count, 0, 0, 0);
@@ -742,14 +796,11 @@ gf_cli_print_tier_info (dict_t *dict, int i, int brick_count)
goto out;
cli_out ("Cold Tier:");
- vol_type = cold_type;
- if ((cold_type != GF_CLUSTER_TYPE_TIER) &&
- (cold_type > 0) &&
- (cold_dist_count < cold_brick_count))
- vol_type = cold_type + GF_CLUSTER_TYPE_MAX - 1;
+ vol_type = get_vol_type (cold_type, cold_dist_count, cold_brick_count);
cli_out ("Cold Tier Type : %s",
- cli_vol_type_str[vol_type]);
+ vol_type_str[vol_type]);
+
gf_cli_print_number_of_bricks (cold_type,
cold_brick_count,
cold_dist_count, 0, cold_replica_count,
@@ -973,15 +1024,11 @@ xml_output:
if (ret)
goto out;
- vol_type = type;
-
// Distributed (stripe/replicate/stripe-replica) setups
- if ((type != GF_CLUSTER_TYPE_TIER) && (type > 0) &&
- (dist_count < brick_count))
- vol_type = type + GF_CLUSTER_TYPE_MAX - 1;
+ vol_type = get_vol_type (type, dist_count, brick_count);
cli_out ("Volume Name: %s", volname);
- cli_out ("Type: %s", cli_vol_type_str[vol_type]);
+ cli_out ("Type: %s", vol_type_str[vol_type]);
cli_out ("Volume ID: %s", volume_id_str);
cli_out ("Status: %s", cli_vol_status_str[status]);
cli_out ("Snapshot Count: %d", snap_count);
@@ -4151,6 +4198,32 @@ out:
}
int32_t
+gf_cli_get_state (call_frame_t *frame, xlator_t *this, void *data)
+{
+ gf_cli_req req = {{0,},};
+ int ret = 0;
+ dict_t *dict = NULL;
+
+ char *odir = NULL;
+
+ if (!frame || !this || !data) {
+ ret = -1;
+ goto out;
+ }
+
+ dict = data;
+
+ ret = cli_to_glusterd (&req, frame, gf_cli_get_state_cbk,
+ (xdrproc_t) xdr_gf_cli_req, dict,
+ GLUSTER_CLI_GET_STATE, this, cli_rpc_prog,
+ NULL);
+out:
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
+
+ return ret;
+}
+
+int32_t
gf_cli_get_next_volume (call_frame_t *frame, xlator_t *this,
void *data)
{
@@ -10918,7 +10991,6 @@ cli_to_glusterd (gf_cli_req *req, call_frame_t *frame,
ret = cli_cmd_submit (NULL, req, frame, prog, procnum, iobref, this,
cbkfn, (xdrproc_t) xdrproc);
-
out:
return ret;
@@ -11256,7 +11328,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_DEPROBE] = {"DEPROBE_QUERY", gf_cli_deprobe},
[GLUSTER_CLI_LIST_FRIENDS] = {"LIST_FRIENDS", gf_cli_list_friends},
[GLUSTER_CLI_UUID_RESET] = {"UUID_RESET", gf_cli3_1_uuid_reset},
- [GLUSTER_CLI_UUID_GET] = {"UUID_GET", gf_cli3_1_uuid_get},
+ [GLUSTER_CLI_UUID_GET] = {"UUID_GET", gf_cli3_1_uuid_get},
[GLUSTER_CLI_CREATE_VOLUME] = {"CREATE_VOLUME", gf_cli_create_volume},
[GLUSTER_CLI_DELETE_VOLUME] = {"DELETE_VOLUME", gf_cli_delete_volume},
[GLUSTER_CLI_START_VOLUME] = {"START_VOLUME", gf_cli_start_volume},
@@ -11297,7 +11369,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_BITROT] = {"BITROT", gf_cli_bitrot},
[GLUSTER_CLI_ATTACH_TIER] = {"ATTACH_TIER", gf_cli_attach_tier},
[GLUSTER_CLI_DETACH_TIER] = {"DETACH_TIER", gf_cli_detach_tier},
- [GLUSTER_CLI_TIER] = {"TIER", gf_cli_tier}
+ [GLUSTER_CLI_TIER] = {"TIER", gf_cli_tier},
+ [GLUSTER_CLI_GET_STATE] = {"GET_STATE", gf_cli_get_state}
};
struct rpc_clnt_program cli_prog = {
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c
index f6158eab794..a91e5e435af 100644
--- a/cli/src/cli-xml-output.c
+++ b/cli/src/cli-xml-output.c
@@ -2720,9 +2720,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
/* For Distributed-(stripe,replicate,stipe-replicate,disperse)
types
*/
- if ((type != GF_CLUSTER_TYPE_TIER) && (type > 0) &&
- (dist_count < brick_count))
- type = type + GF_CLUSTER_TYPE_MAX - 1;
+ type = get_vol_type (type, dist_count, brick_count);
ret = xmlTextWriterWriteFormatElement (local->writer,
(xmlChar *)"type",
@@ -2732,7 +2730,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
ret = xmlTextWriterWriteFormatElement (local->writer,
(xmlChar *)"typeStr",
"%s",
- cli_vol_type_str[type]);
+ vol_type_str[type]);
XML_RET_CHECK_AND_GOTO (ret, out);
memset (key, 0, sizeof (key));
@@ -2819,9 +2817,13 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
goto out;
}
- tier_vol_type = value[HOT_TYPE];
hot_dist_count = (value[HOT_REPLICA_COUNT] ?
value[HOT_REPLICA_COUNT] : 1);
+
+ tier_vol_type = get_vol_type (value[HOT_TYPE],
+ hot_dist_count,
+ value[HOT_BRICK_COUNT]);
+
if ((value[HOT_TYPE] != GF_CLUSTER_TYPE_TIER) &&
(value[HOT_TYPE] > 0) &&
(hot_dist_count < value[HOT_BRICK_COUNT]))
@@ -2835,7 +2837,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
ret = xmlTextWriterWriteFormatElement
(local->writer, (xmlChar *)"hotBrickType",
- "%s", cli_vol_type_str[tier_vol_type]);
+ "%s", vol_type_str[tier_vol_type]);
ret = xmlTextWriterWriteFormatElement (local->writer,
(xmlChar *)"hotreplicaCount",
@@ -2912,13 +2914,9 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
ret = xmlTextWriterEndElement (local->writer);
XML_RET_CHECK_AND_GOTO (ret, out);
- tier_vol_type = value[COLD_TYPE];
- if ((value[COLD_TYPE] != GF_CLUSTER_TYPE_TIER) &&
- (value[COLD_TYPE] > 0) &&
- (value[COLD_DIST_COUNT] < value[COLD_BRICK_COUNT]))
- tier_vol_type = value[COLD_TYPE] +
- GF_CLUSTER_TYPE_MAX - 1;
-
+ tier_vol_type = get_vol_type (value[COLD_TYPE],
+ value[COLD_DIST_COUNT],
+ value[COLD_BRICK_COUNT]);
ret = xmlTextWriterStartElement (local->writer,
(xmlChar *)
@@ -2927,7 +2925,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
ret = xmlTextWriterWriteFormatElement
(local->writer, (xmlChar *)"coldBrickType",
- "%s", cli_vol_type_str[tier_vol_type]);
+ "%s", vol_type_str[tier_vol_type]);
ret = xmlTextWriterWriteFormatElement (local->writer,
(xmlChar *)"coldreplicaCount",
diff --git a/cli/src/cli.h b/cli/src/cli.h
index 73fb67289f7..f9c642ee4d0 100644
--- a/cli/src/cli.h
+++ b/cli/src/cli.h
@@ -71,7 +71,6 @@ struct cli_cmd_word;
struct cli_cmd_tree;
struct cli_cmd;
-extern char *cli_vol_type_str[];
extern char *cli_vol_status_str[];
extern char *cli_vol_task_status_str[];
@@ -261,6 +260,10 @@ cli_cmd_ganesha_parse (struct cli_state *state, const char **words,
int wordcount, dict_t **options, char **op_errstr);
int32_t
+cli_cmd_get_state_parse (struct cli_state *state, const char **words,
+ int wordcount, dict_t **options, char **op_errstr);
+
+int32_t
cli_cmd_volume_add_brick_parse (const char **words, int wordcount,
dict_t **options, int *type);