summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnuradha Talur <atalur@redhat.com>2016-08-22 13:22:03 -0400
committerPranith Kumar Karampuri <pkarampu@redhat.com>2016-08-29 19:55:53 -0700
commit936f8aeac3252951e7fa0cdaa5d260fad3bd5ea0 (patch)
tree66240b8ef55d55ca9535a21f73a5f71c9ff6ade4
parentc204f452dfd9907a0d32f35294a0805701a6d993 (diff)
glusterd : Introduce reset brick
The command basically allows replace brick with src and dst bricks as same. Usage: gluster v reset-brick <volname> <hostname:brick-path> start This command kills the brick to be reset. Once this command is run, admin can do other manual operations that they need to do, like configuring some options for the brick. Once this is done, resetting the brick can be continued with the following options. gluster v reset-brick <vname> <hostname:brick> <hostname:brick> commit {force} Does the job of resetting the brick. 'force' option should be used when the brick already contains volinfo id. Problem: On doing a disk-replacement of a brick in a replicate volume the following 2 scenarios may occur : a) there is a chance that reads are served from this replaced-disk brick, which leads to empty reads. b) potential data loss if next writes succeed only on replaced brick, and heal is done to other bricks from this one. Solution: After disk-replacement, make sure that reset-brick command is run for that brick so that pending markers are set for the brick and it is not chosen as source for reads and heal. But, as of now replace-brick for the same brick-path is not allowed. In order to fix the above mentioned problem, same brick-path replace-brick is needed. With this patch reset-brick commit {force} will be allowed even when source and destination <hostname:brickpath> are identical as long as 1) destination brick is not alive 2) source and destination brick have the same brick uuid and path. Also, the destination brick after replace-brick will use the same port as the source brick. Change-Id: I440b9e892ffb781ea4b8563688c3f85c7a7c89de BUG: 1266876 Signed-off-by: Anuradha Talur <atalur@redhat.com> Reviewed-on: http://review.gluster.org/12250 Smoke: Gluster Build System <jenkins@build.gluster.org> NetBSD-regression: NetBSD Build System <jenkins@build.gluster.org> CentOS-regression: Gluster Build System <jenkins@build.gluster.org> Reviewed-by: Ashish Pandey <aspandey@redhat.com> Reviewed-by: Pranith Kumar Karampuri <pkarampu@redhat.com>
-rw-r--r--cli/src/cli-cmd-parser.c164
-rw-r--r--cli/src/cli-cmd-volume.c61
-rw-r--r--cli/src/cli-rpc-ops.c223
-rw-r--r--cli/src/cli-xml-output.c2
-rw-r--r--cli/src/cli.h7
-rw-r--r--events/eventskeygen.py2
-rw-r--r--heal/src/glfs-heal.c2
-rw-r--r--rpc/rpc-lib/src/protocol-common.h1
-rw-r--r--tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t54
-rw-r--r--xlators/cluster/afr/src/afr-inode-write.c4
-rw-r--r--xlators/mgmt/glusterd/src/Makefile.am3
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-brick-ops.c2
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-hooks.c1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-messages.h29
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt.c33
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt.h6
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-replace-brick.c349
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-reset-brick.c430
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-rpc-ops.c1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-syncop.c1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c327
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h34
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c2
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.c1
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h6
27 files changed, 1431 insertions, 316 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index be0a8e7..86b0287 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -2134,6 +2134,137 @@ out:
return ret;
}
+int32_t
+cli_cmd_brick_op_validate_bricks (const char **words, dict_t *dict,
+ int src, int dst)
+{
+ int ret = -1;
+ char *delimiter = NULL;
+
+ if (validate_brick_name ((char *)words[src])) {
+ cli_err ("wrong brick type: %s, use "
+ "<HOSTNAME>:<export-dir-abs-path>", words[3]);
+ ret = -1;
+ goto out;
+ } else {
+ delimiter = strrchr ((char *)words[src], '/');
+ ret = gf_canonicalize_path (delimiter);
+ if (ret)
+ goto out;
+ }
+
+ ret = dict_set_str (dict, "src-brick", (char *)words[src]);
+ if (ret)
+ goto out;
+
+ if (dst == -1) {
+ ret = 0;
+ goto out;
+ }
+
+ if (validate_brick_name ((char *)words[dst])) {
+ cli_err ("wrong brick type: %s, use "
+ "<HOSTNAME>:<export-dir-abs-path>", words[dst]);
+ ret = -1;
+ goto out;
+ } else {
+ delimiter = strrchr ((char *)words[dst], '/');
+ ret = gf_canonicalize_path (delimiter);
+ if (ret)
+ goto out;
+ }
+
+ ret = dict_set_str (dict, "dst-brick", (char *)words[dst]);
+ if (ret)
+ goto out;
+ ret = 0;
+out:
+ return ret;
+}
+
+int32_t
+cli_cmd_volume_reset_brick_parse (const char **words, int wordcount,
+ dict_t **options)
+{
+ int ret = -1;
+ char *volname = NULL;
+ dict_t *dict = NULL;
+
+ if (wordcount < 5 || wordcount > 7)
+ goto out;
+
+ dict = dict_new ();
+
+ if (!dict)
+ goto out;
+
+ volname = (char *)words[2];
+
+ ret = dict_set_str (dict, "volname", volname);
+ if (ret)
+ goto out;
+
+ if (wordcount == 5) {
+ if (strcmp (words[4], "start")) {
+ cli_err ("Invalid option '%s' for reset-brick. Please "
+ "enter valid reset-brick command", words[4]);
+ ret = -1;
+ goto out;
+ }
+
+ ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, -1);
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (dict, "operation", "GF_RESET_OP_START");
+ if (ret)
+ goto out;
+ } else if (wordcount == 6) {
+ if (strcmp (words[5], "commit")) {
+ cli_err ("Invalid option '%s' for reset-brick. Please "
+ "enter valid reset-brick command", words[5]);
+ ret = -1;
+ goto out;
+ }
+
+ ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4);
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (dict, "operation", "GF_RESET_OP_COMMIT");
+ if (ret)
+ goto out;
+ } else if (wordcount == 7) {
+ if (strcmp (words[5], "commit") || strcmp (words[6], "force")) {
+ cli_err ("Invalid option '%s %s' for reset-brick. Please "
+ "enter valid reset-brick command",
+ words[5], words[6]);
+ ret = -1;
+ goto out;
+ }
+
+ ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4);
+ if (ret)
+ goto out;
+
+ ret = dict_set_str (dict, "operation",
+ "GF_RESET_OP_COMMIT_FORCE");
+ if (ret)
+ goto out;
+ }
+
+ *options = dict;
+
+out:
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR,
+ "Unable to parse reset-brick CLI");
+ if (dict)
+ dict_unref (dict);
+ }
+
+ return ret;
+}
int32_t
cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
@@ -2141,7 +2272,6 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
{
int ret = -1;
char *volname = NULL;
- char *delimiter = NULL;
dict_t *dict = NULL;
GF_ASSERT (words);
@@ -2167,35 +2297,7 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
if (ret)
goto out;
- if (validate_brick_name ((char *)words[3])) {
- cli_err ("wrong brick type: %s, use "
- "<HOSTNAME>:<export-dir-abs-path>", words[3]);
- ret = -1;
- goto out;
- } else {
- delimiter = strrchr ((char *)words[3], ':');
- ret = gf_canonicalize_path (delimiter + 1);
- if (ret)
- goto out;
- }
-
- ret = dict_set_str (dict, "src-brick", (char *)words[3]);
- if (ret)
- goto out;
-
- if (validate_brick_name ((char *)words[4])) {
- cli_err ("wrong brick type: %s, use "
- "<HOSTNAME>:<export-dir-abs-path>", words[4]);
- ret = -1;
- goto out;
- } else {
- delimiter = strrchr ((char *)words[4], ':');
- ret = gf_canonicalize_path (delimiter + 1);
- if (ret)
- goto out;
- }
-
- ret = dict_set_str (dict, "dst-brick", (char *)words[4]);
+ ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4);
if (ret)
goto out;
@@ -2216,7 +2318,7 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
out:
if (ret) {
- gf_log ("cli", GF_LOG_ERROR, "Unable to parse replace-brick CLI");
+ gf_log ("cli", GF_LOG_ERROR, "Unable to parse reset-brick CLI");
if (dict)
dict_unref (dict);
}
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 020697f..2171d35 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -1829,6 +1829,59 @@ out:
}
int
+cli_cmd_volume_reset_brick_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_error = 0;
+ cli_local_t *local = NULL;
+
+#ifdef GF_SOLARIS_HOST_OS
+ cli_out ("Command not supported on Solaris");
+ goto out;
+#endif
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RESET_BRICK];
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame)
+ goto out;
+
+ ret = cli_cmd_volume_reset_brick_parse (words, wordcount, &options);
+
+ if (ret) {
+ cli_usage_out (word->pattern);
+ parse_error = 1;
+ goto out;
+ }
+
+ CLI_LOCAL_INIT (local, words, frame, options);
+
+ if (proc->fn) {
+ ret = proc->fn (frame, THIS, options);
+ }
+
+out:
+ if (ret) {
+ gf_event (EVENT_BRICK_RESET, "Volume reset-brick failed.");
+ cli_cmd_sent_status_get (&sent);
+ if ((sent == 0) && (parse_error == 0))
+ cli_out ("Volume reset-brick failed");
+ } else {
+ gf_event (EVENT_BRICK_RESET, "Volume reset-brick succeeded.");
+ }
+
+ CLI_STACK_DESTROY (frame);
+
+ return ret;
+}
+
+int
cli_cmd_volume_replace_brick_cbk (struct cli_state *state,
struct cli_cmd_word *word,
const char **words,
@@ -1868,9 +1921,12 @@ cli_cmd_volume_replace_brick_cbk (struct cli_state *state,
out:
if (ret) {
+ gf_event (EVENT_BRICK_REPLACE, "Volume replace-brick failed.");
cli_cmd_sent_status_get (&sent);
if ((sent == 0) && (parse_error == 0))
cli_out ("Volume replace-brick failed");
+ } else {
+ gf_event (EVENT_BRICK_RESET, "Volume replace-brick succeeded.");
}
CLI_STACK_DESTROY (frame);
@@ -3016,6 +3072,11 @@ struct cli_cmd volume_cmds[] = {
"Bitrot translator specific operation. For more information about "
"bitrot command type 'man gluster'"
},
+ { "volume reset-brick <VOLNAME> <SOURCE-BRICK> {{start} |"
+ " {<NEW-BRICK> commit}}",
+ cli_cmd_volume_reset_brick_cbk,
+ "reset-brick operations"},
+
{ NULL, NULL, NULL }
};
diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c
index 6259546..6b5277c 100644
--- a/cli/src/cli-rpc-ops.c
+++ b/cli/src/cli-rpc-ops.c
@@ -2961,6 +2961,149 @@ out:
}
int
+gf_cli_reset_brick_cbk (struct rpc_req *req, struct iovec *iov,
+ int count, void *myframe)
+{
+ gf_cli_rsp rsp = {0,};
+ int ret = -1;
+ cli_local_t *local = NULL;
+ call_frame_t *frame = NULL;
+ char *src_brick = NULL;
+ char *dst_brick = NULL;
+ char *status_reply = NULL;
+ char *rb_operation_str = NULL;
+ dict_t *rsp_dict = NULL;
+ char msg[1024] = {0,};
+ char *task_id_str = NULL;
+ char *reset_op = NULL;
+
+ GF_ASSERT (myframe);
+
+ if (-1 == req->rpc_status) {
+ goto out;
+ }
+
+ frame = myframe;
+
+ GF_ASSERT (frame->local);
+
+ local = frame->local;
+
+ ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "Failed to decode xdr response");
+ goto out;
+ }
+
+ ret = dict_get_str (local->dict, "operation", &reset_op);
+ if (ret) {
+ gf_log (frame->this->name, GF_LOG_ERROR,
+ "dict_get on operation failed");
+ goto out;
+ }
+
+ if (rsp.dict.dict_len) {
+ /* Unserialize the dictionary */
+ rsp_dict = dict_new ();
+
+ ret = dict_unserialize (rsp.dict.dict_val,
+ rsp.dict.dict_len,
+ &rsp_dict);
+ if (ret < 0) {
+ gf_log (frame->this->name, GF_LOG_ERROR, "failed to "
+ "unserialize rsp buffer to dictionary");
+ goto out;
+ }
+ }
+
+ if (strcmp (reset_op, "GF_RESET_OP_START") &&
+ strcmp (reset_op, "GF_RESET_OP_COMMIT") &&
+ strcmp (reset_op, "GF_RESET_OP_COMMIT_FORCE")) {
+ rb_operation_str = gf_strdup ("Unknown operation");
+ ret = -1;
+ goto out;
+ }
+
+ if (rsp.op_ret && (strcmp (rsp.op_errstr, ""))) {
+ rb_operation_str = gf_strdup (rsp.op_errstr);
+ } else {
+ if (!strcmp (reset_op, "GF_RESET_OP_START")) {
+ if (rsp.op_ret)
+ rb_operation_str = gf_strdup ("reset-brick "
+ "start "
+ "operation "
+ "failed");
+ else
+ rb_operation_str = gf_strdup ("reset-brick "
+ "start "
+ "operation "
+ "successful");
+ } else if (!strcmp (reset_op, "GF_RESET_OP_COMMIT")) {
+
+ if (rsp.op_ret)
+ rb_operation_str = gf_strdup ("reset-brick "
+ "commit "
+ "operation "
+ "failed");
+ else
+ rb_operation_str = gf_strdup ("reset-brick "
+ "commit "
+ "operation "
+ "successful");
+ } else if (!strcmp (reset_op, "GF_RESET_OP_COMMIT_FORCE")) {
+
+ if (rsp.op_ret)
+ rb_operation_str = gf_strdup ("reset-brick "
+ "commit "
+ "force operation "
+ "failed");
+ else
+ rb_operation_str = gf_strdup ("reset-brick "
+ "commit "
+ "force operation "
+ "successful");
+ }
+ }
+
+ gf_log ("cli", GF_LOG_INFO, "Received resp to reset brick");
+ snprintf (msg, sizeof (msg), "%s",
+ rb_operation_str ? rb_operation_str : "Unknown operation");
+
+ if (global_state->mode & GLUSTER_MODE_XML) {
+ ret = cli_xml_output_vol_replace_brick (rsp_dict,
+ rsp.op_ret,
+ rsp.op_errno, msg);
+ if (ret)
+ gf_log ("cli", GF_LOG_ERROR,
+ "Error outputting to xml");
+ goto out;
+ }
+
+ if (rsp.op_ret)
+ cli_err ("volume reset-brick: failed: %s", msg);
+ else
+ cli_out ("volume reset-brick: success: %s", msg);
+ ret = rsp.op_ret;
+
+out:
+ if (frame)
+ frame->local = NULL;
+
+ if (local)
+ cli_local_wipe (local);
+
+ if (rb_operation_str)
+ GF_FREE (rb_operation_str);
+
+ cli_cmd_broadcast_response (ret);
+ free (rsp.dict.dict_val);
+ if (rsp_dict)
+ dict_unref (rsp_dict);
+
+ return ret;
+}
+int
gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,
int count, void *myframe)
{
@@ -2971,7 +3114,7 @@ gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,
char *rb_operation_str = NULL;
dict_t *rsp_dict = NULL;
char msg[1024] = {0,};
- char *replace_op = 0;
+ char *replace_op = NULL;
GF_ASSERT (myframe);
@@ -3013,7 +3156,7 @@ gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,
}
}
- if (!strcmp(replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
+ if (!strcmp (replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
if (rsp.op_ret || ret)
rb_operation_str = gf_strdup ("replace-brick commit "
@@ -3035,7 +3178,7 @@ gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,
rb_operation_str ? rb_operation_str : "Unknown operation");
if (global_state->mode & GLUSTER_MODE_XML) {
- ret = cli_xml_output_vol_replace_brick (replace_op, rsp_dict,
+ ret = cli_xml_output_vol_replace_brick (rsp_dict,
rsp.op_ret,
rsp.op_errno, msg);
if (ret)
@@ -3054,10 +3197,8 @@ out:
if (frame)
frame->local = NULL;
- if (local) {
- dict_unref (local->dict);
+ if (local)
cli_local_wipe (local);
- }
if (rb_operation_str)
GF_FREE (rb_operation_str);
@@ -4889,8 +5030,73 @@ out:
}
int32_t
+gf_cli_reset_brick (call_frame_t *frame, xlator_t *this, void *data)
+{
+ gf_cli_req req = { {0,} };
+ int ret = 0;
+ dict_t *dict = NULL;
+ char *dst_brick = NULL;
+ char *src_brick = NULL;
+ char *volname = NULL;
+ char *op = NULL;
+
+ if (!frame || !this || !data) {
+ ret = -1;
+ goto out;
+ }
+
+ dict = data;
+
+ ret = dict_get_str (dict, "operation", &op);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "dict_get on operation failed");
+ goto out;
+ }
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "dict_get on volname failed");
+ goto out;
+ }
+
+ ret = dict_get_str (dict, "src-brick", &src_brick);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "dict_get on src-brick failed");
+ goto out;
+ }
+
+ if (!strcmp (op, "GF_RESET_OP_COMMIT") ||
+ !strcmp (op, "GF_RESET_OP_COMMIT_FORCE")) {
+ ret = dict_get_str (dict, "dst-brick", &dst_brick);
+ if (ret) {
+ gf_log (this->name, GF_LOG_DEBUG,
+ "dict_get on dst-brick failed");
+ goto out;
+ }
+ }
+
+ gf_log (this->name, GF_LOG_DEBUG,
+ "Received command reset-brick %s on %s.", op, src_brick);
+
+ ret = cli_to_glusterd (&req, frame, gf_cli_reset_brick_cbk,
+ (xdrproc_t) xdr_gf_cli_req, dict,
+ GLUSTER_CLI_RESET_BRICK, this, cli_rpc_prog,
+ NULL);
+
+out:
+ gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);
+
+ GF_FREE (req.dict.dict_val);
+
+ return ret;
+}
+
+int32_t
gf_cli_replace_brick (call_frame_t *frame, xlator_t *this,
- void *data)
+ void *data)
{
gf_cli_req req = {{0,}};
int ret = 0;
@@ -11345,7 +11551,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_ATTACH_TIER] = {"ATTACH_TIER", gf_cli_attach_tier},
[GLUSTER_CLI_DETACH_TIER] = {"DETACH_TIER", gf_cli_detach_tier},
[GLUSTER_CLI_TIER] = {"TIER", gf_cli_tier},
- [GLUSTER_CLI_GET_STATE] = {"GET_STATE", gf_cli_get_state}
+ [GLUSTER_CLI_GET_STATE] = {"GET_STATE", gf_cli_get_state},
+ [GLUSTER_CLI_RESET_BRICK] = {"RESET_BRICK", gf_cli_reset_brick}
};
struct rpc_clnt_program cli_prog = {
diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c
index f2b1941..6639262 100644
--- a/cli/src/cli-xml-output.c
+++ b/cli/src/cli-xml-output.c
@@ -3861,7 +3861,7 @@ out:
}
int
-cli_xml_output_vol_replace_brick (char *op, dict_t *dict,
+cli_xml_output_vol_replace_brick (dict_t *dict,
int op_ret, int op_errno, char *op_errstr)
{
#if (HAVE_LIB_XML)
diff --git a/cli/src/cli.h b/cli/src/cli.h
index f9c642e..ba0d845 100644
--- a/cli/src/cli.h
+++ b/cli/src/cli.h
@@ -284,6 +284,10 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,
dict_t **options);
int32_t
+cli_cmd_volume_reset_brick_parse (const char **words, int wordcount,
+ dict_t **options);
+
+int32_t
cli_cmd_log_rotate_parse (const char **words, int wordcount, dict_t **options);
int32_t
cli_cmd_log_locate_parse (const char **words, int wordcount, dict_t **options);
@@ -424,7 +428,7 @@ cli_xml_output_vol_remove_brick_detach_tier (gf_boolean_t status_op,
const char *op);
int
-cli_xml_output_vol_replace_brick (char *op, dict_t *dict, int op_ret,
+cli_xml_output_vol_replace_brick (dict_t *dict, int op_ret,
int op_errno, char *op_errstr);
int
@@ -489,5 +493,4 @@ print_quota_list_empty (char *path, int type);
int
gf_gsync_status_t_comparator (const void *p, const void *q);
-
#endif /* __CLI_H__ */
diff --git a/events/eventskeygen.py b/events/eventskeygen.py
index b55c29a..30b518d 100644
--- a/events/eventskeygen.py
+++ b/events/eventskeygen.py
@@ -91,6 +91,8 @@ keys = (
"EVENT_QUOTA_HARD_TIMEOUT",
"EVENT_QUOTA_DEFAULT_SOFT_LIMIT",
"EVENT_QUOTA_CROSSED_SOFT_LIMIT",
+ "EVENT_BRICK_REPLACE",
+ "EVENT_BRICK_RESET",
)
LAST_EVENT = "EVENT_LAST"
diff --git a/heal/src/glfs-heal.c b/heal/src/glfs-heal.c
index 0a880cb..e885dd9 100644
--- a/heal/src/glfs-heal.c
+++ b/heal/src/glfs-heal.c
@@ -517,7 +517,7 @@ out:
(*num_entries)++;
glfsh_output->print_heal_status (path ? path :
- uuid_utoa_r (gfid, gfid_str),
+ uuid_utoa_r (gfid, gfid_str),
gfid,
status ? status : "");
diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h
index 6a134e8..49c3d96 100644
--- a/rpc/rpc-lib/src/protocol-common.h
+++ b/rpc/rpc-lib/src/protocol-common.h
@@ -198,6 +198,7 @@ enum gluster_cli_procnum {
GLUSTER_CLI_DETACH_TIER,
GLUSTER_CLI_TIER,
GLUSTER_CLI_GET_STATE,
+ GLUSTER_CLI_RESET_BRICK,
GLUSTER_CLI_MAXVALUE,
};
diff --git a/tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t b/tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t
new file mode 100644
index 0000000..884b789
--- /dev/null
+++ b/tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t
@@ -0,0 +1,54 @@
+#!/bin/bash
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+cleanup;
+
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1}
+TEST $CLI volume start $V0
+
+TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0;
+# Create files
+for i in {1..5}
+do
+ echo $i > $M0/file$i.txt
+done
+
+# Negative case with brick not killed && volume-id xattrs present
+TEST ! $CLI volume reset-brick $V0 $H0:$B0/${V0}1 $H0:$B0/${V0}1 commit force
+TEST kill_brick $V0 $H0 $B0/${V0}1
+
+# Negative case with brick killed but volume-id xattr present
+TEST ! $CLI volume reset-brick $V0 $H0:$B0/${V0}1 $H0:$B0/${V0}1 commit
+
+TEST $CLI volume reset-brick $V0 $H0:$B0/${V0}1 start
+# Simulated reset disk
+for i in {1..5}
+do
+ rm -rf $B0/${V0}{1}/file$i.txt
+done
+for i in {6..10}
+do
+ echo $i > $M0/file$i.txt
+done
+
+# Now reset the brick
+TEST $CLI volume reset-brick $V0 $H0:$B0/${V0}1 $H0:$B0/${V0}1 commit force
+
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1
+
+EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0
+EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1
+
+TEST $CLI volume heal $V0
+
+EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0
+
+# Check if entry-heal has happened
+TEST diff <(ls $B0/${V0}0 | sort) <(ls $B0/${V0}1 | sort)
+EXPECT "10" echo $(ls $B0/${V0}1 | wc -l)
+
+cleanup;
diff --git a/xlators/cluster/afr/src/afr-inode-write.c b/xlators/cluster/afr/src/afr-inode-write.c
index ddc257d..24ab52f 100644
--- a/xlators/cluster/afr/src/afr-inode-write.c
+++ b/xlators/cluster/afr/src/afr-inode-write.c
@@ -1235,8 +1235,8 @@ _afr_handle_empty_brick (void *opaque)
loc_copy (&local->loc, &data->loc);
- gf_msg_debug (this->name, 0, "New brick is : %s",
- priv->children[empty_index]->name);
+ gf_msg (this->name, GF_LOG_INFO, 0, 0, "New brick is : %s",
+ priv->children[empty_index]->name);
ret = _afr_handle_empty_brick_type (this, frame, &local->loc, empty_index,
AFR_METADATA_TRANSACTION, op_type);
diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am
index 23840cd..faee862 100644
--- a/xlators/mgmt/glusterd/src/Makefile.am
+++ b/xlators/mgmt/glusterd/src/Makefile.am
@@ -16,7 +16,8 @@ glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \
glusterd-proc-mgmt.c glusterd-svc-mgmt.c glusterd-shd-svc.c \
glusterd-nfs-svc.c glusterd-quotad-svc.c glusterd-svc-helper.c \
glusterd-conn-helper.c glusterd-snapd-svc.c glusterd-snapd-svc-helper.c \
- glusterd-bitd-svc.c glusterd-scrub-svc.c glusterd-server-quorum.c
+ glusterd-bitd-svc.c glusterd-scrub-svc.c glusterd-server-quorum.c \
+ glusterd-reset-brick.c
glusterd_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \
diff --git a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c
index 7be1d38..8458876 100644
--- a/xlators/mgmt/glusterd/src/glusterd-brick-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-brick-ops.c
@@ -1830,7 +1830,7 @@ glusterd_op_stage_add_brick (dict_t *dict, char **op_errstr, dict_t *rsp_dict)
brick_alloc = _gf_true;
ret = glusterd_new_brick_validate (brick, brickinfo, msg,
- sizeof (msg));
+ sizeof (msg), NULL);
if (ret) {
*op_errstr = gf_strdup (msg);
ret = -1;
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c
index 4a027f4..18886dc 100644
--- a/xlators/mgmt/glusterd/src/glusterd-handler.c
+++ b/xlators/mgmt/glusterd/src/glusterd-handler.c
@@ -5926,6 +5926,7 @@ rpcsvc_actor_t gd_svc_cli_actors[GLUSTER_CLI_MAXVALUE] = {
[GLUSTER_CLI_GET_VOL_OPT] = {"GET_VOL_OPT", GLUSTER_CLI_GET_VOL_OPT, glusterd_handle_get_vol_opt, NULL, 0, DRC_NA},
[GLUSTER_CLI_BITROT] = {"BITROT", GLUSTER_CLI_BITROT, glusterd_handle_bitrot, NULL, 0, DRC_NA},
[GLUSTER_CLI_GET_STATE] = {"GET_STATE", GLUSTER_CLI_GET_STATE, glusterd_handle_get_state, NULL, 0, DRC_NA},
+ [GLUSTER_CLI_RESET_BRICK] = {"RESET_BRICK", GLUSTER_CLI_RESET_BRICK, glusterd_handle_reset_brick, NULL, 0, DRC_NA},
};
struct rpcsvc_program gd_svc_cli_prog = {
diff --git a/xlators/mgmt/glusterd/src/glusterd-hooks.c b/xlators/mgmt/glusterd/src/glusterd-hooks.c
index 9229da9..77efa6c 100644
--- a/xlators/mgmt/glusterd/src/glusterd-hooks.c
+++ b/xlators/mgmt/glusterd/src/glusterd-hooks.c
@@ -57,6 +57,7 @@ char glusterd_hook_dirnames[GD_OP_MAX][256] =
[GD_OP_LIST_VOLUME] = EMPTY,
[GD_OP_CLEARLOCKS_VOLUME] = EMPTY,
[GD_OP_DEFRAG_BRICK_VOLUME] = EMPTY,
+ [GD_OP_RESET_BRICK] = EMPTY,
};
#undef EMPTY
diff --git a/xlators/mgmt/glusterd/src/glusterd-messages.h b/xlators/mgmt/glusterd/src/glusterd-messages.h
index f0c9ee2..e520c69 100644
--- a/xlators/mgmt/glusterd/src/glusterd-messages.h
+++ b/xlators/mgmt/glusterd/src/glusterd-messages.h
@@ -41,7 +41,7 @@
#define GLUSTERD_COMP_BASE GLFS_MSGID_GLUSTERD
-#define GLFS_NUM_MESSAGES 585
+#define GLFS_NUM_MESSAGES 587
#define GLFS_MSGID_END (GLUSTERD_COMP_BASE + GLFS_NUM_MESSAGES + 1)
/* Messaged with message IDs */
@@ -2837,7 +2837,7 @@
* @recommendedaction
*
*/
-#define GD_MSG_NFS_VOL_FILE_GEN_FAIL (GLUSTERD_COMP_BASE + 349)
+#define GD_MSG_GLUSTER_SERVICE_START_FAIL (GLUSTERD_COMP_BASE + 349)
/*!
* @messageid
@@ -2965,7 +2965,7 @@
* @recommendedaction
*
*/
-#define GD_MSG_NFS_SERVER_STOP_FAIL (GLUSTERD_COMP_BASE + 365)
+#define GD_MSG_GLUSTER_SERVICES_STOP_FAIL (GLUSTERD_COMP_BASE + 365)
/*!
* @messageid
@@ -4727,8 +4727,31 @@
* @recommendation
*
*/
+#define GD_MSG_BRICK_CLEANUP_SUCCESS (GLUSTERD_COMP_BASE + 584)
+
+/*!
+ * @messageid
+ * @diagnosis
+ * @recommendation
+ *
+ */
#define GD_MSG_STATE_STR_GET_FAILED (GLUSTERD_COMP_BASE + 585)
+/*!
+ * @messageid
+ * @diagnosis
+ * @recommendedaction
+ *
+ */
+#define GD_MSG_RESET_BRICK_COMMIT_FORCE_REQ_RCVD (GLUSTERD_COMP_BASE + 586)
+
+/*!
+ * @messageid
+ * @diagnosis
+ * @recommendedaction
+ *
+ */
+#define GD_MSG_RESET_BRICK_CMD_FAIL (GLUSTERD_COMP_BASE + 587)
/*------------*/
#define glfs_msg_end_x GLFS_MSGID_END, "Invalid: End of messages"
#endif /* !_GLUSTERD_MESSAGES_H_ */
diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.c b/xlators/mgmt/glusterd/src/glusterd-mgmt.c
index 6cc7b84..a5d22e4 100644
--- a/xlators/mgmt/glusterd/src/glusterd-mgmt.c
+++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.c
@@ -189,6 +189,17 @@ gd_mgmt_v3_pre_validate_fn (glusterd_op_t op, dict_t *dict,
}
break;
+ case GD_OP_RESET_BRICK:
+ ret = glusterd_reset_brick_prevalidate (dict, op_errstr,
+ rsp_dict);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_WARNING, 0,
+ GD_MSG_PRE_VALIDATION_FAIL,
+ "Reset brick prevalidation failed.");
+ goto out;
+ }
+ break;
+
default:
break;
}
@@ -298,6 +309,17 @@ gd_mgmt_v3_commit_fn (glusterd_op_t op, dict_t *dict,
break;
}
+ case GD_OP_RESET_BRICK:
+ {
+ ret = glusterd_op_reset_brick (dict, rsp_dict);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_COMMIT_OP_FAIL,
+ "Reset-brick commit failed.");
+ goto out;
+ }
+ break;
+ }
default:
break;
@@ -670,6 +692,16 @@ glusterd_pre_validate_aggr_rsp_dict (glusterd_op_t op,
goto out;
}
break;
+ case GD_OP_RESET_BRICK:
+ ret = glusterd_rb_use_rsp_dict (aggr, rsp);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_PRE_VALIDATION_FAIL,
+ "Failed to aggregate prevalidate "
+ "response dictionaries.");
+ goto out;
+ }
+ break;
default:
ret = -1;
gf_msg (this->name, GF_LOG_ERROR, EINVAL,
@@ -972,6 +1004,7 @@ glusterd_mgmt_v3_build_payload (dict_t **req, char **op_errstr, dict_t *dict,
case GD_OP_START_VOLUME:
case GD_OP_ADD_BRICK:
case GD_OP_REPLACE_BRICK:
+ case GD_OP_RESET_BRICK:
{
ret = dict_get_str (dict, "volname", &volname);
if (ret) {
diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.h b/xlators/mgmt/glusterd/src/glusterd-mgmt.h
index bf87ec7..2215f17 100644
--- a/xlators/mgmt/glusterd/src/glusterd-mgmt.h
+++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.h
@@ -74,4 +74,10 @@ glusterd_mgmt_v3_release_peer_locks (glusterd_op_t op, dict_t *dict,
int32_t
glusterd_multiple_mgmt_v3_unlock (dict_t *dict, uuid_t uuid);
+
+int
+glusterd_reset_brick_prevalidate (dict_t *dict, char **op_errstr,
+ dict_t *rsp_dict);
+int
+glusterd_op_reset_brick (dict_t *dict, dict_t *rsp_dict);
#endif /* _GLUSTERD_MGMT_H_ */
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
index 553b7b4..dc28a2b 100644
--- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c
+++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c
@@ -4139,6 +4139,7 @@ glusterd_op_build_payload (dict_t **req, char **op_errstr, dict_t *op_ctx)
case GD_OP_BITROT:
case GD_OP_SCRUB_STATUS:
case GD_OP_SCRUB_ONDEMAND:
+ case GD_OP_RESET_BRICK:
{
do_common = _gf_true;
}
diff --git a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c
index 0df5d43..687ff00 100644
--- a/xlators/mgmt/glusterd/src/glusterd-replace-brick.c
+++ b/xlators/mgmt/glusterd/src/glusterd-replace-brick.c
@@ -27,13 +27,6 @@
#include <signal.h>
-#define GLUSTERD_GET_RB_MNTPT(path, len, volinfo) \
- snprintf (path, len, \
- DEFAULT_VAR_RUN_DIRECTORY"/%s-"RB_CLIENT_MOUNTPOINT, \
- volinfo->volname);
-
-extern uuid_t global_txn_id;
-
int
glusterd_mgmt_v3_initiate_replace_brick_cmd_phases (rpcsvc_request_t *req,
glusterd_op_t op,
@@ -46,14 +39,17 @@ __glusterd_handle_replace_brick (rpcsvc_request_t *req)
dict_t *dict = NULL;
char *src_brick = NULL;
char *dst_brick = NULL;
- int32_t op = 0;
+ char *cli_op = NULL;
+ glusterd_op_t op = -1;
char *volname = NULL;
char msg[2048] = {0,};
xlator_t *this = NULL;
+ glusterd_conf_t *conf = NULL;
GF_ASSERT (req);
this = THIS;
GF_ASSERT (this);
+ conf = this->private;
ret = xdr_to_generic (req->msg[0], &cli_req, (xdrproc_t)xdr_gf_cli_req);
if (ret < 0) {
@@ -95,7 +91,7 @@ __glusterd_handle_replace_brick (rpcsvc_request_t *req)
goto out;
}
- ret = dict_get_int32 (dict, "operation", &op);
+ ret = dict_get_str (dict, "operation", &cli_op);
if (ret) {
gf_msg_debug (this->name, 0,
"dict_get on operation failed");
@@ -103,6 +99,19 @@ __glusterd_handle_replace_brick (rpcsvc_request_t *req)
goto out;
}
+ op = gd_cli_to_gd_op (cli_op);
+
+ if (conf->op_version < GD_OP_VERSION_3_9_0 &&
+ strcmp (cli_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
+ snprintf (msg, sizeof (msg), "Cannot execute command. The "
+ "cluster is operating at version %d. reset-brick "
+ "command %s is unavailable in this version.",
+ conf->op_version,
+ gd_rb_op_to_str (cli_op));
+ ret = -1;
+ goto out;
+ }
+
ret = dict_get_str (dict, "src-brick", &src_brick);
if (ret) {
@@ -114,52 +123,60 @@ __glusterd_handle_replace_brick (rpcsvc_request_t *req)
gf_msg_debug (this->name, 0,
"src brick=%s", src_brick);
- ret = dict_get_str (dict, "dst-brick", &dst_brick);
+ if (!strcmp (cli_op, "GF_RESET_OP_COMMIT") ||
+ !strcmp (cli_op, "GF_RESET_OP_COMMIT_FORCE") ||
+ !strcmp (cli_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
+ ret = dict_get_str (dict, "dst-brick", &dst_brick);
- if (ret) {
- snprintf (msg, sizeof (msg), "Failed to get dest brick");
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_DICT_GET_FAILED, "%s", msg);
- goto out;
+ if (ret) {
+ snprintf (msg, sizeof (msg), "Failed to get"
+ "dest brick");
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED, "%s", msg);
+ goto out;
+ }
+
+ gf_msg_debug (this->name, 0, "dst brick=%s", dst_brick);
}
- gf_msg_debug (this->name, 0, "dst brick=%s", dst_brick);
gf_msg (this->name, GF_LOG_INFO, 0,
- GD_MSG_REPLACE_BRK_COMMIT_FORCE_REQ_RCVD,
- "Received replace brick commit-force "
- "request operation");
+ (op == GD_OP_REPLACE_BRICK) ?
+ GD_MSG_REPLACE_BRK_COMMIT_FORCE_REQ_RCVD :
+ GD_MSG_RESET_BRICK_COMMIT_FORCE_REQ_RCVD,
+ "Received %s request.",
+ gd_rb_op_to_str (cli_op));
+
+ gf_event ((op == GD_OP_REPLACE_BRICK) ? EVENT_BRICK_REPLACE :
+ EVENT_BRICK_RESET, "received %s request. Source bricks %s,"
+ "destination brick %s.", gd_rb_op_to_str (cli_op),
+ src_brick, (dst_brick) ? dst_brick : "");
ret = glusterd_mgmt_v3_initiate_replace_brick_cmd_phases (req,
- GD_OP_REPLACE_BRICK, dict);
+ op, dict);
out:
+ if (ret) {
+ glusterd_op_send_cli_response (op, ret, 0, req,
+ dict, msg);
+ }
+ ret = 0;
free (cli_req.dict.dict_val);//malloced by xdr
return ret;
}
int
-glusterd_handle_replace_brick (rpcsvc_request_t *req)
+glusterd_handle_reset_brick (rpcsvc_request_t *req)
{
return glusterd_big_locked_handler (req,
__glusterd_handle_replace_brick);
}
-static int
-glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo,
- glusterd_brickinfo_t **brickinfo)
+int
+glusterd_handle_replace_brick (rpcsvc_request_t *req)
{
- int32_t ret = -1;
-
- if (!volinfo || !brickinfo)
- goto out;
-
- *brickinfo = volinfo->rep_brick.dst_brick;
-
- ret = 0;
-
-out:
- return ret;
+ return glusterd_big_locked_handler (req,
+ __glusterd_handle_replace_brick);
}
int
@@ -170,21 +187,22 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr,
char *src_brick = NULL;
char *dst_brick = NULL;
char *volname = NULL;
- char *replace_op = NULL;
+ char *op = NULL;
+ glusterd_op_t gd_op = -1;
glusterd_volinfo_t *volinfo = NULL;
glusterd_brickinfo_t *src_brickinfo = NULL;
char *host = NULL;
char *path = NULL;
char msg[2048] = {0};
- char *dup_dstbrick = NULL;
glusterd_peerinfo_t *peerinfo = NULL;
glusterd_brickinfo_t *dst_brickinfo = NULL;
glusterd_conf_t *priv = NULL;
char pidfile[PATH_MAX] = {0};
xlator_t *this = NULL;
gf_boolean_t is_force = _gf_false;
- gsync_status_param_t param = {0,};
- char *c = NULL;
+ pid_t pid = -1;
+ uuid_t volume_id = {0,};
+ char *dup_dstbrick = NULL;
this = THIS;
GF_ASSERT (this);
@@ -192,193 +210,41 @@ glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr,
priv = this->private;
GF_ASSERT (priv);
- ret = dict_get_str (dict, "src-brick", &src_brick);
-
- if (ret) {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_DICT_GET_FAILED, "Unable to get src brick");
- goto out;
- }
-
- gf_msg_debug (this->name, 0, "src brick=%s", src_brick);
-
- ret = dict_get_str (dict, "dst-brick", &dst_brick);
-
- if (ret) {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_DICT_GET_FAILED, "Unable to get dest brick");
- goto out;
- }
-
- gf_msg_debug (this->name, 0, "dst brick=%s", dst_brick);
-
- ret = dict_get_str (dict, "volname", &volname);
-
- if (ret) {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_DICT_GET_FAILED, "Unable to get volume name");
- goto out;
- }
-
- ret = dict_get_str (dict, "operation", &replace_op);
- if (ret) {
- gf_msg_debug (this->name, 0,
- "dict get on replace-brick operation failed");
- goto out;
- }
-
- ret = glusterd_volinfo_find (volname, &volinfo);
- if (ret) {
- snprintf (msg, sizeof (msg), "volume: %s does not exist",
- volname);
- *op_errstr = gf_strdup (msg);
- goto out;
- }
-
- if (GLUSTERD_STATUS_STARTED != volinfo->status) {
- ret = -1;
- snprintf (msg, sizeof (msg), "volume: %s is not started",
- volname);
- *op_errstr = gf_strdup (msg);
- goto out;
- }
-
- ret = glusterd_disallow_op_for_tier (volinfo, GD_OP_REPLACE_BRICK, -1);
- if (ret) {
- snprintf (msg, sizeof (msg), "Replace brick commands are not "
- "supported on tiered volume %s", volname);
- *op_errstr = gf_strdup (msg);
- goto out;
- }
-
- if (!glusterd_store_is_valid_brickpath (volname, dst_brick) ||
- !glusterd_is_valid_volfpath (volname, dst_brick)) {
- snprintf (msg, sizeof (msg), "brick path %s is too "
- "long.", dst_brick);
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_BRKPATH_TOO_LONG, "%s", msg);
- *op_errstr = gf_strdup (msg);
-
- ret = -1;
- goto out;
- }
-
- /* If geo-rep is configured, for this volume, it should be stopped. */
- param.volinfo = volinfo;
- ret = glusterd_check_geo_rep_running (&param, op_errstr);
- if (ret || param.is_active) {
- ret = -1;
+ ret = glusterd_brick_op_prerequisites (dict, &op, &gd_op,
+ &volname, &volinfo,
+ &src_brick, &src_brickinfo,
+ pidfile,
+ op_errstr, rsp_dict);
+ if (ret)
goto out;
- }
- if (glusterd_is_defrag_on(volinfo)) {
- snprintf (msg, sizeof(msg), "Volume name %s rebalance is in "
- "progress. Please retry after completion", volname);
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_OIP_RETRY_LATER, "%s", msg);
- *op_errstr = gf_strdup (msg);
+ if (strcmp (op, "GF_REPLACE_OP_COMMIT_FORCE")) {
ret = -1;
goto out;
- }
-
- if (!strcmp(replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
- is_force = _gf_true;
} else {
- ret = -1;
- goto out;
- }
-
- ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo,
- &src_brickinfo,
- _gf_false);
- if (ret) {
- snprintf (msg, sizeof (msg), "brick: %s does not exist in "
- "volume: %s", src_brick, volname);
- *op_errstr = gf_strdup (msg);
- goto out;
- }
-
- if (dict) {
- if (!glusterd_is_fuse_available ()) {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_RB_CMD_FAIL, "Unable to open /dev/"
- "fuse (%s), replace-brick command failed",
- strerror (errno));
- snprintf (msg, sizeof(msg), "Fuse unavailable\n "
- "Replace-brick failed");
- *op_errstr = gf_strdup (msg);
- ret = -1;
- goto out;
- }
- }
-
- if (gf_is_local_addr (src_brickinfo->hostname)) {
- gf_msg_debug (this->name, 0,
- "I AM THE SOURCE HOST");
- if (src_brickinfo->port && rsp_dict) {
- ret = dict_set_int32 (rsp_dict, "src-brick-port",
- src_brickinfo->port);
- if (ret) {
- gf_msg_debug (this->name, 0,
- "Could not set src-brick-port=%d",
- src_brickinfo->port);
- }
- }
-
- GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo, src_brickinfo,
- priv);
-
- }
-
- dup_dstbrick = gf_strdup (dst_brick);
- if (!dup_dstbrick) {
- ret = -1;
- gf_msg (this->name, GF_LOG_ERROR, ENOMEM,
- GD_MSG_NO_MEMORY, "Memory allocation failed");
- goto out;
- }
-
- /*
- * IPv4 address contains '.' and ipv6 addresses contains ':'
- * So finding the last occurance of ':' to
- * mark the start of brick path
- */
- c = strrchr(dup_dstbrick, ':');
- if (c != NULL) {
- c[0] = '\0';
- host = dup_dstbrick;
- path = c++;
- }
-
- if (!host || !path) {
- gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_BAD_FORMAT,
- "dst brick %s is not of form <HOSTNAME>:<export-dir>",
- dst_brick);
- ret = -1;
- goto out;
- }
+ is_force = _gf_true;
+ }
- ret = glusterd_brickinfo_new_from_brick (dst_brick, &dst_brickinfo,
- _gf_true, NULL);
+ ret = glusterd_get_dst_brick_info (&dst_brick, volname,
+ op_errstr,
+ &dst_brickinfo, &host,
+ dict, &dup_dstbrick);
if (ret)
goto out;
ret = glusterd_new_brick_validate (dst_brick, dst_brickinfo,
- msg, sizeof (msg));
- if (ret) {
+ msg, sizeof (msg), op);
+ /* fail if brick being replaced with itself */
+ if (ret) {
*op_errstr = gf_strdup (msg);
ret = -1;
gf_msg (this->name, GF_LOG_ERROR, 0,
GD_MSG_BRICK_VALIDATE_FAIL, "%s", *op_errstr);
goto out;
- }
+ }
- if (!strcmp(replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
-
- volinfo->rep_brick.src_brick = src_brickinfo;
- volinfo->rep_brick.dst_brick = dst_brickinfo;
- }
+ volinfo->rep_brick.src_brick = src_brickinfo;
+ volinfo->rep_brick.dst_brick = dst_brickinfo;
if (glusterd_rb_check_bricks (volinfo, src_brickinfo, dst_brickinfo)) {
@@ -484,48 +350,8 @@ rb_kill_destination_brick (glusterd_volinfo_t *volinfo,
return glusterd_service_stop ("brick", pidfile, SIGTERM, _gf_true);
}
-static int
-rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict,
- dict_t *req_dict, char *replace_op)
-{
- int ret = 0;
- int dict_ret = 0;
- int dst_port = 0;
-
- dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port);
- if (!dict_ret)
- dst_brickinfo->port = dst_port;
-
- if (gf_is_local_addr (dst_brickinfo->hostname)) {
- gf_msg ("glusterd", GF_LOG_INFO, 0,
- GD_MSG_BRK_PORT_NO_ADD_INDO,
- "adding dst-brick port no");
-
- if (rsp_dict) {
- ret = dict_set_int32 (rsp_dict, "dst-brick-port",
- dst_brickinfo->port);
- if (ret) {
- gf_msg_debug ("glusterd", 0,
- "Could not set dst-brick port no in rsp dict");
- goto out;
- }
- }
-
- if (req_dict) {
- ret = dict_set_int32 (req_dict, "dst-brick-port",
- dst_brickinfo->port);
- if (ret) {
- gf_msg_debug ("glusterd", 0,
- "Could not set dst-brick port no");
- goto out;
- }
- }
- }
-out:
- return ret;
-}
-static int
+int
glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo,
char *old_brick, char *new_brick,
dict_t *dict)
@@ -563,6 +389,7 @@ glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo,
strncpy (new_brickinfo->brick_id, old_brickinfo->brick_id,
sizeof (new_brickinfo->brick_id));
+ new_brickinfo->port = old_brickinfo->port;
/* A bricks mount dir is required only by snapshots which were
* introduced in gluster-3.6.0
@@ -579,8 +406,8 @@ glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo,
sizeof(new_brickinfo->mount_dir));
}
- cds_list_add_tail (&new_brickinfo->brick_list,
- &old_brickinfo->brick_list);
+ cds_list_add (&new_brickinfo->brick_list,
+ &old_brickinfo->brick_list);
volinfo->brick_count++;
@@ -699,11 +526,11 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict)
}
ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict,
- dict, replace_op);
+ dict);
if (ret)
goto out;
- if (strcmp(replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
+ if (strcmp (replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) {
ret = -1;
goto out;
}
@@ -722,8 +549,8 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict)
ret = glusterd_svcs_stop (volinfo);
if (ret) {
gf_msg (this->name, GF_LOG_ERROR, 0,
- GD_MSG_NFS_SERVER_STOP_FAIL,
- "Unable to stop nfs server, ret: %d", ret);
+ GD_MSG_GLUSTER_SERVICES_STOP_FAIL,
+ "Unable to stop gluster services, ret: %d", ret);
}
ret = glusterd_op_perform_replace_brick (volinfo, src_brick,
@@ -732,7 +559,7 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict)
gf_msg (this->name, GF_LOG_CRITICAL, 0,
GD_MSG_BRICK_ADD_FAIL, "Unable to add dst-brick: "
"%s to volume: %s", dst_brick, volinfo->volname);
- (void) glusterd_svcs_manager (volinfo);
+ (void) glusterd_svcs_manager (volinfo);
goto out;
}
@@ -741,8 +568,8 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict)
ret = glusterd_svcs_manager (volinfo);
if (ret) {
gf_msg (this->name, GF_LOG_CRITICAL, 0,
- GD_MSG_NFS_VOL_FILE_GEN_FAIL,
- "Failed to generate nfs volume file");
+ GD_MSG_GLUSTER_SERVICE_START_FAIL,
+ "Failed to start one or more gluster services.");
}
@@ -752,7 +579,7 @@ glusterd_op_replace_brick (dict_t *dict, dict_t *rsp_dict)
volinfo->rep_brick.dst_brick = NULL;
if (!ret)
- ret = glusterd_store_volinfo (volinfo,
+ ret = glusterd_store_volinfo (volinfo,
GLUSTERD_VOLINFO_VER_AC_INCREMENT);
if (ret)
gf_msg (this->name, GF_LOG_ERROR, 0,
diff --git a/xlators/mgmt/glusterd/src/glusterd-reset-brick.c b/xlators/mgmt/glusterd/src/glusterd-reset-brick.c
new file mode 100644
index 0000000..d1efe06
--- /dev/null
+++ b/xlators/mgmt/glusterd/src/glusterd-reset-brick.c
@@ -0,0 +1,430 @@
+/*
+ Copyright (c) 2016 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+#include "common-utils.h"
+#include "cli1-xdr.h"
+#include "xdr-generic.h"
+#include "glusterfs.h"
+#include "glusterd.h"
+#include "glusterd-op-sm.h"
+#include "glusterd-geo-rep.h"
+#include "glusterd-store.h"
+#include "glusterd-utils.h"
+#include "glusterd-svc-mgmt.h"
+#include "glusterd-svc-helper.h"
+#include "glusterd-nfs-svc.h"
+#include "glusterd-volgen.h"
+#include "glusterd-messages.h"
+#include "glusterd-mgmt.h"
+#include "run.h"
+#include "syscall.h"
+
+#include <signal.h>
+
+int
+glusterd_reset_brick_prevalidate (dict_t *dict, char **op_errstr,
+ dict_t *rsp_dict)
+{
+ int ret = 0;
+ int32_t port = 0;
+ char *src_brick = NULL;
+ char *dst_brick = NULL;
+ char *volname = NULL;
+ char *op = NULL;
+ glusterd_op_t gd_op = -1;
+ glusterd_volinfo_t *volinfo = NULL;
+ glusterd_brickinfo_t *src_brickinfo = NULL;
+ char *host = NULL;
+ char msg[2048] = {0};
+ glusterd_peerinfo_t *peerinfo = NULL;
+ glusterd_brickinfo_t *dst_brickinfo = NULL;
+ gf_boolean_t enabled = _gf_false;
+ glusterd_conf_t *priv = NULL;
+ char *savetok = NULL;
+ char pidfile[PATH_MAX] = {0};
+ char *task_id_str = NULL;
+ xlator_t *this = NULL;
+ gf_boolean_t is_force = _gf_false;
+ gsync_status_param_t param = {0,};
+ pid_t pid = -1;
+ uuid_t volume_id = {0,};
+ char *dup_dstbrick = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = glusterd_brick_op_prerequisites (dict, &op, &gd_op,
+ &volname, &volinfo,
+ &src_brick, &src_brickinfo,
+ pidfile,
+ op_errstr, rsp_dict);
+ if (ret)
+ goto out;
+
+ if (!strcmp (op, "GF_RESET_OP_START"))
+ goto done;
+
+ if (!strcmp (op, "GF_RESET_OP_COMMIT_FORCE"))
+ is_force = _gf_true;
+
+ ret = glusterd_get_dst_brick_info (&dst_brick, volname,
+ op_errstr,
+ &dst_brickinfo, &host,
+ dict, &dup_dstbrick);
+ if (ret)
+ goto out;
+
+ ret = glusterd_new_brick_validate (dst_brick, dst_brickinfo,
+ msg, sizeof (msg), op);
+ /* if bricks are not same and reset brick was used, fail command.
+ * Only replace brick should be used to replace with new bricks
+ * to the volume.
+ */
+ if (ret == 0) {
+ if (!gf_uuid_compare (MY_UUID, dst_brickinfo->uuid)) {
+ ret = -1;
+ *op_errstr = gf_strdup
+ ("When destination brick is new,"
+ " please use"
+ " gluster volume "
+ "replace-brick <volname> "
+ "<src-brick> <dst-brick> "
+ "commit force");
+ if (*op_errstr)
+ gf_msg (this->name,
+ GF_LOG_ERROR,
+ EPERM,
+ GD_MSG_BRICK_VALIDATE_FAIL,
+ "%s", *op_errstr);
+ goto out;
+ }
+ } else if (ret == 1) {
+ if (gf_is_service_running (pidfile, &pid)) {
+ ret = -1;
+ *op_errstr = gf_strdup
+ ("Source brick"
+ " must be stopped."
+ " Please use "
+ "gluster volume "
+ "reset-brick <volname> "
+ "<dst-brick> start.");
+ if (*op_errstr)
+ gf_msg (this->name,
+ GF_LOG_ERROR,
+ EPERM,
+ GD_MSG_BRICK_VALIDATE_FAIL,
+ "%s", *op_errstr);
+ goto out;
+ }
+ ret = sys_lgetxattr (dst_brickinfo->path,
+ GF_XATTR_VOL_ID_KEY,
+ volume_id, 16);
+ if (gf_uuid_compare (dst_brickinfo->uuid,
+ src_brickinfo->uuid) ||
+ (ret >= 0 && is_force == _gf_false)) {
+ ret = -1;
+ *op_errstr = gf_strdup ("Brick not available."
+ "It may be containing "
+ "or be contained "
+ "by an existing brick."
+ "Use 'force' option to "
+ "override this.");
+ if (*op_errstr)
+ gf_msg (this->name,
+ GF_LOG_ERROR,
+ EPERM,
+ GD_MSG_BRICK_VALIDATE_FAIL,
+ "%s", *op_errstr);
+ goto out;
+ }
+ ret = 0;
+ } else {
+ *op_errstr = gf_strdup (msg);
+ ret = -1;
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_BRICK_VALIDATE_FAIL, "%s", *op_errstr);
+ goto out;
+ }
+
+ volinfo->rep_brick.src_brick = src_brickinfo;
+ volinfo->rep_brick.dst_brick = dst_brickinfo;
+
+ if (gf_is_local_addr (host)) {
+ ret = glusterd_validate_and_create_brickpath
+ (dst_brickinfo,
+ volinfo->volume_id,
+ op_errstr, is_force);
+ if (ret)
+ goto out;
+ } else {
+ rcu_read_lock ();
+
+ peerinfo = glusterd_peerinfo_find (NULL, host);
+ if (peerinfo == NULL) {
+ ret = -1;
+ snprintf (msg, sizeof (msg),
+ "%s, is not a friend.",
+ host);
+ *op_errstr = gf_strdup (msg);
+
+ } else if (!peerinfo->connected) {
+ snprintf (msg, sizeof (msg), "%s,"
+ "is not connected at "
+ "the moment.", host);
+ *op_errstr = gf_strdup (msg);
+ ret = -1;
+
+ } else if (GD_FRIEND_STATE_BEFRIENDED !=
+ peerinfo->state.state) {
+ snprintf (msg, sizeof (msg),
+ "%s, is not befriended "
+ "at the moment.", host);
+ *op_errstr = gf_strdup (msg);
+ ret = -1;
+ }
+ rcu_read_unlock ();
+
+ if (ret)
+ goto out;
+
+ }
+
+ ret = glusterd_get_brick_mount_dir
+ (dst_brickinfo->path,
+ dst_brickinfo->hostname,
+ dst_brickinfo->mount_dir);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_BRICK_MOUNTDIR_GET_FAIL,
+ "Failed to get brick mount_dir.");
+ goto out;
+ }
+
+ ret = dict_set_dynstr_with_alloc (rsp_dict,
+ "brick1.mount_dir",
+ dst_brickinfo->mount_dir);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_SET_FAILED,
+ "Failed to set brick1.mount_dir");
+ goto out;
+ }
+
+ ret = dict_set_int32 (rsp_dict, "brick_count", 1);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_SET_FAILED,
+ "Failed to set local_brick_count.");
+ goto out;
+ }
+
+done:
+ ret = 0;
+out:
+ GF_FREE (dup_dstbrick);
+ gf_msg_debug (this->name, 0, "Returning %d.", ret);
+
+ return ret;
+}
+
+int
+glusterd_op_reset_brick (dict_t *dict, dict_t *rsp_dict)
+{
+ int ret = 0;
+ dict_t *ctx = NULL;
+ char *op = NULL;
+ glusterd_volinfo_t *volinfo = NULL;
+ char *volname = NULL;
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ char *src_brick = NULL;
+ char *dst_brick = NULL;
+ glusterd_brickinfo_t *src_brickinfo = NULL;
+ glusterd_brickinfo_t *dst_brickinfo = NULL;
+ char *task_id_str = NULL;
+ char pidfile[PATH_MAX] = {0,};
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = dict_get_str (dict, "operation", &op);
+ if (ret) {
+ gf_msg_debug (this->name, 0,
+ "dict_get on operation failed");
+ goto out;
+ }
+
+ ret = dict_get_str (dict, "volname", &volname);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED, "Unable to get volume name");
+ goto out;
+ }
+
+ ret = glusterd_volinfo_find (volname, &volinfo);
+ if (ret)
+ goto out;
+
+ ret = dict_get_str (dict, "src-brick", &src_brick);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED, "Unable to get src brick");
+ goto out;
+ }
+
+ gf_msg_debug (this->name, 0, "src brick=%s", src_brick);
+
+ ret = glusterd_volume_brickinfo_get_by_brick (src_brick, volinfo,
+ &src_brickinfo,
+ _gf_false);
+ if (ret) {
+ gf_msg_debug (this->name, 0,
+ "Unable to get src-brickinfo");
+ goto out;
+ }
+
+ if (!strcmp (op, "GF_RESET_OP_START")) {
+ (void) glusterd_brick_disconnect (src_brickinfo);
+ GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo,
+ src_brickinfo, priv);
+ ret = glusterd_service_stop ("brick", pidfile,
+ SIGTERM, _gf_false);
+ if (ret == 0) {
+ glusterd_set_brick_status (src_brickinfo,
+ GF_BRICK_STOPPED);
+ (void) glusterd_brick_unlink_socket_file
+ (volinfo, src_brickinfo);
+ gf_msg (this->name, GF_LOG_INFO, 0,
+ GD_MSG_BRICK_CLEANUP_SUCCESS,
+ "Brick cleanup successful.");
+ } else {
+ gf_msg (this->name, GF_LOG_CRITICAL, 0,
+ GD_MSG_BRK_CLEANUP_FAIL,
+ "Unable to cleanup src brick");
+ goto out;
+ }
+ goto out;
+ } else if (!strcmp (op, "GF_RESET_OP_COMMIT") ||
+ !strcmp (op, "GF_RESET_OP_COMMIT_FORCE")) {
+ ret = dict_get_str (dict, "dst-brick", &dst_brick);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED,
+ "Unable to get dst brick");
+ goto out;
+ }
+
+ gf_msg_debug (this->name, 0, "dst brick=%s", dst_brick);
+
+ ret = glusterd_get_rb_dst_brickinfo (volinfo,
+ &dst_brickinfo);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_RB_BRICKINFO_GET_FAIL,
+ "Unable to get "
+ "reset brick "
+ "destination brickinfo");
+ goto out;
+ }
+
+ ret = glusterd_resolve_brick (dst_brickinfo);
+ if (ret) {
+ gf_msg_debug (this->name, 0,
+ "Unable to resolve dst-brickinfo");
+ goto out;
+ }
+
+ ret = rb_update_dstbrick_port (dst_brickinfo, rsp_dict,
+ dict);
+ if (ret)
+ goto out;
+
+ if (gf_is_local_addr (dst_brickinfo->hostname)) {
+ gf_msg_debug (this->name, 0, "I AM THE DESTINATION HOST");
+ (void) glusterd_brick_disconnect (src_brickinfo);
+ GLUSTERD_GET_BRICK_PIDFILE (pidfile, volinfo,
+ src_brickinfo, priv);
+ ret = glusterd_service_stop ("brick", pidfile,
+ SIGTERM, _gf_false);
+ if (ret == 0) {
+ glusterd_set_brick_status
+ (src_brickinfo, GF_BRICK_STOPPED);
+ (void) glusterd_brick_unlink_socket_file
+ (volinfo, src_brickinfo);
+ gf_msg (this->name, GF_LOG_INFO, 0,
+ GD_MSG_BRICK_CLEANUP_SUCCESS,
+ "Brick cleanup successful.");
+ } else {
+ gf_msg (this->name, GF_LOG_CRITICAL, 0,
+ GD_MSG_BRK_CLEANUP_FAIL,
+ "Unable to cleanup src brick");
+ goto out;
+ }
+ }
+
+ ret = glusterd_svcs_stop (volinfo);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_GLUSTER_SERVICES_STOP_FAIL,
+ "Unable to stop gluster services, ret: %d",
+ ret);
+ goto out;
+ }
+ ret = glusterd_op_perform_replace_brick (volinfo, src_brick,
+ dst_brick, dict);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_CRITICAL, 0,
+ GD_MSG_BRICK_ADD_FAIL,
+ "Unable to add dst-brick: "
+ "%s to volume: %s", dst_brick,
+ volinfo->volname);
+ (void) glusterd_svcs_manager (volinfo);
+ goto out;
+ }
+
+ volinfo->rebal.defrag_status = 0;
+
+ ret = glusterd_svcs_manager (volinfo);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_CRITICAL, 0,
+ GD_MSG_GLUSTER_SERVICE_START_FAIL,
+ "Failed to start one or more gluster services.");
+ }
+
+
+ ret = glusterd_fetchspec_notify (THIS);
+ glusterd_brickinfo_delete (volinfo->rep_brick.dst_brick);
+ volinfo->rep_brick.src_brick = NULL;
+ volinfo->rep_brick.dst_brick = NULL;
+
+ if (!ret)
+ ret = glusterd_store_volinfo (volinfo,
+ GLUSTERD_VOLINFO_VER_AC_INCREMENT);
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_RBOP_STATE_STORE_FAIL,
+ "Couldn't store"
+ " reset brick operation's state.");
+
+ }
+ } else {
+ ret = -1;
+ goto out;
+ }
+
+
+out:
+ return ret;
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
index 03b6e71..f9e76f3 100644
--- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c
@@ -144,6 +144,7 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret,
case GD_OP_BITROT:
case GD_OP_SCRUB_STATUS:
case GD_OP_SCRUB_ONDEMAND:
+ case GD_OP_RESET_BRICK:
{
/*nothing specific to be done*/
break;
diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c
index 70d1020..2b7a447 100644
--- a/xlators/mgmt/glusterd/src/glusterd-syncop.c
+++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c
@@ -248,6 +248,7 @@ glusterd_syncop_aggr_rsp_dict (glusterd_op_t op, dict_t *aggr, dict_t *rsp)
break;
case GD_OP_REPLACE_BRICK:
+ case GD_OP_RESET_BRICK:
ret = glusterd_rb_use_rsp_dict (aggr, rsp);
if (ret)
goto out;
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c
index ec371d8..0011cac 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.c
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.c
@@ -5970,7 +5970,7 @@ glusterd_is_defrag_on (glusterd_volinfo_t *volinfo)
int
glusterd_new_brick_validate (char *brick, glusterd_brickinfo_t *brickinfo,
- char *op_errstr, size_t len)
+ char *op_errstr, size_t len, char *op)
{
glusterd_brickinfo_t *newbrickinfo = NULL;
int ret = -1;
@@ -6011,8 +6011,12 @@ glusterd_new_brick_validate (char *brick, glusterd_brickinfo_t *brickinfo,
newbrickinfo->path)) {
snprintf(op_errstr, len, "Brick: %s not available."
" Brick may be containing or be contained "
- "by an existing brick", brick);
- ret = -1;
+ "by an existing brick.", brick);
+ if (op && (!strcmp (op, "GF_RESET_OP_COMMIT") ||
+ !strcmp (op, "GF_RESET_OP_COMMIT_FORCE")))
+ ret = 1;
+ else
+ ret = -1;
goto out;
}
@@ -11458,6 +11462,7 @@ glusterd_disallow_op_for_tier (glusterd_volinfo_t *volinfo, glusterd_op_t op,
switch (op) {
case GD_OP_ADD_BRICK:
case GD_OP_REPLACE_BRICK:
+ case GD_OP_RESET_BRICK:
ret = -1;
gf_msg_debug (this->name, 0, "Operation not "
"permitted on tiered volume %s",
@@ -11708,3 +11713,319 @@ get_last_brick_of_brick_group (glusterd_volinfo_t *volinfo,
return last;
}
+
+int
+glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo,
+ glusterd_brickinfo_t **brickinfo)
+{
+ int32_t ret = -1;
+
+ if (!volinfo || !brickinfo)
+ goto out;
+
+ *brickinfo = volinfo->rep_brick.dst_brick;
+
+ ret = 0;
+
+out:
+ return ret;
+}
+
+int
+rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict,
+ dict_t *req_dict)
+{
+ int ret = 0;
+ int dict_ret = 0;
+ int dst_port = 0;
+
+ dict_ret = dict_get_int32 (req_dict, "dst-brick-port", &dst_port);
+ if (!dict_ret)
+ dst_brickinfo->port = dst_port;
+
+ if (gf_is_local_addr (dst_brickinfo->hostname)) {
+ gf_msg ("glusterd", GF_LOG_INFO, 0,
+ GD_MSG_BRK_PORT_NO_ADD_INDO,
+ "adding dst-brick port no %d", dst_port);
+
+ if (rsp_dict) {
+ ret = dict_set_int32 (rsp_dict, "dst-brick-port",
+ dst_brickinfo->port);
+ if (ret) {
+ gf_msg_debug ("glusterd", 0,
+ "Could not set dst-brick port no in rsp dict");
+ goto out;
+ }
+ }
+
+ if (req_dict && !dict_ret) {
+ ret = dict_set_int32 (req_dict, "dst-brick-port",
+ dst_brickinfo->port);
+ if (ret) {
+ gf_msg_debug ("glusterd", 0,
+ "Could not set dst-brick port no");
+ goto out;
+ }
+ }
+ }
+out:
+ return ret;
+}
+
+int
+glusterd_brick_op_prerequisites (dict_t *dict,
+ char **op,
+ glusterd_op_t *gd_op, char **volname,
+ glusterd_volinfo_t **volinfo,
+ char **src_brick, glusterd_brickinfo_t
+ **src_brickinfo, char *pidfile,
+ char **op_errstr, dict_t *rsp_dict)
+{
+ int ret = 0;
+ char msg[2048] = {0};
+ gsync_status_param_t param = {0,};
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ glusterd_volinfo_t *v = NULL;
+ glusterd_brickinfo_t *b = NULL;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = dict_get_str (dict, "operation", op);
+ if (ret) {
+ gf_msg_debug (this->name, 0,
+ "dict get on operation type failed");
+ goto out;
+ }
+
+ *gd_op = gd_cli_to_gd_op (*op);
+ if (*gd_op < 0)
+ goto out;
+
+ ret = dict_get_str (dict, "volname", volname);
+
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED, "Unable to get volume name");
+ goto out;
+ }
+
+ ret = glusterd_volinfo_find (*volname, volinfo);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "volume: %s does not exist",
+ *volname);
+ *op_errstr = gf_strdup (msg);
+ goto out;
+ }
+
+ if (GLUSTERD_STATUS_STARTED != (*volinfo)->status) {
+ ret = -1;
+ snprintf (msg, sizeof (msg), "volume: %s is not started",
+ *volname);
+ *op_errstr = gf_strdup (msg);
+ goto out;
+ }
+
+ ret = glusterd_disallow_op_for_tier (*volinfo, *gd_op, -1);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "%sbrick commands are not "
+ "supported on tiered volume %s",
+ (*gd_op == GD_OP_REPLACE_BRICK) ? "replace-" :
+ "reset-",
+ *volname);
+ *op_errstr = gf_strdup (msg);
+ goto out;
+ }
+
+ /* If geo-rep is configured, for this volume, it should be stopped. */
+ param.volinfo = *volinfo;
+ ret = glusterd_check_geo_rep_running (&param, op_errstr);
+ if (ret || param.is_active) {
+ ret = -1;
+ goto out;
+ }
+
+ if (glusterd_is_defrag_on(*volinfo)) {
+ snprintf (msg, sizeof(msg), "Volume name %s rebalance is in "
+ "progress. Please retry after completion", *volname);
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_OIP_RETRY_LATER, "%s", msg);
+ *op_errstr = gf_strdup (msg);
+ ret = -1;
+ goto out;
+ }
+
+ if (dict) {
+ if (!glusterd_is_fuse_available ()) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ (*gd_op == GD_OP_REPLACE_BRICK) ?
+ GD_MSG_RB_CMD_FAIL :
+ GD_MSG_RESET_BRICK_CMD_FAIL,
+ "Unable to open /dev/"
+ "fuse (%s), %s command failed",
+ strerror (errno), gd_rb_op_to_str (*op));
+ snprintf (msg, sizeof(msg), "Fuse unavailable\n "
+ "%s failed", gd_rb_op_to_str (*op));
+ *op_errstr = gf_strdup (msg);
+ ret = -1;
+ goto out;
+ }
+ }
+
+ ret = dict_get_str (dict, "src-brick", src_brick);
+
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED, "Unable to get src brick");
+ goto out;
+ }
+
+ gf_msg_debug (this->name, 0, "src brick=%s", *src_brick);
+
+ ret = glusterd_volume_brickinfo_get_by_brick (*src_brick, *volinfo,
+ src_brickinfo,
+ _gf_false);
+ if (ret) {
+ snprintf (msg, sizeof (msg), "brick: %s does not exist in "
+ "volume: %s", *src_brick, *volname);
+ *op_errstr = gf_strdup (msg);
+ goto out;
+ }
+
+ if (gf_is_local_addr ((*src_brickinfo)->hostname)) {
+ gf_msg_debug (this->name, 0,
+ "I AM THE SOURCE HOST");
+ if ((*src_brickinfo)->port && rsp_dict) {
+ ret = dict_set_int32 (rsp_dict, "src-brick-port",
+ (*src_brickinfo)->port);
+ if (ret) {
+ gf_msg_debug (this->name, 0,
+ "Could not set src-brick-port=%d",
+ (*src_brickinfo)->port);
+ }
+ }
+
+ v = *volinfo;
+ b = *src_brickinfo;
+ GLUSTERD_GET_BRICK_PIDFILE (pidfile, v, b,
+ priv);
+ }
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
+glusterd_get_dst_brick_info (char **dst_brick, char *volname, char **op_errstr,
+ glusterd_brickinfo_t **dst_brickinfo, char **host,
+ dict_t *dict, char **dup_dstbrick)
+{
+
+ char *path = NULL;
+ char *c = NULL;
+ char msg[2048] = {0};
+ xlator_t *this = NULL;
+ glusterd_conf_t *priv = NULL;
+ int ret = 0;
+
+ this = THIS;
+ GF_ASSERT (this);
+
+ priv = this->private;
+ GF_ASSERT (priv);
+
+ ret = dict_get_str (dict, "dst-brick", dst_brick);
+
+ if (ret) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_DICT_GET_FAILED,
+ "Unable to get dest brick.");
+ goto out;
+ }
+
+ gf_msg_debug (this->name, 0, "dst brick=%s", *dst_brick);
+
+ if (!glusterd_store_is_valid_brickpath (volname, *dst_brick) ||
+ !glusterd_is_valid_volfpath (volname, *dst_brick)) {
+ snprintf (msg, sizeof (msg), "brick path %s is too "
+ "long.", *dst_brick);
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_BRKPATH_TOO_LONG, "%s", msg);
+ *op_errstr = gf_strdup (msg);
+
+ ret = -1;
+ goto out;
+ }
+
+ *dup_dstbrick = gf_strdup (*dst_brick);
+ if (!*dup_dstbrick) {
+ ret = -1;
+ goto out;
+ }
+
+ /*
+ * IPv4 address contains '.' and ipv6 addresses contains ':'
+ * So finding the last occurance of ':' to
+ * mark the start of brick path
+ */
+ c = strrchr(*dup_dstbrick, ':');
+ if (c != NULL) {
+ c[0] = '\0';
+ *host = *dup_dstbrick;
+ path = c++;
+ }
+
+ if (!host || !path) {
+ gf_msg (this->name, GF_LOG_ERROR, 0,
+ GD_MSG_BAD_FORMAT,
+ "dst brick %s is not of "
+ "form <HOSTNAME>:<export-dir>",
+ *dst_brick);
+ ret = -1;
+ goto out;
+ }
+
+ ret = glusterd_brickinfo_new_from_brick (*dst_brick,
+ dst_brickinfo,
+ _gf_true, NULL);
+ if (ret)
+ goto out;
+
+ ret = 0;
+out:
+ return ret;
+}
+
+glusterd_op_t
+gd_cli_to_gd_op (char *cli_op)
+{
+ if (!strcmp (cli_op, "GF_RESET_OP_START") ||
+ !strcmp(cli_op, "GF_RESET_OP_COMMIT") ||
+ !strcmp (cli_op, "GF_RESET_OP_COMMIT_FORCE")) {
+ return GD_OP_RESET_BRICK;
+ }
+
+ if (!strcmp (cli_op, "GF_REPLACE_OP_COMMIT_FORCE"))
+ return GD_OP_REPLACE_BRICK;
+
+ return -1;
+}
+
+char *
+gd_rb_op_to_str (char *op)
+{
+ if (!strcmp (op, "GF_RESET_OP_START"))
+ return "reset-brick start";
+ if (!strcmp (op, "GF_RESET_OP_COMMIT"))
+ return "reset-brick commit";
+ if (!strcmp (op, "GF_RESET_OP_COMMIT_FORCE"))
+ return "reset-brick commit force";
+ if (!strcmp (op, "GF_REPLACE_OP_COMMIT_FORCE"))
+ return "replace-brick commit force";
+ return NULL;
+}
diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h
index ca07efd..419ab48 100644
--- a/xlators/mgmt/glusterd/src/glusterd-utils.h
+++ b/xlators/mgmt/glusterd/src/glusterd-utils.h
@@ -242,7 +242,7 @@ glusterd_volinfo_bricks_delete (glusterd_volinfo_t *volinfo);
int
glusterd_new_brick_validate (char *brick, glusterd_brickinfo_t *brickinfo,
- char *op_errstr, size_t len);
+ char *op_errstr, size_t len, char *op);
int32_t
glusterd_volume_brickinfos_delete (glusterd_volinfo_t *volinfo);
@@ -741,4 +741,36 @@ assign_brick_groups (glusterd_volinfo_t *volinfo);
glusterd_brickinfo_t*
get_last_brick_of_brick_group (glusterd_volinfo_t *volinfo,
glusterd_brickinfo_t *brickinfo);
+int
+glusterd_get_rb_dst_brickinfo (glusterd_volinfo_t *volinfo,
+ glusterd_brickinfo_t **brickinfo);
+int
+rb_update_dstbrick_port (glusterd_brickinfo_t *dst_brickinfo, dict_t *rsp_dict,
+ dict_t *req_dict);
+int
+glusterd_op_perform_replace_brick (glusterd_volinfo_t *volinfo,
+ char *old_brick, char *new_brick,
+ dict_t *dict);
+int32_t
+glusterd_brick_unlink_socket_file (glusterd_volinfo_t *volinfo,
+ glusterd_brickinfo_t *brickinfo);
+char *
+gd_rb_op_to_str (char *op);
+
+glusterd_op_t
+gd_cli_to_gd_op (char *cli_op);
+
+int
+glusterd_get_dst_brick_info (char **dst_brick, char *volname, char **op_errstr,
+ glusterd_brickinfo_t **dst_brickinfo, char **host,
+ dict_t *dict, char **dup_dstbrick);
+
+int
+glusterd_brick_op_prerequisites (dict_t *dict,
+ char **op,
+ glusterd_op_t *gd_op, char **volname,
+ glusterd_volinfo_t **volinfo,
+ char **src_brick, glusterd_brickinfo_t
+ **src_brickinfo, char *pidfile,
+ char **op_errstr, dict_t *rsp_dict);
#endif
diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
index fe5d4c8..b38b0e6 100644
--- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
+++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c
@@ -1253,7 +1253,7 @@ glusterd_op_stage_create_volume (dict_t *dict, char **op_errstr,
goto out;
ret = glusterd_new_brick_validate (brick, brick_info, msg,
- sizeof (msg));
+ sizeof (msg), NULL);
if (ret)
goto out;
diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c
index 7d10827..705ce72 100644
--- a/xlators/mgmt/glusterd/src/glusterd.c
+++ b/xlators/mgmt/glusterd/src/glusterd.c
@@ -123,6 +123,7 @@ const char *gd_op_list[GD_OP_MAX + 1] = {
[GD_OP_SYS_EXEC] = "Execute system commands",
[GD_OP_GSYNC_CREATE] = "Geo-replication Create",
[GD_OP_SNAP] = "Snapshot",
+ [GD_OP_RESET_BRICK] = "Reset Brick",
[GD_OP_MAX] = "Invalid op"
};
diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h
index 430798f..eb03d05 100644
--- a/xlators/mgmt/glusterd/src/glusterd.h
+++ b/xlators/mgmt/glusterd/src/glusterd.h
@@ -119,6 +119,7 @@ typedef enum glusterd_op_ {
GD_OP_TIER_MIGRATE,
GD_OP_SCRUB_STATUS,
GD_OP_SCRUB_ONDEMAND,
+ GD_OP_RESET_BRICK,
GD_OP_MAX,
} glusterd_op_t;
@@ -950,6 +951,9 @@ int
glusterd_handle_fsm_log (rpcsvc_request_t *req);
int
+glusterd_handle_reset_brick (rpcsvc_request_t *req);
+
+int
glusterd_xfer_cli_deprobe_resp (rpcsvc_request_t *req, int32_t op_ret,
int32_t op_errno, char *op_errstr,
char *hostname, dict_t *dict);
@@ -1192,4 +1196,6 @@ int
glusterd_remove_brick_migrate_cbk (glusterd_volinfo_t *volinfo,
gf_defrag_status_t status);
+int
+__glusterd_handle_reset_brick (rpcsvc_request_t *req);
#endif