diff options
author | Anuradha Talur <atalur@redhat.com> | 2016-08-22 13:22:03 -0400 |
---|---|---|
committer | Pranith Kumar Karampuri <pkarampu@redhat.com> | 2016-08-29 19:55:53 -0700 |
commit | 936f8aeac3252951e7fa0cdaa5d260fad3bd5ea0 (patch) | |
tree | 66240b8ef55d55ca9535a21f73a5f71c9ff6ade4 /xlators/mgmt/glusterd/src | |
parent | c204f452dfd9907a0d32f35294a0805701a6d993 (diff) | |
download | glusterfs-936f8aeac3252951e7fa0cdaa5d260fad3bd5ea0.tar.gz glusterfs-936f8aeac3252951e7fa0cdaa5d260fad3bd5ea0.tar.xz glusterfs-936f8aeac3252951e7fa0cdaa5d260fad3bd5ea0.zip |
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>
Diffstat (limited to 'xlators/mgmt/glusterd/src')
-rw-r--r-- | xlators/mgmt/glusterd/src/Makefile.am | 3 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-brick-ops.c | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-hooks.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-messages.h | 29 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt.c | 33 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt.h | 6 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-replace-brick.c | 349 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-reset-brick.c | 430 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-syncop.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 327 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 34 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 2 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 6 |
17 files changed, 956 insertions, 271 deletions
diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index 23840cdb80..faee8625d1 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 7be1d382d5..8458876f50 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 4a027f4ed7..18886dc5d1 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 9229da9c45..77efa6c57b 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 f0c9ee25ed..e520c69add 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 6cc7b84b8b..a5d22e4e26 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 bf87ec710f..2215f17832 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 553b7b4a6c..dc28a2b923 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 0df5d437ca..687ff004eb 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 (¶m, 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 0000000000..d1efe0663f --- /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 03b6e71cd9..f9e76f3fad 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 70d1020858..2b7a4477fc 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 ec371d8081..0011cac007 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 (¶m, 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 ca07efd54b..419ab48323 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 fe5d4c8e34..b38b0e6960 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 7d108276cb..705ce721ea 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 430798f5fb..eb03d05b6d 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 |