|
|
d1681e |
From c45cba4e8959cc3224c293423fdc1f33d3e657c8 Mon Sep 17 00:00:00 2001
|
|
|
d1681e |
From: Jiffin Tony Thottan <jthottan@redhat.com>
|
|
|
d1681e |
Date: Mon, 16 Oct 2017 14:24:29 +0530
|
|
|
d1681e |
Subject: [PATCH 50/74] Revert "glusterd: (storhaug) remove ganesha"
|
|
|
d1681e |
|
|
|
d1681e |
This reverts commit 843e1b04b554ab887ec656ae7b468bb93ee4e2f7.
|
|
|
d1681e |
|
|
|
d1681e |
Change-Id: I06b5450344c33f26da3d94b6f67051d41dfbba17
|
|
|
d1681e |
Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
|
|
|
d1681e |
---
|
|
|
d1681e |
cli/src/cli-cmd-global.c | 54 ++
|
|
|
d1681e |
cli/src/cli-cmd-parser.c | 106 +++
|
|
|
d1681e |
cli/src/cli-cmd.c | 3 +-
|
|
|
d1681e |
cli/src/cli-rpc-ops.c | 79 ++
|
|
|
d1681e |
cli/src/cli.h | 3 +
|
|
|
d1681e |
xlators/mgmt/glusterd/src/Makefile.am | 4 +-
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-errno.h | 2 +-
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-ganesha.c | 898 +++++++++++++++++++++
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-handler.c | 77 ++
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-messages.h | 8 +
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-op-sm.c | 47 ++
|
|
|
d1681e |
.../mgmt/glusterd/src/glusterd-snapshot-utils.c | 196 +++++
|
|
|
d1681e |
.../mgmt/glusterd/src/glusterd-snapshot-utils.h | 7 +
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-snapshot.c | 96 +++
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-store.h | 1 +
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 34 +
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd-volume-set.c | 6 +
|
|
|
d1681e |
xlators/mgmt/glusterd/src/glusterd.h | 16 +-
|
|
|
d1681e |
18 files changed, 1633 insertions(+), 4 deletions(-)
|
|
|
d1681e |
create mode 100644 xlators/mgmt/glusterd/src/glusterd-ganesha.c
|
|
|
d1681e |
|
|
|
d1681e |
diff --git a/cli/src/cli-cmd-global.c b/cli/src/cli-cmd-global.c
|
|
|
d1681e |
index 9873192..881506b 100644
|
|
|
d1681e |
--- a/cli/src/cli-cmd-global.c
|
|
|
d1681e |
+++ b/cli/src/cli-cmd-global.c
|
|
|
d1681e |
@@ -32,6 +32,8 @@ extern rpc_clnt_prog_t *cli_rpc_prog;
|
|
|
d1681e |
int
|
|
|
d1681e |
cli_cmd_global_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,
|
|
|
d1681e |
const char **words, int wordcount);
|
|
|
d1681e |
+int cli_cmd_ganesha_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
|
|
d1681e |
+ const char **words, int wordcount);
|
|
|
d1681e |
int
|
|
|
d1681e |
cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
|
|
d1681e |
const char **words, int wordcount);
|
|
|
d1681e |
@@ -46,6 +48,10 @@ struct cli_cmd global_cmds[] = {
|
|
|
d1681e |
cli_cmd_get_state_cbk,
|
|
|
d1681e |
"Get local state representation of mentioned daemon",
|
|
|
d1681e |
},
|
|
|
d1681e |
+ { "nfs-ganesha {enable| disable} ",
|
|
|
d1681e |
+ cli_cmd_ganesha_cbk,
|
|
|
d1681e |
+ "Enable/disable NFS-Ganesha support",
|
|
|
d1681e |
+ },
|
|
|
d1681e |
{NULL, NULL, NULL}
|
|
|
d1681e |
};
|
|
|
d1681e |
|
|
|
d1681e |
@@ -86,6 +92,54 @@ out:
|
|
|
d1681e |
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+int cli_cmd_ganesha_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
|
|
d1681e |
+ const char **words, int wordcount)
|
|
|
d1681e |
+
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int sent = 0;
|
|
|
d1681e |
+ int parse_error = 0;
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ rpc_clnt_procedure_t *proc = NULL;
|
|
|
d1681e |
+ call_frame_t *frame = NULL;
|
|
|
d1681e |
+ dict_t *options = NULL;
|
|
|
d1681e |
+ cli_local_t *local = NULL;
|
|
|
d1681e |
+ char *op_errstr = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_GANESHA];
|
|
|
d1681e |
+
|
|
|
d1681e |
+ frame = create_frame (THIS, THIS->ctx->pool);
|
|
|
d1681e |
+ if (!frame)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = cli_cmd_ganesha_parse (state, words, wordcount,
|
|
|
d1681e |
+ &options, &op_errstr);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ if (op_errstr) {
|
|
|
d1681e |
+ cli_err ("%s", op_errstr);
|
|
|
d1681e |
+ GF_FREE (op_errstr);
|
|
|
d1681e |
+ } else
|
|
|
d1681e |
+ cli_usage_out (word->pattern);
|
|
|
d1681e |
+ parse_error = 1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ CLI_LOCAL_INIT (local, words, frame, options);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (proc->fn) {
|
|
|
d1681e |
+ ret = proc->fn (frame, THIS, options);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ cli_cmd_sent_status_get (&sent);
|
|
|
d1681e |
+ if ((sent == 0) && (parse_error == 0))
|
|
|
d1681e |
+ cli_out ("Setting global option failed");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ CLI_STACK_DESTROY (frame);
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
int
|
|
|
d1681e |
cli_cmd_get_state_cbk (struct cli_state *state, struct cli_cmd_word *word,
|
|
|
d1681e |
const char **words, int wordcount)
|
|
|
d1681e |
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
|
|
|
d1681e |
index 216e050..a4c601b 100644
|
|
|
d1681e |
--- a/cli/src/cli-cmd-parser.c
|
|
|
d1681e |
+++ b/cli/src/cli-cmd-parser.c
|
|
|
d1681e |
@@ -840,6 +840,112 @@ out:
|
|
|
d1681e |
return ret;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+/* Parsing global option for NFS-Ganesha config
|
|
|
d1681e |
+ * gluster nfs-ganesha enable/disable */
|
|
|
d1681e |
+
|
|
|
d1681e |
+int32_t
|
|
|
d1681e |
+cli_cmd_ganesha_parse (struct cli_state *state,
|
|
|
d1681e |
+ const char **words, int wordcount,
|
|
|
d1681e |
+ dict_t **options, char **op_errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ dict_t *dict = NULL;
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ char *key = NULL;
|
|
|
d1681e |
+ char *value = NULL;
|
|
|
d1681e |
+ char *w = NULL;
|
|
|
d1681e |
+ char *opwords[] = { "enable", "disable", NULL };
|
|
|
d1681e |
+ const char *question = NULL;
|
|
|
d1681e |
+ gf_answer_t answer = GF_ANSWER_NO;
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT (words);
|
|
|
d1681e |
+ GF_ASSERT (options);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ dict = dict_new ();
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (!dict)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (wordcount != 2)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ key = (char *) words[0];
|
|
|
d1681e |
+ value = (char *) words[1];
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (!key || !value) {
|
|
|
d1681e |
+ cli_out ("Usage : nfs-ganesha <enable/disable>");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = gf_strip_whitespace (value, strlen (value));
|
|
|
d1681e |
+ if (ret == -1)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (strcmp (key, "nfs-ganesha")) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "Global option: error: ' %s '"
|
|
|
d1681e |
+ "is not a valid global option.", key);
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ w = str_getunamb (value, opwords);
|
|
|
d1681e |
+ if (!w) {
|
|
|
d1681e |
+ cli_out ("Invalid global option \n"
|
|
|
d1681e |
+ "Usage : nfs-ganesha <enable/disable>");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ question = "Enabling NFS-Ganesha requires Gluster-NFS to be"
|
|
|
d1681e |
+ " disabled across the trusted pool. Do you "
|
|
|
d1681e |
+ "still want to continue?\n";
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (strcmp (value, "enable") == 0) {
|
|
|
d1681e |
+ answer = cli_cmd_get_confirmation (state, question);
|
|
|
d1681e |
+ if (GF_ANSWER_NO == answer) {
|
|
|
d1681e |
+ gf_log ("cli", GF_LOG_ERROR, "Global operation "
|
|
|
d1681e |
+ "cancelled, exiting");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ cli_out ("This will take a few minutes to complete. Please wait ..");
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_set_str (dict, "key", key);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_log (THIS->name, GF_LOG_ERROR, "dict set on key failed");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_set_str (dict, "value", value);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_log (THIS->name, GF_LOG_ERROR, "dict set on value failed");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_set_str (dict, "globalname", "All");
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_log (THIS->name, GF_LOG_ERROR, "dict set on global"
|
|
|
d1681e |
+ " key failed.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_set_int32 (dict, "hold_global_locks", _gf_true);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_log (THIS->name, GF_LOG_ERROR, "dict set on global key "
|
|
|
d1681e |
+ "failed.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ *options = dict;
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ dict_unref (dict);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
int32_t
|
|
|
d1681e |
cli_cmd_get_state_parse (struct cli_state *state,
|
|
|
d1681e |
const char **words, int wordcount,
|
|
|
d1681e |
diff --git a/cli/src/cli-cmd.c b/cli/src/cli-cmd.c
|
|
|
d1681e |
index 236009b..8a75041 100644
|
|
|
d1681e |
--- a/cli/src/cli-cmd.c
|
|
|
d1681e |
+++ b/cli/src/cli-cmd.c
|
|
|
d1681e |
@@ -369,7 +369,8 @@ cli_cmd_submit (struct rpc_clnt* rpc, void *req, call_frame_t *frame,
|
|
|
d1681e |
unsigned timeout = 0;
|
|
|
d1681e |
|
|
|
d1681e |
if ((GLUSTER_CLI_PROFILE_VOLUME == procnum) ||
|
|
|
d1681e |
- (GLUSTER_CLI_HEAL_VOLUME == procnum))
|
|
|
d1681e |
+ (GLUSTER_CLI_HEAL_VOLUME == procnum) ||
|
|
|
d1681e |
+ (GLUSTER_CLI_GANESHA == procnum))
|
|
|
d1681e |
timeout = cli_ten_minutes_timeout;
|
|
|
d1681e |
else
|
|
|
d1681e |
timeout = cli_default_conn_timeout;
|
|
|
d1681e |
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
|
|
|
d1681e |
index eb1ca77..67e29a0 100644
|
|
|
d1681e |
--- a/cli/src/cli-rpc-ops.c
|
|
|
d1681e |
+++ b/cli/src/cli-rpc-ops.c
|
|
|
d1681e |
@@ -2232,6 +2232,60 @@ out:
|
|
|
d1681e |
return ret;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+int
|
|
|
d1681e |
+gf_cli_ganesha_cbk (struct rpc_req *req, struct iovec *iov,
|
|
|
d1681e |
+ int count, void *myframe)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ gf_cli_rsp rsp = {0,};
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ dict_t *dict = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT (myframe);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (-1 == req->rpc_status) {
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);
|
|
|
d1681e |
+ if (ret < 0) {
|
|
|
d1681e |
+ gf_log (((call_frame_t *) myframe)->this->name, GF_LOG_ERROR,
|
|
|
d1681e |
+ "Failed to decode xdr response");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ gf_log ("cli", GF_LOG_DEBUG, "Received resp to ganesha");
|
|
|
d1681e |
+
|
|
|
d1681e |
+ dict = dict_new ();
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (!dict) {
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (rsp.op_ret) {
|
|
|
d1681e |
+ if (strcmp (rsp.op_errstr, ""))
|
|
|
d1681e |
+ cli_err ("nfs-ganesha: failed: %s", rsp.op_errstr);
|
|
|
d1681e |
+ else
|
|
|
d1681e |
+ cli_err ("nfs-ganesha: failed");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ else {
|
|
|
d1681e |
+ cli_out("nfs-ganesha : success ");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = rsp.op_ret;
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ if (dict)
|
|
|
d1681e |
+ dict_unref (dict);
|
|
|
d1681e |
+ cli_cmd_broadcast_response (ret);
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
char *
|
|
|
d1681e |
is_server_debug_xlator (void *myframe)
|
|
|
d1681e |
{
|
|
|
d1681e |
@@ -4840,6 +4894,30 @@ out:
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
int32_t
|
|
|
d1681e |
+gf_cli_ganesha (call_frame_t *frame, xlator_t *this, void *data)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ gf_cli_req req = { {0,} } ;
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+ dict_t *dict = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (!frame || !this || !data) {
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ dict = data;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = cli_to_glusterd (&req, frame, gf_cli_ganesha_cbk,
|
|
|
d1681e |
+ (xdrproc_t) xdr_gf_cli_req, dict,
|
|
|
d1681e |
+ GLUSTER_CLI_GANESHA, this, cli_rpc_prog,
|
|
|
d1681e |
+ NULL);
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int32_t
|
|
|
d1681e |
gf_cli_set_volume (call_frame_t *frame, xlator_t *this,
|
|
|
d1681e |
void *data)
|
|
|
d1681e |
{
|
|
|
d1681e |
@@ -12008,6 +12086,7 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
|
|
|
d1681e |
[GLUSTER_CLI_SYS_EXEC] = {"SYS_EXEC", gf_cli_sys_exec},
|
|
|
d1681e |
[GLUSTER_CLI_SNAP] = {"SNAP", gf_cli_snapshot},
|
|
|
d1681e |
[GLUSTER_CLI_BARRIER_VOLUME] = {"BARRIER VOLUME", gf_cli_barrier_volume},
|
|
|
d1681e |
+ [GLUSTER_CLI_GANESHA] = {"GANESHA", gf_cli_ganesha},
|
|
|
d1681e |
[GLUSTER_CLI_GET_VOL_OPT] = {"GET_VOL_OPT", gf_cli_get_vol_opt},
|
|
|
d1681e |
[GLUSTER_CLI_BITROT] = {"BITROT", gf_cli_bitrot},
|
|
|
d1681e |
[GLUSTER_CLI_ATTACH_TIER] = {"ATTACH_TIER", gf_cli_attach_tier},
|
|
|
d1681e |
diff --git a/cli/src/cli.h b/cli/src/cli.h
|
|
|
d1681e |
index 68dcb8c..c9bf93d 100644
|
|
|
d1681e |
--- a/cli/src/cli.h
|
|
|
d1681e |
+++ b/cli/src/cli.h
|
|
|
d1681e |
@@ -255,6 +255,9 @@ cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **opt);
|
|
|
d1681e |
int32_t
|
|
|
d1681e |
cli_cmd_volume_set_parse (struct cli_state *state, const char **words,
|
|
|
d1681e |
int wordcount, dict_t **options, char **op_errstr);
|
|
|
d1681e |
+int32_t
|
|
|
d1681e |
+cli_cmd_ganesha_parse (struct cli_state *state, const char **words,
|
|
|
d1681e |
+ int wordcount, dict_t **options, char **op_errstr);
|
|
|
d1681e |
|
|
|
d1681e |
int32_t
|
|
|
d1681e |
cli_cmd_get_state_parse (struct cli_state *state, const char **words,
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am
|
|
|
d1681e |
index 4858dee..23ebf37 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/Makefile.am
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/Makefile.am
|
|
|
d1681e |
@@ -5,7 +5,7 @@ glusterd_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS)
|
|
|
d1681e |
glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \
|
|
|
d1681e |
glusterd-op-sm.c glusterd-utils.c glusterd-rpc-ops.c \
|
|
|
d1681e |
glusterd-store.c glusterd-handshake.c glusterd-pmap.c \
|
|
|
d1681e |
- glusterd-volgen.c glusterd-rebalance.c \
|
|
|
d1681e |
+ glusterd-volgen.c glusterd-rebalance.c glusterd-ganesha.c \
|
|
|
d1681e |
glusterd-quota.c glusterd-bitrot.c glusterd-geo-rep.c \
|
|
|
d1681e |
glusterd-replace-brick.c glusterd-log-ops.c glusterd-tier.c \
|
|
|
d1681e |
glusterd-volume-ops.c glusterd-brick-ops.c glusterd-mountbroker.c \
|
|
|
d1681e |
@@ -48,6 +48,8 @@ AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \
|
|
|
d1681e |
-I$(CONTRIBDIR)/mount -I$(CONTRIBDIR)/userspace-rcu \
|
|
|
d1681e |
-DSBIN_DIR=\"$(sbindir)\" -DDATADIR=\"$(localstatedir)\" \
|
|
|
d1681e |
-DGSYNCD_PREFIX=\"$(GLUSTERFS_LIBEXECDIR)\" \
|
|
|
d1681e |
+ -DCONFDIR=\"$(localstatedir)/run/gluster/shared_storage/nfs-ganesha\" \
|
|
|
d1681e |
+ -DGANESHA_PREFIX=\"$(libexecdir)/ganesha\" \
|
|
|
d1681e |
-DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) $(XML_CPPFLAGS)
|
|
|
d1681e |
|
|
|
d1681e |
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-errno.h b/xlators/mgmt/glusterd/src/glusterd-errno.h
|
|
|
d1681e |
index bfb56b5..3301e44 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-errno.h
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-errno.h
|
|
|
d1681e |
@@ -27,7 +27,7 @@ enum glusterd_op_errno {
|
|
|
d1681e |
EG_ISSNAP = 30813, /* Volume is a snap volume */
|
|
|
d1681e |
EG_GEOREPRUN = 30814, /* Geo-Replication is running */
|
|
|
d1681e |
EG_NOTTHINP = 30815, /* Bricks are not thinly provisioned */
|
|
|
d1681e |
- EG_NOGANESHA = 30816, /* obsolete ganesha is not enabled */
|
|
|
d1681e |
+ EG_NOGANESHA = 30816, /* Global nfs-ganesha is not enabled */
|
|
|
d1681e |
};
|
|
|
d1681e |
|
|
|
d1681e |
#endif
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-ganesha.c b/xlators/mgmt/glusterd/src/glusterd-ganesha.c
|
|
|
d1681e |
new file mode 100644
|
|
|
d1681e |
index 0000000..4346bad
|
|
|
d1681e |
--- /dev/null
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-ganesha.c
|
|
|
d1681e |
@@ -0,0 +1,898 @@
|
|
|
d1681e |
+/*
|
|
|
d1681e |
+ Copyright (c) 2015 Red Hat, Inc. <http://www.redhat.com>
|
|
|
d1681e |
+ This file is part of GlusterFS.
|
|
|
d1681e |
+
|
|
|
d1681e |
+ This file is licensed to you under your choice of the GNU Lesser
|
|
|
d1681e |
+ General Public License, version 3 or any later version (LGPLv3 or
|
|
|
d1681e |
+ later), or the GNU General Public License, version 2 (GPLv2), in all
|
|
|
d1681e |
+ cases as published by the Free Software Foundation.
|
|
|
d1681e |
+*/
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+#include "common-utils.h"
|
|
|
d1681e |
+#include "glusterd.h"
|
|
|
d1681e |
+#include "glusterd-op-sm.h"
|
|
|
d1681e |
+#include "glusterd-store.h"
|
|
|
d1681e |
+#include "glusterd-utils.h"
|
|
|
d1681e |
+#include "glusterd-nfs-svc.h"
|
|
|
d1681e |
+#include "glusterd-volgen.h"
|
|
|
d1681e |
+#include "glusterd-messages.h"
|
|
|
d1681e |
+#include "syscall.h"
|
|
|
d1681e |
+
|
|
|
d1681e |
+#include <ctype.h>
|
|
|
d1681e |
+
|
|
|
d1681e |
+int start_ganesha (char **op_errstr);
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+typedef struct service_command {
|
|
|
d1681e |
+ char *binary;
|
|
|
d1681e |
+ char *service;
|
|
|
d1681e |
+ int (*action) (struct service_command *, char *);
|
|
|
d1681e |
+} service_command;
|
|
|
d1681e |
+
|
|
|
d1681e |
+/* parsing_ganesha_ha_conf will allocate the returned string
|
|
|
d1681e |
+ * to be freed (GF_FREE) by the caller
|
|
|
d1681e |
+ * return NULL if error or not found */
|
|
|
d1681e |
+static char*
|
|
|
d1681e |
+parsing_ganesha_ha_conf(const char *key) {
|
|
|
d1681e |
+#define MAX_LINE 1024
|
|
|
d1681e |
+ char scratch[MAX_LINE * 2] = {0,};
|
|
|
d1681e |
+ char *value = NULL, *pointer = NULL, *end_pointer = NULL;
|
|
|
d1681e |
+ FILE *fp;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ fp = fopen (GANESHA_HA_CONF, "r");
|
|
|
d1681e |
+ if (fp == NULL) {
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_FILE_OP_FAILED, "couldn't open the file %s",
|
|
|
d1681e |
+ GANESHA_HA_CONF);
|
|
|
d1681e |
+ goto end_ret;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ while ((pointer = fgets (scratch, MAX_LINE, fp)) != NULL) {
|
|
|
d1681e |
+ /* Read config file until we get matching "^[[:space:]]*key" */
|
|
|
d1681e |
+ if (*pointer == '#') {
|
|
|
d1681e |
+ continue;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ while (isblank(*pointer)) {
|
|
|
d1681e |
+ pointer++;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ if (strncmp (pointer, key, strlen (key))) {
|
|
|
d1681e |
+ continue;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ pointer += strlen (key);
|
|
|
d1681e |
+ /* key found : if we fail to parse, we'll return an error
|
|
|
d1681e |
+ * rather than trying next one
|
|
|
d1681e |
+ * - supposition : conf file is bash compatible : no space
|
|
|
d1681e |
+ * around the '=' */
|
|
|
d1681e |
+ if (*pointer != '=') {
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_GET_CONFIG_INFO_FAILED,
|
|
|
d1681e |
+ "Parsing %s failed at key %s",
|
|
|
d1681e |
+ GANESHA_HA_CONF, key);
|
|
|
d1681e |
+ goto end_close;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ pointer++; /* jump the '=' */
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (*pointer == '"' || *pointer == '\'') {
|
|
|
d1681e |
+ /* dont get the quote */
|
|
|
d1681e |
+ pointer++;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ end_pointer = pointer;
|
|
|
d1681e |
+ /* stop at the next closing quote or blank/newline */
|
|
|
d1681e |
+ do {
|
|
|
d1681e |
+ end_pointer++;
|
|
|
d1681e |
+ } while (!(*end_pointer == '\'' || *end_pointer == '"' ||
|
|
|
d1681e |
+ isspace(*end_pointer) || *end_pointer == '\0'));
|
|
|
d1681e |
+ *end_pointer = '\0';
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* got it. copy it and return */
|
|
|
d1681e |
+ value = gf_strdup (pointer);
|
|
|
d1681e |
+ break;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+end_close:
|
|
|
d1681e |
+ fclose(fp);
|
|
|
d1681e |
+end_ret:
|
|
|
d1681e |
+ return value;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+static int
|
|
|
d1681e |
+sc_systemctl_action (struct service_command *sc, char *command)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, sc->binary, command, sc->service, NULL);
|
|
|
d1681e |
+ return runner_run (&runner);
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+static int
|
|
|
d1681e |
+sc_service_action (struct service_command *sc, char *command)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, sc->binary, sc->service, command, NULL);
|
|
|
d1681e |
+ return runner_run (&runner);
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+static int
|
|
|
d1681e |
+manage_service (char *action)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ struct stat stbuf = {0,};
|
|
|
d1681e |
+ int i = 0;
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+ struct service_command sc_list[] = {
|
|
|
d1681e |
+ { .binary = "/usr/bin/systemctl",
|
|
|
d1681e |
+ .service = "nfs-ganesha",
|
|
|
d1681e |
+ .action = sc_systemctl_action
|
|
|
d1681e |
+ },
|
|
|
d1681e |
+ { .binary = "/sbin/invoke-rc.d",
|
|
|
d1681e |
+ .service = "nfs-ganesha",
|
|
|
d1681e |
+ .action = sc_service_action
|
|
|
d1681e |
+ },
|
|
|
d1681e |
+ { .binary = "/sbin/service",
|
|
|
d1681e |
+ .service = "nfs-ganesha",
|
|
|
d1681e |
+ .action = sc_service_action
|
|
|
d1681e |
+ },
|
|
|
d1681e |
+ { .binary = NULL
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ };
|
|
|
d1681e |
+
|
|
|
d1681e |
+ while (sc_list[i].binary != NULL) {
|
|
|
d1681e |
+ ret = sys_stat (sc_list[i].binary, &stbuf);
|
|
|
d1681e |
+ if (ret == 0) {
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0,
|
|
|
d1681e |
+ "%s found.", sc_list[i].binary);
|
|
|
d1681e |
+ if (strcmp (sc_list[i].binary, "/usr/bin/systemctl") == 0)
|
|
|
d1681e |
+ ret = sc_systemctl_action (&sc_list[i], action);
|
|
|
d1681e |
+ else
|
|
|
d1681e |
+ ret = sc_service_action (&sc_list[i], action);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ i++;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_UNRECOGNIZED_SVC_MNGR,
|
|
|
d1681e |
+ "Could not %s NFS-Ganesha.Service manager for distro"
|
|
|
d1681e |
+ " not recognized.", action);
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+/*
|
|
|
d1681e |
+ * Check if the cluster is a ganesha cluster or not *
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+gf_boolean_t
|
|
|
d1681e |
+glusterd_is_ganesha_cluster () {
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+ gf_boolean_t ret_bool = _gf_false;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO ("ganesha", this, out);
|
|
|
d1681e |
+ priv = this->private;
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, priv, out);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_get_str_boolean (priv->opts,
|
|
|
d1681e |
+ GLUSTERD_STORE_KEY_GANESHA_GLOBAL,
|
|
|
d1681e |
+ _gf_false);
|
|
|
d1681e |
+ if (ret == _gf_true) {
|
|
|
d1681e |
+ ret_bool = _gf_true;
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0,
|
|
|
d1681e |
+ "nfs-ganesha is enabled for the cluster");
|
|
|
d1681e |
+ } else
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0,
|
|
|
d1681e |
+ "nfs-ganesha is disabled for the cluster");
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret_bool;
|
|
|
d1681e |
+
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+/* Check if ganesha.enable is set to 'on', that checks if
|
|
|
d1681e |
+ * a particular volume is exported via NFS-Ganesha */
|
|
|
d1681e |
+gf_boolean_t
|
|
|
d1681e |
+glusterd_check_ganesha_export (glusterd_volinfo_t *volinfo) {
|
|
|
d1681e |
+
|
|
|
d1681e |
+ char *value = NULL;
|
|
|
d1681e |
+ gf_boolean_t is_exported = _gf_false;
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_volinfo_get (volinfo, "ganesha.enable", &value);
|
|
|
d1681e |
+ if ((ret == 0) && value) {
|
|
|
d1681e |
+ if (strcmp (value, "on") == 0) {
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "ganesha.enable set"
|
|
|
d1681e |
+ " to %s", value);
|
|
|
d1681e |
+ is_exported = _gf_true;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ return is_exported;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+/* *
|
|
|
d1681e |
+ * The below function is called as part of commit phase for volume set option
|
|
|
d1681e |
+ * "ganesha.enable". If the value is "on", it creates export configuration file
|
|
|
d1681e |
+ * and then export the volume via dbus command. Incase of "off", the volume
|
|
|
d1681e |
+ * will be already unexported during stage phase, so it will remove the conf
|
|
|
d1681e |
+ * file from shared storage
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_check_ganesha_cmd (char *key, char *value, char **errstr, dict_t *dict)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+ char *volname = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT (key);
|
|
|
d1681e |
+ GF_ASSERT (value);
|
|
|
d1681e |
+ GF_ASSERT (dict);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if ((strcmp (key, "ganesha.enable") == 0)) {
|
|
|
d1681e |
+ if ((strcmp (value, "on")) && (strcmp (value, "off"))) {
|
|
|
d1681e |
+ gf_asprintf (errstr, "Invalid value"
|
|
|
d1681e |
+ " for volume set command. Use on/off only.");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ if (strcmp (value, "on") == 0) {
|
|
|
d1681e |
+ ret = glusterd_handle_ganesha_op (dict, errstr, key,
|
|
|
d1681e |
+ value);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ } else if (is_origin_glusterd (dict)) {
|
|
|
d1681e |
+ ret = dict_get_str (dict, "volname", &volname);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg ("glusterd-ganesha", GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_GET_FAILED,
|
|
|
d1681e |
+ "Unable to get volume name");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ ret = manage_export_config (volname, "off", errstr);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg ("glusterd-ganesha", GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_NFS_GNS_OP_HANDLE_FAIL,
|
|
|
d1681e |
+ "Handling NFS-Ganesha"
|
|
|
d1681e |
+ " op failed.");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_op_stage_set_ganesha (dict_t *dict, char **op_errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ int value = -1;
|
|
|
d1681e |
+ gf_boolean_t option = _gf_false;
|
|
|
d1681e |
+ char *str = NULL;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT (dict);
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_ASSERT (this);
|
|
|
d1681e |
+ priv = this->private;
|
|
|
d1681e |
+ GF_ASSERT (priv);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ value = dict_get_str_boolean (dict, "value", _gf_false);
|
|
|
d1681e |
+ if (value == -1) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_GET_FAILED,
|
|
|
d1681e |
+ "value not present.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ /* This dict_get will fail if the user had never set the key before */
|
|
|
d1681e |
+ /*Ignoring the ret value and proceeding */
|
|
|
d1681e |
+ ret = dict_get_str (priv->opts, GLUSTERD_STORE_KEY_GANESHA_GLOBAL, &str);
|
|
|
d1681e |
+ if (ret == -1) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_WARNING, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_GET_FAILED, "Global dict not present.");
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ /* Validity of the value is already checked */
|
|
|
d1681e |
+ ret = gf_string2boolean (str, &option);
|
|
|
d1681e |
+ /* Check if the feature is already enabled, fail in that case */
|
|
|
d1681e |
+ if (value == option) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "nfs-ganesha is already %sd.", str);
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (value) {
|
|
|
d1681e |
+ ret = start_ganesha (op_errstr);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_NFS_GNS_START_FAIL,
|
|
|
d1681e |
+ "Could not start NFS-Ganesha");
|
|
|
d1681e |
+
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ ret = stop_ganesha (op_errstr);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "Could not stop "
|
|
|
d1681e |
+ "NFS-Ganesha.");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ if (!(*op_errstr)) {
|
|
|
d1681e |
+ *op_errstr = gf_strdup ("Error, Validation Failed");
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0,
|
|
|
d1681e |
+ "Error, Cannot Validate option :%s",
|
|
|
d1681e |
+ GLUSTERD_STORE_KEY_GANESHA_GLOBAL);
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0,
|
|
|
d1681e |
+ "Error, Cannot Validate option");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_op_set_ganesha (dict_t *dict, char **errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ char *key = NULL;
|
|
|
d1681e |
+ char *value = NULL;
|
|
|
d1681e |
+ char *next_version = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_ASSERT (this);
|
|
|
d1681e |
+ GF_ASSERT (dict);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ priv = this->private;
|
|
|
d1681e |
+ GF_ASSERT (priv);
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_get_str (dict, "key", &key);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_GET_FAILED,
|
|
|
d1681e |
+ "Couldn't get key in global option set");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_get_str (dict, "value", &value);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_GET_FAILED,
|
|
|
d1681e |
+ "Couldn't get value in global option set");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_handle_ganesha_op (dict, errstr, key, value);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_NFS_GNS_SETUP_FAIL,
|
|
|
d1681e |
+ "Initial NFS-Ganesha set up failed");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ ret = dict_set_dynstr_with_alloc (priv->opts,
|
|
|
d1681e |
+ GLUSTERD_STORE_KEY_GANESHA_GLOBAL,
|
|
|
d1681e |
+ value);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_WARNING, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_SET_FAILED, "Failed to set"
|
|
|
d1681e |
+ " nfs-ganesha in dict.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ ret = glusterd_get_next_global_opt_version_str (priv->opts,
|
|
|
d1681e |
+ &next_version);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "Could not fetch "
|
|
|
d1681e |
+ " global op version");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ ret = dict_set_str (priv->opts, GLUSTERD_GLOBAL_OPT_VERSION,
|
|
|
d1681e |
+ next_version);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_store_options (this, priv->opts);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_STORE_FAIL, "Failed to store options");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0, "returning %d", ret);
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+/* Following function parse GANESHA_HA_CONF
|
|
|
d1681e |
+ * The sample file looks like below,
|
|
|
d1681e |
+ * HA_NAME="ganesha-ha-360"
|
|
|
d1681e |
+ * HA_VOL_NAME="ha-state"
|
|
|
d1681e |
+ * HA_CLUSTER_NODES="server1,server2"
|
|
|
d1681e |
+ * VIP_rhs_1="10.x.x.x"
|
|
|
d1681e |
+ * VIP_rhs_2="10.x.x.x." */
|
|
|
d1681e |
+
|
|
|
d1681e |
+/* Check if the localhost is listed as one of nfs-ganesha nodes */
|
|
|
d1681e |
+gf_boolean_t
|
|
|
d1681e |
+check_host_list (void)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ char *hostname, *hostlist;
|
|
|
d1681e |
+ gf_boolean_t ret = _gf_false;
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ priv = THIS->private;
|
|
|
d1681e |
+ GF_ASSERT (priv);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ hostlist = parsing_ganesha_ha_conf ("HA_CLUSTER_NODES");
|
|
|
d1681e |
+ if (hostlist == NULL) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_INFO, errno,
|
|
|
d1681e |
+ GD_MSG_GET_CONFIG_INFO_FAILED,
|
|
|
d1681e |
+ "couldn't get HA_CLUSTER_NODES from file %s",
|
|
|
d1681e |
+ GANESHA_HA_CONF);
|
|
|
d1681e |
+ return _gf_false;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* Hostlist is a comma separated list now */
|
|
|
d1681e |
+ hostname = strtok (hostlist, ",");
|
|
|
d1681e |
+ while (hostname != NULL) {
|
|
|
d1681e |
+ ret = gf_is_local_addr (hostname);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_INFO, 0,
|
|
|
d1681e |
+ GD_MSG_NFS_GNS_HOST_FOUND,
|
|
|
d1681e |
+ "ganesha host found "
|
|
|
d1681e |
+ "Hostname is %s", hostname);
|
|
|
d1681e |
+ break;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ hostname = strtok (NULL, ",");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_FREE (hostlist);
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+manage_export_config (char *volname, char *value, char **op_errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT(volname);
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, "sh",
|
|
|
d1681e |
+ GANESHA_PREFIX"/create-export-ganesha.sh",
|
|
|
d1681e |
+ CONFDIR, value, volname, NULL);
|
|
|
d1681e |
+ ret = runner_run(&runner);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "Failed to create"
|
|
|
d1681e |
+ " NFS-Ganesha export config file.");
|
|
|
d1681e |
+
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+/* Exports and unexports a particular volume via NFS-Ganesha */
|
|
|
d1681e |
+int
|
|
|
d1681e |
+ganesha_manage_export (dict_t *dict, char *value, char **op_errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ glusterd_volinfo_t *volinfo = NULL;
|
|
|
d1681e |
+ dict_t *vol_opts = NULL;
|
|
|
d1681e |
+ char *volname = NULL;
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ gf_boolean_t option = _gf_false;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_ASSERT (this);
|
|
|
d1681e |
+ priv = this->private;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT (value);
|
|
|
d1681e |
+ GF_ASSERT (dict);
|
|
|
d1681e |
+ GF_ASSERT (priv);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_get_str (dict, "volname", &volname);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_GET_FAILED,
|
|
|
d1681e |
+ "Unable to get volume name");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ ret = gf_string2boolean (value, &option);
|
|
|
d1681e |
+ if (ret == -1) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, EINVAL,
|
|
|
d1681e |
+ GD_MSG_INVALID_ENTRY, "invalid value.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_volinfo_find (volname, &volinfo);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, EINVAL,
|
|
|
d1681e |
+ GD_MSG_VOL_NOT_FOUND,
|
|
|
d1681e |
+ FMTSTR_CHECK_VOL_EXISTS, volname);
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_check_ganesha_export (volinfo);
|
|
|
d1681e |
+ if (ret && option) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "ganesha.enable "
|
|
|
d1681e |
+ "is already 'on'.");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ } else if (!option && !ret) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "ganesha.enable "
|
|
|
d1681e |
+ "is already 'off'.");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* Check if global option is enabled, proceed only then */
|
|
|
d1681e |
+ ret = dict_get_str_boolean (priv->opts,
|
|
|
d1681e |
+ GLUSTERD_STORE_KEY_GANESHA_GLOBAL, _gf_false);
|
|
|
d1681e |
+ if (ret == -1) {
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0, "Failed to get "
|
|
|
d1681e |
+ "global option dict.");
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "The option "
|
|
|
d1681e |
+ "nfs-ganesha should be "
|
|
|
d1681e |
+ "enabled before setting ganesha.enable.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ if (!ret) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "The option "
|
|
|
d1681e |
+ "nfs-ganesha should be "
|
|
|
d1681e |
+ "enabled before setting ganesha.enable.");
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* *
|
|
|
d1681e |
+ * Create the export file from the node where ganesha.enable "on"
|
|
|
d1681e |
+ * is executed
|
|
|
d1681e |
+ * */
|
|
|
d1681e |
+ if (option) {
|
|
|
d1681e |
+ ret = manage_export_config (volname, "on", op_errstr);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_EXPORT_FILE_CREATE_FAIL,
|
|
|
d1681e |
+ "Failed to create"
|
|
|
d1681e |
+ "export file for NFS-Ganesha\n");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (check_host_list()) {
|
|
|
d1681e |
+ runner_add_args (&runner, "sh", GANESHA_PREFIX"/dbus-send.sh",
|
|
|
d1681e |
+ CONFDIR, value, volname, NULL);
|
|
|
d1681e |
+ ret = runner_run (&runner);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_asprintf(op_errstr, "Dynamic export"
|
|
|
d1681e |
+ " addition/deletion failed."
|
|
|
d1681e |
+ " Please see log file for details");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ vol_opts = volinfo->dict;
|
|
|
d1681e |
+ ret = dict_set_dynstr_with_alloc (vol_opts,
|
|
|
d1681e |
+ "features.cache-invalidation", value);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "Cache-invalidation could not"
|
|
|
d1681e |
+ " be set to %s.", value);
|
|
|
d1681e |
+ ret = glusterd_store_volinfo (volinfo,
|
|
|
d1681e |
+ GLUSTERD_VOLINFO_VER_AC_INCREMENT);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "failed to store volinfo for %s"
|
|
|
d1681e |
+ , volinfo->volname);
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+tear_down_cluster(gf_boolean_t run_teardown)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+ struct stat st = {0,};
|
|
|
d1681e |
+ DIR *dir = NULL;
|
|
|
d1681e |
+ struct dirent *entry = NULL;
|
|
|
d1681e |
+ struct dirent scratch[2] = {{0,},};
|
|
|
d1681e |
+ char path[PATH_MAX] = {0,};
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (run_teardown) {
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, "sh",
|
|
|
d1681e |
+ GANESHA_PREFIX"/ganesha-ha.sh", "teardown",
|
|
|
d1681e |
+ CONFDIR, NULL);
|
|
|
d1681e |
+ ret = runner_run(&runner);
|
|
|
d1681e |
+ /* *
|
|
|
d1681e |
+ * Remove all the entries in CONFDIR expect ganesha.conf and
|
|
|
d1681e |
+ * ganesha-ha.conf
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ dir = sys_opendir (CONFDIR);
|
|
|
d1681e |
+ if (!dir) {
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "Failed to open directory %s. "
|
|
|
d1681e |
+ "Reason : %s", CONFDIR, strerror (errno));
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_FOR_EACH_ENTRY_IN_DIR (entry, dir, scratch);
|
|
|
d1681e |
+ while (entry) {
|
|
|
d1681e |
+ snprintf (path, PATH_MAX, "%s/%s", CONFDIR, entry->d_name);
|
|
|
d1681e |
+ ret = sys_lstat (path, &st);
|
|
|
d1681e |
+ if (ret == -1) {
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "Failed to stat entry %s :"
|
|
|
d1681e |
+ " %s", path, strerror (errno));
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (strcmp(entry->d_name, "ganesha.conf") == 0 ||
|
|
|
d1681e |
+ strcmp(entry->d_name, "ganesha-ha.conf") == 0)
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, " %s is not required"
|
|
|
d1681e |
+ " to remove", path);
|
|
|
d1681e |
+ else if (S_ISDIR (st.st_mode))
|
|
|
d1681e |
+ ret = recursive_rmdir (path);
|
|
|
d1681e |
+ else
|
|
|
d1681e |
+ ret = sys_unlink (path);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, " Failed to remove %s. "
|
|
|
d1681e |
+ "Reason : %s", path, strerror (errno));
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "%s %s", ret ?
|
|
|
d1681e |
+ "Failed to remove" : "Removed", entry->d_name);
|
|
|
d1681e |
+ GF_FOR_EACH_ENTRY_IN_DIR (entry, dir, scratch);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = sys_closedir (dir);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "Failed to close dir %s. Reason :"
|
|
|
d1681e |
+ " %s", CONFDIR, strerror (errno));
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+setup_cluster(gf_boolean_t run_setup)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (run_setup) {
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, "sh", GANESHA_PREFIX"/ganesha-ha.sh",
|
|
|
d1681e |
+ "setup", CONFDIR, NULL);
|
|
|
d1681e |
+ ret = runner_run (&runner);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+static int
|
|
|
d1681e |
+teardown (gf_boolean_t run_teardown, char **op_errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+ int ret = 1;
|
|
|
d1681e |
+ glusterd_volinfo_t *volinfo = NULL;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ dict_t *vol_opts = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ priv = THIS->private;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = tear_down_cluster (run_teardown);
|
|
|
d1681e |
+ if (ret == -1) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "Cleanup of NFS-Ganesha"
|
|
|
d1681e |
+ " HA config failed.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, "sh", GANESHA_PREFIX"/ganesha-ha.sh",
|
|
|
d1681e |
+ "cleanup", CONFDIR, NULL);
|
|
|
d1681e |
+ ret = runner_run (&runner);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg_debug (THIS->name, 0, "Could not clean up"
|
|
|
d1681e |
+ " NFS-Ganesha related config");
|
|
|
d1681e |
+
|
|
|
d1681e |
+ cds_list_for_each_entry (volinfo, &priv->volumes, vol_list) {
|
|
|
d1681e |
+ vol_opts = volinfo->dict;
|
|
|
d1681e |
+ /* All the volumes exported via NFS-Ganesha will be
|
|
|
d1681e |
+ unexported, hence setting the appropriate keys */
|
|
|
d1681e |
+ ret = dict_set_str (vol_opts, "features.cache-invalidation",
|
|
|
d1681e |
+ "off");
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_WARNING, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_SET_FAILED,
|
|
|
d1681e |
+ "Could not set features.cache-invalidation "
|
|
|
d1681e |
+ "to off for %s", volinfo->volname);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_set_str (vol_opts, "ganesha.enable", "off");
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_WARNING, errno,
|
|
|
d1681e |
+ GD_MSG_DICT_SET_FAILED,
|
|
|
d1681e |
+ "Could not set ganesha.enable to off for %s",
|
|
|
d1681e |
+ volinfo->volname);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_store_volinfo (volinfo,
|
|
|
d1681e |
+ GLUSTERD_VOLINFO_VER_AC_INCREMENT);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_WARNING, 0,
|
|
|
d1681e |
+ GD_MSG_VOLINFO_SET_FAIL,
|
|
|
d1681e |
+ "failed to store volinfo for %s",
|
|
|
d1681e |
+ volinfo->volname);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+stop_ganesha (char **op_errstr) {
|
|
|
d1681e |
+
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, "sh", GANESHA_PREFIX"/ganesha-ha.sh",
|
|
|
d1681e |
+ "--setup-ganesha-conf-files", CONFDIR, "no", NULL);
|
|
|
d1681e |
+ ret = runner_run (&runner);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "removal of symlink ganesha.conf "
|
|
|
d1681e |
+ "in /etc/ganesha failed");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (check_host_list ()) {
|
|
|
d1681e |
+ ret = manage_service ("stop");
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "NFS-Ganesha service could not"
|
|
|
d1681e |
+ "be stopped.");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+start_ganesha (char **op_errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ dict_t *vol_opts = NULL;
|
|
|
d1681e |
+ glusterd_volinfo_t *volinfo = NULL;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ runner_t runner = {0,};
|
|
|
d1681e |
+
|
|
|
d1681e |
+ priv = THIS->private;
|
|
|
d1681e |
+ GF_ASSERT (priv);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ cds_list_for_each_entry (volinfo, &priv->volumes, vol_list) {
|
|
|
d1681e |
+ vol_opts = volinfo->dict;
|
|
|
d1681e |
+ /* Gluster-nfs has to be disabled across the trusted pool */
|
|
|
d1681e |
+ /* before attempting to start nfs-ganesha */
|
|
|
d1681e |
+ ret = dict_set_str (vol_opts, NFS_DISABLE_MAP_KEY, "on");
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_store_volinfo (volinfo,
|
|
|
d1681e |
+ GLUSTERD_VOLINFO_VER_AC_INCREMENT);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ *op_errstr = gf_strdup ("Failed to store the "
|
|
|
d1681e |
+ "Volume information");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* If the nfs svc is not initialized it means that the service is not
|
|
|
d1681e |
+ * running, hence we can skip the process of stopping gluster-nfs
|
|
|
d1681e |
+ * service
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ if (priv->nfs_svc.inited) {
|
|
|
d1681e |
+ ret = priv->nfs_svc.stop (&(priv->nfs_svc), SIGKILL);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "Gluster-NFS service could"
|
|
|
d1681e |
+ "not be stopped, exiting.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (check_host_list()) {
|
|
|
d1681e |
+ runinit (&runner);
|
|
|
d1681e |
+ runner_add_args (&runner, "sh", GANESHA_PREFIX"/ganesha-ha.sh",
|
|
|
d1681e |
+ "--setup-ganesha-conf-files", CONFDIR, "yes",
|
|
|
d1681e |
+ NULL);
|
|
|
d1681e |
+ ret = runner_run (&runner);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "creation of symlink ganesha.conf "
|
|
|
d1681e |
+ "in /etc/ganesha failed");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ ret = manage_service ("start");
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "NFS-Ganesha failed to start."
|
|
|
d1681e |
+ "Please see log file for details");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+static int
|
|
|
d1681e |
+pre_setup (gf_boolean_t run_setup, char **op_errstr)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = 0;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = check_host_list();
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ ret = setup_cluster(run_setup);
|
|
|
d1681e |
+ if (ret == -1)
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "Failed to set up HA "
|
|
|
d1681e |
+ "config for NFS-Ganesha. "
|
|
|
d1681e |
+ "Please check the log file for details");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_handle_ganesha_op (dict_t *dict, char **op_errstr,
|
|
|
d1681e |
+ char *key, char *value)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+
|
|
|
d1681e |
+ int32_t ret = -1;
|
|
|
d1681e |
+ gf_boolean_t option = _gf_false;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT (dict);
|
|
|
d1681e |
+ GF_ASSERT (op_errstr);
|
|
|
d1681e |
+ GF_ASSERT (key);
|
|
|
d1681e |
+ GF_ASSERT (value);
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (strcmp (key, "ganesha.enable") == 0) {
|
|
|
d1681e |
+ ret = ganesha_manage_export (dict, value, op_errstr);
|
|
|
d1681e |
+ if (ret < 0)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* It is possible that the key might not be set */
|
|
|
d1681e |
+ ret = gf_string2boolean (value, &option);
|
|
|
d1681e |
+ if (ret == -1) {
|
|
|
d1681e |
+ gf_asprintf (op_errstr, "Invalid value in key-value pair.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (strcmp (key, GLUSTERD_STORE_KEY_GANESHA_GLOBAL) == 0) {
|
|
|
d1681e |
+ /* *
|
|
|
d1681e |
+ * The set up/teardown of pcs cluster should be performed only
|
|
|
d1681e |
+ * once. This will done on the node in which the cli command
|
|
|
d1681e |
+ * 'gluster nfs-ganesha <enable/disable>' got executed. So that
|
|
|
d1681e |
+ * node should part of ganesha HA cluster
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ if (option) {
|
|
|
d1681e |
+ ret = pre_setup (is_origin_glusterd (dict), op_errstr);
|
|
|
d1681e |
+ if (ret < 0)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ ret = teardown (is_origin_glusterd (dict), op_errstr);
|
|
|
d1681e |
+ if (ret < 0)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
|
|
|
d1681e |
index c3b9252..a3e1fdc 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
|
|
|
d1681e |
@@ -1884,6 +1884,82 @@ glusterd_op_begin (rpcsvc_request_t *req, glusterd_op_t op, void *ctx,
|
|
|
d1681e |
return ret;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+int
|
|
|
d1681e |
+__glusterd_handle_ganesha_cmd (rpcsvc_request_t *req)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int32_t ret = -1;
|
|
|
d1681e |
+ gf_cli_req cli_req = { {0,} } ;
|
|
|
d1681e |
+ dict_t *dict = NULL;
|
|
|
d1681e |
+ glusterd_op_t cli_op = GD_OP_GANESHA;
|
|
|
d1681e |
+ char *op_errstr = NULL;
|
|
|
d1681e |
+ char err_str[2048] = {0,};
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_ASSERT (this);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_ASSERT (req);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
|
|
|
d1681e |
+ if (ret < 0) {
|
|
|
d1681e |
+ snprintf (err_str, sizeof (err_str), "Failed to decode "
|
|
|
d1681e |
+ "request received from cli");
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_REQ_DECODE_FAIL, "%s", err_str);
|
|
|
d1681e |
+ req->rpc_err = GARBAGE_ARGS;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (cli_req.dict.dict_len) {
|
|
|
d1681e |
+ /* Unserialize the dictionary */
|
|
|
d1681e |
+ dict = dict_new ();
|
|
|
d1681e |
+ if (!dict) {
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = dict_unserialize (cli_req.dict.dict_val,
|
|
|
d1681e |
+ cli_req.dict.dict_len,
|
|
|
d1681e |
+ &dict);
|
|
|
d1681e |
+ if (ret < 0) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_DICT_UNSERIALIZE_FAIL,
|
|
|
d1681e |
+ "failed to "
|
|
|
d1681e |
+ "unserialize req-buffer to dictionary");
|
|
|
d1681e |
+ snprintf (err_str, sizeof (err_str), "Unable to decode "
|
|
|
d1681e |
+ "the command");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ dict->extra_stdfree = cli_req.dict.dict_val;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ gf_msg_trace (this->name, 0, "Received global option request");
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_op_begin_synctask (req, GD_OP_GANESHA, dict);
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ if (err_str[0] == '\0')
|
|
|
d1681e |
+ snprintf (err_str, sizeof (err_str),
|
|
|
d1681e |
+ "Operation failed");
|
|
|
d1681e |
+ ret = glusterd_op_send_cli_response (cli_op, ret, 0, req,
|
|
|
d1681e |
+ dict, err_str);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ if (op_errstr)
|
|
|
d1681e |
+ GF_FREE (op_errstr);
|
|
|
d1681e |
+ if (dict)
|
|
|
d1681e |
+ dict_unref(dict);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_handle_ganesha_cmd (rpcsvc_request_t *req)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ return glusterd_big_locked_handler (req, __glusterd_handle_ganesha_cmd);
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
static int
|
|
|
d1681e |
__glusterd_handle_reset_volume (rpcsvc_request_t *req)
|
|
|
d1681e |
{
|
|
|
d1681e |
@@ -6470,6 +6546,7 @@ rpcsvc_actor_t gd_svc_cli_actors[GLUSTER_CLI_MAXVALUE] = {
|
|
|
d1681e |
[GLUSTER_CLI_SYS_EXEC] = {"SYS_EXEC", GLUSTER_CLI_SYS_EXEC, glusterd_handle_sys_exec, NULL, 0, DRC_NA},
|
|
|
d1681e |
[GLUSTER_CLI_SNAP] = {"SNAP", GLUSTER_CLI_SNAP, glusterd_handle_snapshot, NULL, 0, DRC_NA},
|
|
|
d1681e |
[GLUSTER_CLI_BARRIER_VOLUME] = {"BARRIER_VOLUME", GLUSTER_CLI_BARRIER_VOLUME, glusterd_handle_barrier, NULL, 0, DRC_NA},
|
|
|
d1681e |
+ [GLUSTER_CLI_GANESHA] = { "GANESHA" , GLUSTER_CLI_GANESHA, glusterd_handle_ganesha_cmd, NULL, 0, DRC_NA},
|
|
|
d1681e |
[GLUSTER_CLI_GET_VOL_OPT] = {"GET_VOL_OPT", GLUSTER_CLI_GET_VOL_OPT, glusterd_handle_get_vol_opt, NULL, 0, DRC_NA},
|
|
|
d1681e |
[GLUSTER_CLI_BITROT] = {"BITROT", GLUSTER_CLI_BITROT, glusterd_handle_bitrot, NULL, 0, DRC_NA},
|
|
|
d1681e |
[GLUSTER_CLI_GET_STATE] = {"GET_STATE", GLUSTER_CLI_GET_STATE, glusterd_handle_get_state, NULL, 0, DRC_NA},
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-messages.h b/xlators/mgmt/glusterd/src/glusterd-messages.h
|
|
|
d1681e |
index de9ae92..cc7f371 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-messages.h
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-messages.h
|
|
|
d1681e |
@@ -4767,6 +4767,14 @@
|
|
|
d1681e |
* @recommendedaction
|
|
|
d1681e |
*
|
|
|
d1681e |
*/
|
|
|
d1681e |
+#define GD_MSG_NFS_GANESHA_DISABLED (GLUSTERD_COMP_BASE + 589)
|
|
|
d1681e |
+
|
|
|
d1681e |
+/*!
|
|
|
d1681e |
+ * @messageid
|
|
|
d1681e |
+ * @diagnosis
|
|
|
d1681e |
+ * @recommendedaction
|
|
|
d1681e |
+ *
|
|
|
d1681e |
+ */
|
|
|
d1681e |
#define GD_MSG_TIERD_STOP_FAIL (GLUSTERD_COMP_BASE + 590)
|
|
|
d1681e |
|
|
|
d1681e |
/*!
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
|
|
|
d1681e |
index 5b8f833..06e9e25 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
|
|
|
d1681e |
@@ -1126,6 +1126,12 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr)
|
|
|
d1681e |
if (ret)
|
|
|
d1681e |
goto out;
|
|
|
d1681e |
|
|
|
d1681e |
+ if ((strcmp (key, "ganesha.enable") == 0) &&
|
|
|
d1681e |
+ (strcmp (value, "off") == 0)) {
|
|
|
d1681e |
+ ret = ganesha_manage_export (dict, "off", op_errstr);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
ret = glusterd_check_quota_cmd (key, value, errstr, sizeof (errstr));
|
|
|
d1681e |
if (ret)
|
|
|
d1681e |
goto out;
|
|
|
d1681e |
@@ -1642,6 +1648,21 @@ glusterd_op_stage_reset_volume (dict_t *dict, char **op_errstr)
|
|
|
d1681e |
goto out;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ /* *
|
|
|
d1681e |
+ * If key ganesha.enable is set, then volume should be unexported from
|
|
|
d1681e |
+ * ganesha server. Also it is a volume-level option, perform only when
|
|
|
d1681e |
+ * volume name not equal to "all"(in other words if volinfo != NULL)
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ if (volinfo && (!strcmp (key, "all") || !strcmp(key, "ganesha.enable"))) {
|
|
|
d1681e |
+ if (glusterd_check_ganesha_export (volinfo)) {
|
|
|
d1681e |
+ ret = ganesha_manage_export (dict, "off", op_errstr);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_WARNING, 0,
|
|
|
d1681e |
+ GD_MSG_NFS_GNS_RESET_FAIL,
|
|
|
d1681e |
+ "Could not reset ganesha.enable key");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
if (strcmp(key, "all")) {
|
|
|
d1681e |
exists = glusterd_check_option_exists (key, &key_fixed);
|
|
|
d1681e |
if (exists == -1) {
|
|
|
d1681e |
@@ -2364,6 +2385,16 @@ glusterd_op_reset_volume (dict_t *dict, char **op_rspstr)
|
|
|
d1681e |
}
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ if (!strcmp(key, "ganesha.enable") || !strcmp (key, "all")) {
|
|
|
d1681e |
+ if (glusterd_check_ganesha_export (volinfo)) {
|
|
|
d1681e |
+ ret = manage_export_config (volname, "off", op_rspstr);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_WARNING, 0,
|
|
|
d1681e |
+ GD_MSG_NFS_GNS_RESET_FAIL,
|
|
|
d1681e |
+ "Could not reset ganesha.enable key");
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
out:
|
|
|
d1681e |
GF_FREE (key_fixed);
|
|
|
d1681e |
if (quorum_action)
|
|
|
d1681e |
@@ -2960,6 +2991,9 @@ glusterd_op_set_volume (dict_t *dict, char **errstr)
|
|
|
d1681e |
}
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ ret = glusterd_check_ganesha_cmd (key, value, errstr, dict);
|
|
|
d1681e |
+ if (ret == -1)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
if (!is_key_glusterd_hooks_friendly (key)) {
|
|
|
d1681e |
ret = glusterd_check_option_exists (key, &key_fixed);
|
|
|
d1681e |
GF_ASSERT (ret);
|
|
|
d1681e |
@@ -4568,6 +4602,12 @@ glusterd_op_build_payload (dict_t **req, char **op_errstr, dict_t *op_ctx)
|
|
|
d1681e |
}
|
|
|
d1681e |
break;
|
|
|
d1681e |
|
|
|
d1681e |
+ case GD_OP_GANESHA:
|
|
|
d1681e |
+ {
|
|
|
d1681e |
+ dict_copy (dict, req_dict);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ break;
|
|
|
d1681e |
+
|
|
|
d1681e |
default:
|
|
|
d1681e |
break;
|
|
|
d1681e |
}
|
|
|
d1681e |
@@ -6062,6 +6102,10 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr,
|
|
|
d1681e |
ret = glusterd_op_stage_set_volume (dict, op_errstr);
|
|
|
d1681e |
break;
|
|
|
d1681e |
|
|
|
d1681e |
+ case GD_OP_GANESHA:
|
|
|
d1681e |
+ ret = glusterd_op_stage_set_ganesha (dict, op_errstr);
|
|
|
d1681e |
+ break;
|
|
|
d1681e |
+
|
|
|
d1681e |
case GD_OP_RESET_VOLUME:
|
|
|
d1681e |
ret = glusterd_op_stage_reset_volume (dict, op_errstr);
|
|
|
d1681e |
break;
|
|
|
d1681e |
@@ -6195,6 +6239,9 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr,
|
|
|
d1681e |
case GD_OP_SET_VOLUME:
|
|
|
d1681e |
ret = glusterd_op_set_volume (dict, op_errstr);
|
|
|
d1681e |
break;
|
|
|
d1681e |
+ case GD_OP_GANESHA:
|
|
|
d1681e |
+ ret = glusterd_op_set_ganesha (dict, op_errstr);
|
|
|
d1681e |
+ break;
|
|
|
d1681e |
|
|
|
d1681e |
|
|
|
d1681e |
case GD_OP_RESET_VOLUME:
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
|
|
|
d1681e |
index 4cbade1..2a0d321 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c
|
|
|
d1681e |
@@ -3702,6 +3702,146 @@ out:
|
|
|
d1681e |
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+/* *
|
|
|
d1681e |
+ * Here there are two possibilities, either destination is snaphot or
|
|
|
d1681e |
+ * clone. In the case of snapshot nfs_ganesha export file will be copied
|
|
|
d1681e |
+ * to snapdir. If it is clone , then new export file will be created for
|
|
|
d1681e |
+ * the clone in the GANESHA_EXPORT_DIRECTORY, replacing occurences of
|
|
|
d1681e |
+ * volname with clonename
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_copy_nfs_ganesha_file (glusterd_volinfo_t *src_vol,
|
|
|
d1681e |
+ glusterd_volinfo_t *dest_vol)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+
|
|
|
d1681e |
+ int32_t ret = -1;
|
|
|
d1681e |
+ char snap_dir[PATH_MAX] = {0,};
|
|
|
d1681e |
+ char src_path[PATH_MAX] = {0,};
|
|
|
d1681e |
+ char dest_path[PATH_MAX] = {0,};
|
|
|
d1681e |
+ char buffer[BUFSIZ] = {0,};
|
|
|
d1681e |
+ char *find_ptr = NULL;
|
|
|
d1681e |
+ char *buff_ptr = NULL;
|
|
|
d1681e |
+ char *tmp_ptr = NULL;
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ struct stat stbuf = {0,};
|
|
|
d1681e |
+ FILE *src = NULL;
|
|
|
d1681e |
+ FILE *dest = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO ("snapshot", this, out);
|
|
|
d1681e |
+ priv = this->private;
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, priv, out);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, src_vol, out);
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, dest_vol, out);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (glusterd_check_ganesha_export(src_vol) == _gf_false) {
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0, "%s is not exported via "
|
|
|
d1681e |
+ "NFS-Ganesha. Skipping copy of export conf.",
|
|
|
d1681e |
+ src_vol->volname);
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (src_vol->is_snap_volume) {
|
|
|
d1681e |
+ GLUSTERD_GET_SNAP_DIR (snap_dir, src_vol->snapshot, priv);
|
|
|
d1681e |
+ ret = snprintf (src_path, PATH_MAX, "%s/export.%s.conf",
|
|
|
d1681e |
+ snap_dir, src_vol->snapshot->snapname);
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ ret = snprintf (src_path, PATH_MAX, "%s/export.%s.conf",
|
|
|
d1681e |
+ GANESHA_EXPORT_DIRECTORY, src_vol->volname);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ if (ret < 0 || ret >= PATH_MAX)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = sys_lstat (src_path, &stbuf);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ /*
|
|
|
d1681e |
+ * This code path is hit, only when the src_vol is being *
|
|
|
d1681e |
+ * exported via NFS-Ganesha. So if the conf file is not *
|
|
|
d1681e |
+ * available, we fail the snapshot operation. *
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, errno,
|
|
|
d1681e |
+ GD_MSG_FILE_OP_FAILED,
|
|
|
d1681e |
+ "Stat on %s failed with %s",
|
|
|
d1681e |
+ src_path, strerror (errno));
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (dest_vol->is_snap_volume) {
|
|
|
d1681e |
+ memset (snap_dir, 0 , PATH_MAX);
|
|
|
d1681e |
+ GLUSTERD_GET_SNAP_DIR (snap_dir, dest_vol->snapshot, priv);
|
|
|
d1681e |
+ ret = snprintf (dest_path, sizeof (dest_path),
|
|
|
d1681e |
+ "%s/export.%s.conf", snap_dir,
|
|
|
d1681e |
+ dest_vol->snapshot->snapname);
|
|
|
d1681e |
+ if (ret < 0)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_copy_file (src_path, dest_path);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
|
|
|
d1681e |
+ GD_MSG_NO_MEMORY, "Failed to copy %s in %s",
|
|
|
d1681e |
+ src_path, dest_path);
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ ret = snprintf (dest_path, sizeof (dest_path),
|
|
|
d1681e |
+ "%s/export.%s.conf", GANESHA_EXPORT_DIRECTORY,
|
|
|
d1681e |
+ dest_vol->volname);
|
|
|
d1681e |
+ if (ret < 0)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ src = fopen (src_path, "r");
|
|
|
d1681e |
+ dest = fopen (dest_path, "w");
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (!src || !dest) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_FILE_OP_FAILED,
|
|
|
d1681e |
+ "Failed to open %s",
|
|
|
d1681e |
+ dest ? src_path : dest_path);
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* *
|
|
|
d1681e |
+ * if the source volume is snapshot, the export conf file
|
|
|
d1681e |
+ * consists of orginal volname
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ if (src_vol->is_snap_volume)
|
|
|
d1681e |
+ find_ptr = gf_strdup (src_vol->parent_volname);
|
|
|
d1681e |
+ else
|
|
|
d1681e |
+ find_ptr = gf_strdup (src_vol->volname);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ if (!find_ptr)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /* Replacing volname with clonename */
|
|
|
d1681e |
+ while (fgets(buffer, BUFSIZ, src)) {
|
|
|
d1681e |
+ buff_ptr = buffer;
|
|
|
d1681e |
+ while ((tmp_ptr = strstr(buff_ptr, find_ptr))) {
|
|
|
d1681e |
+ while (buff_ptr < tmp_ptr)
|
|
|
d1681e |
+ fputc((int)*buff_ptr++, dest);
|
|
|
d1681e |
+ fputs(dest_vol->volname, dest);
|
|
|
d1681e |
+ buff_ptr += strlen(find_ptr);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ fputs(buff_ptr, dest);
|
|
|
d1681e |
+ memset (buffer, 0, BUFSIZ);
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ if (src)
|
|
|
d1681e |
+ fclose (src);
|
|
|
d1681e |
+ if (dest)
|
|
|
d1681e |
+ fclose (dest);
|
|
|
d1681e |
+ if (find_ptr)
|
|
|
d1681e |
+ GF_FREE(find_ptr);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
int32_t
|
|
|
d1681e |
glusterd_restore_geo_rep_files (glusterd_volinfo_t *snap_vol)
|
|
|
d1681e |
{
|
|
|
d1681e |
@@ -3792,6 +3932,62 @@ out:
|
|
|
d1681e |
return ret;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_restore_nfs_ganesha_file (glusterd_volinfo_t *src_vol,
|
|
|
d1681e |
+ glusterd_snap_t *snap)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+
|
|
|
d1681e |
+ int32_t ret = -1;
|
|
|
d1681e |
+ char snap_dir[PATH_MAX] = "";
|
|
|
d1681e |
+ char src_path[PATH_MAX] = "";
|
|
|
d1681e |
+ char dest_path[PATH_MAX] = "";
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+ glusterd_conf_t *priv = NULL;
|
|
|
d1681e |
+ struct stat stbuf = {0,};
|
|
|
d1681e |
+
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO ("snapshot", this, out);
|
|
|
d1681e |
+ priv = this->private;
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, priv, out);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, src_vol, out);
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, snap, out);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GLUSTERD_GET_SNAP_DIR (snap_dir, snap, priv);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = snprintf (src_path, sizeof (src_path), "%s/export.%s.conf",
|
|
|
d1681e |
+ snap_dir, snap->snapname);
|
|
|
d1681e |
+ if (ret < 0)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = sys_lstat (src_path, &stbuf);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ if (errno == ENOENT) {
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0, "%s not found", src_path);
|
|
|
d1681e |
+ } else
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_WARNING, errno,
|
|
|
d1681e |
+ GD_MSG_FILE_OP_FAILED,
|
|
|
d1681e |
+ "Stat on %s failed with %s",
|
|
|
d1681e |
+ src_path, strerror (errno));
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = snprintf (dest_path, sizeof (dest_path), "%s/export.%s.conf",
|
|
|
d1681e |
+ GANESHA_EXPORT_DIRECTORY, src_vol->volname);
|
|
|
d1681e |
+ if (ret < 0)
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = glusterd_copy_file (src_path, dest_path);
|
|
|
d1681e |
+ if (ret)
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
|
|
|
d1681e |
+ GD_MSG_NO_MEMORY, "Failed to copy %s in %s",
|
|
|
d1681e |
+ src_path, dest_path);
|
|
|
d1681e |
+
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+
|
|
|
d1681e |
+}
|
|
|
d1681e |
/* Snapd functions */
|
|
|
d1681e |
int
|
|
|
d1681e |
glusterd_is_snapd_enabled (glusterd_volinfo_t *volinfo)
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h
|
|
|
d1681e |
index b13493d..e050166 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h
|
|
|
d1681e |
@@ -99,12 +99,19 @@ glusterd_get_geo_rep_session (char *slave_key, char *origin_volname,
|
|
|
d1681e |
int32_t
|
|
|
d1681e |
glusterd_restore_geo_rep_files (glusterd_volinfo_t *snap_vol);
|
|
|
d1681e |
|
|
|
d1681e |
+int
|
|
|
d1681e |
+glusterd_restore_nfs_ganesha_file (glusterd_volinfo_t *src_vol,
|
|
|
d1681e |
+ glusterd_snap_t *snap);
|
|
|
d1681e |
int32_t
|
|
|
d1681e |
glusterd_copy_quota_files (glusterd_volinfo_t *src_vol,
|
|
|
d1681e |
glusterd_volinfo_t *dest_vol,
|
|
|
d1681e |
gf_boolean_t *conf_present);
|
|
|
d1681e |
|
|
|
d1681e |
int
|
|
|
d1681e |
+glusterd_copy_nfs_ganesha_file (glusterd_volinfo_t *src_vol,
|
|
|
d1681e |
+ glusterd_volinfo_t *dest_vol);
|
|
|
d1681e |
+
|
|
|
d1681e |
+int
|
|
|
d1681e |
glusterd_snap_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict);
|
|
|
d1681e |
|
|
|
d1681e |
int
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
|
|
|
d1681e |
index 6306d29..c38d2ff 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c
|
|
|
d1681e |
@@ -904,6 +904,76 @@ out:
|
|
|
d1681e |
return ret;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+/*
|
|
|
d1681e |
+ * This function validates the particulat snapshot with respect to the current
|
|
|
d1681e |
+ * cluster. If the snapshot has ganesha enabled, and the cluster is not a nfs
|
|
|
d1681e |
+ * ganesha cluster, we fail the validation. Other scenarios where either the
|
|
|
d1681e |
+ * snapshot does not have ganesha enabled or it has and the cluster is a nfs
|
|
|
d1681e |
+ * ganesha cluster, we pass the validation
|
|
|
d1681e |
+ *
|
|
|
d1681e |
+ * @param snap snap object of the snapshot to be validated
|
|
|
d1681e |
+ * @return Negative value on Failure and 0 in success
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+int32_t
|
|
|
d1681e |
+glusterd_snapshot_validate_ganesha_conf (glusterd_snap_t *snap,
|
|
|
d1681e |
+ char **op_errstr,
|
|
|
d1681e |
+ uint32_t *op_errno)
|
|
|
d1681e |
+{
|
|
|
d1681e |
+ int ret = -1;
|
|
|
d1681e |
+ glusterd_volinfo_t *snap_vol = NULL;
|
|
|
d1681e |
+ xlator_t *this = NULL;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ this = THIS;
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO ("snapshot", this, out);
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, snap, out);
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, op_errstr, out);
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, op_errno, out);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ snap_vol = list_entry (snap->volumes.next,
|
|
|
d1681e |
+ glusterd_volinfo_t, vol_list);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ GF_VALIDATE_OR_GOTO (this->name, snap_vol, out);
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /*
|
|
|
d1681e |
+ * Check if the snapshot has ganesha enabled *
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ if (glusterd_check_ganesha_export(snap_vol) == _gf_false) {
|
|
|
d1681e |
+ /*
|
|
|
d1681e |
+ * If the snapshot has not been exported via ganesha *
|
|
|
d1681e |
+ * then we can proceed. *
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ /*
|
|
|
d1681e |
+ * At this point we are certain that the snapshot has been exported *
|
|
|
d1681e |
+ * via ganesha. So we check if the cluster is a nfs-ganesha cluster *
|
|
|
d1681e |
+ * If it a nfs-ganesha cluster, then we proceed. Else we fail. *
|
|
|
d1681e |
+ */
|
|
|
d1681e |
+ if (glusterd_is_ganesha_cluster() != _gf_true) {
|
|
|
d1681e |
+ ret = gf_asprintf (op_errstr, "Snapshot(%s) has a "
|
|
|
d1681e |
+ "nfs-ganesha export conf file. "
|
|
|
d1681e |
+ "cluster.enable-shared-storage and "
|
|
|
d1681e |
+ "nfs-ganesha should be enabled "
|
|
|
d1681e |
+ "before restoring this snapshot.",
|
|
|
d1681e |
+ snap->snapname);
|
|
|
d1681e |
+ *op_errno = EG_NOGANESHA;
|
|
|
d1681e |
+ if (ret < 0) {
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, EINVAL,
|
|
|
d1681e |
+ GD_MSG_NFS_GANESHA_DISABLED, "%s", *op_errstr);
|
|
|
d1681e |
+ ret = -1;
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+out:
|
|
|
d1681e |
+ return ret;
|
|
|
d1681e |
+}
|
|
|
d1681e |
+
|
|
|
d1681e |
/* This function is called before actual restore is taken place. This function
|
|
|
d1681e |
* will validate whether the snapshot volumes are ready to be restored or not.
|
|
|
d1681e |
*
|
|
|
d1681e |
@@ -974,6 +1044,15 @@ glusterd_snapshot_restore_prevalidate (dict_t *dict, char **op_errstr,
|
|
|
d1681e |
goto out;
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ ret = glusterd_snapshot_validate_ganesha_conf (snap, op_errstr,
|
|
|
d1681e |
+ op_errno);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_SNAPSHOT_OP_FAILED,
|
|
|
d1681e |
+ "ganesha conf validation failed.");
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
ret = dict_set_str (rsp_dict, "snapname", snapname);
|
|
|
d1681e |
if (ret) {
|
|
|
d1681e |
gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
@@ -5369,6 +5448,13 @@ glusterd_do_snap_vol (glusterd_volinfo_t *origin_vol, glusterd_snap_t *snap,
|
|
|
d1681e |
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ ret = glusterd_copy_nfs_ganesha_file (origin_vol, snap_vol);
|
|
|
d1681e |
+ if (ret < 0) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_VOL_OP_FAILED, "Failed to copy export "
|
|
|
d1681e |
+ "file for volume %s", origin_vol->volname);
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
glusterd_auth_set_username (snap_vol, username);
|
|
|
d1681e |
glusterd_auth_set_password (snap_vol, password);
|
|
|
d1681e |
|
|
|
d1681e |
@@ -9968,6 +10054,16 @@ gd_restore_snap_volume (dict_t *dict, dict_t *rsp_dict,
|
|
|
d1681e |
snap_vol->snapshot->snapname);
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ ret = glusterd_restore_nfs_ganesha_file (orig_vol, snap);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_WARNING, 0,
|
|
|
d1681e |
+ GD_MSG_SNAP_RESTORE_FAIL,
|
|
|
d1681e |
+ "Failed to restore "
|
|
|
d1681e |
+ "nfs-ganesha export file for snap %s",
|
|
|
d1681e |
+ snap_vol->snapshot->snapname);
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
/* Need not save cksum, as we will copy cksum file in *
|
|
|
d1681e |
* this function *
|
|
|
d1681e |
*/
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h
|
|
|
d1681e |
index 603151a..bf504e0 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-store.h
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-store.h
|
|
|
d1681e |
@@ -83,6 +83,7 @@ typedef enum glusterd_store_ver_ac_{
|
|
|
d1681e |
#define GLUSTERD_STORE_KEY_SNAP_MAX_SOFT_LIMIT "snap-max-soft-limit"
|
|
|
d1681e |
#define GLUSTERD_STORE_KEY_SNAPD_PORT "snapd-port"
|
|
|
d1681e |
#define GLUSTERD_STORE_KEY_SNAP_ACTIVATE "snap-activate-on-create"
|
|
|
d1681e |
+#define GLUSTERD_STORE_KEY_GANESHA_GLOBAL "nfs-ganesha"
|
|
|
d1681e |
|
|
|
d1681e |
#define GLUSTERD_STORE_KEY_BRICK_HOSTNAME "hostname"
|
|
|
d1681e |
#define GLUSTERD_STORE_KEY_BRICK_PATH "path"
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
|
|
|
d1681e |
index bec5f72..0914fb1 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
|
|
|
d1681e |
@@ -1737,6 +1737,16 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr)
|
|
|
d1681e |
ret = -1;
|
|
|
d1681e |
goto out;
|
|
|
d1681e |
}
|
|
|
d1681e |
+ ret = glusterd_check_ganesha_export (volinfo);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ ret = ganesha_manage_export(dict, "off", op_errstr);
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (THIS->name, GF_LOG_WARNING, 0,
|
|
|
d1681e |
+ GD_MSG_NFS_GNS_UNEXPRT_VOL_FAIL, "Could not "
|
|
|
d1681e |
+ "unexport volume via NFS-Ganesha");
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
|
|
|
d1681e |
if (glusterd_is_defrag_on (volinfo)) {
|
|
|
d1681e |
snprintf (msg, sizeof(msg), "rebalance session is "
|
|
|
d1681e |
@@ -2595,6 +2605,8 @@ glusterd_op_start_volume (dict_t *dict, char **op_errstr)
|
|
|
d1681e |
char *brick_mount_dir = NULL;
|
|
|
d1681e |
char key[PATH_MAX] = "";
|
|
|
d1681e |
char *volname = NULL;
|
|
|
d1681e |
+ char *str = NULL;
|
|
|
d1681e |
+ gf_boolean_t option = _gf_false;
|
|
|
d1681e |
int flags = 0;
|
|
|
d1681e |
glusterd_volinfo_t *volinfo = NULL;
|
|
|
d1681e |
glusterd_brickinfo_t *brickinfo = NULL;
|
|
|
d1681e |
@@ -2657,6 +2669,28 @@ glusterd_op_start_volume (dict_t *dict, char **op_errstr)
|
|
|
d1681e |
}
|
|
|
d1681e |
}
|
|
|
d1681e |
|
|
|
d1681e |
+ ret = dict_get_str (conf->opts, GLUSTERD_STORE_KEY_GANESHA_GLOBAL, &str);
|
|
|
d1681e |
+ if (ret != 0) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_INFO, 0,
|
|
|
d1681e |
+ GD_MSG_DICT_GET_FAILED, "Global dict not present.");
|
|
|
d1681e |
+ ret = 0;
|
|
|
d1681e |
+
|
|
|
d1681e |
+ } else {
|
|
|
d1681e |
+ ret = gf_string2boolean (str, &option);
|
|
|
d1681e |
+ /* Check if the feature is enabled and set nfs-disable to true */
|
|
|
d1681e |
+ if (option) {
|
|
|
d1681e |
+ gf_msg_debug (this->name, 0, "NFS-Ganesha is enabled");
|
|
|
d1681e |
+ /* Gluster-nfs should not start when NFS-Ganesha is enabled*/
|
|
|
d1681e |
+ ret = dict_set_str (volinfo->dict, NFS_DISABLE_MAP_KEY, "on");
|
|
|
d1681e |
+ if (ret) {
|
|
|
d1681e |
+ gf_msg (this->name, GF_LOG_ERROR, 0,
|
|
|
d1681e |
+ GD_MSG_DICT_SET_FAILED, "Failed to set nfs.disable for"
|
|
|
d1681e |
+ "volume %s", volname);
|
|
|
d1681e |
+ goto out;
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+ }
|
|
|
d1681e |
+
|
|
|
d1681e |
ret = glusterd_start_volume (volinfo, flags, _gf_true);
|
|
|
d1681e |
if (ret)
|
|
|
d1681e |
goto out;
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
|
|
|
d1681e |
index 2210b82..7fe76e5 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c
|
|
|
d1681e |
@@ -3210,6 +3210,12 @@ struct volopt_map_entry glusterd_volopt_map[] = {
|
|
|
d1681e |
.op_version = GD_OP_VERSION_3_7_0,
|
|
|
d1681e |
.flags = OPT_FLAG_CLIENT_OPT
|
|
|
d1681e |
},
|
|
|
d1681e |
+ { .key = "ganesha.enable",
|
|
|
d1681e |
+ .voltype = "features/ganesha",
|
|
|
d1681e |
+ .value = "off",
|
|
|
d1681e |
+ .option = "ganesha.enable",
|
|
|
d1681e |
+ .op_version = GD_OP_VERSION_3_7_0,
|
|
|
d1681e |
+ },
|
|
|
d1681e |
{ .key = "features.shard",
|
|
|
d1681e |
.voltype = "features/shard",
|
|
|
d1681e |
.value = "off",
|
|
|
d1681e |
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
|
|
|
d1681e |
index 59b1775..2d8dbb9 100644
|
|
|
d1681e |
--- a/xlators/mgmt/glusterd/src/glusterd.h
|
|
|
d1681e |
+++ b/xlators/mgmt/glusterd/src/glusterd.h
|
|
|
d1681e |
@@ -57,6 +57,8 @@
|
|
|
d1681e |
#define GLUSTERD_BRICKMUX_LIMIT_KEY "cluster.max-bricks-per-process"
|
|
|
d1681e |
#define GLUSTERD_LOCALTIME_LOGGING_KEY "cluster.localtime-logging"
|
|
|
d1681e |
|
|
|
d1681e |
+#define GANESHA_HA_CONF CONFDIR "/ganesha-ha.conf"
|
|
|
d1681e |
+#define GANESHA_EXPORT_DIRECTORY CONFDIR"/exports"
|
|
|
d1681e |
#define GLUSTERD_SNAPS_MAX_HARD_LIMIT 256
|
|
|
d1681e |
#define GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT 90
|
|
|
d1681e |
#define GLUSTERD_SNAPS_MAX_SOFT_LIMIT_PERCENT 100
|
|
|
d1681e |
@@ -117,7 +119,7 @@ typedef enum glusterd_op_ {
|
|
|
d1681e |
GD_OP_GSYNC_CREATE,
|
|
|
d1681e |
GD_OP_SNAP,
|
|
|
d1681e |
GD_OP_BARRIER,
|
|
|
d1681e |
- GD_OP_GANESHA, /* obsolete */
|
|
|
d1681e |
+ GD_OP_GANESHA,
|
|
|
d1681e |
GD_OP_BITROT,
|
|
|
d1681e |
GD_OP_DETACH_TIER,
|
|
|
d1681e |
GD_OP_TIER_MIGRATE,
|
|
|
d1681e |
@@ -1168,8 +1170,20 @@ int glusterd_op_create_volume (dict_t *dict, char **op_errstr);
|
|
|
d1681e |
int glusterd_op_start_volume (dict_t *dict, char **op_errstr);
|
|
|
d1681e |
int glusterd_op_stop_volume (dict_t *dict);
|
|
|
d1681e |
int glusterd_op_delete_volume (dict_t *dict);
|
|
|
d1681e |
+int glusterd_handle_ganesha_op (dict_t *dict, char **op_errstr,
|
|
|
d1681e |
+ char *key, char *value);
|
|
|
d1681e |
+int glusterd_check_ganesha_cmd (char *key, char *value,
|
|
|
d1681e |
+ char **errstr, dict_t *dict);
|
|
|
d1681e |
+int glusterd_op_stage_set_ganesha (dict_t *dict, char **op_errstr);
|
|
|
d1681e |
+int glusterd_op_set_ganesha (dict_t *dict, char **errstr);
|
|
|
d1681e |
+int ganesha_manage_export (dict_t *dict, char *value, char **op_errstr);
|
|
|
d1681e |
int manage_export_config (char *volname, char *value, char **op_errstr);
|
|
|
d1681e |
|
|
|
d1681e |
+gf_boolean_t
|
|
|
d1681e |
+glusterd_is_ganesha_cluster ();
|
|
|
d1681e |
+gf_boolean_t glusterd_check_ganesha_export (glusterd_volinfo_t *volinfo);
|
|
|
d1681e |
+int stop_ganesha (char **op_errstr);
|
|
|
d1681e |
+int tear_down_cluster (gf_boolean_t run_teardown);
|
|
|
d1681e |
int glusterd_op_add_brick (dict_t *dict, char **op_errstr);
|
|
|
d1681e |
int glusterd_op_add_tier_brick (dict_t *dict, char **op_errstr);
|
|
|
d1681e |
int glusterd_op_remove_brick (dict_t *dict, char **op_errstr);
|
|
|
d1681e |
--
|
|
|
d1681e |
1.8.3.1
|
|
|
d1681e |
|