diff options
| author | Sanju Rakonde <srakonde@redhat.com> | 2018-11-30 16:16:55 +0530 | 
|---|---|---|
| committer | Atin Mukherjee <amukherj@redhat.com> | 2018-12-18 04:01:52 +0000 | 
| commit | 0b4b111fbd80a5d400a07d61e2b99f230f9be76f (patch) | |
| tree | 14cebfa5fcc3da89e7e86cfdc96b1a08acba7ebb | |
| parent | 9ff080382cb8c8aab561f4131c3f631e33670338 (diff) | |
glusterd: migrating rebalance commands to mgmt_v3 framework
Current rebalance commands use the op_state machine framework.
Porting it to use the mgmt_v3 framework.
Change-Id: I6faf4a6335c2e2f3d54bbde79908a7749e4613e7
fixes: bz#1655827
Signed-off-by: Sanju Rakonde <srakonde@redhat.com>
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 3 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt.c | 122 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-mgmt.h | 5 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.h | 3 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rebalance.c | 496 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-syncop.c | 9 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 4 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 9 | 
8 files changed, 630 insertions, 21 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index b07c6017f22..e18dfaceae2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -3093,7 +3093,8 @@ __glusterd_handle_cli_profile_volume(rpcsvc_request_t *req)          glusterd_friend_sm();          glusterd_op_sm();      } else { -        ret = glusterd_mgmt_v3_initiate_profile_phases(req, cli_op, dict); +        ret = glusterd_mgmt_v3_initiate_all_phases_with_brickop_phase( +            req, cli_op, dict);      }  out: diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.c b/xlators/mgmt/glusterd/src/glusterd-mgmt.c index eb3022612be..ccb4fd31841 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt.c +++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.c @@ -220,6 +220,15 @@ gd_mgmt_v3_pre_validate_fn(glusterd_op_t op, dict_t *dict, char **op_errstr,                  goto out;              }              break; +        case GD_OP_REBALANCE: +        case GD_OP_DEFRAG_BRICK_VOLUME: +            ret = glusterd_mgmt_v3_op_stage_rebalance(dict, op_errstr); +            if (ret) { +                gf_log(this->name, GF_LOG_WARNING, +                       "Rebalance Prevalidate Failed"); +                goto out; +            } +            break;          case GD_OP_MAX_OPVERSION:              ret = 0; @@ -258,7 +267,9 @@ gd_mgmt_v3_brick_op_fn(glusterd_op_t op, dict_t *dict, char **op_errstr,              }              break;          } -        case GD_OP_PROFILE_VOLUME: { +        case GD_OP_PROFILE_VOLUME: +        case GD_OP_REBALANCE: +        case GD_OP_DEFRAG_BRICK_VOLUME: {              ret = gd_brick_op_phase(op, rsp_dict, dict, op_errstr);              if (ret) {                  gf_log(this->name, GF_LOG_WARNING, @@ -413,6 +424,16 @@ gd_mgmt_v3_commit_fn(glusterd_op_t op, dict_t *dict, char **op_errstr,              }              break;          } +        case GD_OP_REBALANCE: +        case GD_OP_DEFRAG_BRICK_VOLUME: { +            ret = glusterd_mgmt_v3_op_rebalance(dict, op_errstr, rsp_dict); +            if (ret) { +                gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_COMMIT_OP_FAIL, +                       "Rebalance Commit Failed"); +                goto out; +            } +            break; +        }          default:              break; @@ -851,6 +872,8 @@ glusterd_pre_validate_aggr_rsp_dict(glusterd_op_t op, dict_t *aggr, dict_t *rsp)          case GD_OP_TIER_START_STOP:          case GD_OP_REMOVE_TIER_BRICK:          case GD_OP_PROFILE_VOLUME: +        case GD_OP_DEFRAG_BRICK_VOLUME: +        case GD_OP_REBALANCE:              break;          case GD_OP_MAX_OPVERSION:              break; @@ -1161,6 +1184,7 @@ glusterd_mgmt_v3_build_payload(dict_t **req, char **op_errstr, dict_t *dict,          case GD_OP_START_VOLUME:          case GD_OP_STOP_VOLUME:          case GD_OP_ADD_BRICK: +        case GD_OP_DEFRAG_BRICK_VOLUME:          case GD_OP_REPLACE_BRICK:          case GD_OP_RESET_BRICK:          case GD_OP_ADD_TIER_BRICK: @@ -1181,6 +1205,29 @@ glusterd_mgmt_v3_build_payload(dict_t **req, char **op_errstr, dict_t *dict,              }              dict_copy(dict, req_dict);          } break; + +        case GD_OP_REBALANCE: { +            if (gd_set_commit_hash(dict) != 0) { +                ret = -1; +                goto out; +            } +            ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); +            if (ret) { +                gf_msg(this->name, GF_LOG_CRITICAL, errno, +                       GD_MSG_DICT_GET_FAILED, +                       "volname is not present in " +                       "operation ctx"); +                goto out; +            } + +            if (strcasecmp(volname, "all")) { +                ret = glusterd_dict_set_volid(dict, volname, op_errstr); +                if (ret) +                    goto out; +            } +            dict_copy(dict, req_dict); +        } break; +          case GD_OP_TIER_START_STOP:          case GD_OP_REMOVE_TIER_BRICK:          case GD_OP_DETACH_TIER_STATUS: @@ -1209,6 +1256,7 @@ gd_mgmt_v3_brick_op_cbk_fn(struct rpc_req *req, struct iovec *iov, int count,      call_frame_t *frame = NULL;      int32_t op_ret = -1;      int32_t op_errno = -1; +    dict_t *rsp_dict = NULL;      xlator_t *this = NULL;      uuid_t *peerid = NULL; @@ -1238,12 +1286,44 @@ gd_mgmt_v3_brick_op_cbk_fn(struct rpc_req *req, struct iovec *iov, int count,      if (ret < 0)          goto out; +    if (rsp.dict.dict_len) { +        /* Unserialize the dictionary */ +        rsp_dict = dict_new(); + +        ret = dict_unserialize(rsp.dict.dict_val, rsp.dict.dict_len, &rsp_dict); +        if (ret < 0) { +            free(rsp.dict.dict_val); +            goto out; +        } else { +            rsp_dict->extra_stdfree = rsp.dict.dict_val; +        } +    } +      gf_uuid_copy(args->uuid, rsp.uuid); +    pthread_mutex_lock(&args->lock_dict); +    { +        if (rsp.op == GD_OP_DEFRAG_BRICK_VOLUME) +            ret = glusterd_syncop_aggr_rsp_dict(rsp.op, args->dict, rsp_dict); +    } +    pthread_mutex_unlock(&args->lock_dict); -    op_ret = rsp.op_ret; -    op_errno = rsp.op_errno; +    if (ret) { +        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_RESP_AGGR_FAIL, "%s", +               "Failed to aggregate response from " +               " node/brick"); +        if (!rsp.op_ret) +            op_ret = ret; +        else { +            op_ret = rsp.op_ret; +            op_errno = rsp.op_errno; +        } +    } else { +        op_ret = rsp.op_ret; +        op_errno = rsp.op_errno; +    }  out: +      gd_mgmt_v3_collate_errors(args, op_ret, op_errno, rsp.op_errstr,                                GLUSTERD_MGMT_V3_BRICK_OP, *peerid, rsp.uuid); @@ -1313,11 +1393,12 @@ out:  }  int -glusterd_mgmt_v3_brick_op(glusterd_op_t op, dict_t *rsp_dict, dict_t *req_dict, +glusterd_mgmt_v3_brick_op(glusterd_op_t op, dict_t *op_ctx, dict_t *req_dict,                            char **op_errstr, uint32_t txn_generation)  {      int32_t ret = -1;      int32_t peer_cnt = 0; +    dict_t *rsp_dict = NULL;      glusterd_peerinfo_t *peerinfo = NULL;      struct syncargs args = {0};      uuid_t peer_uuid = {0}; @@ -1332,6 +1413,13 @@ glusterd_mgmt_v3_brick_op(glusterd_op_t op, dict_t *rsp_dict, dict_t *req_dict,      GF_ASSERT(req_dict);      GF_ASSERT(op_errstr); +    rsp_dict = dict_new(); +    if (!rsp_dict) { +        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_CREATE_FAIL, +               "Failed to create response dictionary"); +        goto out; +    } +      /* Perform brick op on local node */      ret = gd_mgmt_v3_brick_op_fn(op, req_dict, op_errstr, rsp_dict); @@ -1353,9 +1441,21 @@ glusterd_mgmt_v3_brick_op(glusterd_op_t op, dict_t *rsp_dict, dict_t *req_dict,          }          goto out;      } +    if (op == GD_OP_DEFRAG_BRICK_VOLUME || op == GD_OP_PROFILE_VOLUME) { +        ret = glusterd_syncop_aggr_rsp_dict(op, op_ctx, rsp_dict); +        if (ret) { +            gf_log(this->name, GF_LOG_ERROR, "%s", +                   "Failed to aggregate response from " +                   " node/brick"); +            goto out; +        } +    } + +    dict_unref(rsp_dict); +    rsp_dict = NULL;      /* Sending brick op req to other nodes in the cluster */ -    gd_syncargs_init(&args, rsp_dict); +    gd_syncargs_init(&args, op_ctx);      synctask_barrier_init((&args));      peer_cnt = 0; @@ -1571,6 +1671,13 @@ glusterd_mgmt_v3_commit(glusterd_op_t op, dict_t *op_ctx, dict_t *req_dict,      GF_ASSERT(op_errstr);      GF_VALIDATE_OR_GOTO(this->name, op_errno, out); +    if (op == GD_OP_REBALANCE || op == GD_OP_DEFRAG_BRICK_VOLUME) { +        ret = glusterd_set_rebalance_id_in_rsp_dict(req_dict, op_ctx); +        if (ret) { +            gf_log(this->name, GF_LOG_WARNING, +                   "Failed to set rebalance id in dict."); +        } +    }      rsp_dict = dict_new();      if (!rsp_dict) {          gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_CREATE_FAIL, @@ -2088,8 +2195,9 @@ out:  }  int32_t -glusterd_mgmt_v3_initiate_profile_phases(rpcsvc_request_t *req, -                                         glusterd_op_t op, dict_t *dict) +glusterd_mgmt_v3_initiate_all_phases_with_brickop_phase(rpcsvc_request_t *req, +                                                        glusterd_op_t op, +                                                        dict_t *dict)  {      int32_t ret = -1;      int32_t op_ret = -1; diff --git a/xlators/mgmt/glusterd/src/glusterd-mgmt.h b/xlators/mgmt/glusterd/src/glusterd-mgmt.h index 6bd211965cf..71f793d0397 100644 --- a/xlators/mgmt/glusterd/src/glusterd-mgmt.h +++ b/xlators/mgmt/glusterd/src/glusterd-mgmt.h @@ -36,8 +36,9 @@ glusterd_mgmt_v3_initiate_all_phases(rpcsvc_request_t *req, glusterd_op_t op,                                       dict_t *dict);  int32_t -glusterd_mgmt_v3_initiate_profile_phases(rpcsvc_request_t *req, -                                         glusterd_op_t op, dict_t *dict); +glusterd_mgmt_v3_initiate_all_phases_with_brickop_phase(rpcsvc_request_t *req, +                                                        glusterd_op_t op, +                                                        dict_t *dict);  int32_t  glusterd_mgmt_v3_initiate_snap_phases(rpcsvc_request_t *req, glusterd_op_t op, diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index cedd05c0c3e..5f62ce0ad44 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -317,4 +317,7 @@ glusterd_op_stats_volume(dict_t *dict, char **op_errstr, dict_t *rsp_dict);  int  glusterd_op_stage_stats_volume(dict_t *dict, char **op_errstr); + +int +gd_set_commit_hash(dict_t *dict);  #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-rebalance.c b/xlators/mgmt/glusterd/src/glusterd-rebalance.c index 63a613eaf97..34b0294474c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rebalance.c +++ b/xlators/mgmt/glusterd/src/glusterd-rebalance.c @@ -23,6 +23,7 @@  #include "glusterd-sm.h"  #include "glusterd-op-sm.h"  #include "glusterd-utils.h" +#include "glusterd-mgmt.h"  #include "glusterd-messages.h"  #include "glusterd-store.h"  #include <glusterfs/run.h> @@ -506,6 +507,7 @@ __glusterd_handle_defrag_volume(rpcsvc_request_t *req)          0,      }};      glusterd_conf_t *priv = NULL; +    int32_t op = GD_OP_NONE;      dict_t *dict = NULL;      char *volname = NULL;      gf_cli_defrag_type cmd = 0; @@ -567,16 +569,24 @@ __glusterd_handle_defrag_volume(rpcsvc_request_t *req)      if ((cmd == GF_DEFRAG_CMD_STATUS) || (cmd == GF_DEFRAG_CMD_STATUS_TIER) ||          (cmd == GF_DEFRAG_CMD_STOP_DETACH_TIER) ||          (cmd == GF_DEFRAG_CMD_STOP) || (cmd == GF_DEFRAG_CMD_DETACH_STATUS)) { -        ret = glusterd_op_begin(req, GD_OP_DEFRAG_BRICK_VOLUME, dict, msg, -                                sizeof(msg)); +        op = GD_OP_DEFRAG_BRICK_VOLUME;      } else -        ret = glusterd_op_begin(req, GD_OP_REBALANCE, dict, msg, sizeof(msg)); +        op = GD_OP_REBALANCE; +    if (priv->op_version < GD_OP_VERSION_6_0) { +        gf_msg_debug(this->name, 0, +                     "The cluster is operating at " +                     "version less than %d. Falling back " +                     "to op-sm framework.", +                     GD_OP_VERSION_6_0); +        ret = glusterd_op_begin(req, op, dict, msg, sizeof(msg)); +        glusterd_friend_sm(); +        glusterd_op_sm(); +    } else { +        ret = glusterd_mgmt_v3_initiate_all_phases_with_brickop_phase(req, op, +                                                                      dict); +    }  out: - -    glusterd_friend_sm(); -    glusterd_op_sm(); -      if (ret) {          if (msg[0] == '\0')              snprintf(msg, sizeof(msg), "Operation failed"); @@ -585,8 +595,8 @@ out:      }      free(cli_req.dict.dict_val);  // malloced by xdr - -    return 0; +    gf_msg_debug(this->name, 0, "Returning %d", ret); +    return ret;  }  int @@ -629,6 +639,474 @@ glusterd_brick_validation(dict_t *dict, char *key, data_t *value, void *data)  }  int +glusterd_set_rebalance_id_in_rsp_dict(dict_t *req_dict, dict_t *rsp_dict) +{ +    int ret = -1; +    int32_t cmd = 0; +    char *volname = NULL; +    glusterd_volinfo_t *volinfo = NULL; +    char msg[2048] = {0}; +    char *task_id_str = NULL; +    xlator_t *this = NULL; + +    this = THIS; +    GF_ASSERT(this); + +    GF_ASSERT(rsp_dict); +    GF_ASSERT(req_dict); + +    ret = dict_get_strn(rsp_dict, "volname", SLEN("volname"), &volname); +    if (ret) { +        gf_msg_debug(this->name, 0, "volname not found"); +        goto out; +    } + +    ret = dict_get_int32n(rsp_dict, "rebalance-command", +                          SLEN("rebalance-command"), &cmd); +    if (ret) { +        gf_msg_debug(this->name, 0, "cmd not found"); +        goto out; +    } + +    ret = glusterd_rebalance_cmd_validate(cmd, volname, &volinfo, msg, +                                          sizeof(msg)); +    if (ret) { +        gf_msg_debug(this->name, 0, "failed to validate"); +        goto out; +    } + +    /* reblance id is generted in glusterd_mgmt_v3_op_stage_rebalance(), but +     * rsp_dict is unavailable there. So copying it to rsp_dict from req_dict +     * here. So that cli can display the rebalance id.*/ +    if ((cmd == GF_DEFRAG_CMD_START) || +        (cmd == GF_DEFRAG_CMD_START_LAYOUT_FIX) || +        (cmd == GF_DEFRAG_CMD_START_FORCE) || +        (cmd == GF_DEFRAG_CMD_START_TIER)) { +        if (is_origin_glusterd(rsp_dict)) { +            ret = dict_get_strn(req_dict, GF_REBALANCE_TID_KEY, +                                SLEN(GF_REBALANCE_TID_KEY), &task_id_str); +            if (ret) { +                snprintf(msg, sizeof(msg), "Missing rebalance-id"); +                gf_msg(this->name, GF_LOG_WARNING, 0, +                       GD_MSG_REBALANCE_ID_MISSING, "%s", msg); +                ret = 0; +            } else { +                gf_uuid_parse(task_id_str, volinfo->rebal.rebalance_id); +                ret = glusterd_copy_uuid_to_dict(volinfo->rebal.rebalance_id, +                                                 rsp_dict, GF_REBALANCE_TID_KEY, +                                                 SLEN(GF_REBALANCE_TID_KEY)); +                if (ret) { +                    snprintf(msg, sizeof(msg), +                             "Failed to set rebalance id for volume %s", +                             volname); +                    gf_msg(this->name, GF_LOG_WARNING, 0, +                           GD_MSG_DICT_SET_FAILED, "%s", msg); +                } +            } +        } +    } + +    /* Set task-id, if available, in rsp_dict for operations other than +     * start. This is needed when we want rebalance id in xml output +     */ +    if (cmd == GF_DEFRAG_CMD_STATUS || cmd == GF_DEFRAG_CMD_STOP || +        cmd == GF_DEFRAG_CMD_STATUS_TIER) { +        if (!gf_uuid_is_null(volinfo->rebal.rebalance_id)) { +            if (GD_OP_REMOVE_BRICK == volinfo->rebal.op) +                ret = glusterd_copy_uuid_to_dict( +                    volinfo->rebal.rebalance_id, rsp_dict, +                    GF_REMOVE_BRICK_TID_KEY, SLEN(GF_REMOVE_BRICK_TID_KEY)); +            else +                ret = glusterd_copy_uuid_to_dict(volinfo->rebal.rebalance_id, +                                                 rsp_dict, GF_REBALANCE_TID_KEY, +                                                 SLEN(GF_REBALANCE_TID_KEY)); +            if (ret) { +                gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED, +                       "Failed to set task-id for volume %s", volname); +                goto out; +            } +        } +    } +out: +    return ret; +} + +int +glusterd_mgmt_v3_op_stage_rebalance(dict_t *dict, char **op_errstr) +{ +    char *volname = NULL; +    char *cmd_str = NULL; +    int ret = 0; +    int32_t cmd = 0; +    char msg[2048] = {0}; +    glusterd_volinfo_t *volinfo = NULL; +    char *task_id_str = NULL; +    xlator_t *this = 0; +    int32_t is_force = 0; + +    this = THIS; +    GF_ASSERT(this); + +    ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); +    if (ret) { +        gf_msg_debug(this->name, 0, "volname not found"); +        goto out; +    } + +    ret = dict_get_int32n(dict, "rebalance-command", SLEN("rebalance-command"), +                          &cmd); +    if (ret) { +        gf_msg_debug(this->name, 0, "cmd not found"); +        goto out; +    } + +    ret = glusterd_rebalance_cmd_validate(cmd, volname, &volinfo, msg, +                                          sizeof(msg)); +    if (ret) { +        gf_msg_debug(this->name, 0, "failed to validate"); +        goto out; +    } +    switch (cmd) { +        case GF_DEFRAG_CMD_START_TIER: +            ret = dict_get_int32n(dict, "force", SLEN("force"), &is_force); +            if (ret) +                is_force = 0; + +            if (volinfo->type != GF_CLUSTER_TYPE_TIER) { +                gf_asprintf(op_errstr, +                            "volume %s is not a tier " +                            "volume.", +                            volinfo->volname); +                ret = -1; +                goto out; +            } +            if ((!is_force) && glusterd_is_tier_daemon_running(volinfo)) { +                ret = gf_asprintf(op_errstr, +                                  "A Tier daemon is " +                                  "already running on volume %s", +                                  volname); +                ret = -1; +                goto out; +            } +            /* Fall through */ +        case GF_DEFRAG_CMD_START: +        case GF_DEFRAG_CMD_START_LAYOUT_FIX: +            /* Check if the connected clients are all of version +             * glusterfs-3.6 and higher. This is needed to prevent some data +             * loss issues that could occur when older clients are connected +             * when rebalance is run. This check can be bypassed by using +             * 'force' +             */ +            ret = glusterd_check_client_op_version_support( +                volname, GD_OP_VERSION_3_6_0, NULL); +            if (ret) { +                ret = gf_asprintf(op_errstr, +                                  "Volume %s has one or " +                                  "more connected clients of a version" +                                  " lower than GlusterFS-v3.6.0. " +                                  "Starting rebalance in this state " +                                  "could lead to data loss.\nPlease " +                                  "disconnect those clients before " +                                  "attempting this command again.", +                                  volname); +                goto out; +            } +            /* Fall through */ +        case GF_DEFRAG_CMD_START_FORCE: +            if (is_origin_glusterd(dict)) { +                ret = glusterd_generate_and_set_task_id( +                    dict, GF_REBALANCE_TID_KEY, SLEN(GF_REBALANCE_TID_KEY)); +                if (ret) { +                    gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_TASKID_GEN_FAIL, +                           "Failed to generate task-id"); +                    goto out; +                } +            } else { +                ret = dict_get_strn(dict, GF_REBALANCE_TID_KEY, +                                    SLEN(GF_REBALANCE_TID_KEY), &task_id_str); +                if (ret) { +                    snprintf(msg, sizeof(msg), "Missing rebalance-id"); +                    gf_msg(this->name, GF_LOG_WARNING, 0, +                           GD_MSG_REBALANCE_ID_MISSING, "%s", msg); +                    ret = 0; +                } +            } +            ret = glusterd_defrag_start_validate(volinfo, msg, sizeof(msg), +                                                 GD_OP_REBALANCE); +            if (ret) { +                gf_msg_debug(this->name, 0, +                             "defrag start validate " +                             "failed for volume %s.", +                             volinfo->volname); +                goto out; +            } +            break; +        case GF_DEFRAG_CMD_STATUS_TIER: +        case GF_DEFRAG_CMD_STATUS: +        case GF_DEFRAG_CMD_STOP: + +            ret = dict_get_strn(dict, "cmd-str", SLEN("cmd-str"), &cmd_str); +            if (ret) { +                gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, +                       "Failed to get " +                       "command string"); +                ret = -1; +                goto out; +            } +            if ((strstr(cmd_str, "rebalance") != NULL) && +                (volinfo->rebal.op != GD_OP_REBALANCE)) { +                snprintf(msg, sizeof(msg), +                         "Rebalance not started " +                         "for volume %s.", +                         volinfo->volname); +                ret = -1; +                goto out; +            } + +            if (strstr(cmd_str, "remove-brick") != NULL) { +                if (volinfo->rebal.op != GD_OP_REMOVE_BRICK) { +                    snprintf(msg, sizeof(msg), +                             "remove-brick not " +                             "started for volume %s.", +                             volinfo->volname); +                    ret = -1; +                    goto out; +                } + +                /* For remove-brick status/stop command check whether +                 * given input brick is part of volume or not.*/ + +                ret = dict_foreach_fnmatch(dict, "brick*", +                                           glusterd_brick_validation, volinfo); +                if (ret == -1) { +                    snprintf(msg, sizeof(msg), +                             "Incorrect brick" +                             " for volume %s", +                             volinfo->volname); +                    goto out; +                } +            } +            if (cmd == GF_DEFRAG_CMD_STATUS_TIER) { +                if (volinfo->type != GF_CLUSTER_TYPE_TIER) { +                    snprintf(msg, sizeof(msg), +                             "volume %s is not " +                             "a tier volume.", +                             volinfo->volname); +                    ret = -1; +                    goto out; +                } +            } + +            break; + +        case GF_DEFRAG_CMD_STOP_DETACH_TIER: +        case GF_DEFRAG_CMD_DETACH_STATUS: +            if (volinfo->type != GF_CLUSTER_TYPE_TIER) { +                snprintf(msg, sizeof(msg), +                         "volume %s is not " +                         "a tier volume.", +                         volinfo->volname); +                ret = -1; +                goto out; +            } + +            if (volinfo->rebal.op != GD_OP_REMOVE_BRICK) { +                snprintf(msg, sizeof(msg), +                         "Detach-tier " +                         "not started"); +                ret = -1; +                goto out; +            } +            break; +        default: +            break; +    } + +    ret = 0; +out: +    if (ret && op_errstr && msg[0]) +        *op_errstr = gf_strdup(msg); + +    return ret; +} + +int +glusterd_mgmt_v3_op_rebalance(dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ +    char *volname = NULL; +    int ret = 0; +    int32_t cmd = 0; +    char msg[2048] = {0}; +    glusterd_volinfo_t *volinfo = NULL; +    glusterd_brickinfo_t *brickinfo = NULL; +    glusterd_brickinfo_t *tmp = NULL; +    gf_boolean_t volfile_update = _gf_false; +    char *task_id_str = NULL; +    xlator_t *this = NULL; +    uint32_t commit_hash; +    int32_t is_force = 0; + +    this = THIS; +    GF_ASSERT(this); + +    ret = dict_get_strn(dict, "volname", SLEN("volname"), &volname); +    if (ret) { +        gf_msg_debug(this->name, 0, "volname not given"); +        goto out; +    } + +    ret = dict_get_int32n(dict, "rebalance-command", SLEN("rebalance-command"), +                          &cmd); +    if (ret) { +        gf_msg_debug(this->name, 0, "command not given"); +        goto out; +    } + +    ret = glusterd_rebalance_cmd_validate(cmd, volname, &volinfo, msg, +                                          sizeof(msg)); +    if (ret) { +        gf_msg_debug(this->name, 0, "cmd validate failed"); +        goto out; +    } + +    switch (cmd) { +        case GF_DEFRAG_CMD_START: +        case GF_DEFRAG_CMD_START_LAYOUT_FIX: +        case GF_DEFRAG_CMD_START_FORCE: +        case GF_DEFRAG_CMD_START_TIER: + +            ret = dict_get_int32n(dict, "force", SLEN("force"), &is_force); +            if (ret) +                is_force = 0; +            if (!is_force) { +                /* Reset defrag status to 'NOT STARTED' whenever a +                 * remove-brick/rebalance command is issued to remove +                 * stale information from previous run. +                 */ +                volinfo->rebal.defrag_status = GF_DEFRAG_STATUS_NOT_STARTED; + +                ret = dict_get_strn(dict, GF_REBALANCE_TID_KEY, +                                    SLEN(GF_REBALANCE_TID_KEY), &task_id_str); +                if (ret) { +                    gf_msg_debug(this->name, 0, +                                 "Missing rebalance" +                                 " id"); +                    ret = 0; +                } else { +                    gf_uuid_parse(task_id_str, volinfo->rebal.rebalance_id); +                    volinfo->rebal.op = GD_OP_REBALANCE; +                } +                if (!gd_should_i_start_rebalance(volinfo)) { +                    /* Store the rebalance-id and rebalance command +                     * even if the peer isn't starting a rebalance +                     * process. On peers where a rebalance process +                     * is started, glusterd_handle_defrag_start +                     * performs the storing. +                     * Storing this is needed for having +                     * 'volume status' work correctly. +                     */ +                    glusterd_store_perform_node_state_store(volinfo); +                    break; +                } +                if (dict_get_uint32(dict, "commit-hash", &commit_hash) == 0) { +                    volinfo->rebal.commit_hash = commit_hash; +                } +                ret = glusterd_handle_defrag_start(volinfo, msg, sizeof(msg), +                                                   cmd, NULL, GD_OP_REBALANCE); +                break; +            } else { +                /* Reset defrag status to 'STARTED' so that the +                 * pid is checked and restarted accordingly. +                 * If the pid is not running it executes the +                 * "NOT_STARTED" case and restarts the process +                 */ +                volinfo->rebal.defrag_status = GF_DEFRAG_STATUS_STARTED; +                volinfo->rebal.defrag_cmd = cmd; +                volinfo->rebal.op = GD_OP_REBALANCE; + +                ret = dict_get_strn(dict, GF_REBALANCE_TID_KEY, +                                    SLEN(GF_REBALANCE_TID_KEY), &task_id_str); +                if (ret) { +                    gf_msg_debug(this->name, 0, +                                 "Missing rebalance" +                                 " id"); +                    ret = 0; +                } else { +                    gf_uuid_parse(task_id_str, volinfo->rebal.rebalance_id); +                    volinfo->rebal.op = GD_OP_REBALANCE; +                } +                if (dict_get_uint32(dict, "commit-hash", &commit_hash) == 0) { +                    volinfo->rebal.commit_hash = commit_hash; +                } +                ret = glusterd_restart_rebalance_for_volume(volinfo); +                break; +            } +        case GF_DEFRAG_CMD_STOP: +        case GF_DEFRAG_CMD_STOP_DETACH_TIER: +            /* Clear task-id only on explicitly stopping rebalance. +             * Also clear the stored operation, so it doesn't cause trouble +             * with future rebalance/remove-brick starts +             */ +            gf_uuid_clear(volinfo->rebal.rebalance_id); +            volinfo->rebal.op = GD_OP_NONE; + +            /* Fall back to the old volume file in case of decommission*/ +            cds_list_for_each_entry_safe(brickinfo, tmp, &volinfo->bricks, +                                         brick_list) +            { +                if (!brickinfo->decommissioned) +                    continue; +                brickinfo->decommissioned = 0; +                volfile_update = _gf_true; +            } + +            if (volfile_update == _gf_false) { +                ret = 0; +                break; +            } + +            ret = glusterd_create_volfiles_and_notify_services(volinfo); +            if (ret) { +                gf_msg(this->name, GF_LOG_WARNING, 0, +                       GD_MSG_VOLFILE_CREATE_FAIL, "failed to create volfiles"); +                goto out; +            } + +            ret = glusterd_store_volinfo(volinfo, +                                         GLUSTERD_VOLINFO_VER_AC_INCREMENT); +            if (ret) { +                gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_VOLINFO_SET_FAIL, +                       "failed to store volinfo"); +                goto out; +            } + +            if (volinfo->type == GF_CLUSTER_TYPE_TIER && +                cmd == GF_OP_CMD_STOP_DETACH_TIER) { +                glusterd_defrag_info_set(volinfo, dict, +                                         GF_DEFRAG_CMD_START_TIER, +                                         GF_DEFRAG_CMD_START, GD_OP_REBALANCE); +                glusterd_restart_rebalance_for_volume(volinfo); +            } + +            ret = 0; +            break; + +        case GF_DEFRAG_CMD_START_DETACH_TIER: +        case GF_DEFRAG_CMD_STATUS: +        case GF_DEFRAG_CMD_STATUS_TIER: +            break; +        default: +            break; +    } + +out: +    if (ret && op_errstr && msg[0]) +        *op_errstr = gf_strdup(msg); + +    return ret; +} + +int  glusterd_op_stage_rebalance(dict_t *dict, char **op_errstr)  {      char *volname = NULL; diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c index bdb4b137d6b..4bf11e065e3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-syncop.c +++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c @@ -309,6 +309,15 @@ glusterd_syncop_aggr_rsp_dict(glusterd_op_t op, dict_t *aggr, dict_t *rsp)              ret = glusterd_max_opversion_use_rsp_dict(aggr, rsp);              break; +        case GD_OP_PROFILE_VOLUME: +            ret = glusterd_profile_volume_use_rsp_dict(aggr, rsp); +            break; + +        case GD_OP_REBALANCE: +        case GD_OP_DEFRAG_BRICK_VOLUME: +            ret = glusterd_volume_rebalance_use_rsp_dict(aggr, rsp); +            break; +          case GD_OP_TIER_STATUS:          case GD_OP_DETACH_TIER_STATUS:          case GD_OP_REMOVE_TIER_BRICK: diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 8466270eb5c..e9b30504a0c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -10778,7 +10778,7 @@ glusterd_volume_rebalance_use_rsp_dict(dict_t *aggr, dict_t *rsp_dict)      int ret = 0;      int32_t index = 0;      int32_t count = 0; -    int32_t current_index = 2; +    int32_t current_index = 1;      int32_t value32 = 0;      uint64_t value = 0;      char *peer_uuid_str = NULL; @@ -10813,7 +10813,7 @@ glusterd_volume_rebalance_use_rsp_dict(dict_t *aggr, dict_t *rsp_dict)      ret = dict_get_int32n(rsp_dict, "count", SLEN("count"), &index);      if (ret)          gf_msg("glusterd", GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED, -               "failed to get index"); +               "failed to get index from rsp dict");      keylen = snprintf(key, sizeof(key), "node-uuid-%d", index);      ret = dict_get_strn(rsp_dict, key, keylen, &node_uuid); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 6e616f1ef8c..67867f86913 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -1370,6 +1370,15 @@ int  glusterd_op_stage_remove_brick(dict_t *dict, char **op_errstr);  int +glusterd_set_rebalance_id_in_rsp_dict(dict_t *req_dict, dict_t *rsp_dict); + +int +glusterd_mgmt_v3_op_stage_rebalance(dict_t *dict, char **op_errstr); + +int +glusterd_mgmt_v3_op_rebalance(dict_t *dict, char **op_errstr, dict_t *rsp_dict); + +int  glusterd_op_stage_rebalance(dict_t *dict, char **op_errstr);  int  glusterd_op_rebalance(dict_t *dict, char **op_errstr, dict_t *rsp_dict);  | 
