cli: add a command 'gluster pool list [--xml]'

* unlike 'gluster peer status', which lists only info about peers,
  this command lists localhost also in the list, so the sorted
  output from all the nodes should match.

* made the output script friendly by keeping it one output per line.

Change-Id: I853656753b35c617debbcceecbb71c8d6dd3c334
BUG: 764638
Original-review: http://review.gluster.org/4221
Original-author: Amar Tumballi <amarts@redhat.com>
Signed-off-by: Niels de Vos <ndevos@redhat.com>
Reviewed-on: http://review.gluster.org/4862
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
This commit is contained in:
Niels de Vos 2013-04-20 16:55:15 +02:00 committed by Vijay Bellur
parent 5e0116109e
commit e6b6d1235d
6 changed files with 242 additions and 87 deletions

View File

@ -184,7 +184,7 @@ cli_cmd_peer_status_cbk (struct cli_state *state, struct cli_cmd_word *word,
goto out;
if (proc->fn) {
ret = proc->fn (frame, THIS, (char *)words[1] );
ret = proc->fn (frame, THIS, (void *)GF_CLI_LIST_PEERS);
}
out:
@ -199,6 +199,45 @@ out:
return ret;
}
int
cli_cmd_pool_list_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;
int sent = 0;
int parse_error = 0;
if (wordcount != 2) {
cli_usage_out (word->pattern);
parse_error = 1;
goto out;
}
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_LIST_FRIENDS];
frame = create_frame (THIS, THIS->ctx->pool);
if (!frame)
goto out;
if (proc->fn) {
ret = proc->fn (frame, THIS,
(void *)GF_CLI_LIST_POOL_NODES);
}
out:
if (ret) {
cli_cmd_sent_status_get (&sent);
if ((sent == 0) && (parse_error == 0))
cli_err ("pool list: command execution failed");
}
CLI_STACK_DESTROY (frame);
return ret;
}
struct cli_cmd cli_probe_cmds[] = {
{ "peer probe <HOSTNAME>",
cli_cmd_peer_probe_cbk,
@ -216,6 +255,10 @@ struct cli_cmd cli_probe_cmds[] = {
cli_cmd_peer_help_cbk,
"Help command for peer "},
{ "pool list",
cli_cmd_pool_list_cbk,
"list all the nodes in the pool (including localhost)"},
{ NULL, NULL, NULL }
};

View File

@ -295,12 +295,9 @@ out:
}
int
gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov,
int count, void *myframe)
gf_cli_output_peer_status (dict_t *dict, int count)
{
gf1_cli_peer_list_rsp rsp = {0,};
int ret = -1;
dict_t *dict = NULL;
char *uuid_buf = NULL;
char *hostname_buf = NULL;
int32_t i = 1;
@ -309,7 +306,130 @@ gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov,
int32_t port = 0;
int32_t connected = 0;
char *connected_str = NULL;
cli_out ("Number of Peers: %d", count);
i = 1;
while ( i <= count) {
snprintf (key, 256, "friend%d.uuid", i);
ret = dict_get_str (dict, key, &uuid_buf);
if (ret)
goto out;
snprintf (key, 256, "friend%d.hostname", i);
ret = dict_get_str (dict, key, &hostname_buf);
if (ret)
goto out;
snprintf (key, 256, "friend%d.connected", i);
ret = dict_get_int32 (dict, key, &connected);
if (ret)
goto out;
if (connected)
connected_str = "Connected";
else
connected_str = "Disconnected";
snprintf (key, 256, "friend%d.port", i);
ret = dict_get_int32 (dict, key, &port);
if (ret)
goto out;
snprintf (key, 256, "friend%d.state", i);
ret = dict_get_str (dict, key, &state);
if (ret)
goto out;
if (!port) {
cli_out ("\nHostname: %s\nUuid: %s\nState: %s "
"(%s)",
hostname_buf, uuid_buf, state,
connected_str);
} else {
cli_out ("\nHostname: %s\nPort: %d\nUuid: %s\n"
"State: %s (%s)", hostname_buf, port,
uuid_buf, state, connected_str);
}
i++;
}
ret = 0;
out:
return ret;
}
int
gf_cli_output_pool_list (dict_t *dict, int count)
{
int ret = -1;
char *uuid_buf = NULL;
char *hostname_buf = NULL;
int32_t i = 1;
char key[256] = {0,};
int32_t connected = 0;
char *connected_str = NULL;
if (count >= 1)
cli_out ("UUID\t\t\t\t\tHostname\tState");
while ( i <= count) {
snprintf (key, 256, "friend%d.uuid", i);
ret = dict_get_str (dict, key, &uuid_buf);
if (ret)
goto out;
snprintf (key, 256, "friend%d.hostname", i);
ret = dict_get_str (dict, key, &hostname_buf);
if (ret)
goto out;
snprintf (key, 256, "friend%d.connected", i);
ret = dict_get_int32 (dict, key, &connected);
if (ret)
goto out;
if (connected)
connected_str = "Connected";
else
connected_str = "Disconnected";
cli_out ("%s\t%s\t%s ", uuid_buf, hostname_buf,
connected_str);
i++;
}
ret = 0;
out:
return ret;
}
/* function pointer for gf_cli_output_{pool_list,peer_status} */
typedef int (*cli_friend_output_fn) (dict_t*, int);
int
gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov,
int count, void *myframe)
{
gf1_cli_peer_list_rsp rsp = {0,};
int ret = -1;
dict_t *dict = NULL;
char msg[1024] = {0,};
char *cmd = NULL;
cli_friend_output_fn friend_output_fn;
call_frame_t *frame = NULL;
unsigned long flags = 0;
frame = myframe;
flags = (long)frame->local;
if (flags == GF_CLI_LIST_POOL_NODES) {
cmd = "pool list";
friend_output_fn = &gf_cli_output_pool_list;
} else {
cmd = "peer status";
friend_output_fn = &gf_cli_output_peer_status;
}
/* 'free' the flags set by gf_cli_list_friends */
frame->local = NULL;
if (-1 == req->rpc_status) {
goto out;
@ -324,7 +444,7 @@ gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov,
goto out;
}
gf_log ("cli", GF_LOG_INFO, "Received resp to list: %d",
gf_log ("cli", GF_LOG_DEBUG, "Received resp to list: %d",
rsp.op_ret);
ret = rsp.op_ret;
@ -333,7 +453,7 @@ gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov,
if (!rsp.friends.friends_len) {
snprintf (msg, sizeof (msg),
"peer status: No peers present");
"%s: No peers present", cmd);
if (global_state->mode & GLUSTER_MODE_XML) {
ret = cli_xml_output_peer_status (dict,
rsp.op_ret,
@ -380,49 +500,9 @@ gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov,
goto out;
}
cli_out ("Number of Peers: %d", count);
i = 1;
while ( i <= count) {
snprintf (key, 256, "friend%d.uuid", i);
ret = dict_get_str (dict, key, &uuid_buf);
if (ret)
goto out;
snprintf (key, 256, "friend%d.hostname", i);
ret = dict_get_str (dict, key, &hostname_buf);
if (ret)
goto out;
snprintf (key, 256, "friend%d.connected", i);
ret = dict_get_int32 (dict, key, &connected);
if (ret)
goto out;
if (connected)
connected_str = "Connected";
else
connected_str = "Disconnected";
snprintf (key, 256, "friend%d.port", i);
ret = dict_get_int32 (dict, key, &port);
if (ret)
goto out;
snprintf (key, 256, "friend%d.state", i);
ret = dict_get_str (dict, key, &state);
if (ret)
goto out;
if (!port) {
cli_out ("\nHostname: %s\nUuid: %s\nState: %s "
"(%s)",
hostname_buf, uuid_buf, state,
connected_str);
} else {
cli_out ("\nHostname: %s\nPort: %d\nUuid: %s\n"
"State: %s (%s)", hostname_buf, port,
uuid_buf, state, connected_str);
}
i++;
ret = friend_output_fn (dict, count);
if (ret) {
goto out;
}
} else {
if (global_state->mode & GLUSTER_MODE_XML) {
@ -443,7 +523,7 @@ gf_cli_list_friends_cbk (struct rpc_req *req, struct iovec *iov,
out:
cli_cmd_broadcast_response (ret);
if (ret)
cli_err ("peer status: failed");
cli_err ("%s: failed", cmd);
if (dict)
dict_destroy (dict);
@ -2676,18 +2756,22 @@ out:
int32_t
gf_cli_list_friends (call_frame_t *frame, xlator_t *this,
void *data)
void *data)
{
gf1_cli_peer_list_req req = {0,};
int ret = 0;
unsigned long flags = 0;
if (!frame || !this) {
ret = -1;
goto out;
}
req.flags = GF_CLI_LIST_ALL;
GF_ASSERT (frame->local == NULL);
flags = (long)data;
req.flags = flags;
frame->local = (void*)flags;
ret = cli_cmd_submit (&req, frame, cli_rpc_prog,
GLUSTER_CLI_LIST_FRIENDS, NULL,
this, gf_cli_list_friends_cbk,

View File

@ -2801,29 +2801,30 @@ cli_xml_output_peer_status (dict_t *dict, int op_ret, int op_errno,
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "friend%d.stateId", i);
ret = dict_get_int32 (dict, key, &state_id);
if (ret)
goto out;
if (!ret) {
/* ignore */
ret = xmlTextWriterWriteFormatElement (writer,
(xmlChar *)"state",
"%d", state_id);
XML_RET_CHECK_AND_GOTO (ret, out);
ret = xmlTextWriterWriteFormatElement (writer,
(xmlChar *)"state", "%d", state_id);
XML_RET_CHECK_AND_GOTO (ret, out);
}
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "friend%d.state", i);
ret = dict_get_str (dict, key, &state_str);
if (ret)
goto out;
if (!ret) {
/* ignore */
ret = xmlTextWriterWriteFormatElement (writer,
(xmlChar *)"stateStr",
"%s", state_str);
XML_RET_CHECK_AND_GOTO (ret, out);
ret = xmlTextWriterWriteFormatElement (writer,
(xmlChar *)"stateStr", "%s", state_str);
XML_RET_CHECK_AND_GOTO (ret, out);
}
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "friend%d.port", i);
ret = dict_get_int32 (dict, key, &port);
if (port != 0) {
if (!ret) {
/* ignore */
ret = xmlTextWriterWriteFormatElement
(writer, (xmlChar *)"port", "%d", port);
XML_RET_CHECK_AND_GOTO (ret, out);

View File

@ -92,7 +92,8 @@ enum gf_quota_type {
typedef enum gf_quota_type gf_quota_type;
enum gf1_cli_friends_list {
GF_CLI_LIST_ALL = 1,
GF_CLI_LIST_PEERS = 1,
GF_CLI_LIST_POOL_NODES = 2,
};
typedef enum gf1_cli_friends_list gf1_cli_friends_list;

13
tests/bugs/bug-764638.t Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
. $(dirname $0)/../include.rc
cleanup;
TEST glusterd
TEST pidof glusterd
TEST $CLI pool list;
TEST $CLI pool list --xml;
cleanup;

View File

@ -2949,37 +2949,50 @@ glusterd_list_friends (rpcsvc_request_t *req, dict_t *dict, int32_t flags)
int32_t count = 0;
dict_t *friends = NULL;
gf1_cli_peer_list_rsp rsp = {0,};
char my_uuid_str[64] = {0,};
char key[256] = {0,};
priv = THIS->private;
GF_ASSERT (priv);
if (!list_empty (&priv->peers)) {
friends = dict_new ();
if (!friends) {
gf_log ("", GF_LOG_WARNING, "Out of Memory");
goto out;
}
} else {
ret = 0;
friends = dict_new ();
if (!friends) {
gf_log ("", GF_LOG_WARNING, "Out of Memory");
goto out;
}
if (flags == GF_CLI_LIST_ALL) {
list_for_each_entry (entry, &priv->peers, uuid_list) {
count++;
ret = glusterd_add_peer_detail_to_dict (entry,
if (!list_empty (&priv->peers)) {
list_for_each_entry (entry, &priv->peers, uuid_list) {
count++;
ret = glusterd_add_peer_detail_to_dict (entry,
friends, count);
if (ret)
goto out;
}
ret = dict_set_int32 (friends, "count", count);
if (ret)
goto out;
}
}
if (flags == GF_CLI_LIST_POOL_NODES) {
count++;
snprintf (key, 256, "friend%d.uuid", count);
uuid_utoa_r (MY_UUID, my_uuid_str);
ret = dict_set_str (friends, key, my_uuid_str);
if (ret)
goto out;
snprintf (key, 256, "friend%d.hostname", count);
ret = dict_set_str (friends, key, "localhost");
if (ret)
goto out;
snprintf (key, 256, "friend%d.connected", count);
ret = dict_set_int32 (friends, key, 1);
if (ret)
goto out;
}
ret = dict_set_int32 (friends, "count", count);
if (ret)
goto out;
ret = dict_allocate_and_serialize (friends, &rsp.friends.friends_val,
&rsp.friends.friends_len);