summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrutika Dhananjay <kdhananj@redhat.com>2013-09-24 17:01:46 +0530
committerAnand Avati <avati@redhat.com>2013-10-08 23:13:16 -0700
commite51ca3c1c991416895e1e8693f7c3e6332d57464 (patch)
tree1d77373831ba8129eaaa3e6c257702062591f6e3
parent11bb1fc5849a557d1a26e59bd651fbd0d07a1b8d (diff)
cli,glusterd: Implement 'volume status tasks'
oVirt's Gluster Integration needs an inexpensive command that can be executed every 10 seconds to monitor async tasks and their parameters, for all volumes. The solution involves adding a 'tasks' sub-command to 'volume status' to fetch only the async task IDs, type and other relevant parameters. Only the originator glusterd participates in this command as all the information needed is available on all the nodes. This is to make the command suitable for being executed every 10 seconds. Change-Id: I1edc607baf29b001a5585079dec681d7c641b3d1 BUG: 1012346 Signed-off-by: Krutika Dhananjay <kdhananj@redhat.com> Reviewed-on: http://review.gluster.org/6006 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Kaushal M <kaushal@redhat.com>
-rw-r--r--cli/src/cli-cmd-parser.c19
-rw-r--r--cli/src/cli-cmd-volume.c2
-rw-r--r--cli/src/cli-rpc-ops.c155
-rw-r--r--cli/src/cli-xml-output.c31
-rw-r--r--cli/src/cli.h2
-rw-r--r--rpc/xdr/src/cli1-xdr.h1
-rw-r--r--rpc/xdr/src/cli1-xdr.x1
-rw-r--r--tests/bugs/bug-857330/common.rc2
-rwxr-xr-xtests/bugs/bug-857330/normal.t6
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c76
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-syncop.c11
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c29
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h2
13 files changed, 253 insertions, 84 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index 33a6c0104..62f5c3723 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -2182,7 +2182,7 @@ cli_cmd_get_statusop (const char *arg)
uint32_t ret = GF_CLI_STATUS_NONE;
char *w = NULL;
char *opwords[] = {"detail", "mem", "clients", "fd",
- "inode", "callpool", NULL};
+ "inode", "callpool", "tasks", NULL};
struct {
char *opname;
uint32_t opcode;
@@ -2193,6 +2193,7 @@ cli_cmd_get_statusop (const char *arg)
{ "fd", GF_CLI_STATUS_FD },
{ "inode", GF_CLI_STATUS_INODE },
{ "callpool", GF_CLI_STATUS_CALLPOOL },
+ { "tasks", GF_CLI_STATUS_TASKS },
{ NULL }
};
@@ -2307,8 +2308,9 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,
if (!strcmp (words[3], "nfs")) {
if (cmd == GF_CLI_STATUS_FD ||
- cmd == GF_CLI_STATUS_DETAIL) {
- cli_err ("Detail/FD status not available"
+ cmd == GF_CLI_STATUS_DETAIL ||
+ cmd == GF_CLI_STATUS_TASKS) {
+ cli_err ("Detail/FD/Tasks status not available"
" for NFS Servers");
ret = -1;
goto out;
@@ -2317,14 +2319,21 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,
} else if (!strcmp (words[3], "shd")){
if (cmd == GF_CLI_STATUS_FD ||
cmd == GF_CLI_STATUS_CLIENTS ||
- cmd == GF_CLI_STATUS_DETAIL) {
- cli_err ("Detail/FD/Clients status not "
+ cmd == GF_CLI_STATUS_DETAIL ||
+ cmd == GF_CLI_STATUS_TASKS) {
+ cli_err ("Detail/FD/Clients/Tasks status not "
"available for Self-heal Daemons");
ret = -1;
goto out;
}
cmd |= GF_CLI_STATUS_SHD;
} else {
+ if (cmd == GF_CLI_STATUS_TASKS) {
+ cli_err ("Tasks status not available for "
+ "bricks");
+ ret = -1;
+ goto out;
+ }
cmd |= GF_CLI_STATUS_BRICK;
ret = dict_set_str (dict, "brick", (char *)words[3]);
}
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 040f610ad..56ad65ebb 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -1914,7 +1914,7 @@ struct cli_cmd volume_cmds[] = {
"volume top operations"},
{ "volume status [all | <VOLNAME> [nfs|shd|<BRICK>]]"
- " [detail|clients|mem|inode|fd|callpool]",
+ " [detail|clients|mem|inode|fd|callpool|tasks]",
cli_cmd_volume_status_cbk,
"display status of all or specified volume(s)/brick"},
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index f9605c104..5dddbb41b 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -6299,43 +6299,57 @@ out:
return;
}
-
static void
-cli_print_volume_tasks (dict_t *dict) {
- int ret = -1;
- int tasks = 0;
- char *op = 0;
- char *task_id_str = NULL;
- int status = 0;
- char key[1024] = {0,};
- int i = 0;
+cli_print_volume_status_tasks (dict_t *dict)
+{
+ int ret = -1;
+ int i = 0;
+ int j = 0;
+ int count = 0;
+ int task_count = 0;
+ int status = 0;
+ char *op = NULL;
+ char *task_id_str = NULL;
+ char *volname = NULL;
+ char key[1024] = {0,};
+ char task[1024] = {0,};
+ char *brick = NULL;
+ char *src_brick = NULL;
+ char *dest_brick = NULL;
- ret = dict_get_int32 (dict, "tasks", &tasks);
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret)
+ goto out;
+
+ ret = dict_get_int32 (dict, "tasks", &task_count);
if (ret) {
- gf_log ("cli", GF_LOG_ERROR,
- "Failed to get tasks count");
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get tasks count");
return;
}
- if (tasks == 0) {
+ cli_out ("Task Status of Volume %s", volname);
+ cli_print_line (CLI_BRICK_STATUS_LINE_LEN);
+
+ if (task_count == 0) {
cli_out ("There are no active volume tasks");
+ cli_out (" ");
return;
}
- cli_out ("%15s%40s%15s", "Task", "ID", "Status");
- cli_out ("%15s%40s%15s", "----", "--", "------");
- for (i = 0; i < tasks; i++) {
+ for (i = 0; i < task_count; i++) {
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "task%d.type", i);
ret = dict_get_str(dict, key, &op);
if (ret)
return;
+ cli_out ("%-20s : %-20s", "Task", op);
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "task%d.id", i);
ret = dict_get_str (dict, key, &task_id_str);
if (ret)
return;
+ cli_out ("%-20s : %-20s", "ID", task_id_str);
memset (key, 0, sizeof (key));
snprintf (key, sizeof (key), "task%d.status", i);
@@ -6343,22 +6357,63 @@ cli_print_volume_tasks (dict_t *dict) {
if (ret)
return;
+ snprintf (task, sizeof (task), "task%d", i);
+
/*
Replace brick only has two states - In progress and Complete
Ref: xlators/mgmt/glusterd/src/glusterd-replace-brick.c
*/
+
if (!strcmp (op, "Replace brick")) {
- if (status) {
- status = GF_DEFRAG_STATUS_COMPLETE;
- } else {
- status = GF_DEFRAG_STATUS_STARTED;
- }
- }
+ if (status)
+ status = GF_DEFRAG_STATUS_COMPLETE;
+ else
+ status = GF_DEFRAG_STATUS_STARTED;
+
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.src-brick", task);
+ ret = dict_get_str (dict, key, &src_brick);
+ if (ret)
+ goto out;
+
+ cli_out ("%-20s : %-20s", "Source Brick", src_brick);
- cli_out ("%15s%40s%15s", op, task_id_str,
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.dst-brick", task);
+ ret = dict_get_str (dict, key, &dest_brick);
+ if (ret)
+ goto out;
+
+ cli_out ("%-20s : %-20s", "Destination Brick",
+ dest_brick);
+
+ } else if (!strcmp (op, "Remove brick")) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key), "%s.count", task);
+ ret = dict_get_int32 (dict, key, &count);
+ if (ret)
+ goto out;
+
+ cli_out ("%-20s", "Removed bricks:");
+
+ for (j = 1; j <= count; j++) {
+ memset (key, 0, sizeof (key));
+ snprintf (key, sizeof (key),"%s.brick%d",
+ task, j);
+ ret = dict_get_str (dict, key, &brick);
+ if (ret)
+ goto out;
+
+ cli_out ("%-20s", brick);
+ }
+ }
+ cli_out ("%-20s : %-20s", "Status",
cli_vol_task_status_str[status]);
+ cli_out (" ");
}
+out:
+ return;
}
static int
@@ -6462,23 +6517,6 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,
if ((cmd & GF_CLI_STATUS_NFS) || (cmd & GF_CLI_STATUS_SHD))
notbrick = _gf_true;
- ret = dict_get_int32 (dict, "count", &count);
- if (ret)
- goto out;
- if (count == 0) {
- ret = -1;
- goto out;
- }
-
- ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max);
- if (ret)
- goto out;
- ret = dict_get_int32 (dict, "other-count", &other_count);
- if (ret)
- goto out;
-
- index_max = brick_index_max + other_count;
-
if (global_state->mode & GLUSTER_MODE_XML) {
if (!local->all) {
ret = cli_xml_output_vol_status_begin (local,
@@ -6491,11 +6529,21 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,
goto out;
}
}
- ret = cli_xml_output_vol_status (local, dict);
- if (ret) {
- gf_log ("cli", GF_LOG_ERROR,
- "Error outputting to xml");
- goto out;
+ if (cmd & GF_CLI_STATUS_TASKS) {
+ ret = cli_xml_output_vol_status_tasks_detail (local,
+ dict);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR,"Error outputting "
+ "to xml");
+ goto out;
+ }
+ } else {
+ ret = cli_xml_output_vol_status (local, dict);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR,
+ "Error outputting to xml");
+ goto out;
+ }
}
if (!local->all) {
@@ -6531,6 +6579,10 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,
cli_print_volume_status_callpool (dict, notbrick);
goto cont;
break;
+ case GF_CLI_STATUS_TASKS:
+ cli_print_volume_status_tasks (dict);
+ goto cont;
+ break;
default:
break;
}
@@ -6539,6 +6591,17 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,
if (ret)
goto out;
+ ret = dict_get_int32 (dict, "brick-index-max", &brick_index_max);
+ if (ret)
+ goto out;
+
+ ret = dict_get_int32 (dict, "other-count", &other_count);
+ if (ret)
+ goto out;
+
+ index_max = brick_index_max + other_count;
+
+
cli_out ("Status of volume: %s", volname);
if ((cmd & GF_CLI_STATUS_DETAIL) == 0) {
@@ -6612,7 +6675,7 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,
cli_out (" ");
if ((cmd & GF_CLI_STATUS_MASK) == GF_CLI_STATUS_NONE)
- cli_print_volume_tasks (dict);
+ cli_print_volume_status_tasks (dict);
cont:
ret = rsp.op_ret;
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c
index 6cc734a18..cc021a34d 100644
--- a/cli/src/cli-xml-output.c
+++ b/cli/src/cli-xml-output.c
@@ -1564,6 +1564,36 @@ out:
gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
+
+int
+cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict)
+{
+ int ret = -1;
+ char *volname = NULL;
+
+ /*<volume>*/
+ ret = xmlTextWriterStartElement (local->writer, (xmlChar *)"volume");
+ XML_RET_CHECK_AND_GOTO (ret, out);
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret)
+ goto out;
+ ret = xmlTextWriterWriteFormatElement (local->writer,
+ (xmlChar *)"volName", "%s",
+ volname);
+ XML_RET_CHECK_AND_GOTO (ret, out);
+
+ ret = cli_xml_output_vol_status_tasks (local, dict);
+ if (ret)
+ goto out;
+
+ /* </volume> */
+ ret = xmlTextWriterEndElement (local->writer);
+ XML_RET_CHECK_AND_GOTO (ret, out);
+
+out:
+ return ret;
+}
#endif
int
@@ -1683,7 +1713,6 @@ cli_xml_output_vol_status (cli_local_t *local, dict_t *dict)
goto out;
}
break;
-
default:
break;
diff --git a/cli/src/cli.h b/cli/src/cli.h
index 5a491eba7..a36c1606f 100644
--- a/cli/src/cli.h
+++ b/cli/src/cli.h
@@ -393,6 +393,8 @@ cli_xml_output_generic_volume (char *op, dict_t *dict, int op_ret, int op_errno,
int
cli_xml_output_vol_gsync (dict_t *dict, int op_ret, int op_errno,
char *op_errstr);
+int
+cli_xml_output_vol_status_tasks_detail (cli_local_t *local, dict_t *dict);
char *
is_server_debug_xlator (void *myframe);
diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h
index 10453bbb0..d418fabf3 100644
--- a/rpc/xdr/src/cli1-xdr.h
+++ b/rpc/xdr/src/cli1-xdr.h
@@ -159,6 +159,7 @@ enum gf_cli_status_type {
GF_CLI_STATUS_FD = 0x0008,
GF_CLI_STATUS_CALLPOOL = 0x0010,
GF_CLI_STATUS_DETAIL = 0x0020,
+ GF_CLI_STATUS_TASKS = 0x0040,
GF_CLI_STATUS_MASK = 0x00FF,
GF_CLI_STATUS_VOL = 0x0100,
GF_CLI_STATUS_ALL = 0x0200,
diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x
index 8018e3034..cc7ca8e24 100644
--- a/rpc/xdr/src/cli1-xdr.x
+++ b/rpc/xdr/src/cli1-xdr.x
@@ -113,6 +113,7 @@ enum gf_cli_status_type {
GF_CLI_STATUS_FD = 0x0008, /*0000000001000*/
GF_CLI_STATUS_CALLPOOL = 0x0010, /*0000000010000*/
GF_CLI_STATUS_DETAIL = 0x0020, /*0000000100000*/
+ GF_CLI_STATUS_TASKS = 0x0040, /*0000001000000*/
GF_CLI_STATUS_MASK = 0x00FF, /*0000011111111 Used to get the op*/
GF_CLI_STATUS_VOL = 0x0100, /*0000100000000*/
GF_CLI_STATUS_ALL = 0x0200, /*0001000000000*/
diff --git a/tests/bugs/bug-857330/common.rc b/tests/bugs/bug-857330/common.rc
index 4e5a73a0b..e5a7cd79a 100644
--- a/tests/bugs/bug-857330/common.rc
+++ b/tests/bugs/bug-857330/common.rc
@@ -22,7 +22,7 @@ function check-and-store-task-id()
function get-task-id()
{
- $CLI $COMMAND | grep $PATTERN | grep -o -E "$UUID_REGEX"
+ $CLI $COMMAND | grep $PATTERN | grep -o -E "$UUID_REGEX" | tail -n1
}
diff --git a/tests/bugs/bug-857330/normal.t b/tests/bugs/bug-857330/normal.t
index 4455d1620..24dfe52c4 100755
--- a/tests/bugs/bug-857330/normal.t
+++ b/tests/bugs/bug-857330/normal.t
@@ -28,7 +28,7 @@ PATTERN="ID:"
TEST check-and-store-task-id
COMMAND="volume status $V0"
-PATTERN="Rebalance"
+PATTERN="ID"
EXPECT $TASK_ID get-task-id
COMMAND="volume rebalance $V0 status"
@@ -45,7 +45,7 @@ PATTERN="ID:"
TEST check-and-store-task-id
COMMAND="volume status $V0"
-PATTERN="Replace"
+PATTERN="ID"
EXPECT $TASK_ID get-task-id
COMMAND="volume replace-brick $V0 $REP_BRICK_PAIR status"
@@ -62,7 +62,7 @@ PATTERN="ID:"
TEST check-and-store-task-id
COMMAND="volume status $V0"
-PATTERN="Remove"
+PATTERN="ID"
EXPECT $TASK_ID get-task-id
COMMAND="volume remove-brick $V0 $H0:$B0/${V0}3 status"
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index d77735998..2dfe3cde1 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -2095,6 +2095,50 @@ out:
}
static int
+glusterd_aggregate_task_status (dict_t *rsp_dict, glusterd_volinfo_t *volinfo)
+{
+ int ret = -1;
+ int tasks = 0;
+ xlator_t *this = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ if (!uuid_is_null (volinfo->rebal.rebalance_id)) {
+ ret = _add_task_to_dict (rsp_dict, volinfo, volinfo->rebal.op,
+ tasks);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to add task details to dict");
+ goto out;
+ }
+ tasks++;
+ }
+
+ if (!uuid_is_null (volinfo->rep_brick.rb_id)) {
+ ret = _add_task_to_dict (rsp_dict, volinfo, GD_OP_REPLACE_BRICK,
+ tasks);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Failed to add task details to dict");
+ goto out;
+ }
+ tasks++;
+ }
+
+ ret = dict_set_int32 (rsp_dict, "tasks", tasks);
+ if (ret) {
+ gf_log (this->name, GF_LOG_ERROR,
+ "Error setting tasks count in dict");
+ goto out;
+ }
+ ret = 0;
+
+out:
+ return ret;
+}
+
+static int
glusterd_op_status_volume (dict_t *dict, char **op_errstr,
dict_t *rsp_dict)
{
@@ -2114,7 +2158,6 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr,
gf_boolean_t nfs_disabled = _gf_false;
gf_boolean_t shd_enabled = _gf_true;
gf_boolean_t origin_glusterd = _gf_false;
- int tasks = 0;
this = THIS;
GF_ASSERT (this);
@@ -2197,6 +2240,10 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr,
brick_index);
node_count++;
+ } else if ((cmd & GF_CLI_STATUS_TASKS) != 0) {
+ ret = glusterd_aggregate_task_status (rsp_dict, volinfo);
+ goto out;
+
} else {
list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
brick_index++;
@@ -2278,31 +2325,10 @@ glusterd_op_status_volume (dict_t *dict, char **op_errstr,
!origin_glusterd)
goto out;
- if (!uuid_is_null (volinfo->rebal.rebalance_id)) {
- ret = _add_task_to_dict (rsp_dict, volinfo, volinfo->rebal.op,
- tasks);
- if (ret) {
- gf_log (this->name, GF_LOG_ERROR,
- "Failed to add task details to dict");
- goto out;
- }
- tasks++;
- }
- if (!uuid_is_null (volinfo->rep_brick.rb_id)) {
- ret = _add_task_to_dict (rsp_dict, volinfo, GD_OP_REPLACE_BRICK,
- tasks);
- if (ret) {
- gf_log (this->name, GF_LOG_ERROR,
- "Failed to add task details to dict");
- goto out;
- }
- tasks++;
- }
-
- ret = dict_set_int32 (rsp_dict, "tasks", tasks);
+ ret = glusterd_aggregate_task_status (rsp_dict, volinfo);
if (ret)
- gf_log (this->name, GF_LOG_ERROR,
- "Error setting tasks count in dict");
+ goto out;
+ ret = 0;
out:
gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);
diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c
index a854e0530..b3bab6fdc 100644
--- a/xlators/mgmt/glusterd/src/glusterd-syncop.c
+++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c
@@ -1189,9 +1189,16 @@ gd_sync_task_begin (dict_t *op_ctx, rpcsvc_request_t * req)
* the 'cluster' lock*/
glusterd_op_set_op (op);
INIT_LIST_HEAD (&conf->xaction_peers);
- npeers = gd_build_peers_list (&conf->peers, &conf->xaction_peers, op);
- ret = gd_lock_op_phase (&conf->xaction_peers, op, op_ctx, &op_errstr, npeers);
+ /* Make 'volume status tasks' command a local operation.
+ * This is accomplished by setting npeers to 0.
+ */
+ if (!glusterd_is_status_tasks_op (op, op_ctx))
+ npeers = gd_build_peers_list (&conf->peers,
+ &conf->xaction_peers, op);
+
+ ret = gd_lock_op_phase (&conf->xaction_peers, op, op_ctx, &op_errstr,
+ npeers);
if (ret)
goto out;
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index b0f9a210f..bef3da74b 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -6813,6 +6813,12 @@ glusterd_volume_status_copy_to_op_ctx_dict (dict_t *aggr, dict_t *rsp_dict)
}
}
+ if ((cmd & GF_CLI_STATUS_TASKS) != 0) {
+ dict_copy (rsp_dict, aggr);
+ ret = 0;
+ goto out;
+ }
+
ret = dict_get_int32 (rsp_dict, "count", &rsp_node_count);
if (ret) {
ret = 0; //no bricks in the rsp
@@ -7695,3 +7701,26 @@ out:
gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);
return ret;
}
+
+gf_boolean_t
+glusterd_is_status_tasks_op (glusterd_op_t op, dict_t *dict)
+{
+ int ret = -1;
+ uint32_t cmd = GF_CLI_STATUS_NONE;
+ gf_boolean_t is_status_tasks = _gf_false;
+
+ if (op != GD_OP_STATUS_VOLUME)
+ goto out;
+
+ ret = dict_get_uint32 (dict, "cmd", &cmd);
+ if (ret) {
+ gf_log (THIS->name, GF_LOG_ERROR, "Failed to get opcode");
+ goto out;
+ }
+
+ if (cmd & GF_CLI_STATUS_TASKS)
+ is_status_tasks = _gf_true;
+
+out:
+ return is_status_tasks;
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index 89888b419..34143cf62 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -565,4 +565,6 @@ glusterd_check_gsync_running_local (char *master, char *slave,
char *conf_path,
gf_boolean_t *is_run);
+gf_boolean_t
+glusterd_is_status_tasks_op (glusterd_op_t op, dict_t *dict);
#endif