3604df
From db9066b2c7a2a66e7aec334ccf834d1c95ef715b Mon Sep 17 00:00:00 2001
3604df
From: Samikshan Bairagya <samikshan@gmail.com>
3604df
Date: Thu, 7 Jul 2016 20:33:02 +0530
3604df
Subject: [PATCH 28/79] glusterd/cli: cli to get local state representation from glusterd
3604df
3604df
Backport of http://review.gluster.org/14873
3604df
3604df
Currently there is no existing CLI that can be used to get the
3604df
local state representation of the cluster as maintained in glusterd
3604df
in a readable as well as parseable format.
3604df
3604df
The CLI added has the following usage:
3604df
3604df
 # gluster get-state [daemon] [odir <path/to/output/dir>] [file <filename>]
3604df
3604df
This would dump data points that reflect the local state
3604df
representation of the cluster as maintained in glusterd (no other
3604df
daemons are supported as of now) to a file inside the specified
3604df
output directory. The default output directory and filename is
3604df
/var/run/gluster and glusterd_state_<timestamp> respectively. The
3604df
option for specifying the daemon name leaves room to add support for
3604df
other daemons in the future. Following are the data points captured
3604df
as of now to represent the state from the local glusterd pov:
3604df
3604df
 * Peer:
3604df
    - Primary hostname
3604df
    - uuid
3604df
    - state
3604df
    - connection status
3604df
    - List of hostnames
3604df
3604df
 * Volumes:
3604df
    - name, id, transport type, status
3604df
    - counts: bricks, snap, subvol, stripe, arbiter, disperse,
3604df
 redundancy
3604df
    - snapd status
3604df
    - quorum status
3604df
    - tiering related information
3604df
    - rebalance status
3604df
    - replace bricks status
3604df
    - snapshots
3604df
3604df
 * Bricks:
3604df
    - Path, hostname (for all bricks these info will be shown)
3604df
    - port, rdma port, status, mount options, filesystem type and
3604df
signed in status for bricks running locally.
3604df
3604df
 * Services:
3604df
    - name, online status for initialised services
3604df
3604df
 * Others:
3604df
    - Base port, last allocated port
3604df
    - op-version
3604df
    - MYUUID
3604df
3604df
> Reviewed-on: http://review.gluster.org/14873
3604df
> Reviewed-by: Avra Sengupta <asengupt@redhat.com>
3604df
> Smoke: Gluster Build System <jenkins@build.gluster.org>
3604df
> CentOS-regression: Gluster Build System <jenkins@build.gluster.org>
3604df
> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org>
3604df
> Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
3604df
3604df
Change-Id: I4a45cc5407ab92d8afdbbd2098ece851f7e3d618
3604df
BUG: 1353427
3604df
Signed-off-by: Samikshan Bairagya <sbairagy@redhat.com>
3604df
Reviewed-on: https://code.engineering.redhat.com/gerrit/84660
3604df
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
3604df
---
3604df
 cli/src/cli-cmd-global.c                           |   57 +++-
3604df
 cli/src/cli-cmd-parser.c                           |  114 +++++
3604df
 cli/src/cli-rpc-ops.c                              |  135 ++++--
3604df
 cli/src/cli-xml-output.c                           |   26 +-
3604df
 cli/src/cli.h                                      |    5 +-
3604df
 doc/gluster.8                                      |    3 +
3604df
 libglusterfs/src/Makefile.am                       |   17 +-
3604df
 libglusterfs/src/common-utils.c                    |   23 +
3604df
 libglusterfs/src/common-utils.h                    |    3 +
3604df
 rpc/rpc-lib/src/protocol-common.h                  |    1 +
3604df
 .../cli/bug-1353156-get-state-cli-validations.t    |  141 ++++++
3604df
 xlators/mgmt/glusterd/src/glusterd-handler.c       |  516 ++++++++++++++++++++
3604df
 xlators/mgmt/glusterd/src/glusterd-messages.h      |   19 +-
3604df
 xlators/mgmt/glusterd/src/glusterd-peer-utils.c    |   51 ++
3604df
 xlators/mgmt/glusterd/src/glusterd-peer-utils.h    |    3 +
3604df
 .../mgmt/glusterd/src/glusterd-snapshot-utils.c    |   36 ++
3604df
 .../mgmt/glusterd/src/glusterd-snapshot-utils.h    |    2 +
3604df
 xlators/mgmt/glusterd/src/glusterd-utils.c         |  194 ++++++++
3604df
 xlators/mgmt/glusterd/src/glusterd-utils.h         |   26 +
3604df
 xlators/mgmt/glusterd/src/glusterd.h               |    1 +
3604df
 21 files changed, 1321 insertions(+), 53 deletions(-)
3604df
 create mode 100644 tests/bugs/cli/bug-1353156-get-state-cli-validations.t
3604df
3604df
diff --git a/cli/src/cli-cmd-global.c b/cli/src/cli-cmd-global.c
3604df
index 53ee0ab..f4544da 100644
3604df
--- a/cli/src/cli-cmd-global.c
3604df
+++ b/cli/src/cli-cmd-global.c
3604df
@@ -34,7 +34,9 @@ cli_cmd_global_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
3604df
                          const char **words, int wordcount);
3604df
 int cli_cmd_ganesha_cbk (struct cli_state *state, struct cli_cmd_word *word,
3604df
                                          const char **words, int wordcount);
3604df
-
3604df
+int
3604df
+cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
3604df
+                              const char **words, int wordcount);
3604df
 
3604df
 struct cli_cmd global_cmds[] = {
3604df
         { "global help",
3604df
@@ -45,6 +47,10 @@ struct cli_cmd global_cmds[] = {
3604df
            cli_cmd_ganesha_cbk,
3604df
           "Enable/disable NFS-Ganesha support",
3604df
         },
3604df
+        { "get-state [<daemon>] [odir </path/to/output/dir/>] [file <filename>]",
3604df
+          cli_cmd_get_state_cbk,
3604df
+          "Get local state representation of mentioned daemon",
3604df
+        },
3604df
         {NULL,  NULL,  NULL}
3604df
 };
3604df
 
3604df
@@ -133,3 +139,52 @@ out:
3604df
         return ret;
3604df
 }
3604df
 
3604df
+int
3604df
+cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
3604df
+                       const char **words, int wordcount)
3604df
+{
3604df
+        int                     sent        =   0;
3604df
+        int                     parse_error =   0;
3604df
+        int                     ret         =  -1;
3604df
+        rpc_clnt_procedure_t    *proc       =  NULL;
3604df
+        call_frame_t            *frame      =  NULL;
3604df
+        dict_t                  *options    =  NULL;
3604df
+        cli_local_t             *local      =  NULL;
3604df
+        char                    *op_errstr  =  NULL;
3604df
+
3604df
+        frame = create_frame (THIS, THIS->ctx->pool);
3604df
+        if (!frame)
3604df
+                goto out;
3604df
+
3604df
+        ret = cli_cmd_get_state_parse (state, words, wordcount, &options,
3604df
+                                       &op_errstr);
3604df
+
3604df
+        if (ret) {
3604df
+                if (op_errstr) {
3604df
+                        cli_err ("%s", op_errstr);
3604df
+                        cli_usage_out (word->pattern);
3604df
+                        GF_FREE (op_errstr);
3604df
+                } else
3604df
+                        cli_usage_out (word->pattern);
3604df
+
3604df
+                parse_error = 1;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        CLI_LOCAL_INIT (local, words, frame, options);
3604df
+
3604df
+        proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_STATE];
3604df
+        if (proc->fn)
3604df
+                ret = proc->fn (frame, THIS, options);
3604df
+out:
3604df
+        if (ret) {
3604df
+                cli_cmd_sent_status_get (&sent);
3604df
+                if ((sent == 0) && (parse_error == 0))
3604df
+                        cli_out ("Getting daemon state failed");
3604df
+        }
3604df
+
3604df
+        CLI_STACK_DESTROY (frame);
3604df
+
3604df
+        return ret;
3604df
+}
3604df
+
3604df
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
3604df
index b20cea6..836a464 100644
3604df
--- a/cli/src/cli-cmd-parser.c
3604df
+++ b/cli/src/cli-cmd-parser.c
3604df
@@ -936,6 +936,120 @@ out:
3604df
 }
3604df
 
3604df
 int32_t
3604df
+cli_cmd_get_state_parse (struct cli_state *state,
3604df
+                         const char **words, int wordcount,
3604df
+                         dict_t **options, char **op_errstr)
3604df
+{
3604df
+        dict_t    *dict                 = NULL;
3604df
+        int        ret                  = -1;
3604df
+        uint32_t   cmd                  = 0;
3604df
+        char      *odir                 = NULL;
3604df
+        char      *filename             = NULL;
3604df
+        char      *daemon_name          = NULL;
3604df
+        int        count                = 0;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO ("cli", options, out);
3604df
+        GF_VALIDATE_OR_GOTO ("cli", words, out);
3604df
+
3604df
+        dict = dict_new ();
3604df
+        if (!dict)
3604df
+                goto out;
3604df
+
3604df
+        if (wordcount < 1 || wordcount > 6) {
3604df
+                *op_errstr = gf_strdup ("Problem parsing arguments."
3604df
+                                        " Check usage.");
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        if (wordcount >= 1) {
3604df
+                gf_asprintf (&daemon_name, "%s", "glusterd");
3604df
+
3604df
+                for (count = 1; count < wordcount; count++) {
3604df
+                        if (strcmp (words[count], "odir") == 0 ||
3604df
+                                        strcmp (words[count], "file") == 0) {
3604df
+                                if (strcmp (words[count], "odir") == 0) {
3604df
+                                        if (++count < wordcount) {
3604df
+                                                odir = (char *) words[count];
3604df
+                                                continue;
3604df
+                                        } else {
3604df
+                                                ret = -1;
3604df
+                                                goto out;
3604df
+                                        }
3604df
+                                } else if (strcmp (words[count], "file") == 0) {
3604df
+                                        if (++count < wordcount) {
3604df
+                                                filename = (char *) words[count];
3604df
+                                                continue;
3604df
+                                        } else {
3604df
+                                                ret = -1;
3604df
+                                                goto out;
3604df
+                                        }
3604df
+                                }
3604df
+                        } else {
3604df
+                                if (count > 1) {
3604df
+                                        *op_errstr = gf_strdup ("Problem "
3604df
+                                                        "parsing arguments. "
3604df
+                                                        "Check usage.");
3604df
+                                        ret = -1;
3604df
+                                        goto out;
3604df
+
3604df
+                                }
3604df
+                                if (strcmp (words[count], "glusterd") == 0) {
3604df
+                                        continue;
3604df
+                                } else {
3604df
+                                        *op_errstr = gf_strdup ("glusterd is "
3604df
+                                                 "the only supported daemon.");
3604df
+                                        ret = -1;
3604df
+                                        goto out;
3604df
+                                }
3604df
+                        }
3604df
+                }
3604df
+
3604df
+                ret = dict_set_str (dict, "daemon", daemon_name);
3604df
+                if (ret) {
3604df
+                        *op_errstr = gf_strdup ("Command failed. Please check "
3604df
+                                                " log file for more details.");
3604df
+                        gf_log (THIS->name, GF_LOG_ERROR,
3604df
+                                "Setting daemon name to dictionary failed");
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                if (odir) {
3604df
+                        ret = dict_set_str (dict, "odir", odir);
3604df
+                        if (ret) {
3604df
+                                *op_errstr = gf_strdup ("Command failed. Please"
3604df
+                                                        " check log file for"
3604df
+                                                        " more details.");
3604df
+                                gf_log (THIS->name, GF_LOG_ERROR,
3604df
+                                        "Setting output directory to"
3604df
+                                        "dictionary failed");
3604df
+                                goto out;
3604df
+                        }
3604df
+                }
3604df
+
3604df
+                if (filename) {
3604df
+                        ret = dict_set_str (dict, "filename", filename);
3604df
+                        if (ret) {
3604df
+                                *op_errstr = gf_strdup ("Command failed. Please"
3604df
+                                                        " check log file for"
3604df
+                                                        " more  details.");
3604df
+                                gf_log (THIS->name, GF_LOG_ERROR,
3604df
+                                        "Setting filename to dictionary failed");
3604df
+                                goto out;
3604df
+                        }
3604df
+                }
3604df
+        }
3604df
+
3604df
+ out:
3604df
+        if (dict)
3604df
+                *options = dict;
3604df
+
3604df
+        if (ret && dict)
3604df
+                dict_unref (dict);
3604df
+
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int32_t
3604df
 cli_cmd_inode_quota_parse (const char **words, int wordcount, dict_t **options)
3604df
 {
3604df
         dict_t          *dict    = NULL;
3604df
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
3604df
index d88ddd7..77a2e24 100644
3604df
--- a/cli/src/cli-rpc-ops.c
3604df
+++ b/cli/src/cli-rpc-ops.c
3604df
@@ -55,17 +55,6 @@ int32_t
3604df
 gf_cli_remove_brick (call_frame_t *frame, xlator_t *this,
3604df
                      void *data);
3604df
 
3604df
-char *cli_vol_type_str[] = {"Distribute",
3604df
-                            "Stripe",
3604df
-                            "Replicate",
3604df
-                            "Striped-Replicate",
3604df
-                            "Disperse",
3604df
-                            "Tier",
3604df
-                            "Distributed-Stripe",
3604df
-                            "Distributed-Replicate",
3604df
-                            "Distributed-Striped-Replicate",
3604df
-                            "Distributed-Disperse",
3604df
-                           };
3604df
 
3604df
 char *cli_vol_status_str[] = {"Created",
3604df
                               "Started",
3604df
@@ -503,6 +492,73 @@ out:
3604df
         return ret;
3604df
 }
3604df
 
3604df
+int
3604df
+gf_cli_get_state_cbk (struct rpc_req *req, struct iovec *iov,
3604df
+                      int count, void *myframe)
3604df
+{
3604df
+        gf_cli_rsp           rsp            = {0,};
3604df
+        int                  ret            = -1;
3604df
+        dict_t               *dict          = NULL;
3604df
+        char                 *daemon_name   = NULL;
3604df
+        char                 *ofilepath     = NULL;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO ("cli", myframe, out);
3604df
+
3604df
+        if (-1 == req->rpc_status) {
3604df
+                goto out;
3604df
+        }
3604df
+        ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);
3604df
+        if (ret < 0) {
3604df
+                gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR,
3604df
+                        "Failed to decode xdr response");
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        dict = dict_new ();
3604df
+
3604df
+        if (!dict) {
3604df
+                ret = -1;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict);
3604df
+        if (ret)
3604df
+                goto out;
3604df
+
3604df
+        if (rsp.op_ret) {
3604df
+                if (strcmp (rsp.op_errstr, ""))
3604df
+                        cli_err ("Failed to get daemon state: %s", rsp.op_errstr);
3604df
+                else
3604df
+                        cli_err ("Failed to get daemon state. Check glusterd"
3604df
+                                 " log file for more details");
3604df
+        } else {
3604df
+                ret = dict_get_str (dict, "daemon", &daemon_name);
3604df
+                if (ret)
3604df
+                        gf_log ("cli", GF_LOG_ERROR, "Couldn't get daemon name");
3604df
+
3604df
+                ret = dict_get_str (dict, "ofilepath", &ofilepath);
3604df
+                if (ret)
3604df
+                        gf_log ("cli", GF_LOG_ERROR, "Couldn't get filepath");
3604df
+
3604df
+                if (daemon_name && ofilepath)
3604df
+                        cli_out ("%s state dumped to %s",
3604df
+                                 daemon_name, ofilepath);
3604df
+        }
3604df
+
3604df
+        ret = rsp.op_ret;
3604df
+
3604df
+out:
3604df
+        free (rsp.dict.dict_val);
3604df
+        free (rsp.op_errstr);
3604df
+
3604df
+        if (dict)
3604df
+                dict_unref (dict);
3604df
+
3604df
+        cli_cmd_broadcast_response (ret);
3604df
+
3604df
+        return ret;
3604df
+}
3604df
+
3604df
 void
3604df
 cli_out_options ( char *substr, char *optstr, char *valstr)
3604df
 {
3604df
@@ -725,13 +781,11 @@ gf_cli_print_tier_info (dict_t *dict, int i, int brick_count)
3604df
         vol_type = hot_type;
3604df
         hot_dist_count = (hot_replica_count ?
3604df
                           hot_replica_count : 1);
3604df
-        if ((hot_type != GF_CLUSTER_TYPE_TIER) &&
3604df
-            (hot_type > 0) &&
3604df
-            (hot_dist_count < hot_brick_count))
3604df
-                vol_type = hot_type + GF_CLUSTER_TYPE_MAX - 1;
3604df
 
3604df
+        vol_type = get_vol_type (hot_type, hot_dist_count, hot_brick_count);
3604df
         cli_out ("Hot Tier Type : %s",
3604df
-                 cli_vol_type_str[vol_type]);
3604df
+                 vol_type_str[vol_type]);
3604df
+
3604df
         gf_cli_print_number_of_bricks (hot_type,
3604df
                         hot_brick_count, hot_dist_count, 0,
3604df
                         hot_replica_count, 0, 0, 0);
3604df
@@ -742,14 +796,11 @@ gf_cli_print_tier_info (dict_t *dict, int i, int brick_count)
3604df
                 goto out;
3604df
 
3604df
         cli_out ("Cold Tier:");
3604df
-        vol_type = cold_type;
3604df
-        if ((cold_type != GF_CLUSTER_TYPE_TIER) &&
3604df
-            (cold_type > 0) &&
3604df
-            (cold_dist_count < cold_brick_count))
3604df
-                vol_type = cold_type + GF_CLUSTER_TYPE_MAX - 1;
3604df
 
3604df
+        vol_type = get_vol_type (cold_type, cold_dist_count, cold_brick_count);
3604df
         cli_out ("Cold Tier Type : %s",
3604df
-                        cli_vol_type_str[vol_type]);
3604df
+                        vol_type_str[vol_type]);
3604df
+
3604df
         gf_cli_print_number_of_bricks (cold_type,
3604df
                 cold_brick_count,
3604df
                 cold_dist_count, 0, cold_replica_count,
3604df
@@ -973,15 +1024,11 @@ xml_output:
3604df
                 if (ret)
3604df
                         goto out;
3604df
 
3604df
-                vol_type = type;
3604df
-
3604df
                 // Distributed (stripe/replicate/stripe-replica) setups
3604df
-                if ((type != GF_CLUSTER_TYPE_TIER) && (type > 0) &&
3604df
-                    (dist_count < brick_count))
3604df
-                       vol_type = type + GF_CLUSTER_TYPE_MAX - 1;
3604df
+                vol_type = get_vol_type (type, dist_count, brick_count);
3604df
 
3604df
                 cli_out ("Volume Name: %s", volname);
3604df
-                cli_out ("Type: %s", cli_vol_type_str[vol_type]);
3604df
+                cli_out ("Type: %s", vol_type_str[vol_type]);
3604df
                 cli_out ("Volume ID: %s", volume_id_str);
3604df
                 cli_out ("Status: %s", cli_vol_status_str[status]);
3604df
                 cli_out ("Snapshot Count: %d", snap_count);
3604df
@@ -4153,6 +4200,32 @@ out:
3604df
 }
3604df
 
3604df
 int32_t
3604df
+gf_cli_get_state (call_frame_t *frame, xlator_t *this, void *data)
3604df
+{
3604df
+        gf_cli_req              req =  {{0,},};
3604df
+        int                     ret = 0;
3604df
+        dict_t                  *dict = NULL;
3604df
+
3604df
+        char                    *odir       =  NULL;
3604df
+
3604df
+        if (!frame || !this ||  !data) {
3604df
+                ret = -1;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        dict = data;
3604df
+
3604df
+        ret = cli_to_glusterd (&req, frame, gf_cli_get_state_cbk,
3604df
+                               (xdrproc_t) xdr_gf_cli_req, dict,
3604df
+                               GLUSTER_CLI_GET_STATE, this, cli_rpc_prog,
3604df
+                               NULL);
3604df
+out:
3604df
+        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
3604df
+
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int32_t
3604df
 gf_cli_get_next_volume (call_frame_t *frame, xlator_t *this,
3604df
                            void *data)
3604df
 {
3604df
@@ -10922,7 +10995,6 @@ cli_to_glusterd (gf_cli_req *req, call_frame_t *frame,
3604df
 
3604df
         ret = cli_cmd_submit (NULL, req, frame, prog, procnum, iobref, this,
3604df
                               cbkfn, (xdrproc_t) xdrproc);
3604df
-
3604df
 out:
3604df
         return ret;
3604df
 
3604df
@@ -11260,7 +11332,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
3604df
         [GLUSTER_CLI_DEPROBE]          = {"DEPROBE_QUERY", gf_cli_deprobe},
3604df
         [GLUSTER_CLI_LIST_FRIENDS]     = {"LIST_FRIENDS", gf_cli_list_friends},
3604df
         [GLUSTER_CLI_UUID_RESET]       = {"UUID_RESET", gf_cli3_1_uuid_reset},
3604df
-        [GLUSTER_CLI_UUID_GET]       = {"UUID_GET", gf_cli3_1_uuid_get},
3604df
+        [GLUSTER_CLI_UUID_GET]         = {"UUID_GET", gf_cli3_1_uuid_get},
3604df
         [GLUSTER_CLI_CREATE_VOLUME]    = {"CREATE_VOLUME", gf_cli_create_volume},
3604df
         [GLUSTER_CLI_DELETE_VOLUME]    = {"DELETE_VOLUME", gf_cli_delete_volume},
3604df
         [GLUSTER_CLI_START_VOLUME]     = {"START_VOLUME", gf_cli_start_volume},
3604df
@@ -11301,7 +11373,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
3604df
         [GLUSTER_CLI_BITROT]           = {"BITROT", gf_cli_bitrot},
3604df
         [GLUSTER_CLI_ATTACH_TIER]      = {"ATTACH_TIER", gf_cli_attach_tier},
3604df
         [GLUSTER_CLI_DETACH_TIER]      = {"DETACH_TIER", gf_cli_detach_tier},
3604df
-        [GLUSTER_CLI_TIER]             = {"TIER", gf_cli_tier}
3604df
+        [GLUSTER_CLI_TIER]             = {"TIER", gf_cli_tier},
3604df
+        [GLUSTER_CLI_GET_STATE]        = {"GET_STATE", gf_cli_get_state}
3604df
 };
3604df
 
3604df
 struct rpc_clnt_program cli_prog = {
3604df
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c
3604df
index dbc8aa7..34f85f2 100644
3604df
--- a/cli/src/cli-xml-output.c
3604df
+++ b/cli/src/cli-xml-output.c
3604df
@@ -2720,9 +2720,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
3604df
                 /* For Distributed-(stripe,replicate,stipe-replicate,disperse)
3604df
                    types
3604df
                  */
3604df
-                if ((type != GF_CLUSTER_TYPE_TIER) && (type > 0) &&
3604df
-                    (dist_count < brick_count))
3604df
-                       type = type + GF_CLUSTER_TYPE_MAX - 1;
3604df
+                type = get_vol_type (type, dist_count, brick_count);
3604df
 
3604df
                 ret = xmlTextWriterWriteFormatElement (local->writer,
3604df
                                                        (xmlChar *)"type",
3604df
@@ -2732,7 +2730,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
3604df
                 ret = xmlTextWriterWriteFormatElement (local->writer,
3604df
                                                        (xmlChar *)"typeStr",
3604df
                                                        "%s",
3604df
-                                                       cli_vol_type_str[type]);
3604df
+                                                       vol_type_str[type]);
3604df
                 XML_RET_CHECK_AND_GOTO (ret, out);
3604df
 
3604df
                 memset (key, 0, sizeof (key));
3604df
@@ -2819,9 +2817,13 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
3604df
                                         goto out;
3604df
                         }
3604df
 
3604df
-                        tier_vol_type = value[HOT_TYPE];
3604df
                         hot_dist_count = (value[HOT_REPLICA_COUNT] ?
3604df
                                           value[HOT_REPLICA_COUNT] : 1);
3604df
+
3604df
+                        tier_vol_type = get_vol_type (value[HOT_TYPE],
3604df
+                                                      hot_dist_count,
3604df
+                                                      value[HOT_BRICK_COUNT]);
3604df
+
3604df
                         if ((value[HOT_TYPE] != GF_CLUSTER_TYPE_TIER) &&
3604df
                             (value[HOT_TYPE] > 0) &&
3604df
                             (hot_dist_count < value[HOT_BRICK_COUNT]))
3604df
@@ -2835,7 +2837,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
3604df
 
3604df
                         ret = xmlTextWriterWriteFormatElement
3604df
                                 (local->writer, (xmlChar *)"hotBrickType",
3604df
-                                 "%s", cli_vol_type_str[tier_vol_type]);
3604df
+                                 "%s", vol_type_str[tier_vol_type]);
3604df
 
3604df
                         ret = xmlTextWriterWriteFormatElement (local->writer,
3604df
                                                    (xmlChar *)"hotreplicaCount",
3604df
@@ -2912,13 +2914,9 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
3604df
                         ret = xmlTextWriterEndElement (local->writer);
3604df
                         XML_RET_CHECK_AND_GOTO (ret, out);
3604df
 
3604df
-                        tier_vol_type = value[COLD_TYPE];
3604df
-                        if ((value[COLD_TYPE] != GF_CLUSTER_TYPE_TIER) &&
3604df
-                            (value[COLD_TYPE] > 0) &&
3604df
-                            (value[COLD_DIST_COUNT] < value[COLD_BRICK_COUNT]))
3604df
-                                tier_vol_type = value[COLD_TYPE] +
3604df
-                                        GF_CLUSTER_TYPE_MAX - 1;
3604df
-
3604df
+                        tier_vol_type = get_vol_type (value[COLD_TYPE],
3604df
+                                                      value[COLD_DIST_COUNT],
3604df
+                                                      value[COLD_BRICK_COUNT]);
3604df
 
3604df
                         ret = xmlTextWriterStartElement (local->writer,
3604df
                                                          (xmlChar *)
3604df
@@ -2927,7 +2925,7 @@ cli_xml_output_vol_info (cli_local_t *local, dict_t *dict)
3604df
 
3604df
                         ret = xmlTextWriterWriteFormatElement
3604df
                                 (local->writer, (xmlChar *)"coldBrickType",
3604df
-                                 "%s", cli_vol_type_str[tier_vol_type]);
3604df
+                                 "%s", vol_type_str[tier_vol_type]);
3604df
 
3604df
                         ret = xmlTextWriterWriteFormatElement (local->writer,
3604df
                                         (xmlChar *)"coldreplicaCount",
3604df
diff --git a/cli/src/cli.h b/cli/src/cli.h
3604df
index 73fb672..f9c642e 100644
3604df
--- a/cli/src/cli.h
3604df
+++ b/cli/src/cli.h
3604df
@@ -71,7 +71,6 @@ struct cli_cmd_word;
3604df
 struct cli_cmd_tree;
3604df
 struct cli_cmd;
3604df
 
3604df
-extern char *cli_vol_type_str[];
3604df
 extern char *cli_vol_status_str[];
3604df
 extern char *cli_vol_task_status_str[];
3604df
 
3604df
@@ -261,6 +260,10 @@ cli_cmd_ganesha_parse (struct cli_state *state, const char **words,
3604df
                        int wordcount, dict_t **options, char **op_errstr);
3604df
 
3604df
 int32_t
3604df
+cli_cmd_get_state_parse (struct cli_state *state, const char **words,
3604df
+                         int wordcount, dict_t **options, char **op_errstr);
3604df
+
3604df
+int32_t
3604df
 cli_cmd_volume_add_brick_parse (const char **words, int wordcount,
3604df
                                 dict_t **options, int *type);
3604df
 
3604df
diff --git a/doc/gluster.8 b/doc/gluster.8
3604df
index 89bf5c3..c9a9d50 100644
3604df
--- a/doc/gluster.8
3604df
+++ b/doc/gluster.8
3604df
@@ -269,6 +269,9 @@ Selects <HOSTNAME:BRICKNAME> as the source for all the files that are in split-b
3604df
 Selects the split-brained <FILE> present in <HOSTNAME:BRICKNAME> as source and completes heal.
3604df
 .SS "Other Commands"
3604df
 .TP
3604df
+\fB\ get-state [<daemon>] [odir </path/to/output/dir/>] [file <filename>] \fR
3604df
+Get local state representation of mentioned daemon and store data in provided path information
3604df
+.TP
3604df
 \fB\ help \fR
3604df
 Display the command options.
3604df
 .TP
3604df
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am
3604df
index 2a4f764..89c7fa0 100644
3604df
--- a/libglusterfs/src/Makefile.am
3604df
+++ b/libglusterfs/src/Makefile.am
3604df
@@ -6,9 +6,10 @@ libglusterfs_la_CFLAGS = $(GF_CFLAGS) $(GF_DARWIN_LIBGLUSTERFS_CFLAGS) \
3604df
 libglusterfs_la_CPPFLAGS = $(GF_CPPFLAGS) -D__USE_FILE_OFFSET64 \
3604df
 	-DXLATORDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator\" \
3604df
 	-DXLATORPARENTDIR=\"$(libdir)/glusterfs/$(PACKAGE_VERSION)\" \
3604df
-	-I$(top_srcdir)/rpc/rpc-lib/src/ -I$(CONTRIBDIR)/rbtree \
3604df
-	-I$(CONTRIBDIR)/libexecinfo ${ARGP_STANDALONE_CPPFLAGS} \
3604df
-	-DSBIN_DIR=\"$(sbindir)\" -I$(CONTRIBDIR)/timer-wheel
3604df
+	-I$(top_srcdir)/rpc/xdr/src/ -I$(top_srcdir)/rpc/rpc-lib/src/ \
3604df
+	-I$(CONTRIBDIR)/rbtree -I$(CONTRIBDIR)/libexecinfo \
3604df
+	${ARGP_STANDALONE_CPPFLAGS} -DSBIN_DIR=\"$(sbindir)\" \
3604df
+	-I$(CONTRIBDIR)/timer-wheel
3604df
 
3604df
 libglusterfs_la_LIBADD = @LEXLIB@ $(ZLIB_LIBS) $(MATH_LIB) $(UUID_LIBS)
3604df
 libglusterfs_la_LDFLAGS = -version-info $(LIBGLUSTERFS_LT_VERSION)
3604df
@@ -35,9 +36,9 @@ libglusterfs_la_SOURCES = dict.c xlator.c logging.c \
3604df
 	compound-fop-utils.c
3604df
 
3604df
 nodist_libglusterfs_la_SOURCES = y.tab.c graph.lex.c defaults.c
3604df
-nodist_libglusterfs_la_HEADERS = y.tab.h glusterfs-fops.h
3604df
+nodist_libglusterfs_la_HEADERS = y.tab.h glusterfs-fops.h cli1-xdr.h
3604df
 
3604df
-BUILT_SOURCES = graph.lex.c defaults.c glusterfs-fops.h
3604df
+BUILT_SOURCES = graph.lex.c defaults.c glusterfs-fops.h cli1-xdr.h
3604df
 
3604df
 libglusterfs_la_HEADERS = common-utils.h defaults.h default-args.h \
3604df
 	dict.h glusterfs.h hashfn.h timespec.h logging.h xlator.h \
3604df
@@ -91,6 +92,12 @@ $(top_srcdir)/rpc/xdr/src/glusterfs-fops.h: $(top_srcdir)/rpc/xdr/src/glusterfs-
3604df
 glusterfs-fops.h: $(top_srcdir)/rpc/xdr/src/glusterfs-fops.h
3604df
 	cp $(top_srcdir)/rpc/xdr/src/glusterfs-fops.h .
3604df
 
3604df
+$(top_srcdir)/rpc/xdr/src/cli1-xdr.h: $(top_srcdir)/rpc/xdr/src/cli1-xdr.x
3604df
+	$(MAKE) -C $(top_builddir)/rpc/xdr/src/ `basename $@`
3604df
+
3604df
+cli1-xdr.h: $(top_srcdir)/rpc/xdr/src/cli1-xdr.h
3604df
+	cp $(top_srcdir)/rpc/xdr/src/cli1-xdr.h .
3604df
+
3604df
 CLEANFILES = $(nodist_libglusterfs_la_SOURCES) $(nodist_libglusterfs_la_HEADERS)
3604df
 
3604df
 if UNITTEST
3604df
diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c
3604df
index 9583352..e51933d 100644
3604df
--- a/libglusterfs/src/common-utils.c
3604df
+++ b/libglusterfs/src/common-utils.c
3604df
@@ -45,6 +45,7 @@
3604df
 #include "globals.h"
3604df
 #include "lkowner.h"
3604df
 #include "syscall.h"
3604df
+#include "cli1-xdr.h"
3604df
 #include <ifaddrs.h>
3604df
 #include "libglusterfs-messages.h"
3604df
 
3604df
@@ -52,6 +53,18 @@
3604df
 #define AI_ADDRCONFIG 0
3604df
 #endif /* AI_ADDRCONFIG */
3604df
 
3604df
+char *vol_type_str[] = {"Distribute",
3604df
+                        "Stripe",
3604df
+                        "Replicate",
3604df
+                        "Striped-Replicate",
3604df
+                        "Disperse",
3604df
+                        "Tier",
3604df
+                        "Distributed-Stripe",
3604df
+                        "Distributed-Replicate",
3604df
+                        "Distributed-Striped-Replicate",
3604df
+                        "Distributed-Disperse",
3604df
+                       };
3604df
+
3604df
 typedef int32_t (*rw_op_t)(int32_t fd, char *buf, int32_t size);
3604df
 typedef int32_t (*rwv_op_t)(int32_t fd, const struct iovec *buf, int32_t size);
3604df
 
3604df
@@ -2722,6 +2735,16 @@ out:
3604df
 }
3604df
 
3604df
 int
3604df
+get_vol_type (int type, int dist_count, int brick_count)
3604df
+{
3604df
+        if ((type != GF_CLUSTER_TYPE_TIER) && (type > 0) &&
3604df
+             (dist_count < brick_count))
3604df
+              type = type + GF_CLUSTER_TYPE_MAX - 1;
3604df
+
3604df
+        return type;
3604df
+}
3604df
+
3604df
+int
3604df
 validate_brick_name (char *brick)
3604df
 {
3604df
         char *delimiter = NULL;
3604df
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
3604df
index 2930fea..d71c143 100644
3604df
--- a/libglusterfs/src/common-utils.h
3604df
+++ b/libglusterfs/src/common-utils.h
3604df
@@ -207,6 +207,8 @@ struct list_node {
3604df
         struct list_head list;
3604df
 };
3604df
 
3604df
+extern char *vol_type_str[];
3604df
+
3604df
 struct list_node *list_node_add (void *ptr, struct list_head *list);
3604df
 struct list_node *list_node_add_order (void *ptr, struct list_head *list,
3604df
                                        int (*compare)(struct list_head *,
3604df
@@ -757,6 +759,7 @@ void gf_array_insertionsort (void *a, int l, int r, size_t elem_size,
3604df
 int gf_is_str_int (const char *value);
3604df
 
3604df
 char *gf_uint64_2human_readable (uint64_t);
3604df
+int get_vol_type (int type, int dist_count, int brick_count);
3604df
 int validate_brick_name (char *brick);
3604df
 char *get_host_name (char *word, char **host);
3604df
 char *get_path_name (char *word, char **path);
3604df
diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h
3604df
index 915d358..c1a488e 100644
3604df
--- a/rpc/rpc-lib/src/protocol-common.h
3604df
+++ b/rpc/rpc-lib/src/protocol-common.h
3604df
@@ -192,6 +192,7 @@ enum gluster_cli_procnum {
3604df
         GLUSTER_CLI_ATTACH_TIER,
3604df
         GLUSTER_CLI_DETACH_TIER,
3604df
         GLUSTER_CLI_TIER,
3604df
+        GLUSTER_CLI_GET_STATE,
3604df
         GLUSTER_CLI_MAXVALUE,
3604df
 };
3604df
 
3604df
diff --git a/tests/bugs/cli/bug-1353156-get-state-cli-validations.t b/tests/bugs/cli/bug-1353156-get-state-cli-validations.t
3604df
new file mode 100644
3604df
index 0000000..9dc1f07
3604df
--- /dev/null
3604df
+++ b/tests/bugs/cli/bug-1353156-get-state-cli-validations.t
3604df
@@ -0,0 +1,141 @@
3604df
+#!/bin/bash
3604df
+
3604df
+. $(dirname $0)/../../include.rc
3604df
+. $(dirname $0)/../../volume.rc
3604df
+. $(dirname $0)/../../fileio.rc
3604df
+. $(dirname $0)/../../snapshot.rc
3604df
+
3604df
+cleanup;
3604df
+
3604df
+ODIR="/var/tmp/gdstates/"
3604df
+NOEXDIR="/var/tmp/gdstatesfoo/"
3604df
+
3604df
+function get_daemon_not_supported_part {
3604df
+        echo $1
3604df
+}
3604df
+
3604df
+function get_usage_part {
3604df
+        echo $7
3604df
+}
3604df
+
3604df
+function get_directory_doesnt_exist_part {
3604df
+        echo $1
3604df
+}
3604df
+
3604df
+function get_parsing_arguments_part {
3604df
+        echo $1
3604df
+}
3604df
+
3604df
+TEST glusterd
3604df
+TEST pidof glusterd
3604df
+TEST mkdir $ODIR
3604df
+
3604df
+TEST $CLI volume create $V0 disperse $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3
3604df
+TEST $CLI volume start $V0
3604df
+TEST $CLI volume tier $V0 attach replica 2 $H0:$B1/b4 $H0:$B1/b5
3604df
+
3604df
+TEST setup_lvm 1
3604df
+TEST $CLI volume create $V1 $H0:$L1;
3604df
+TEST $CLI volume start $V1
3604df
+
3604df
+TEST $CLI snapshot create ${V1}_snap $V1
3604df
+
3604df
+OPATH=$(echo `$CLI get-state` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+OPATH=$(echo `$CLI get-state glusterd` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+TEST ! $CLI get-state glusterfsd;
3604df
+ERRSTR=$($CLI get-state glusterfsd 2>&1 >/dev/null);
3604df
+EXPECT 'glusterd' get_daemon_not_supported_part $ERRSTR;
3604df
+EXPECT 'Usage:' get_usage_part $ERRSTR;
3604df
+
3604df
+OPATH=$(echo `$CLI get-state file gdstate` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+OPATH=$(echo `$CLI get-state glusterd file gdstate` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+TEST ! $CLI get-state glusterfsd file gdstate;
3604df
+ERRSTR=$($CLI get-state glusterfsd file gdstate 2>&1 >/dev/null);
3604df
+EXPECT 'glusterd' get_daemon_not_supported_part $ERRSTR;
3604df
+EXPECT 'Usage:' get_usage_part $ERRSTR;
3604df
+
3604df
+OPATH=$(echo `$CLI get-state odir $ODIR` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+OPATH=$(echo `$CLI get-state glusterd odir $ODIR` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+OPATH=$(echo `$CLI get-state odir $ODIR file gdstate` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+OPATH=$(echo `$CLI get-state glusterd odir $ODIR file gdstate` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+OPATH=$(echo `$CLI get-state glusterd odir $ODIR file gdstate` | awk '{print $5}' | tr -d '\n')
3604df
+TEST fd=`fd_available`
3604df
+TEST fd_open $fd "r" $OPATH;
3604df
+TEST fd_close $fd;
3604df
+rm $OPATH
3604df
+
3604df
+TEST ! $CLI get-state glusterfsd odir $ODIR;
3604df
+ERRSTR=$($CLI get-state glusterfsd odir $ODIR 2>&1 >/dev/null);
3604df
+EXPECT 'glusterd' get_daemon_not_supported_part $ERRSTR;
3604df
+EXPECT 'Usage:' get_usage_part $ERRSTR;
3604df
+
3604df
+TEST ! $CLI get-state glusterfsd odir $ODIR file gdstate;
3604df
+ERRSTR=$($CLI get-state glusterfsd odir $ODIR file gdstate 2>&1 >/dev/null);
3604df
+EXPECT 'glusterd' get_daemon_not_supported_part $ERRSTR;
3604df
+EXPECT 'Usage:' get_usage_part $ERRSTR;
3604df
+
3604df
+TEST ! $CLI get-state glusterfsd odir $NOEXDIR file gdstate;
3604df
+ERRSTR=$($CLI get-state glusterfsd odir $NOEXDIR file gdstate 2>&1 >/dev/null);
3604df
+EXPECT 'glusterd' get_daemon_not_supported_part $ERRSTR;
3604df
+EXPECT 'Usage:' get_usage_part $ERRSTR;
3604df
+
3604df
+TEST ! $CLI get-state odir $NOEXDIR;
3604df
+ERRSTR=$($CLI get-state odir $NOEXDIR 2>&1 >/dev/null);
3604df
+EXPECT 'Failed' get_directory_doesnt_exist_part $ERRSTR;
3604df
+
3604df
+TEST ! $CLI get-state odir $NOEXDIR file gdstate;
3604df
+ERRSTR=$($CLI get-state odir $NOEXDIR 2>&1 >/dev/null);
3604df
+EXPECT 'Failed' get_directory_doesnt_exist_part $ERRSTR;
3604df
+
3604df
+TEST ! $CLI get-state foo bar;
3604df
+ERRSTR=$($CLI get-state foo bar 2>&1 >/dev/null);
3604df
+EXPECT 'glusterd' get_daemon_not_supported_part $ERRSTR;
3604df
+EXPECT 'Usage:' get_usage_part $ERRSTR;
3604df
+
3604df
+TEST ! $CLI get-state glusterd foo bar;
3604df
+ERRSTR=$($CLI get-state glusterd foo bar 2>&1 >/dev/null);
3604df
+EXPECT 'Problem' get_parsing_arguments_part $ERRSTR;
3604df
+
3604df
+rm -Rf $ODIR
3604df
+cleanup;
3604df
+
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
3604df
index 8ca9d2a..7009231 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
3604df
@@ -4936,6 +4936,521 @@ glusterd_handle_get_vol_opt (rpcsvc_request_t *req)
3604df
 {
3604df
         return glusterd_big_locked_handler (req, __glusterd_handle_get_vol_opt);
3604df
 }
3604df
+
3604df
+static int
3604df
+glusterd_print_global_options (dict_t *opts, char *key, data_t *val, void *data)
3604df
+{
3604df
+        FILE *fp = NULL;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, key, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, val, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, data, out);
3604df
+
3604df
+        fp = (FILE *) data;
3604df
+        fprintf (fp, "%s: %s\n", key, val->data);
3604df
+out:
3604df
+        return 0;
3604df
+}
3604df
+
3604df
+static int
3604df
+glusterd_print_snapinfo_by_vol (FILE *fp, glusterd_volinfo_t *volinfo, int volcount)
3604df
+{
3604df
+        int                     ret = -1;
3604df
+        glusterd_volinfo_t      *snap_vol = NULL;
3604df
+        glusterd_volinfo_t      *tmp_vol = NULL;
3604df
+        glusterd_snap_t         *snapinfo = NULL;
3604df
+        int                     snapcount = 0;
3604df
+        char                    timestr[64] = {0,};
3604df
+        char                    snap_status_str[STATUS_STRLEN] = {0,};
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, fp, out);
3604df
+
3604df
+        cds_list_for_each_entry_safe (snap_vol, tmp_vol, &volinfo->snap_volumes,
3604df
+                                      snapvol_list) {
3604df
+                snapcount++;
3604df
+                snapinfo = snap_vol->snapshot;
3604df
+
3604df
+                ret = glusterd_get_snap_status_str (snapinfo, snap_status_str);
3604df
+                if (ret) {
3604df
+                        gf_msg (THIS->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                "Failed to get status for snapshot: %s",
3604df
+                                snapinfo->snapname);
3604df
+
3604df
+                        goto out;
3604df
+                }
3604df
+                gf_time_fmt (timestr, sizeof timestr, snapinfo->time_stamp,
3604df
+                             gf_timefmt_FT);
3604df
+
3604df
+                fprintf (fp, "Volume%d.snapshot%d.name: %s\n",
3604df
+                         volcount, snapcount, snapinfo->snapname);
3604df
+                fprintf (fp, "Volume%d.snapshot%d.id: %s\n", volcount, snapcount,
3604df
+                         gf_strdup (uuid_utoa (snapinfo->snap_id)));
3604df
+                fprintf (fp, "Volume%d.snapshot%d.time: %s\n",
3604df
+                         volcount, snapcount, timestr);
3604df
+
3604df
+                if (snapinfo->description)
3604df
+                        fprintf (fp, "Volume%d.snapshot%d.description: %s\n",
3604df
+                         volcount, snapcount, snapinfo->description);
3604df
+                fprintf (fp, "Volume%d.snapshot%d.status: %s\n",
3604df
+                         volcount, snapcount, snap_status_str);
3604df
+        }
3604df
+
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+static int
3604df
+glusterd_get_state (rpcsvc_request_t *req, dict_t *dict)
3604df
+{
3604df
+        int32_t                      ret = -1;
3604df
+        gf_cli_rsp                   rsp = {0,};
3604df
+        int                          fd = -1;
3604df
+        FILE                        *fp = NULL;
3604df
+        DIR                         *dp = NULL;
3604df
+        char                         err_str[2048] = {0,};
3604df
+        glusterd_conf_t             *priv = NULL;
3604df
+        glusterd_peerinfo_t         *peerinfo = NULL;
3604df
+        glusterd_peer_hostname_t    *peer_hostname_info = NULL;
3604df
+        glusterd_volinfo_t          *volinfo = NULL;
3604df
+        glusterd_brickinfo_t        *brickinfo = NULL;
3604df
+        glusterd_snap_t             *snapinfo = NULL;
3604df
+        xlator_t                    *this = NULL;
3604df
+        char                        *odir = NULL;
3604df
+        char                        *filename = NULL;
3604df
+        char                        *ofilepath = NULL;
3604df
+        int                          count = 0;
3604df
+        int                          count_bkp = 0;
3604df
+        int                          odirlen = 0;
3604df
+        time_t                       now = 0;
3604df
+        char                         timestamp[16] = {0,};
3604df
+
3604df
+        char    *vol_type_str = NULL;
3604df
+        char    *hot_tier_type_str = NULL;
3604df
+        char    *cold_tier_type_str = NULL;
3604df
+
3604df
+        char     transport_type_str[STATUS_STRLEN] = {0,};
3604df
+        char     quorum_status_str[STATUS_STRLEN] = {0,};
3604df
+        char     rebal_status_str[STATUS_STRLEN] = {0,};
3604df
+        char     peer_state_str[STATUS_STRLEN] = {0,};
3604df
+        char     vol_status_str[STATUS_STRLEN] = {0,};
3604df
+
3604df
+        this = THIS;
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, this, out);
3604df
+
3604df
+        priv = THIS->private;
3604df
+        GF_VALIDATE_OR_GOTO (this->name, priv, out);
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (this->name, dict, out);
3604df
+
3604df
+        ret = dict_get_str (dict, "odir", &odir;;
3604df
+        if (ret) {
3604df
+                gf_asprintf (&odir, "%s", "/var/run/gluster/");
3604df
+                gf_msg (this->name, GF_LOG_INFO, 0,
3604df
+                        GD_MSG_DICT_GET_FAILED,
3604df
+                        "Default output directory: %s", odir);
3604df
+        }
3604df
+
3604df
+        dp = sys_opendir (odir);
3604df
+        if (dp) {
3604df
+                sys_closedir (dp);
3604df
+        } else {
3604df
+                if (errno == ENOENT) {
3604df
+                        snprintf (err_str, sizeof (err_str),
3604df
+                                  "Output directory %s does not exist.", odir);
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_DICT_GET_FAILED, "%s", err_str);
3604df
+                } else if (errno == ENOTDIR) {
3604df
+                        snprintf (err_str, sizeof (err_str), "Output directory "
3604df
+                                  "does not exist. %s points to a file.", odir);
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_DICT_GET_FAILED, "%s", err_str);
3604df
+                }
3604df
+
3604df
+                ret = -1;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        ret = dict_get_str (dict, "filename", &filename);
3604df
+        if (ret) {
3604df
+                now = time (NULL);
3604df
+                strftime (timestamp, sizeof (timestamp),
3604df
+                          "%Y%m%d_%H%M%S", localtime (&now));
3604df
+                gf_asprintf (&filename, "%s_%s", "glusterd_state", timestamp);
3604df
+
3604df
+                gf_msg (this->name, GF_LOG_INFO, 0,
3604df
+                        GD_MSG_DICT_GET_FAILED,
3604df
+                        "Default filename: %s", filename);
3604df
+        }
3604df
+
3604df
+        odirlen = strlen (odir);
3604df
+        if (odir[odirlen-1] != '/')
3604df
+                strcat (odir, "/");
3604df
+
3604df
+        gf_asprintf (&ofilepath, "%s%s", odir, filename);
3604df
+
3604df
+        ret = dict_set_str (dict, "ofilepath", ofilepath);
3604df
+        if (ret) {
3604df
+                gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                        GD_MSG_DICT_SET_FAILED, "Unable to set output path");
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        fp = fopen (ofilepath, "w");
3604df
+        if (!fp) {
3604df
+                snprintf (err_str, sizeof (err_str),
3604df
+                          "Failed to open file at %s", ofilepath);
3604df
+                gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                        GD_MSG_DICT_GET_FAILED, "%s", err_str);
3604df
+                ret = -1;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        fprintf (fp, "[Global]\n");
3604df
+
3604df
+        fprintf (fp, "MYUUID: %s\n", gf_strdup (uuid_utoa (priv->uuid)));
3604df
+        fprintf (fp, "op-version: %d\n", priv->op_version);
3604df
+
3604df
+        fprintf (fp, "\n[Global options]\n");
3604df
+
3604df
+        if (priv->opts)
3604df
+                dict_foreach (priv->opts, glusterd_print_global_options, fp);
3604df
+
3604df
+        rcu_read_lock ();
3604df
+        fprintf (fp, "\n[Peers]\n");
3604df
+
3604df
+        cds_list_for_each_entry_rcu (peerinfo, &priv->peers, uuid_list) {
3604df
+                ret = gd_peer_state_str (peerinfo, peer_state_str);
3604df
+                if (ret) {
3604df
+                        rcu_read_unlock ();
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                "Failed to get peer state");
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                fprintf (fp, "Peer%d.primary_hostname: %s\n", ++count,
3604df
+                         peerinfo->hostname);
3604df
+                fprintf (fp, "Peer%d.uuid: %s\n", count, gd_peer_uuid_str (peerinfo));
3604df
+                fprintf (fp, "Peer%d.state: %s\n", count, peer_state_str);
3604df
+                fprintf (fp, "Peer%d.connected: %d\n", count, peerinfo->connected);
3604df
+
3604df
+                fprintf (fp, "Peer%d.hostnames: ", count);
3604df
+                cds_list_for_each_entry (peer_hostname_info,
3604df
+                                         &peerinfo->hostnames, hostname_list)
3604df
+                        fprintf (fp, "%s, ", peer_hostname_info->hostname);
3604df
+                fprintf (fp, "\n");
3604df
+        }
3604df
+        rcu_read_unlock ();
3604df
+
3604df
+        count = 0;
3604df
+        fprintf (fp, "\n[Volumes]\n");
3604df
+
3604df
+        cds_list_for_each_entry (volinfo, &priv->volumes, vol_list) {
3604df
+                ret = glusterd_volume_get_type_str (volinfo, &vol_type_str);
3604df
+                if (ret) {
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                "Failed to get type for volume: %s",
3604df
+                                volinfo->volname);
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                ret = glusterd_volume_get_status_str (volinfo, vol_status_str);
3604df
+                if (ret) {
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                "Failed to get status for volume: %s",
3604df
+                                volinfo->volname);
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                ret = glusterd_volume_get_transport_type_str (volinfo,
3604df
+                                                              transport_type_str);
3604df
+                if (ret) {
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                "Failed to get transport type for volume: %s",
3604df
+                                volinfo->volname);
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                ret = glusterd_volume_get_quorum_status_str (volinfo,
3604df
+                                                             quorum_status_str);
3604df
+                if (ret) {
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                "Failed to get quorum status for volume: %s",
3604df
+                                volinfo->volname);
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                ret = glusterd_volume_get_rebalance_status_str (volinfo,
3604df
+                                                                rebal_status_str);
3604df
+                if (ret) {
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                "Failed to get rebalance status for volume: %s",
3604df
+                                volinfo->volname);
3604df
+                        goto out;
3604df
+                }
3604df
+
3604df
+                fprintf (fp, "Volume%d.name: %s\n", ++count, volinfo->volname);
3604df
+                fprintf (fp, "Volume%d.id: %s\n", count,
3604df
+                         gf_strdup (uuid_utoa (volinfo->volume_id)));
3604df
+                fprintf (fp, "Volume%d.type: %s\n", count, vol_type_str);
3604df
+                fprintf (fp, "Volume%d.transport_type: %s\n", count,
3604df
+                         transport_type_str);
3604df
+                fprintf (fp, "Volume%d.status: %s\n", count, vol_status_str);
3604df
+                fprintf (fp, "Volume%d.brickcount: %d\n", count,
3604df
+                         volinfo->brick_count);
3604df
+
3604df
+                count_bkp = count;
3604df
+                count = 0;
3604df
+                cds_list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) {
3604df
+                        fprintf (fp, "Volume%d.Brick%d.path: %s:%s\n",
3604df
+                                 count_bkp, ++count, brickinfo->hostname,
3604df
+                                 brickinfo->path);
3604df
+                        fprintf (fp, "Volume%d.Brick%d.hostname: %s\n",
3604df
+                                 count_bkp, count, brickinfo->hostname);
3604df
+
3604df
+                        /* Add following information only for bricks
3604df
+                         *  local to current node */
3604df
+                        if (gf_uuid_compare (brickinfo->uuid, MY_UUID))
3604df
+                                continue;
3604df
+                        fprintf (fp, "Volume%d.Brick%d.port: %d\n", count_bkp,
3604df
+                                 count, brickinfo->port);
3604df
+                        fprintf (fp, "Volume%d.Brick%d.rdma_port: %d\n", count_bkp,
3604df
+                                 count, brickinfo->rdma_port);
3604df
+                        fprintf (fp, "Volume%d.Brick%d.status: %s\n", count_bkp,
3604df
+                                 count, brickinfo->status ? "Started" : "Stopped");
3604df
+                        fprintf (fp, "Volume%d.Brick%d.filesystem_type: %s\n",
3604df
+                                 count_bkp, count, brickinfo->fstype);
3604df
+                        fprintf (fp, "Volume%d.Brick%d.mount_options: %s\n",
3604df
+                                 count_bkp, count, brickinfo->mnt_opts);
3604df
+                        fprintf (fp, "Volume%d.Brick%d.signedin: %s\n", count_bkp,
3604df
+                                 count, brickinfo->signed_in ? "True" : "False");
3604df
+                }
3604df
+
3604df
+                count = count_bkp;
3604df
+
3604df
+                ret = glusterd_print_snapinfo_by_vol (fp, volinfo, count);
3604df
+                if (ret)
3604df
+                        goto out;
3604df
+
3604df
+                fprintf (fp, "Volume%d.snap_count: %"PRIu64"\n", count,
3604df
+                         volinfo->snap_count);
3604df
+                fprintf (fp, "Volume%d.stripe_count: %d\n", count,
3604df
+                         volinfo->stripe_count);
3604df
+                fprintf (fp, "Volume%d.subvol_count: %d\n", count,
3604df
+                         volinfo->subvol_count);
3604df
+                fprintf (fp, "Volume%d.arbiter_count: %d\n", count,
3604df
+                         volinfo->arbiter_count);
3604df
+                fprintf (fp, "Volume%d.disperse_count: %d\n", count,
3604df
+                         volinfo->disperse_count);
3604df
+                fprintf (fp, "Volume%d.redundancy_count: %d\n", count,
3604df
+                         volinfo->redundancy_count);
3604df
+                fprintf (fp, "Volume%d.quorum_status: %s\n", count,
3604df
+                                quorum_status_str);
3604df
+
3604df
+                fprintf (fp, "Volume%d.snapd_svc.online_status: %s\n", count,
3604df
+                         volinfo->snapd.svc.online ? "Online" : "Offline");
3604df
+                fprintf (fp, "Volume%d.snapd_svc.inited: %s\n", count,
3604df
+                         volinfo->snapd.svc.inited ? "True" : "False");
3604df
+
3604df
+                fprintf (fp, "Volume%d.rebalance.id: %s\n", count,
3604df
+                         gf_strdup (uuid_utoa (volinfo->rebal.rebalance_id)));
3604df
+                fprintf (fp, "Volume%d.rebalance.status: %s\n", count,
3604df
+                         rebal_status_str);
3604df
+                fprintf (fp, "Volume%d.rebalance.failures: %"PRIu64"\n", count,
3604df
+                         volinfo->rebal.rebalance_failures);
3604df
+                fprintf (fp, "Volume%d.rebalance.skipped: %"PRIu64"\n", count,
3604df
+                         volinfo->rebal.skipped_files);
3604df
+                fprintf (fp, "Volume%d.rebalance.lookedup: %"PRIu64"\n", count,
3604df
+                         volinfo->rebal.lookedup_files);
3604df
+                fprintf (fp, "Volume%d.rebalance.files: %"PRIu64"\n", count,
3604df
+                         volinfo->rebal.rebalance_files);
3604df
+                fprintf (fp, "Volume%d.rebalance.data: %"PRIu64"\n", count,
3604df
+                         volinfo->rebal.rebalance_data);
3604df
+                fprintf (fp, "Volume%d.rebalance.data: %"PRIu64"\n", count,
3604df
+                         volinfo->rebal.rebalance_data);
3604df
+
3604df
+                if (volinfo->type == GF_CLUSTER_TYPE_TIER) {
3604df
+                        ret = glusterd_volume_get_hot_tier_type_str (
3604df
+                                                volinfo, &hot_tier_type_str);
3604df
+                        if (ret) {
3604df
+                                gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                        GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                        "Failed to get hot tier type for "
3604df
+                                        "volume: %s", volinfo->volname);
3604df
+                                goto out;
3604df
+                        }
3604df
+
3604df
+                        ret = glusterd_volume_get_cold_tier_type_str (
3604df
+                                                volinfo, &cold_tier_type_str);
3604df
+                        if (ret) {
3604df
+                               gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                        GD_MSG_STATE_STR_GET_FAILED,
3604df
+                                        "Failed to get cold tier type for "
3604df
+                                        "volume: %s", volinfo->volname);
3604df
+                               goto out;
3604df
+                        }
3604df
+
3604df
+                        fprintf (fp, "Volume%d.tier_info.cold_tier_type: %s\n",
3604df
+                                 count, cold_tier_type_str);
3604df
+                        fprintf (fp, "Volume%d.tier_info.cold_brick_count: %d\n",
3604df
+                                 count, volinfo->tier_info.cold_brick_count);
3604df
+                        fprintf (fp, "Volume%d.tier_info.cold_replica_count: %d\n",
3604df
+                                 count, volinfo->tier_info.cold_replica_count);
3604df
+                        fprintf (fp, "Volume%d.tier_info.cold_disperse_count: %d\n",
3604df
+                                 count, volinfo->tier_info.cold_disperse_count);
3604df
+                        fprintf (fp, "Volume%d.tier_info.cold_dist_leaf_count: %d\n",
3604df
+                                 count, volinfo->tier_info.cold_dist_leaf_count);
3604df
+                        fprintf (fp, "Volume%d.tier_info.cold_redundancy_count: %d\n",
3604df
+                                 count, volinfo->tier_info.cold_redundancy_count);
3604df
+                        fprintf (fp, "Volume%d.tier_info.hot_tier_type: %s\n",
3604df
+                                 count, hot_tier_type_str);
3604df
+                        fprintf (fp, "Volume%d.tier_info.hot_brick_count: %d\n",
3604df
+                                 count, volinfo->tier_info.hot_brick_count);
3604df
+                        fprintf (fp, "Volume%d.tier_info.hot_replica_count: %d\n",
3604df
+                                 count, volinfo->tier_info.hot_replica_count);
3604df
+                        fprintf (fp, "Volume%d.tier_info.promoted: %d\n",
3604df
+                                 count, volinfo->tier_info.promoted);
3604df
+                        fprintf (fp, "Volume%d.tier_info.demoted: %d\n",
3604df
+                                 count, volinfo->tier_info.demoted);
3604df
+                }
3604df
+
3604df
+                if (volinfo->rep_brick.src_brick && volinfo->rep_brick.dst_brick) {
3604df
+                        fprintf (fp, "Volume%d.replace_brick.src: %s:%s\n", count,
3604df
+                                 volinfo->rep_brick.src_brick->hostname,
3604df
+                                 volinfo->rep_brick.src_brick->path);
3604df
+                        fprintf (fp, "Volume%d.replace_brick.dest: %s:%s\n", count,
3604df
+                                 volinfo->rep_brick.dst_brick->hostname,
3604df
+                                 volinfo->rep_brick.dst_brick->path);
3604df
+                }
3604df
+
3604df
+                fprintf (fp, "\n");
3604df
+        }
3604df
+
3604df
+        count = 0;
3604df
+
3604df
+        fprintf (fp, "\n[Services]\n");
3604df
+
3604df
+        if (priv->shd_svc.inited) {
3604df
+                fprintf (fp, "svc%d.name: %s\n", ++count, priv->shd_svc.name);
3604df
+                fprintf (fp, "svc%d.online_status: %s\n\n", count,
3604df
+                         priv->shd_svc.online ? "Online" : "Offline");
3604df
+        }
3604df
+
3604df
+        if (priv->nfs_svc.inited) {
3604df
+                fprintf (fp, "svc%d.name: %s\n", ++count, priv->nfs_svc.name);
3604df
+                fprintf (fp, "svc%d.online_status: %s\n\n", count,
3604df
+                         priv->nfs_svc.online ? "Online" : "Offline");
3604df
+        }
3604df
+
3604df
+        if (priv->bitd_svc.inited) {
3604df
+                fprintf (fp, "svc%d.name: %s\n", ++count, priv->bitd_svc.name);
3604df
+                fprintf (fp, "svc%d.online_status: %s\n\n", count,
3604df
+                         priv->bitd_svc.online ? "Online" : "Offline");
3604df
+        }
3604df
+
3604df
+        if (priv->scrub_svc.inited) {
3604df
+                fprintf (fp, "svc%d.name: %s\n", ++count, priv->scrub_svc.name);
3604df
+                fprintf (fp, "svc%d.online_status: %s\n\n", count,
3604df
+                         priv->scrub_svc.online ? "Online" : "Offline");
3604df
+        }
3604df
+
3604df
+        if (priv->quotad_svc.inited) {
3604df
+                fprintf (fp, "svc%d.name: %s\n", ++count, priv->quotad_svc.name);
3604df
+                fprintf (fp, "svc%d.online_status: %s\n\n", count,
3604df
+                         priv->quotad_svc.online ? "Online" : "Offline");
3604df
+        }
3604df
+
3604df
+        fprintf (fp, "\n[Misc]\n");
3604df
+        if (priv->pmap) {
3604df
+                fprintf (fp, "Base port: %d\n", priv->pmap->base_port);
3604df
+                fprintf (fp, "Last allocated port: %d\n",
3604df
+                         priv->pmap->last_alloc);
3604df
+        }
3604df
+out:
3604df
+
3604df
+        if (fp)
3604df
+                fclose(fp);
3604df
+
3604df
+        rsp.op_ret = ret;
3604df
+        rsp.op_errstr = err_str;
3604df
+
3604df
+        ret = dict_allocate_and_serialize (dict, &rsp.dict.dict_val,
3604df
+                                           &rsp.dict.dict_len);
3604df
+        glusterd_to_cli (req, &rsp, NULL, 0, NULL,
3604df
+                         (xdrproc_t)xdr_gf_cli_rsp, dict);
3604df
+
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+static int
3604df
+__glusterd_handle_get_state (rpcsvc_request_t *req)
3604df
+{
3604df
+        int32_t                         ret = -1;
3604df
+        gf_cli_req                      cli_req = {{0,},};
3604df
+        dict_t                          *dict = NULL;
3604df
+        char                            err_str[2048] = {0,};
3604df
+        xlator_t                        *this = NULL;
3604df
+
3604df
+        this = THIS;
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, this, out);
3604df
+        GF_VALIDATE_OR_GOTO (this->name, req, out);
3604df
+
3604df
+        ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
3604df
+        if (ret < 0) {
3604df
+                snprintf (err_str, sizeof (err_str), "Failed to decode "
3604df
+                          "request received from cli");
3604df
+                gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                        GD_MSG_REQ_DECODE_FAIL, "%s", err_str);
3604df
+                req->rpc_err = GARBAGE_ARGS;
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        if (cli_req.dict.dict_len) {
3604df
+                /* Unserialize the dictionary */
3604df
+                dict  = dict_new ();
3604df
+
3604df
+                ret = dict_unserialize (cli_req.dict.dict_val,
3604df
+                                        cli_req.dict.dict_len,
3604df
+                                        &dict);
3604df
+                if (ret < 0) {
3604df
+                        gf_msg (this->name, GF_LOG_ERROR, 0,
3604df
+                                GD_MSG_DICT_UNSERIALIZE_FAIL,
3604df
+                                "failed to "
3604df
+                                "unserialize req-buffer to dictionary");
3604df
+                        snprintf (err_str, sizeof (err_str), "Unable to decode"
3604df
+                                  " the command");
3604df
+                        goto out;
3604df
+                } else {
3604df
+                        dict->extra_stdfree = cli_req.dict.dict_val;
3604df
+                }
3604df
+        }
3604df
+
3604df
+        gf_msg (this->name, GF_LOG_INFO, 0, GD_MSG_DAEMON_STATE_REQ_RCVD,
3604df
+                "Received request to get state for glusterd");
3604df
+
3604df
+        ret = glusterd_get_state (req, dict);
3604df
+
3604df
+out:
3604df
+        if (dict)
3604df
+                dict_unref (dict);
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int
3604df
+glusterd_handle_get_state (rpcsvc_request_t *req)
3604df
+{
3604df
+        return glusterd_big_locked_handler (req,
3604df
+                                            __glusterd_handle_get_state);
3604df
+}
3604df
+
3604df
 static int
3604df
 get_brickinfo_from_brickid (char *brickid, glusterd_brickinfo_t **brickinfo)
3604df
 {
3604df
@@ -5373,6 +5888,7 @@ rpcsvc_actor_t gd_svc_cli_actors[GLUSTER_CLI_MAXVALUE] = {
3604df
         [GLUSTER_CLI_GANESHA]            = { "GANESHA"  ,         GLUSTER_CLI_GANESHA,          glusterd_handle_ganesha_cmd,           NULL, 0, DRC_NA},
3604df
         [GLUSTER_CLI_GET_VOL_OPT]        = {"GET_VOL_OPT",        GLUSTER_CLI_GET_VOL_OPT,      glusterd_handle_get_vol_opt,           NULL, 0, DRC_NA},
3604df
         [GLUSTER_CLI_BITROT]             = {"BITROT",             GLUSTER_CLI_BITROT,           glusterd_handle_bitrot,                NULL, 0, DRC_NA},
3604df
+        [GLUSTER_CLI_GET_STATE]          = {"GET_STATE",          GLUSTER_CLI_GET_STATE,        glusterd_handle_get_state,             NULL, 0, DRC_NA},
3604df
 };
3604df
 
3604df
 struct rpcsvc_program gd_svc_cli_prog = {
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-messages.h b/xlators/mgmt/glusterd/src/glusterd-messages.h
3604df
index 2c76dbf..af492e0 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-messages.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-messages.h
3604df
@@ -41,7 +41,7 @@
3604df
 
3604df
 #define GLUSTERD_COMP_BASE      GLFS_MSGID_GLUSTERD
3604df
 
3604df
-#define GLFS_NUM_MESSAGES       583
3604df
+#define GLFS_NUM_MESSAGES       585
3604df
 
3604df
 #define GLFS_MSGID_END          (GLUSTERD_COMP_BASE + GLFS_NUM_MESSAGES + 1)
3604df
 /* Messaged with message IDs */
3604df
@@ -4689,6 +4689,7 @@
3604df
  */
3604df
 #define GD_MSG_MNTBROKER_LABEL_NULL                (GLUSTERD_COMP_BASE + 580)
3604df
 
3604df
+
3604df
 /*!
3604df
  * @messageid
3604df
  * @diagnosis
3604df
@@ -4713,6 +4714,22 @@
3604df
  */
3604df
 #define GD_MSG_SYSCALL_FAIL                          (GLUSTERD_COMP_BASE + 583)
3604df
 
3604df
+/*!
3604df
+ * @messageid
3604df
+ * @diagnosis
3604df
+ * @recommendation
3604df
+ *
3604df
+ */
3604df
+#define GD_MSG_DAEMON_STATE_REQ_RCVD              (GLUSTERD_COMP_BASE + 584)
3604df
+
3604df
+/*!
3604df
+ * @messageid
3604df
+ * @diagnosis
3604df
+ * @recommendation
3604df
+ *
3604df
+ */
3604df
+#define GD_MSG_STATE_STR_GET_FAILED               (GLUSTERD_COMP_BASE + 585)
3604df
+
3604df
 /*------------*/
3604df
 #define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
3604df
 #endif /* !_GLUSTERD_MESSAGES_H_ */
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c
3604df
index 72d6b17..509efb7 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-peer-utils.c
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.c
3604df
@@ -393,6 +393,57 @@ gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo)
3604df
         return peerinfo->uuid_str;
3604df
 }
3604df
 
3604df
+int
3604df
+gd_peer_state_str (glusterd_peerinfo_t *peerinfo, char *state_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, peerinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, state_str, out);
3604df
+
3604df
+        switch (peerinfo->state.state) {
3604df
+        case GD_FRIEND_STATE_DEFAULT:
3604df
+                gf_asprintf (&state_str, "%s", "default");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_REQ_SENT:
3604df
+                gf_asprintf (&state_str, "%s", "request sent");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_REQ_RCVD:
3604df
+                gf_asprintf (&state_str, "%s", "request received");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_BEFRIENDED:
3604df
+                gf_asprintf (&state_str, "%s", "befriended");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_REQ_ACCEPTED:
3604df
+                gf_asprintf (&state_str, "%s", "request accepted");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_REQ_SENT_RCVD:
3604df
+                gf_asprintf (&state_str, "%s", "request sent received");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_REJECTED:
3604df
+                gf_asprintf (&state_str, "%s", "rejected");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_UNFRIEND_SENT:
3604df
+                gf_asprintf (&state_str, "%s", "unfriend sent");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_PROBE_RCVD:
3604df
+                gf_asprintf (&state_str, "%s", "probe received");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_CONNECTED_RCVD:
3604df
+                gf_asprintf (&state_str, "%s", "connected received");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_CONNECTED_ACCEPTED:
3604df
+                gf_asprintf (&state_str, "%s", "connected accepted");
3604df
+                break;
3604df
+        case GD_FRIEND_STATE_MAX:
3604df
+                goto out;
3604df
+        }
3604df
+
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
 gf_boolean_t
3604df
 glusterd_are_all_peers_up ()
3604df
 {
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-peer-utils.h b/xlators/mgmt/glusterd/src/glusterd-peer-utils.h
3604df
index 9332cf2..ee78b03 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-peer-utils.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-peer-utils.h
3604df
@@ -42,6 +42,9 @@ glusterd_uuid_to_hostname (uuid_t uuid);
3604df
 char*
3604df
 gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo);
3604df
 
3604df
+int
3604df
+gd_peer_state_str (glusterd_peerinfo_t *peerinfo, char *state_str);
3604df
+
3604df
 gf_boolean_t
3604df
 glusterd_are_all_peers_up ();
3604df
 
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
3604df
index a4660c7..2fa9a59 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
3604df
@@ -4087,3 +4087,39 @@ gd_get_snap_conf_values_if_present (dict_t *dict, uint64_t *sys_hard_limit,
3604df
                         GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT);
3604df
         }
3604df
 }
3604df
+
3604df
+int
3604df
+glusterd_get_snap_status_str (glusterd_snap_t *snapinfo, char *snap_status_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, snapinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, snap_status_str, out);
3604df
+
3604df
+        switch (snapinfo->snap_status) {
3604df
+        case GD_SNAP_STATUS_NONE:
3604df
+                sprintf (snap_status_str, "%s", "none");
3604df
+                break;
3604df
+        case GD_SNAP_STATUS_INIT:
3604df
+                sprintf (snap_status_str, "%s", "init");
3604df
+                break;
3604df
+        case GD_SNAP_STATUS_IN_USE:
3604df
+                sprintf (snap_status_str, "%s", "in_use");
3604df
+                break;
3604df
+        case GD_SNAP_STATUS_DECOMMISSION:
3604df
+                sprintf (snap_status_str, "%s", "decommissioned");
3604df
+                break;
3604df
+        case GD_SNAP_STATUS_UNDER_RESTORE:
3604df
+                sprintf (snap_status_str, "%s", "under_restore");
3604df
+                break;
3604df
+        case GD_SNAP_STATUS_RESTORED:
3604df
+                sprintf (snap_status_str, "%s", "restored");
3604df
+                break;
3604df
+        default:
3604df
+                goto out;
3604df
+        }
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h
3604df
index c0e7e8e..b964a43 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h
3604df
@@ -161,6 +161,8 @@ glusterd_is_snap_soft_limit_reached (glusterd_volinfo_t *volinfo,
3604df
 void
3604df
 gd_get_snap_conf_values_if_present (dict_t *opts, uint64_t *sys_hard_limit,
3604df
                                     uint64_t *sys_soft_limit);
3604df
+int
3604df
+glusterd_get_snap_status_str (glusterd_snap_t *snapinfo, char *snap_status_str);
3604df
 
3604df
 #endif
3604df
 
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
3604df
index 44c9284..66c8b63 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
3604df
@@ -59,6 +59,7 @@
3604df
 #include "glusterd-bitd-svc.h"
3604df
 #include "glusterd-server-quorum.h"
3604df
 #include "quota-common-utils.h"
3604df
+#include "common-utils.h"
3604df
 
3604df
 #include "xdr-generic.h"
3604df
 #include <sys/resource.h>
3604df
@@ -11219,6 +11220,199 @@ glusterd_is_volume_started (glusterd_volinfo_t  *volinfo)
3604df
         return (volinfo->status == GLUSTERD_STATUS_STARTED);
3604df
 }
3604df
 
3604df
+int
3604df
+glusterd_volume_get_type_str (glusterd_volinfo_t *volinfo, char **voltype_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+        int type = 0;
3604df
+        int brick_count = 0;
3604df
+        int dist_count = 0;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+
3604df
+        type = get_vol_type (volinfo->type, volinfo->brick_count,
3604df
+                             volinfo->dist_leaf_count);
3604df
+
3604df
+        *voltype_str = vol_type_str[type];
3604df
+
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int
3604df
+glusterd_volume_get_status_str (glusterd_volinfo_t *volinfo, char *status_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, status_str, out);
3604df
+
3604df
+        switch (volinfo->status) {
3604df
+        case GLUSTERD_STATUS_NONE:
3604df
+                sprintf (status_str, "%s", "Created");
3604df
+                break;
3604df
+        case GLUSTERD_STATUS_STARTED:
3604df
+                sprintf (status_str, "%s", "Started");
3604df
+                break;
3604df
+        case GLUSTERD_STATUS_STOPPED:
3604df
+                sprintf (status_str, "%s", "Stopped");
3604df
+                break;
3604df
+        default:
3604df
+                goto out;
3604df
+
3604df
+        }
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int
3604df
+glusterd_volume_get_transport_type_str (glusterd_volinfo_t *volinfo,
3604df
+                                        char *transport_type_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, transport_type_str, out);
3604df
+
3604df
+        switch (volinfo->transport_type) {
3604df
+        case GF_TRANSPORT_TCP:
3604df
+                sprintf (transport_type_str, "%s", "tcp");
3604df
+                break;
3604df
+        case GF_TRANSPORT_RDMA:
3604df
+                sprintf (transport_type_str, "%s", "rdma");
3604df
+                break;
3604df
+        case GF_TRANSPORT_BOTH_TCP_RDMA:
3604df
+                sprintf (transport_type_str, "%s", "tcp_rdma_both");
3604df
+                break;
3604df
+        default:
3604df
+                goto out;
3604df
+
3604df
+        }
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int
3604df
+glusterd_volume_get_quorum_status_str (glusterd_volinfo_t *volinfo,
3604df
+                                       char *quorum_status_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, quorum_status_str, out);
3604df
+
3604df
+        switch (volinfo->quorum_status) {
3604df
+        case NOT_APPLICABLE_QUORUM:
3604df
+                sprintf (quorum_status_str, "%s", "not_applicable");
3604df
+                break;
3604df
+        case MEETS_QUORUM:
3604df
+                sprintf (quorum_status_str, "%s", "meets");
3604df
+                break;
3604df
+        case DOESNT_MEET_QUORUM:
3604df
+                sprintf (quorum_status_str, "%s", "does_not_meet");
3604df
+                break;
3604df
+        default:
3604df
+                goto out;
3604df
+
3604df
+        }
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int
3604df
+glusterd_volume_get_rebalance_status_str (glusterd_volinfo_t *volinfo,
3604df
+                                          char *rebal_status_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, rebal_status_str, out);
3604df
+
3604df
+        switch (volinfo->rebal.defrag_status) {
3604df
+        case GF_DEFRAG_STATUS_NOT_STARTED:
3604df
+                sprintf (rebal_status_str, "%s", "not_started");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_STARTED:
3604df
+                sprintf (rebal_status_str, "%s", "started");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_STOPPED:
3604df
+                sprintf (rebal_status_str, "%s", "stopped");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_COMPLETE:
3604df
+                sprintf (rebal_status_str, "%s", "completed");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_FAILED:
3604df
+                sprintf (rebal_status_str, "%s", "failed");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_LAYOUT_FIX_STARTED:
3604df
+                sprintf (rebal_status_str, "%s", "layout_fix_started");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_LAYOUT_FIX_STOPPED:
3604df
+                sprintf (rebal_status_str, "%s", "layout_fix_stopped");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_LAYOUT_FIX_COMPLETE:
3604df
+                sprintf (rebal_status_str, "%s", "layout_fix_complete");
3604df
+                break;
3604df
+        case GF_DEFRAG_STATUS_LAYOUT_FIX_FAILED:
3604df
+                sprintf (rebal_status_str, "%s", "layout_fix_failed");
3604df
+                break;
3604df
+        default:
3604df
+                goto out;
3604df
+        }
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int
3604df
+glusterd_volume_get_hot_tier_type_str (glusterd_volinfo_t *volinfo,
3604df
+                                       char **hot_tier_type_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+        int hot_tier_type = 0;
3604df
+        int hot_dist_count = 0;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, hot_tier_type_str, out);
3604df
+
3604df
+        hot_dist_count = volinfo->tier_info.hot_replica_count ?
3604df
+                                volinfo->tier_info.hot_replica_count : 1;
3604df
+
3604df
+        hot_tier_type = get_vol_type (volinfo->tier_info.hot_type, hot_dist_count,
3604df
+                                      volinfo->tier_info.hot_brick_count);
3604df
+
3604df
+        *hot_tier_type_str = vol_type_str[hot_tier_type];
3604df
+
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
+int
3604df
+glusterd_volume_get_cold_tier_type_str (glusterd_volinfo_t *volinfo,
3604df
+                                        char **cold_tier_type_str)
3604df
+{
3604df
+        int ret = -1;
3604df
+        int cold_tier_type = 0;
3604df
+
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, volinfo, out);
3604df
+        GF_VALIDATE_OR_GOTO (THIS->name, cold_tier_type_str, out);
3604df
+
3604df
+        cold_tier_type = get_vol_type (volinfo->tier_info.cold_type,
3604df
+                                       volinfo->tier_info.cold_dist_leaf_count,
3604df
+                                       volinfo->tier_info.cold_brick_count);
3604df
+
3604df
+        *cold_tier_type_str = vol_type_str[cold_tier_type];
3604df
+
3604df
+        ret = 0;
3604df
+out:
3604df
+        return ret;
3604df
+}
3604df
+
3604df
 /* This function will insert the element to the list in a order.
3604df
    Order will be based on the compare function provided as a input.
3604df
    If element to be inserted in ascending order compare should return:
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
3604df
index f4c4138..ca07efd 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
3604df
@@ -678,6 +678,32 @@ glusterd_nfs_pmap_deregister ();
3604df
 gf_boolean_t
3604df
 glusterd_is_volume_started (glusterd_volinfo_t  *volinfo);
3604df
 
3604df
+int
3604df
+glusterd_volume_get_type_str (glusterd_volinfo_t *volinfo, char **vol_type_str);
3604df
+
3604df
+int
3604df
+glusterd_volume_get_status_str (glusterd_volinfo_t *volinfo, char *status_str);
3604df
+
3604df
+int
3604df
+glusterd_volume_get_transport_type_str (glusterd_volinfo_t *volinfo,
3604df
+                                        char *transport_type_str);
3604df
+
3604df
+int
3604df
+glusterd_volume_get_quorum_status_str (glusterd_volinfo_t *volinfo,
3604df
+                                       char *quorum_status_str);
3604df
+
3604df
+int
3604df
+glusterd_volume_get_rebalance_status_str (glusterd_volinfo_t *volinfo,
3604df
+                                          char *rebal_status_str);
3604df
+
3604df
+int
3604df
+glusterd_volume_get_hot_tier_type_str (glusterd_volinfo_t *volinfo,
3604df
+                                       char **hot_tier_type_str);
3604df
+
3604df
+int
3604df
+glusterd_volume_get_cold_tier_type_str (glusterd_volinfo_t *volinfo,
3604df
+                                        char **cold_tier_type_str);
3604df
+
3604df
 void
3604df
 glusterd_list_add_order (struct cds_list_head *new, struct cds_list_head *head,
3604df
                         int (*compare)(struct cds_list_head *,
3604df
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
3604df
index 3aaedbc..29aaf64 100644
3604df
--- a/xlators/mgmt/glusterd/src/glusterd.h
3604df
+++ b/xlators/mgmt/glusterd/src/glusterd.h
3604df
@@ -55,6 +55,7 @@
3604df
 #define GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT 90
3604df
 #define GLUSTERD_SNAPS_MAX_SOFT_LIMIT_PERCENT 100
3604df
 #define GLUSTERD_SERVER_QUORUM "server"
3604df
+#define STATUS_STRLEN   128
3604df
 
3604df
 #define FMTSTR_CHECK_VOL_EXISTS "Volume %s does not exist"
3604df
 #define FMTSTR_RESOLVE_BRICK "Could not find peer on which brick %s:%s resides"
3604df
-- 
3604df
1.7.1
3604df