diff options
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 23840cdb80e..faee8625d1c 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 7be1d382d5f..8458876f50f 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 4a027f4ed7d..18886dc5d15 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 9229da9c45f..77efa6c57b3 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 f0c9ee25ed6..e520c69add2 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 6cc7b84b8b2..a5d22e4e265 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 bf87ec710f1..2215f178327 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 553b7b4a6cf..dc28a2b9236 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 0df5d437ca5..687ff004eb5 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 00000000000..d1efe0663fb --- /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 03b6e71cd9a..f9e76f3fad5 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 70d10208584..2b7a4477fca 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 ec371d80815..0011cac0078 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 ca07efd54ba..419ab48323a 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 fe5d4c8e348..b38b0e6960e 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 7d108276cb4..705ce721ea8 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 430798f5fbd..eb03d05b6d9 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 |