diff options
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 61 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 145 | ||||
| -rw-r--r-- | cli/src/cli-xml-output.c | 78 | ||||
| -rw-r--r-- | cli/src/cli.h | 3 | ||||
| -rw-r--r-- | doc/gluster.8 | 3 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/protocol-common.h | 1 | ||||
| -rw-r--r-- | tests/bugs/bug-983317.t | 25 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 243 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 278 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 9 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 139 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.h | 86 | 
12 files changed, 915 insertions, 156 deletions
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index c743b8bc9f0..52b5adb6129 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -2347,6 +2347,60 @@ out:          return ret;  } + +int +cli_cmd_volume_getopt_cbk (struct cli_state *state, struct cli_cmd_word *word, +                        const char **words, int wordcount) +{ +        int                   ret       = -1; +        rpc_clnt_procedure_t *proc      = NULL; +        call_frame_t         *frame     = NULL; +        dict_t               *options   = NULL; +        int                   sent      = 0; +        int                   parse_err = 0; +        cli_local_t          *local     = NULL; + +        if (wordcount != 4) { +                cli_usage_out (word->pattern); +                parse_err = 1; +                goto out; +        } + +        frame = create_frame (THIS, THIS->ctx->pool); +        if (!frame) +                goto out; + +        options = dict_new (); +        if (!options) +                goto out; + +        ret = dict_set_str (options, "volname", (char *)words[2]); +        if (ret) +                goto out; + +        ret = dict_set_str (options, "key", (char *)words[3]); +        if (ret) +                goto out; + +        proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GET_VOL_OPT]; + +        CLI_LOCAL_INIT (local, words, frame, options); + +        if (proc->fn) +                ret = proc->fn (frame, THIS, options); + +out: +        if (ret) { +                cli_cmd_sent_status_get (&sent); +                if ((sent == 0) && (parse_err == 0)) +                        cli_err ("Volume get option failed"); +        } +        CLI_STACK_DESTROY (frame); +        if (options) +                dict_unref (options); +        return ret; +} +  struct cli_cmd volume_cmds[] = {          { "volume info [all|<VOLNAME>]",            cli_cmd_volume_info_cbk, @@ -2473,8 +2527,11 @@ struct cli_cmd volume_cmds[] = {          },          {"volume barrier <VOLNAME> {enable|disable}",           cli_cmd_volume_barrier_cbk, -         "Barrier/unbarrier file operations on a volume"}, - +         "Barrier/unbarrier file operations on a volume" +        }, +        {"volume get <VOLNAME> <key|all>", +         cli_cmd_volume_getopt_cbk, +         "Get the value of the all options or given option for volume <VOLNAME>"},          { NULL, NULL, NULL }  }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index bbb7e56590a..ed3faf70c39 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -9272,6 +9272,7 @@ out:          cli_cmd_broadcast_response (ret);          return ret;  } +  int  gf_cli_barrier_volume (call_frame_t *frame, xlator_t *this, void *data)  { @@ -9295,6 +9296,149 @@ out:          return ret;  } +int32_t +gf_cli_get_vol_opt_cbk (struct rpc_req *req, struct iovec *iov, int count, +                        void *myframe) +{ +        gf_cli_rsp   rsp  = {0,}; +        int          ret  = -1; +        dict_t      *dict = NULL; +        char        *key  = NULL; +        char        *value = NULL; +        char         msg[1024] = {0,}; +        int          i     = 0; +        char         dict_key[50] = {0,}; + +        if (-1 == req->rpc_status) +                goto out; +        ret = xdr_to_generic (*iov, &rsp, +                              (xdrproc_t)xdr_gf_cli_rsp); +        if (ret < 0) { +                gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR, +                        "Failed to decode xdr response"); +                goto out; +        } +        gf_log ("cli", GF_LOG_DEBUG, "Received response to get volume option"); + +        if (rsp.op_ret) { +                if (strcmp (rsp.op_errstr, "")) +                        snprintf (msg, sizeof (msg), "volume get option: " +                                  "failed: %s", rsp.op_errstr); +                else +                        snprintf (msg, sizeof (msg), "volume get option: " +                                  "failed"); + +                if (global_state->mode & GLUSTER_MODE_XML) { +                        ret = cli_xml_output_str ("volGetopts", msg, rsp.op_ret, +                                          rsp.op_errno, rsp.op_errstr); +                        if (ret) { +                                gf_log ("cli", GF_LOG_ERROR, +                                        "Error outputting to xml"); +                        } +                } else { +                        cli_err (msg); +                } +                ret = 0; /* setting ret to 0 ensures we do not end up displaying +                            double error messages */ +                goto out; +        } +        dict = dict_new (); + +        if (!dict) { +                ret = -1; +                goto out; +        } + +        ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, +                        "Failed rsp_dict unserialization"); +                goto out; +        } + +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_vol_getopts (dict, rsp.op_ret, +                                                  rsp.op_errno, +                                                  rsp.op_errstr); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "xml output generation " +                                "failed"); +                        ret = 0; +                } +                goto out; +        } + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to retrieve count " +                        "from the dictionary"); +                goto out; +        } +        if (count <= 0) { +                gf_log ("cli", GF_LOG_ERROR, "Value of count :%d is " +                        "invalid", count); +                ret = -1; +                goto out; +        } + +        cli_out ("%-40s%-40s", "Option", "Value"); +        cli_out ("%-40s%-40s", "------", "-----"); +        for (i=1; i<=count; i++) { +                sprintf (dict_key, "key%d", i); +                ret = dict_get_str (dict, dict_key, &key); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to" +                                " retrieve %s from the " +                                "dictionary", dict_key); +                        goto out; +                } +                sprintf (dict_key, "value%d", i); +                ret = dict_get_str (dict, dict_key, &value); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to " +                                "retrieve key value for %s from" +                                "the dictionary", dict_key); +                        goto out; +                } +                cli_out ("%-40s%-40s", key, value); +        } + +out: +        if (ret) { +                cli_out ("volume get option failed. Check the cli/glusterd log " +                         "file for more details"); +        } +        if (dict) +                dict_unref (dict); +        free (rsp.op_errstr); +        free (rsp.dict.dict_val); +        cli_cmd_broadcast_response (ret); +        return ret; +} + +int +gf_cli_get_vol_opt (call_frame_t *frame, xlator_t *this, void *data) +{ +        gf_cli_req  req     = {{0,}}; +        dict_t     *options = NULL; +        int         ret     = -1; + +        if (!frame || !this || !data) +                goto out; + +        options = data; + +        ret = cli_to_glusterd (&req, frame, gf_cli_get_vol_opt_cbk, +                               (xdrproc_t)xdr_gf_cli_req, options, +                               GLUSTER_CLI_GET_VOL_OPT, this, cli_rpc_prog, +                               NULL); +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + +        GF_FREE (req.dict.dict_val); +        return ret; +} +  int  cli_to_glusterd (gf_cli_req *req, call_frame_t *frame,                   fop_cbk_fn_t cbkfn, xdrproc_t xdrproc, dict_t *dict, @@ -9408,6 +9552,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {          [GLUSTER_CLI_SYS_EXEC]         = {"SYS_EXEC", gf_cli_sys_exec},          [GLUSTER_CLI_SNAP]             = {"SNAP", gf_cli_snapshot},          [GLUSTER_CLI_BARRIER_VOLUME]   = {"BARRIER VOLUME", gf_cli_barrier_volume}, +        [GLUSTER_CLI_GET_VOL_OPT]      = {"GET_VOL_OPT", gf_cli_get_vol_opt},  };  struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c index da178d903e8..840ff32e52b 100644 --- a/cli/src/cli-xml-output.c +++ b/cli/src/cli-xml-output.c @@ -5693,3 +5693,81 @@ out:  #endif /* HAVE_LIB_XML */  } +int +cli_xml_output_vol_getopts (dict_t *dict, int op_ret, int op_errno, +                            char *op_errstr) +{ +#if (HAVE_LIB_XML) +        int                     i = 0; +        int                     ret = -1; +        int                     count = 0; +        xmlTextWriterPtr        writer = NULL; +        xmlDocPtr               doc = NULL; +        char                    *key = NULL; +        char                    *value = NULL; +        char                    dict_key[50] = {0,}; + +        ret = cli_begin_xml_output (&writer, &doc); +        if (ret) +                goto out; + +        ret = cli_xml_output_common (writer, op_ret, op_errno, op_errstr); +        if (ret) +                goto out; + +        ret = xmlTextWriterStartElement (writer, (xmlChar *)"volGetopts"); +        XML_RET_CHECK_AND_GOTO (ret, out); + +        ret = dict_get_int32 (dict, "count", &count); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to retrieve count " +                        "from the dictionary"); +                goto out; +        } +        if (count <= 0) { +                gf_log ("cli", GF_LOG_ERROR, "Value of count :%d is " +                        "invalid", count); +                ret = -1; +                goto out; +        } +        ret = xmlTextWriterWriteFormatElement (writer, (xmlChar *)"count", +                                               "%d", count); + +        XML_RET_CHECK_AND_GOTO (ret, out); + +        for (i=1; i<=count; i++) { +                sprintf (dict_key, "key%d", i); +                ret = dict_get_str (dict, dict_key, &key); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to" +                                " retrieve %s from the " +                                "dictionary", dict_key); +                        goto out; +                } +                sprintf (dict_key, "value%d", i); +                ret = dict_get_str (dict, dict_key, &value); +                if (ret) { +                        gf_log ("cli", GF_LOG_ERROR, "Failed to " +                                "retrieve key value for %s from" +                                "the dictionary", dict_key); +                        goto out; +                } +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"Option", +                                                       "%s", key); +                XML_RET_CHECK_AND_GOTO (ret, out); + +                ret = xmlTextWriterWriteFormatElement (writer, +                                                       (xmlChar *)"Value", +                                                       "%s", value); +                XML_RET_CHECK_AND_GOTO (ret, out); +        } +        ret = cli_end_xml_output (writer, doc); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +#else +        return 0; +#endif /* HAVE_LIB_XML */ +} diff --git a/cli/src/cli.h b/cli/src/cli.h index b49cced70f0..89aedc5697d 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -408,4 +408,7 @@ int32_t  cli_cmd_snapshot_parse (const char **words, int wordcount, dict_t **options,                          struct cli_state *state); +int +cli_xml_output_vol_getopts (dict_t *dict, int op_ret, int op_errno, +                             char *op_errstr);  #endif /* __CLI_H__ */ diff --git a/doc/gluster.8 b/doc/gluster.8 index e45c011b189..ae26c1820c2 100644 --- a/doc/gluster.8 +++ b/doc/gluster.8 @@ -55,6 +55,9 @@ Rename the specified volume.  \fB\ volume set <VOLNAME> <OPTION> <PARAMETER> [<OPTION> <PARAMETER>] ... \fR  Set the volume options.  .TP +\fB\ volume get <VOLNAME> <OPTION/all>\fR +Get the volume options. +.TP  \fB\ volume help \fR  Display help for the volume command.  .SS "Brick Commands" diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index b3e677afd17..096bcc8d9d1 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -175,6 +175,7 @@ enum gluster_cli_procnum {          GLUSTER_CLI_SYS_EXEC,          GLUSTER_CLI_SNAP,          GLUSTER_CLI_BARRIER_VOLUME, +        GLUSTER_CLI_GET_VOL_OPT,          GLUSTER_CLI_MAXVALUE,  }; diff --git a/tests/bugs/bug-983317.t b/tests/bugs/bug-983317.t new file mode 100644 index 00000000000..7355cbaafd1 --- /dev/null +++ b/tests/bugs/bug-983317.t @@ -0,0 +1,25 @@ +#!/bin/bash + +. $(dirname $0)/../include.rc +. $(dirname $0)/../volume.rc + +cleanup; +TEST glusterd +TEST pidof glusterd + +TEST $CLI volume create $V0 $H0:$B0/$V0 + +# Set a volume option +TEST $CLI volume set $V0 open-behind on +TEST $CLI volume start $V0 + +# Execute volume get without having an explicit option, this should fail +TEST ! $CLI volume get $V0 + +# Execute volume get with an explicit option +TEST $CLI volume get $V0 open-behind + +# Execute volume get with 'all" +TEST $CLI volume get $V0 all + +cleanup; diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 8e4071221de..9ee26b52160 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -13,7 +13,6 @@  #endif  #include <inttypes.h> -  #include "globals.h"  #include "glusterfs.h"  #include "compat.h" @@ -4025,6 +4024,245 @@ glusterd_handle_barrier (rpcsvc_request_t *req)  {          return glusterd_big_locked_handler (req, __glusterd_handle_barrier);  } + +int32_t +glusterd_get_volume_opts (rpcsvc_request_t *req, dict_t *dict) +{ +        int32_t                   ret = -1; +        int32_t                   count = 1; +        int                       exists = 0; +        char                      *key = NULL; +        char                      *orig_key = NULL; +        char                      *key_fixed = NULL; +        char                      *volname = NULL; +        char                      err_str[2048] = {0,}; +        char                      dict_key[50] = {0,}; +        xlator_t                  *this = NULL; +        glusterd_conf_t           *priv = NULL; +        glusterd_volinfo_t        *volinfo = NULL; +        gf_cli_rsp                rsp = {0,}; +        char                      op_version_buff[10] = {0,}; + +        this = THIS; +        GF_ASSERT (this); + +        priv = this->private; +        GF_ASSERT (priv); + +        GF_ASSERT (req); +        GF_ASSERT (dict); + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                snprintf (err_str, sizeof (err_str), "Failed to get volume " +                          "name while handling get volume option command"); +                gf_log (this->name, GF_LOG_ERROR, "%s", err_str); +                goto out; +        } + +        ret = dict_get_str (dict, "key", &key); +        if (ret) { +                snprintf (err_str, sizeof (err_str), "Failed to get key " +                          "while handling get volume option for %s", volname); +                gf_log (this->name, GF_LOG_ERROR, "%s", err_str); +                goto out; +        } +        gf_log (this->name, GF_LOG_DEBUG, "Received get volume opt request for " +                "volume %s", volname); + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                snprintf (err_str, sizeof(err_str), +                          FMTSTR_CHECK_VOL_EXISTS, volname); +                gf_log (this->name, GF_LOG_ERROR, FMTSTR_CHECK_VOL_EXISTS, +                        volname); +                goto out; +        } +        if (strcmp(key, "all")) { +                exists = glusterd_check_option_exists (key, &key_fixed); +                if (!exists) { +                        snprintf (err_str, sizeof (err_str), "Option " +                                  "with name: %s does not exist", key); +                        gf_log (this->name, GF_LOG_ERROR, "%s", +                                err_str); +                        if (key_fixed) +                                snprintf (err_str + ret, +                                          sizeof (err_str) - ret, +                                          "Did you mean %s?", +                                          key_fixed); +                        ret = -1; +                        goto out; +                } +                if (key_fixed) { +                        orig_key = key; +                        key = key_fixed; +                } +                if (strcmp (key, "cluster.op-version") == 0) { +                        sprintf (dict_key, "key%d", count); +                        ret = dict_set_str(dict, dict_key, key); +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                       "set %s in dictionary", key); +                                goto out; +                        } +                        sprintf (dict_key, "value%d", count); +                        sprintf (op_version_buff, "%d", priv->op_version); +                        ret = dict_set_str (dict, dict_key, op_version_buff); +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                        "set value for key %s in dictionary", +                                        key); +                                goto out; +                        } +                } +                else if (strcmp (key, "config.memory-accounting") == 0) { +                        sprintf (dict_key, "key%d", count); +                        ret = dict_set_str(dict, dict_key, key); +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                       "set %s in dictionary", key); +                                goto out; +                        } +                        sprintf (dict_key, "value%d", count); + +                        if (volinfo->memory_accounting) +                                ret = dict_set_str(dict, dict_key,"Enabled"); +                        else +                                ret = dict_set_str(dict, dict_key,"Disabled"); +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                        "set value for key %s in dictionary", +                                        key); +                                goto out; +                        } +                } +                else if (strcmp (key, "config.transport") == 0) { +                        sprintf (dict_key, "key%d", count); +                        ret = dict_set_str(dict, dict_key, key); +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                        "set %s in dictionary", key); +                                goto out; +                        } +                        sprintf (dict_key, "value%d", count); + +                        if (volinfo->transport_type == GF_TRANSPORT_RDMA) +                                ret = dict_set_str(dict, dict_key,"rdma"); +                        else if (volinfo->transport_type == GF_TRANSPORT_TCP) +                                ret = dict_set_str(dict, dict_key,"tcp"); +                        else if (volinfo->transport_type == +                                 GF_TRANSPORT_BOTH_TCP_RDMA) +                                ret = dict_set_str(dict, dict_key,"tcp,rdma"); +                        else +                                ret = dict_set_str(dict, dict_key,"none"); + +                        if (ret) { +                                gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                        "set value for key %s in dictionary", +                                        key); +                                goto out; +                        } +                } +                else { +                        ret = glusterd_get_default_val_for_volopt (dict, +                                                                  _gf_false, +                                                                  key, orig_key, +                                                                  volinfo->dict, +                                                                  &rsp.op_errstr); +                        if (ret && !rsp.op_errstr) { +                                snprintf (err_str, sizeof(err_str), +                                          "Failed to fetch the value of" +                                          " %s, check log file for more" +                                          " details", key); +                        } +                } +        } else { +                /* Handle the "all" volume option request */ +                ret = glusterd_get_default_val_for_volopt (dict, _gf_true, NULL, +                                                           NULL, volinfo->dict, +                                                           &rsp.op_errstr); +                if (ret && !rsp.op_errstr) { +                        snprintf (err_str, sizeof(err_str), +                                  "Failed to fetch the value of all volume " +                                  "options, check log file for more details"); +                } + +        } + +out: +        if (ret) { +                if (!rsp.op_errstr) +                        rsp.op_errstr = err_str; +                rsp.op_ret =  ret; +        } +        else { +                rsp.op_errstr = ""; +                rsp.op_ret = 0; +        } + +        ret = dict_allocate_and_serialize (dict, &rsp.dict.dict_val, +                                           &rsp.dict.dict_len); + +        glusterd_submit_reply (req, &rsp, NULL, 0, NULL, +                               (xdrproc_t)xdr_gf_cli_rsp); +        return ret; +} + +int +__glusterd_handle_get_vol_opt (rpcsvc_request_t *req) +{ +        int32_t                         ret = -1; +        gf_cli_req                      cli_req = {{0,}}; +        dict_t                          *dict = NULL; +        char                            err_str[2048] = {0,}; +        xlator_t                        *this = NULL; + +        this = THIS; +        GF_ASSERT (this); + +        GF_ASSERT (req); + +        ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req); +        if (ret < 0) { +                snprintf (err_str, sizeof (err_str), "Failed to decode " +                          "request received from cli"); +                gf_log (this->name, GF_LOG_ERROR, "%s", err_str); +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        if (cli_req.dict.dict_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); + +                ret = dict_unserialize (cli_req.dict.dict_val, +                                        cli_req.dict.dict_len, +                                        &dict); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        snprintf (err_str, sizeof (err_str), "Unable to decode " +                                  "the command"); +                        goto out; +                } else { +                        dict->extra_stdfree = cli_req.dict.dict_val; +                } +        } +        ret = glusterd_get_volume_opts (req, dict); + +out: +        if (dict) +                dict_unref (dict); + +        return ret; +} + +int +glusterd_handle_get_vol_opt (rpcsvc_request_t *req) +{ +        return glusterd_big_locked_handler (req, __glusterd_handle_get_vol_opt); +}  static int  get_brickinfo_from_brickid (char *brickid, glusterd_brickinfo_t **brickinfo)  { @@ -4503,7 +4741,8 @@ rpcsvc_actor_t gd_svc_cli_actors[GLUSTER_CLI_MAXVALUE] = {          [GLUSTER_CLI_COPY_FILE]          = {"COPY_FILE",          GLUSTER_CLI_COPY_FILE,        glusterd_handle_copy_file,             NULL, 0, DRC_NA},          [GLUSTER_CLI_SYS_EXEC]           = {"SYS_EXEC",           GLUSTER_CLI_SYS_EXEC,         glusterd_handle_sys_exec,              NULL, 0, DRC_NA},          [GLUSTER_CLI_SNAP]               = {"SNAP",               GLUSTER_CLI_SNAP,             glusterd_handle_snapshot,              NULL, 0, DRC_NA}, -        [GLUSTER_CLI_BARRIER_VOLUME] = {"BARRIER_VOLUME", GLUSTER_CLI_BARRIER_VOLUME, glusterd_handle_barrier, NULL, 0, DRC_NA}, +        [GLUSTER_CLI_BARRIER_VOLUME]     = {"BARRIER_VOLUME",     GLUSTER_CLI_BARRIER_VOLUME,   glusterd_handle_barrier,               NULL, 0, DRC_NA}, +        [GLUSTER_CLI_GET_VOL_OPT]        = {"GET_VOL_OPT",        GLUSTER_CLI_GET_VOL_OPT,      glusterd_handle_get_vol_opt,           NULL, 0, DRC_NA},  };  struct rpcsvc_program gd_svc_cli_prog = { diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index f84bdbe7208..d8ad209caab 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -18,6 +18,11 @@  #else  #include "mntent_compat.h"  #endif +#include <dlfcn.h> +#if (HAVE_LIB_XML) +#include <libxml/encoding.h> +#include <libxml/xmlwriter.h> +#endif  #include "globals.h"  #include "glusterfs.h" @@ -46,6 +51,7 @@  #include "glusterd-syncop.h"  #include "glusterd-locks.h"  #include "glusterd-messages.h" +#include "glusterd-volgen.h"  #include "xdr-generic.h"  #include <sys/resource.h> @@ -80,6 +86,8 @@  #define CEILING_POS(X) (((X)-(int)(X)) > 0 ? (int)((X)+1) : (int)(X)) +extern struct volopt_map_entry glusterd_volopt_map[]; +  static glusterd_lock_t lock; @@ -13627,3 +13635,273 @@ out:          GF_FREE (mnt_pt);          return ret;  } + +int +glusterd_get_value_for_vme_entry (struct volopt_map_entry *vme, char **def_val) +{ +        int                      ret = -1; +        char                    *key = NULL; +        xlator_t                *this = NULL; +        char                    *descr = NULL; +        char                    *local_def_val = NULL; +        void                    *dl_handle = NULL; +        volume_opt_list_t        vol_opt_handle = {{0},}; + +        this = THIS; +        GF_ASSERT (this); + +        INIT_LIST_HEAD (&vol_opt_handle.list); + +        if (_get_xlator_opt_key_from_vme (vme, &key)) { +                gf_log (this->name, GF_LOG_ERROR, "Failed to get %s key from " +                        "volume option entry", vme->key); +                goto out; +        } + +        ret = xlator_volopt_dynload (vme->voltype, &dl_handle, &vol_opt_handle); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "xlator_volopt_dynload error " +                        "(%d)", ret); +                ret = -2; +                goto cont; +        } + +        ret = xlator_option_info_list (&vol_opt_handle,key, +                                       &local_def_val, &descr); +        if (ret) { +                /*Swallow Error if option not found*/ +                gf_log (this->name, GF_LOG_ERROR, "Failed to get option for %s " +                        "key", key); +                ret = -2; +                goto cont; +        } +        if (!local_def_val) +                local_def_val = "(null)"; + +        *def_val = gf_strdup (local_def_val); + +cont: +        if (dl_handle) { +                dlclose (dl_handle); +                dl_handle = NULL; +                vol_opt_handle.given_opt = NULL; +        } +        if (key) { +                _free_xlator_opt_key (key); +                key = NULL; +        } + +        if (ret) +                goto out; + +out: +        gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_get_default_val_for_volopt (dict_t *ctx, gf_boolean_t all_opts, +                                     char *input_key, char *orig_key, +                                     dict_t *vol_dict, char **op_errstr) +{ +        struct volopt_map_entry *vme = NULL; +        int                      ret = -1; +        int                      count = 0; +        char                     err_str[PATH_MAX] = ""; +        xlator_t                *this = NULL; +        char                    *def_val = NULL; +        char                     dict_key[50] = {0,}; +        gf_boolean_t             key_found = _gf_false; + +        this = THIS; +        GF_ASSERT (this); + +        GF_VALIDATE_OR_GOTO (this->name, vol_dict, out); + +        /* Check whether key is passed for a single option */ +        if (!all_opts && !input_key) { +                gf_log (this->name, GF_LOG_ERROR, "Key is NULL"); +                goto out; +        } + +        for (vme = &glusterd_volopt_map[0]; vme->key; vme++) { +                if (!all_opts && strcmp (vme->key, input_key)) +                        continue; + +                key_found = _gf_true; +                /* First look for the key in the vol_dict, if its not +                 * present then look for translator default value */ +                ret = dict_get_str (vol_dict, vme->key, &def_val); +                if (!def_val) { +                        if (vme->value) { +                                def_val = vme->value; +                        } else { +                                ret = glusterd_get_value_for_vme_entry +                                         (vme, &def_val); +                                if (!all_opts && ret) +                                        goto out; +                                else if (ret == -2) +                                        continue; +                        } +                } +                count++; +                sprintf (dict_key, "key%d", count); +                ret = dict_set_str(ctx, dict_key, vme->key); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                "set %s in dictionary", vme->key); +                        goto out; +                } +                sprintf (dict_key, "value%d", count); +                ret = dict_set_dynstr_with_alloc (ctx, dict_key, def_val); +                if (ret) { +                        gf_log (this->name, GF_LOG_ERROR, "Failed to " +                                "set %s for key %s in dictionary", def_val, +                                vme->key); +                        goto out; +                } +                def_val = NULL; +                if (!all_opts) +                        break; + +        } +        if (!all_opts && !key_found) +                goto out; + +        ret = dict_set_int32 (ctx, "count", count); +        if (ret) { +                gf_log (this->name, GF_LOG_ERROR, "Failed to set count " +                        "in dictionary"); +        } + +out: +        if (ret && !all_opts && !key_found) { +                snprintf (err_str, sizeof (err_str), +                          "option %s does not exist", orig_key); +                *op_errstr = gf_strdup (err_str); +        } +        gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_get_volopt_content (dict_t * ctx, gf_boolean_t xml_out) +{ +        void                    *dl_handle = NULL; +        volume_opt_list_t        vol_opt_handle = {{0},}; +        char                    *key = NULL; +        struct volopt_map_entry *vme = NULL; +        int                      ret = -1; +        char                    *def_val = NULL; +        char                    *descr = NULL; +        char                     output_string[51200] = {0, }; +        char                    *output = NULL; +        char                     tmp_str[2048] = {0, }; +#if (HAVE_LIB_XML) +        xmlTextWriterPtr         writer = NULL; +        xmlBufferPtr             buf = NULL; + +        if (xml_out) { +                ret = init_sethelp_xml_doc (&writer, &buf); +                if (ret) /*logging done in init_xml_lib*/ +                        goto out; +        } +#endif + +        INIT_LIST_HEAD (&vol_opt_handle.list); + +        for (vme = &glusterd_volopt_map[0]; vme->key; vme++) { + +                if ((vme->type == NO_DOC) || (vme->type == GLOBAL_NO_DOC)) +                        continue; + +                if (vme->description) { +                        descr = vme->description; +                        def_val = vme->value; +                } else { +                        if (_get_xlator_opt_key_from_vme (vme, &key)) { +                                gf_log ("glusterd", GF_LOG_DEBUG, "Failed to " +                                        "get %s key from volume option entry", +                                        vme->key); +                                goto out; /*Some error while geting key*/ +                        } + +                        ret = xlator_volopt_dynload (vme->voltype, +                                                     &dl_handle, +                                                     &vol_opt_handle); + +                        if (ret) { +                                gf_log ("glusterd", GF_LOG_DEBUG, +                                        "xlator_volopt_dynload error(%d)", ret); +                                ret = 0; +                                goto cont; +                        } + +                        ret = xlator_option_info_list (&vol_opt_handle, key, +                                                       &def_val, &descr); +                        if (ret) { /*Swallow Error i.e if option not found*/ +                                gf_log ("glusterd", GF_LOG_DEBUG, +                                        "Failed to get option for %s key", key); +                                ret = 0; +                                goto cont; +                        } +                } + +                if (xml_out) { +#if (HAVE_LIB_XML) +                        if (xml_add_volset_element (writer,vme->key, +                                                    def_val, descr)) { +                                ret = -1; +                                goto cont; +                        } +#else +                        gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); +#endif +                } else { +                        snprintf (tmp_str, sizeof (tmp_str), "Option: %s\nDefault " +                                        "Value: %s\nDescription: %s\n\n", +                                        vme->key, def_val, descr); +                        strcat (output_string, tmp_str); +                } +cont: +                if (dl_handle) { +                        dlclose (dl_handle); +                        dl_handle = NULL; +                        vol_opt_handle.given_opt = NULL; +                } +                if (key) { +                        _free_xlator_opt_key (key); +                        key = NULL; +                } +                if (ret) +                        goto out; +        } + +#if (HAVE_LIB_XML) +        if ((xml_out) && +            (ret = end_sethelp_xml_doc (writer))) +                goto out; +#else +        if (xml_out) +                gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); +#endif + +        if (!xml_out) +                output = gf_strdup (output_string); +        else +#if (HAVE_LIB_XML) +                output = gf_strdup ((char *)buf->content); +#else +                gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); +#endif + +        if (NULL == output) { +                ret = -1; +                goto out; +        } + +        ret = dict_set_dynstr (ctx, "help-str", output); +out: +        gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 2e06c2a6341..fe89e15aaf6 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -900,4 +900,13 @@ glusterd_update_fs_label (glusterd_brickinfo_t *brickinfo);  void  gd_get_snap_conf_values_if_present (dict_t *opts, uint64_t *sys_hard_limit,                                      uint64_t *sys_soft_limit); + +int +glusterd_get_volopt_content (dict_t *dict, gf_boolean_t xml_out); + +int +glusterd_get_default_val_for_volopt (dict_t *dict, gf_boolean_t all_opts, +                                         char *key, char *orig_key, +                                         dict_t *vol_dict, char **err_str); +  #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 7981e2977e8..7cd95fad5f2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -18,11 +18,6 @@  #include <dlfcn.h>  #include <utime.h> -#if (HAVE_LIB_XML) -#include <libxml/encoding.h> -#include <libxml/xmlwriter.h> -#endif -  #include "xlator.h"  #include "glusterd.h"  #include "defaults.h" @@ -1939,7 +1934,7 @@ nfsperfxl_option_handler (volgen_graph_t *graph, struct volopt_map_entry *vme,  }  #if (HAVE_LIB_XML) -static int +int  end_sethelp_xml_doc (xmlTextWriterPtr writer)  {          int             ret = -1; @@ -1965,7 +1960,7 @@ end_sethelp_xml_doc (xmlTextWriterPtr writer)  } -static int +int  init_sethelp_xml_doc (xmlTextWriterPtr *writer, xmlBufferPtr  *buf)  {          int ret; @@ -2012,7 +2007,7 @@ init_sethelp_xml_doc (xmlTextWriterPtr *writer, xmlBufferPtr  *buf)  } -static int +int  xml_add_volset_element (xmlTextWriterPtr writer, const char *name,                                   const char *def_val, const char *dscrpt)  { @@ -2073,7 +2068,7 @@ xml_add_volset_element (xmlTextWriterPtr writer, const char *name,  #endif -static int +int  _get_xlator_opt_key_from_vme ( struct volopt_map_entry *vme, char **key)  {          int ret = 0; @@ -2117,7 +2112,7 @@ _get_xlator_opt_key_from_vme ( struct volopt_map_entry *vme, char **key)          return ret;  } -static void +void  _free_xlator_opt_key (char *key)  {          GF_ASSERT (key); @@ -2130,130 +2125,6 @@ _free_xlator_opt_key (char *key)          return;  } -int -glusterd_get_volopt_content (dict_t * ctx, gf_boolean_t xml_out) -{ -        void                    *dl_handle = NULL; -        volume_opt_list_t        vol_opt_handle = {{0},}; -        char                    *key = NULL; -        struct volopt_map_entry *vme = NULL; -        int                      ret = -1; -        char                    *def_val = NULL; -        char                    *descr = NULL; -        char                     output_string[51200] = {0, }; -        char                    *output = NULL; -        char                     tmp_str[2048] = {0, }; -#if (HAVE_LIB_XML) -        xmlTextWriterPtr         writer = NULL; -        xmlBufferPtr             buf = NULL; - -        if (xml_out) { -                ret = init_sethelp_xml_doc (&writer, &buf); -                if (ret) /*logging done in init_xml_lib*/ -                        goto out; -        } -#endif - -        INIT_LIST_HEAD (&vol_opt_handle.list); - -        for (vme = &glusterd_volopt_map[0]; vme->key; vme++) { - -                if ((vme->type == NO_DOC) || (vme->type == GLOBAL_NO_DOC)) -                        continue; - -                if (vme->description) { -                        descr = vme->description; -                        def_val = vme->value; -                } else { -                        if (_get_xlator_opt_key_from_vme (vme, &key)) { -                                gf_log ("glusterd", GF_LOG_DEBUG, "Failed to " -                                        "get %s key from volume option entry", -                                        vme->key); -                                goto out; /*Some error while geting key*/ -                        } - -                        ret = xlator_volopt_dynload (vme->voltype, -                                                     &dl_handle, -                                                     &vol_opt_handle); - -                        if (ret) { -                                gf_log ("glusterd", GF_LOG_DEBUG, -                                        "xlator_volopt_dynload error(%d)", ret); -                                ret = 0; -                                goto cont; -                        } - -                        ret = xlator_option_info_list (&vol_opt_handle, key, -                                                       &def_val, &descr); -                        if (ret) { /*Swallow Error i.e if option not found*/ -                                gf_log ("glusterd", GF_LOG_DEBUG, -                                        "Failed to get option for %s key", key); -                                ret = 0; -                                goto cont; -                        } -                } - -                if (xml_out) { -#if (HAVE_LIB_XML) -                        if (xml_add_volset_element (writer,vme->key, -                                                    def_val, descr)) { -                                ret = -1; -                                goto cont; -                        } -#else -                        gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); -#endif -                } else { -                        snprintf (tmp_str, sizeof (tmp_str), "Option: %s\nDefault " -                                        "Value: %s\nDescription: %s\n\n", -                                        vme->key, def_val, descr); -                        strcat (output_string, tmp_str); -                } -cont: -                if (dl_handle) { -                        dlclose (dl_handle); -                        dl_handle = NULL; -                        vol_opt_handle.given_opt = NULL; -                } -                if (key) { -                        _free_xlator_opt_key (key); -                        key = NULL; -                } -                if (ret) -                        goto out; -        } - -#if (HAVE_LIB_XML) -        if ((xml_out) && -            (ret = end_sethelp_xml_doc (writer))) -                goto out; -#else -        if (xml_out) -                gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); -#endif - -        if (!xml_out) -                output = gf_strdup (output_string); -        else -#if (HAVE_LIB_XML) -                output = gf_strdup ((char *)buf->content); -#else -                gf_log ("glusterd", GF_LOG_ERROR, "Libxml not present"); -#endif - -        if (NULL == output) { -                ret = -1; -                goto out; -        } - -        ret = dict_set_dynstr (ctx, "help-str", output); -out: -        gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); -        return ret; - -} - -  static xlator_t *  volgen_graph_build_client (volgen_graph_t *graph, glusterd_volinfo_t *volinfo,                             char *hostname, char *subvol, char *xl_id, diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h index 71b6a770fac..4eb696e5ba4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.h +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h @@ -15,6 +15,11 @@  #include "config.h"  #endif +#if (HAVE_LIB_XML) +#include <libxml/encoding.h> +#include <libxml/xmlwriter.h> +#endif +  #include "glusterd.h"  /* volopt map key name definitions */ @@ -114,58 +119,103 @@ struct volopt_map_entry {          //gf_boolean_t client_option;  }; -int glusterd_create_rb_volfiles (glusterd_volinfo_t *volinfo, +int +glusterd_create_rb_volfiles (glusterd_volinfo_t *volinfo,                                   glusterd_brickinfo_t *brickinfo); -int glusterd_create_volfiles (glusterd_volinfo_t *volinfo); +int +glusterd_create_volfiles (glusterd_volinfo_t *volinfo); -int glusterd_create_volfiles_and_notify_services (glusterd_volinfo_t *volinfo); +int +glusterd_create_volfiles_and_notify_services (glusterd_volinfo_t *volinfo); -void glusterd_get_nfs_filepath (char *filename); +void +glusterd_get_nfs_filepath (char *filename);  void glusterd_get_shd_filepath (char *filename); -int glusterd_create_nfs_volfile (); -int glusterd_create_shd_volfile (); -int glusterd_create_quotad_volfile (); -int glusterd_create_snapd_volfile (glusterd_volinfo_t *volinfo); +int +glusterd_create_nfs_volfile (); + +int +glusterd_create_shd_volfile (); + +int +glusterd_create_quotad_volfile (); + +int +glusterd_create_snapd_volfile (glusterd_volinfo_t *volinfo); -int glusterd_delete_volfile (glusterd_volinfo_t *volinfo, +int +glusterd_delete_volfile (glusterd_volinfo_t *volinfo,                               glusterd_brickinfo_t *brickinfo);  int  glusterd_delete_snap_volfile (glusterd_volinfo_t *volinfo,                                glusterd_volinfo_t *snap_volinfo,                                glusterd_brickinfo_t *brickinfo); -int glusterd_volinfo_get (glusterd_volinfo_t *volinfo, char *key, char **value); -int glusterd_volinfo_get_boolean (glusterd_volinfo_t *volinfo, char *key); +int +glusterd_volinfo_get (glusterd_volinfo_t *volinfo, char *key, char **value); + +int +glusterd_volinfo_get_boolean (glusterd_volinfo_t *volinfo, char *key); -int glusterd_validate_globalopts (glusterd_volinfo_t *volinfo, dict_t *val_dict, char **op_errstr); +int +glusterd_validate_globalopts (glusterd_volinfo_t *volinfo, dict_t *val_dict, +                              char **op_errstr); + +int +glusterd_validate_localopts (dict_t *val_dict, char **op_errstr); + +gf_boolean_t +glusterd_check_globaloption (char *key); -int glusterd_validate_localopts (dict_t *val_dict, char **op_errstr); -gf_boolean_t glusterd_check_globaloption (char *key);  gf_boolean_t  glusterd_check_voloption_flags (char *key, int32_t flags); +  gf_boolean_t  glusterd_is_valid_volfpath (char *volname, char *brick); -int generate_brick_volfiles (glusterd_volinfo_t *volinfo); -int generate_snap_brick_volfiles (glusterd_volinfo_t *volinfo, + +int +generate_brick_volfiles (glusterd_volinfo_t *volinfo); + +int +generate_snap_brick_volfiles (glusterd_volinfo_t *volinfo,                                    glusterd_volinfo_t *snap_volinfo); -int generate_client_volfiles (glusterd_volinfo_t *volinfo, +int +generate_client_volfiles (glusterd_volinfo_t *volinfo,                                glusterd_client_type_t client_type);  int  generate_snap_client_volfiles (glusterd_volinfo_t *actual_volinfo,                                 glusterd_volinfo_t *snap_volinfo,                                 glusterd_client_type_t client_type,                                 gf_boolean_t vol_restore); -int glusterd_get_volopt_content (dict_t *dict, gf_boolean_t xml_out); + +int +_get_xlator_opt_key_from_vme ( struct volopt_map_entry *vme, char **key); + +void +_free_xlator_opt_key (char *key); + +int +init_sethelp_xml_doc (xmlTextWriterPtr *writer, xmlBufferPtr  *buf); + +int +xml_add_volset_element (xmlTextWriterPtr writer, const char *name, +                        const char *def_val, const char *dscrpt); +  char*  glusterd_get_trans_type_rb (gf_transport_type ttype); +  int  glusterd_check_nfs_volfile_identical (gf_boolean_t *identical); +  int  glusterd_check_nfs_topology_identical (gf_boolean_t *identical); +int +end_sethelp_xml_doc (xmlTextWriterPtr writer); +  uint32_t  glusterd_get_op_version_for_key (char *key);  | 
