diff options
27 files changed, 1431 insertions, 316 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index be0a8e756d5..86b02877159 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -2134,6 +2134,137 @@ out:          return ret;  } +int32_t +cli_cmd_brick_op_validate_bricks (const char **words, dict_t *dict, +				  int src, int dst) +{ +        int             ret = -1; +        char            *delimiter  = NULL; + +        if (validate_brick_name ((char *)words[src])) { +                cli_err ("wrong brick type: %s, use " +                         "<HOSTNAME>:<export-dir-abs-path>", words[3]); +                ret = -1; +                goto out; +        } else { +                delimiter = strrchr ((char *)words[src], '/'); +                ret = gf_canonicalize_path (delimiter); +                if (ret) +                        goto out; +        } + +        ret = dict_set_str (dict, "src-brick", (char *)words[src]); +        if (ret) +                goto out; + +        if (dst == -1) { +                ret = 0; +                goto out; +        } + +        if (validate_brick_name ((char *)words[dst])) { +                cli_err ("wrong brick type: %s, use " +                         "<HOSTNAME>:<export-dir-abs-path>", words[dst]); +                ret = -1; +                goto out; +        } else { +                delimiter = strrchr ((char *)words[dst], '/'); +                ret = gf_canonicalize_path (delimiter); +                if (ret) +                        goto out; +        } + +        ret = dict_set_str (dict, "dst-brick", (char *)words[dst]); +        if (ret) +                goto out; +        ret = 0; +out: +	return ret; +} + +int32_t +cli_cmd_volume_reset_brick_parse (const char **words, int wordcount, +                                  dict_t **options) +{ +        int                   ret        = -1; +        char                 *volname    = NULL; +        dict_t               *dict       = NULL; + +        if (wordcount < 5 || wordcount > 7) +                goto out; + +        dict = dict_new (); + +        if (!dict) +                goto out; + +        volname = (char *)words[2]; + +        ret = dict_set_str (dict, "volname", volname); +        if (ret) +                goto out; + +        if (wordcount == 5) { +                if (strcmp (words[4], "start")) { +                        cli_err ("Invalid option '%s' for reset-brick. Please " +                                 "enter valid reset-brick command", words[4]); +                        ret = -1; +                        goto out; +                } + +                ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, -1); +                if (ret) +                        goto out; + +                ret = dict_set_str (dict, "operation", "GF_RESET_OP_START"); +                if (ret) +                        goto out; +        } else if (wordcount == 6) { +                if (strcmp (words[5], "commit")) { +                        cli_err ("Invalid option '%s' for reset-brick. Please " +                                 "enter valid reset-brick command", words[5]); +                        ret = -1; +                        goto out; +                } + +                ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4); +                if (ret) +                        goto out; + +                ret = dict_set_str (dict, "operation", "GF_RESET_OP_COMMIT"); +                if (ret) +                        goto out; +        } else if (wordcount == 7) { +                if (strcmp (words[5], "commit") || strcmp (words[6], "force")) { +                        cli_err ("Invalid option '%s %s' for reset-brick. Please " +                                 "enter valid reset-brick command", +                                  words[5], words[6]); +                        ret = -1; +                        goto out; +                } + +                ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4); +                if (ret) +                        goto out; + +                ret = dict_set_str (dict, "operation", +                                    "GF_RESET_OP_COMMIT_FORCE"); +                if (ret) +                        goto out; +        } + +        *options = dict; + +out: +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, +                        "Unable to parse reset-brick CLI"); +                if (dict) +                        dict_unref (dict); +        } + +        return ret; +}  int32_t  cli_cmd_volume_replace_brick_parse (const char **words, int wordcount, @@ -2141,7 +2272,6 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,  {          int                   ret        = -1;          char                 *volname    = NULL; -        char                 *delimiter  = NULL;          dict_t               *dict       = NULL;          GF_ASSERT (words); @@ -2167,35 +2297,7 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,          if (ret)                  goto out; -        if (validate_brick_name ((char *)words[3])) { -                cli_err ("wrong brick type: %s, use " -                         "<HOSTNAME>:<export-dir-abs-path>", words[3]); -                ret = -1; -                goto out; -        } else { -                delimiter = strrchr ((char *)words[3], ':'); -                ret = gf_canonicalize_path (delimiter + 1); -                if (ret) -                        goto out; -        } - -        ret = dict_set_str (dict, "src-brick", (char *)words[3]); -        if (ret) -                goto out; - -        if (validate_brick_name ((char *)words[4])) { -                cli_err ("wrong brick type: %s, use " -                         "<HOSTNAME>:<export-dir-abs-path>", words[4]); -                ret = -1; -                goto out; -        } else { -                delimiter = strrchr ((char *)words[4], ':'); -                ret = gf_canonicalize_path (delimiter + 1); -                if (ret) -                        goto out; -        } - -        ret = dict_set_str (dict, "dst-brick", (char *)words[4]); +        ret = cli_cmd_brick_op_validate_bricks (words, dict, 3, 4);          if (ret)                  goto out; @@ -2216,7 +2318,7 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,  out:          if (ret) { -                gf_log ("cli", GF_LOG_ERROR, "Unable to parse replace-brick CLI"); +                gf_log ("cli", GF_LOG_ERROR, "Unable to parse reset-brick CLI");                  if (dict)                          dict_unref (dict);          } diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 020697ff56b..2171d357aa5 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1829,6 +1829,59 @@ out:  }  int +cli_cmd_volume_reset_brick_cbk (struct cli_state *state, +                                struct cli_cmd_word *word, +                                const char **words, +                                int wordcount) +{ +        int                      ret          = -1; +        rpc_clnt_procedure_t    *proc         = NULL; +        call_frame_t            *frame        = NULL; +        dict_t                  *options = NULL; +        int                      sent = 0; +        int                      parse_error = 0; +        cli_local_t             *local = NULL; + +#ifdef GF_SOLARIS_HOST_OS +        cli_out ("Command not supported on Solaris"); +        goto out; +#endif +        proc = &cli_rpc_prog->proctable[GLUSTER_CLI_RESET_BRICK]; + +        frame = create_frame (THIS, THIS->ctx->pool); +        if (!frame) +                goto out; + +        ret = cli_cmd_volume_reset_brick_parse (words, wordcount, &options); + +        if (ret) { +                cli_usage_out (word->pattern); +                parse_error = 1; +                goto out; +        } + +        CLI_LOCAL_INIT (local, words, frame, options); + +        if (proc->fn) { +                ret = proc->fn (frame, THIS, options); +        } + +out: +        if (ret) { +                gf_event (EVENT_BRICK_RESET, "Volume reset-brick failed."); +                cli_cmd_sent_status_get (&sent); +                if ((sent == 0) && (parse_error == 0)) +                        cli_out ("Volume reset-brick failed"); +        } else { +                gf_event (EVENT_BRICK_RESET, "Volume reset-brick succeeded."); +        } + +        CLI_STACK_DESTROY (frame); + +        return ret; +} + +int  cli_cmd_volume_replace_brick_cbk (struct cli_state *state,                                    struct cli_cmd_word *word,                                    const char **words, @@ -1868,9 +1921,12 @@ cli_cmd_volume_replace_brick_cbk (struct cli_state *state,  out:          if (ret) { +                gf_event (EVENT_BRICK_REPLACE, "Volume replace-brick failed.");                  cli_cmd_sent_status_get (&sent);                  if ((sent == 0) && (parse_error == 0))                          cli_out ("Volume replace-brick failed"); +        } else { +                gf_event (EVENT_BRICK_RESET, "Volume replace-brick succeeded.");          }          CLI_STACK_DESTROY (frame); @@ -3016,6 +3072,11 @@ struct cli_cmd volume_cmds[] = {           "Bitrot translator specific operation. For more information about "           "bitrot command type  'man gluster'"          }, +        { "volume reset-brick <VOLNAME> <SOURCE-BRICK> {{start} |" +          " {<NEW-BRICK> commit}}", +          cli_cmd_volume_reset_brick_cbk, +          "reset-brick operations"}, +          { NULL, NULL, NULL }  }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 6259546b6e9..6b5277ced95 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -2961,6 +2961,149 @@ out:  }  int +gf_cli_reset_brick_cbk (struct rpc_req *req, struct iovec *iov, +                        int count, void *myframe) +{ +        gf_cli_rsp                       rsp              = {0,}; +        int                              ret              = -1; +        cli_local_t                     *local            = NULL; +        call_frame_t                    *frame            = NULL; +        char                            *src_brick        = NULL; +        char                            *dst_brick        = NULL; +        char                            *status_reply     = NULL; +        char                            *rb_operation_str = NULL; +        dict_t                          *rsp_dict         = NULL; +        char                             msg[1024]        = {0,}; +        char                            *task_id_str      = NULL; +        char                            *reset_op         = NULL; + +        GF_ASSERT (myframe); + +        if (-1 == req->rpc_status) { +                goto out; +        } + +        frame = myframe; + +        GF_ASSERT (frame->local); + +        local = frame->local; + +        ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); +        if (ret < 0) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "Failed to decode xdr response"); +                goto out; +        } + +        ret = dict_get_str (local->dict, "operation", &reset_op); +        if (ret) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "dict_get on operation failed"); +                goto out; +        } + +        if (rsp.dict.dict_len) { +                /* Unserialize the dictionary */ +                rsp_dict  = dict_new (); + +                ret = dict_unserialize (rsp.dict.dict_val, +                                rsp.dict.dict_len, +                                &rsp_dict); +                if (ret < 0) { +                        gf_log (frame->this->name, GF_LOG_ERROR, "failed to " +                                "unserialize rsp buffer to dictionary"); +                        goto out; +                } +        } + +        if (strcmp (reset_op, "GF_RESET_OP_START") && +            strcmp (reset_op, "GF_RESET_OP_COMMIT") && +            strcmp (reset_op, "GF_RESET_OP_COMMIT_FORCE")) { +                rb_operation_str = gf_strdup ("Unknown operation"); +                ret = -1; +                goto out; +        } + +        if (rsp.op_ret && (strcmp (rsp.op_errstr, ""))) { +                rb_operation_str = gf_strdup (rsp.op_errstr); +        } else { +                if (!strcmp (reset_op, "GF_RESET_OP_START")) { +                        if (rsp.op_ret) +                                rb_operation_str = gf_strdup ("reset-brick " +                                                              "start " +                                                              "operation " +                                                              "failed"); +                        else +                                rb_operation_str = gf_strdup ("reset-brick " +                                                              "start " +                                                              "operation " +                                                              "successful"); +                } else if (!strcmp (reset_op, "GF_RESET_OP_COMMIT")) { + +                        if (rsp.op_ret) +                                rb_operation_str = gf_strdup ("reset-brick " +                                                              "commit " +                                                              "operation " +                                                              "failed"); +                        else +                                rb_operation_str = gf_strdup ("reset-brick " +                                                              "commit " +                                                              "operation " +                                                              "successful"); +                } else if (!strcmp (reset_op, "GF_RESET_OP_COMMIT_FORCE")) { + +                        if (rsp.op_ret) +                                rb_operation_str = gf_strdup ("reset-brick " +                                                              "commit " +                                                              "force operation " +                                                              "failed"); +                        else +                                rb_operation_str = gf_strdup ("reset-brick " +                                                              "commit " +                                                              "force operation " +                                                              "successful"); +                } +        } + +        gf_log ("cli", GF_LOG_INFO, "Received resp to reset brick"); +        snprintf (msg, sizeof (msg), "%s", +                  rb_operation_str ? rb_operation_str : "Unknown operation"); + +        if (global_state->mode & GLUSTER_MODE_XML) { +                ret = cli_xml_output_vol_replace_brick (rsp_dict, +                                                        rsp.op_ret, +                                                        rsp.op_errno, msg); +                if (ret) +                        gf_log ("cli", GF_LOG_ERROR, +                                "Error outputting to xml"); +                goto out; +        } + +        if (rsp.op_ret) +                cli_err ("volume reset-brick: failed: %s", msg); +        else +                cli_out ("volume reset-brick: success: %s", msg); +        ret = rsp.op_ret; + +out: +        if (frame) +                frame->local = NULL; + +        if (local) +                cli_local_wipe (local); + +        if (rb_operation_str) +                GF_FREE (rb_operation_str); + +        cli_cmd_broadcast_response (ret); +        free (rsp.dict.dict_val); +        if (rsp_dict) +                dict_unref (rsp_dict); + +        return ret; +} +int  gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,                               int count, void *myframe)  { @@ -2971,7 +3114,7 @@ gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,          char                            *rb_operation_str = NULL;          dict_t                          *rsp_dict         = NULL;          char                             msg[1024]        = {0,}; -        char                            *replace_op       = 0; +        char                            *replace_op       = NULL;          GF_ASSERT (myframe); @@ -3013,7 +3156,7 @@ gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,                  }          } -        if (!strcmp(replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) { +        if (!strcmp (replace_op, "GF_REPLACE_OP_COMMIT_FORCE")) {                  if (rsp.op_ret || ret)                          rb_operation_str = gf_strdup ("replace-brick commit " @@ -3035,7 +3178,7 @@ gf_cli_replace_brick_cbk (struct rpc_req *req, struct iovec *iov,                    rb_operation_str ? rb_operation_str : "Unknown operation");          if (global_state->mode & GLUSTER_MODE_XML) { -                ret = cli_xml_output_vol_replace_brick (replace_op, rsp_dict, +                ret = cli_xml_output_vol_replace_brick (rsp_dict,                                                          rsp.op_ret,                                                          rsp.op_errno, msg);                  if (ret) @@ -3054,10 +3197,8 @@ out:          if (frame)                  frame->local = NULL; -        if (local) { -                dict_unref (local->dict); +        if (local)                  cli_local_wipe (local); -        }          if (rb_operation_str)                  GF_FREE (rb_operation_str); @@ -4889,8 +5030,73 @@ out:  }  int32_t +gf_cli_reset_brick (call_frame_t *frame, xlator_t *this, void *data) +{ +        gf_cli_req                  req        =  { {0,} }; +        int                         ret        = 0; +        dict_t                     *dict       = NULL; +        char                       *dst_brick  = NULL; +        char                       *src_brick  = NULL; +        char                       *volname    = NULL; +        char                       *op         = NULL; + +        if (!frame || !this ||  !data) { +                ret = -1; +                goto out; +        } + +        dict = data; + +        ret = dict_get_str (dict, "operation", &op); +        if (ret) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "dict_get on operation failed"); +                goto out; +        } + +        ret = dict_get_str (dict, "volname", &volname); +        if (ret) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "dict_get on volname failed"); +                goto out; +        } + +        ret = dict_get_str (dict, "src-brick", &src_brick); +        if (ret) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "dict_get on src-brick failed"); +                goto out; +        } + +        if (!strcmp (op, "GF_RESET_OP_COMMIT") || +            !strcmp (op, "GF_RESET_OP_COMMIT_FORCE")) { +                ret = dict_get_str (dict, "dst-brick", &dst_brick); +                if (ret) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "dict_get on dst-brick failed"); +                        goto out; +                } +        } + +        gf_log (this->name, GF_LOG_DEBUG, +                "Received command reset-brick %s on %s.", op, src_brick); + +        ret = cli_to_glusterd (&req, frame, gf_cli_reset_brick_cbk, +                               (xdrproc_t) xdr_gf_cli_req, dict, +                               GLUSTER_CLI_RESET_BRICK, this, cli_rpc_prog, +                               NULL); + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); + +        GF_FREE (req.dict.dict_val); + +        return ret; +} + +int32_t  gf_cli_replace_brick (call_frame_t *frame, xlator_t *this, -                         void *data) +                      void *data)  {          gf_cli_req                  req        =  {{0,}};          int                         ret        = 0; @@ -11345,7 +11551,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {          [GLUSTER_CLI_ATTACH_TIER]      = {"ATTACH_TIER", gf_cli_attach_tier},          [GLUSTER_CLI_DETACH_TIER]      = {"DETACH_TIER", gf_cli_detach_tier},          [GLUSTER_CLI_TIER]             = {"TIER", gf_cli_tier}, -        [GLUSTER_CLI_GET_STATE]        = {"GET_STATE", gf_cli_get_state} +        [GLUSTER_CLI_GET_STATE]        = {"GET_STATE", gf_cli_get_state}, +        [GLUSTER_CLI_RESET_BRICK]      = {"RESET_BRICK", gf_cli_reset_brick}  };  struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli-xml-output.c b/cli/src/cli-xml-output.c index f2b1941b77b..6639262066c 100644 --- a/cli/src/cli-xml-output.c +++ b/cli/src/cli-xml-output.c @@ -3861,7 +3861,7 @@ out:  }  int -cli_xml_output_vol_replace_brick (char *op, dict_t *dict, +cli_xml_output_vol_replace_brick (dict_t *dict,                                    int op_ret, int op_errno, char *op_errstr)  {  #if (HAVE_LIB_XML) diff --git a/cli/src/cli.h b/cli/src/cli.h index f9c642ee4d0..ba0d845381a 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -284,6 +284,10 @@ cli_cmd_volume_replace_brick_parse (const char **words, int wordcount,                                     dict_t **options);  int32_t +cli_cmd_volume_reset_brick_parse (const char **words, int wordcount, +                                  dict_t **options); + +int32_t  cli_cmd_log_rotate_parse (const char **words, int wordcount, dict_t **options);  int32_t  cli_cmd_log_locate_parse (const char **words, int wordcount, dict_t **options); @@ -424,7 +428,7 @@ cli_xml_output_vol_remove_brick_detach_tier (gf_boolean_t status_op,                                               const char *op);  int -cli_xml_output_vol_replace_brick (char *op, dict_t *dict, int op_ret, +cli_xml_output_vol_replace_brick (dict_t *dict, int op_ret,                                    int op_errno, char *op_errstr);  int @@ -489,5 +493,4 @@ print_quota_list_empty (char *path, int type);  int  gf_gsync_status_t_comparator (const void *p, const void *q); -  #endif /* __CLI_H__ */ diff --git a/events/eventskeygen.py b/events/eventskeygen.py index b55c29ae5a6..30b518dc18a 100644 --- a/events/eventskeygen.py +++ b/events/eventskeygen.py @@ -91,6 +91,8 @@ keys = (      "EVENT_QUOTA_HARD_TIMEOUT",      "EVENT_QUOTA_DEFAULT_SOFT_LIMIT",      "EVENT_QUOTA_CROSSED_SOFT_LIMIT", +    "EVENT_BRICK_REPLACE", +    "EVENT_BRICK_RESET",  )  LAST_EVENT = "EVENT_LAST" diff --git a/heal/src/glfs-heal.c b/heal/src/glfs-heal.c index 0a880cb752e..e885dd9fe63 100644 --- a/heal/src/glfs-heal.c +++ b/heal/src/glfs-heal.c @@ -517,7 +517,7 @@ out:          (*num_entries)++;          glfsh_output->print_heal_status (path ? path : -                                                uuid_utoa_r (gfid, gfid_str), +                                         uuid_utoa_r (gfid, gfid_str),                                           gfid,                                           status ? status : ""); diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index 6a134e84163..49c3d963578 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -198,6 +198,7 @@ enum gluster_cli_procnum {          GLUSTER_CLI_DETACH_TIER,          GLUSTER_CLI_TIER,          GLUSTER_CLI_GET_STATE, +        GLUSTER_CLI_RESET_BRICK,          GLUSTER_CLI_MAXVALUE,  }; diff --git a/tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t b/tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t new file mode 100644 index 00000000000..884b7892954 --- /dev/null +++ b/tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t @@ -0,0 +1,54 @@ +#!/bin/bash +. $(dirname $0)/../../include.rc +. $(dirname $0)/../../volume.rc +cleanup; + +TEST glusterd +TEST pidof glusterd +TEST $CLI volume create $V0 replica 2 $H0:$B0/${V0}{0,1} +TEST $CLI volume start $V0 + +TEST glusterfs --volfile-id=$V0 --volfile-server=$H0 $M0; +# Create files +for i in {1..5} +do +        echo $i > $M0/file$i.txt +done + +# Negative case with brick not killed && volume-id xattrs present +TEST ! $CLI volume reset-brick $V0 $H0:$B0/${V0}1 $H0:$B0/${V0}1 commit force +TEST kill_brick $V0 $H0 $B0/${V0}1 + +# Negative case with brick killed but volume-id xattr present +TEST ! $CLI volume reset-brick $V0 $H0:$B0/${V0}1 $H0:$B0/${V0}1 commit + +TEST $CLI volume reset-brick $V0 $H0:$B0/${V0}1 start +# Simulated reset disk +for i in {1..5} +do +        rm -rf $B0/${V0}{1}/file$i.txt +done +for i in {6..10} +do +        echo $i > $M0/file$i.txt +done + +# Now reset the brick +TEST $CLI volume reset-brick $V0 $H0:$B0/${V0}1 $H0:$B0/${V0}1 commit force + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 0 +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "1" afr_child_up_status $V0 1 + +EXPECT_WITHIN $PROCESS_UP_TIMEOUT "Y" glustershd_up_status +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 0 +EXPECT_WITHIN $CHILD_UP_TIMEOUT "1" afr_child_up_status_in_shd $V0 1 + +TEST $CLI volume heal $V0 + +EXPECT_WITHIN $HEAL_TIMEOUT "0" get_pending_heal_count $V0 + +# Check if entry-heal has happened +TEST diff <(ls $B0/${V0}0 | sort) <(ls $B0/${V0}1 | sort) +EXPECT "10" echo $(ls $B0/${V0}1 | wc -l) + +cleanup; diff --git a/xlators/cluster/afr/src/afr-inode-write.c b/xlators/cluster/afr/src/afr-inode-write.c index ddc257dbde4..24ab52f0266 100644 --- a/xlators/cluster/afr/src/afr-inode-write.c +++ b/xlators/cluster/afr/src/afr-inode-write.c @@ -1235,8 +1235,8 @@ _afr_handle_empty_brick (void *opaque)          loc_copy (&local->loc, &data->loc); -        gf_msg_debug (this->name, 0, "New brick is : %s", -                      priv->children[empty_index]->name); +        gf_msg (this->name, GF_LOG_INFO, 0, 0, "New brick is : %s", +                priv->children[empty_index]->name);          ret = _afr_handle_empty_brick_type (this, frame, &local->loc, empty_index,                                            AFR_METADATA_TRANSACTION, op_type); diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index 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  | 
