diff options
author | Atin Mukherjee <amukherj@redhat.com> | 2014-06-30 10:33:25 +0530 |
---|---|---|
committer | Kaushal M <kaushal@redhat.com> | 2014-08-26 04:17:51 -0700 |
commit | c080403393987f807b9ca81be140618fa5e994f1 (patch) | |
tree | ff49f5f43e6d2208dbf15b9aac9b3f8a50bd8702 | |
parent | acabde2c297c4175946565017ba17a251ad3fb1c (diff) |
cli/glusterd: Support of volume get for a specific volume option
This patch introduces a cli command to display a specific volume option/all
volume options of a specific volume with the following usage:
Usage: volume get <VOLNAME> <key|all>
Change-Id: Ic88edb33c5509d7a37cd5ade6341e45e3cdbf59d
BUG: 983317
Signed-off-by: Atin Mukherjee <amukherj@redhat.com>
Reviewed-on: http://review.gluster.org/8305
Reviewed-by: Kaushal M <kaushal@redhat.com>
Tested-by: Gluster Build System <jenkins@build.gluster.com>
-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); |