diff options
| author | Kaushal M <kaushal@gluster.com> | 2011-08-03 18:12:21 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vijay@gluster.com> | 2011-09-18 23:46:09 -0700 | 
| commit | e378778686fca24934e76c41e6496b12162a5420 (patch) | |
| tree | b917a0af19eed73e3f600cf92982aa9760ad73ee | |
| parent | 46a7adafe94b14778328d77a7f743fbce17341e3 (diff) | |
cli : check for bad brick order while creating replicate volume
gluster cli now checks the brick order when creating
a replicate or distributed-replicate volume.
If a non-optimal order is found the user is given a
warning and asked if the volume creation can proceed.
Change-Id: I38c4cb65bffb40ccf95319cf3f4f3423a4cdebe9
BUG: 2407
Reviewed-on: http://review.gluster.com/151
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vijay@gluster.com>
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 186 | ||||
| -rw-r--r-- | cli/src/cli-cmd.h | 14 | ||||
| -rwxr-xr-x | smoke.sh | 2 | 
3 files changed, 200 insertions, 2 deletions
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 16dc32328..ec5784176 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -23,6 +23,11 @@  #include <stdint.h>  #include <pthread.h> +#include <sys/socket.h> +#include <netdb.h> +#include <sys/types.h> +#include <netinet/in.h> +  #ifndef _CONFIG_H  #define _CONFIG_H  #include "config.h" @@ -150,6 +155,156 @@ out:          return ret;  } +gf_ai_compare_t +cli_cmd_compare_addrinfo (struct addrinfo *first, struct addrinfo *next) +{ +        int             ret = -1; +        struct addrinfo *tmp1 = NULL; +        struct addrinfo *tmp2 = NULL; +        char            firstip[NI_MAXHOST] = {0.}; +        char            nextip[NI_MAXHOST] = {0,}; + +        for (tmp1 = first; tmp1 != NULL; tmp1 = tmp1->ai_next) { +                ret = getnameinfo (tmp1->ai_addr, tmp1->ai_addrlen, firstip, +                                   NI_MAXHOST, NULL, 0, NI_NUMERICHOST); +                if (ret) +                        return GF_AI_COMPARE_ERROR; +                for (tmp2 = next; tmp2 != NULL; tmp2 = tmp2->ai_next) { +                        ret = getnameinfo (tmp2->ai_addr, tmp2->ai_addrlen, nextip, +                                           NI_MAXHOST, NULL, 0, NI_NUMERICHOST); +                        if (ret) +                                return GF_AI_COMPARE_ERROR; +                        if (!strcmp (firstip, nextip)) { +                                return GF_AI_COMPARE_MATCH; +                        } +                } +        } +        return GF_AI_COMPARE_NO_MATCH; +} + +/* Check for non optimal brick order for replicate : + * Checks if bricks belonging to a replicate volume + * are present on the same server + */ +int32_t +cli_cmd_check_brick_order (struct cli_state *state, const char *bricks, +                           int brick_count, int sub_count) +{ +        int             ret = -1; +        int             i = 0; +        int             j = 0; +        int             k = 0; +        addrinfo_list_t *ai_list = NULL; +        addrinfo_list_t *ai_list_tmp1 = NULL; +        addrinfo_list_t *ai_list_tmp2 = NULL; +        char            *brick = NULL; +        char            *brick_list = NULL; +        char            *brick_list_dup = NULL; +        char            *tmpptr = NULL; +        struct addrinfo *ai_info = NULL; +        gf_answer_t     answer = GF_ANSWER_NO; +        const char      *failed_question = NULL; +        const char      *found_question = NULL; +        failed_question = "Failed to perform brick order check. " +                          "Do you want to continue creating the volume? "; +        found_question =  "Multiple bricks of a replicate volume are present" +                          " on the same server. This setup is not optimal.\n" +                          "Do you still want to continue creating the volume? "; + +        GF_ASSERT (bricks); +        GF_ASSERT (brick_count > 0); +        GF_ASSERT (sub_count > 0); + +        ai_list = malloc (sizeof (addrinfo_list_t)); +        ai_list->info = NULL; +        INIT_LIST_HEAD (&ai_list->list); +        brick_list = gf_strdup (bricks); +        if (brick_list == NULL) { +                gf_log ("cli", GF_LOG_DEBUG, "failed to allocate memory"); +                goto check_failed; +        } +        brick_list_dup = brick_list; +        /* Resolve hostnames and get addrinfo */ +        while (i < brick_count) { +                ++i; +                brick = strtok_r (brick_list, " \n", &tmpptr); +                brick_list = tmpptr; +                if (brick == NULL) +                        goto check_failed; +                brick = strtok_r (brick, ":", &tmpptr); +                if (brick == NULL) +                        goto check_failed; +                ret = getaddrinfo (brick, NULL, NULL, &ai_info); +                if (ret) +                        goto check_failed; +                ai_list_tmp1 = malloc (sizeof (addrinfo_list_t)); +                if (ai_list_tmp1 == NULL) +                        goto check_failed; +                ai_list_tmp1->info = ai_info; +                list_add_tail (&ai_list_tmp1->list, &ai_list->list); +                ai_list_tmp1 = NULL; +        } + +        i = 0; +        ai_list_tmp1 = list_entry (ai_list->list.next, addrinfo_list_t, list); + +        /* Check for bad brick order */ +        while (i < brick_count) { +                ++i; +                ai_info = ai_list_tmp1->info; +                ai_list_tmp1 = list_entry (ai_list_tmp1->list.next, +                                           addrinfo_list_t, list); +                if ( 0 == i % sub_count) { +                        j = 0; +                        continue; +                } +                ai_list_tmp2 = ai_list_tmp1; +                k = j; +                while (k < sub_count - 1) { +                        ++k; +                        ret = cli_cmd_compare_addrinfo (ai_info, +                                                        ai_list_tmp2->info); +                        if (GF_AI_COMPARE_ERROR == ret) +                                goto check_failed; +                        if (GF_AI_COMPARE_MATCH == ret) +                                goto found_bad_brick_order; +                        ai_list_tmp2 = list_entry (ai_list_tmp2->list.next, +                                                   addrinfo_list_t, list); +                } +                ++j; +        } +        gf_log ("cli", GF_LOG_INFO, "Brick order okay"); +        ret = 0; +        goto out; + +check_failed: +        gf_log ("cli", GF_LOG_INFO, "Failed bad brick order check"); +        answer = cli_cmd_get_confirmation(state, failed_question); +        if (GF_ANSWER_YES == answer) +                ret = 0; +        goto out; + +found_bad_brick_order: +        gf_log ("cli", GF_LOG_INFO, "Bad brick order found"); +        answer = cli_cmd_get_confirmation (state, found_question); +        if (GF_ANSWER_YES == answer) +                ret = 0; +out: +        ai_list_tmp2 = NULL; +        i = 0; +        if (brick_list_dup) +                GF_FREE (brick_list_dup); +        list_for_each_entry (ai_list_tmp1, &ai_list->list, list) { +                if (ai_list_tmp1->info) +                        freeaddrinfo (ai_list_tmp1->info); +                if (ai_list_tmp2) +                        free (ai_list_tmp2); +                ai_list_tmp2 = ai_list_tmp1; +        } +        free (ai_list_tmp2); +        return ret; +} +  int  cli_cmd_volume_create_cbk (struct cli_state *state, struct cli_cmd_word *word,                             const char **words, int wordcount) @@ -160,6 +315,11 @@ cli_cmd_volume_create_cbk (struct cli_state *state, struct cli_cmd_word *word,          dict_t                  *options = NULL;          int                     sent = 0;          int                     parse_error = 0; +        char                    *brick_list = NULL; +        int32_t                 brick_count = 0; +        int32_t                 sub_count = 0; +        int32_t                 type = GF_CLUSTER_TYPE_NONE; +          proc = &cli_rpc_prog->proctable[GLUSTER_CLI_CREATE_VOLUME]; @@ -174,7 +334,31 @@ cli_cmd_volume_create_cbk (struct cli_state *state, struct cli_cmd_word *word,                  parse_error = 1;                  goto out;          } - +        /*Check brick order if type is replicate*/ +        if (dict_get_int32 (options, "type", &type) == 0 && type == GF_CLUSTER_TYPE_REPLICATE) { +                if ((ret = dict_get_str (options, "bricks", &brick_list)) != 0) { +                        gf_log ("cli", GF_LOG_ERROR, "Replica bricks check : " +                                                     "Could not retrieve bricks list"); +                        goto out; +                } +                if ((ret = dict_get_int32 (options, "count", &brick_count)) != 0) { +                        gf_log ("cli", GF_LOG_ERROR, "Replica bricks check : " +                                                     "Could not retrieve brick count"); +                        goto out; +                } +                if ((ret = dict_get_int32 (options, "replica-count", &sub_count)) != 0) { +                        gf_log ("cli", GF_LOG_ERROR, "Replica bricks check : " +                                                    "Could not retrieve replica count"); +                        goto out; +                } +                gf_log ("cli", GF_LOG_INFO, "Replicate cluster type found." +                                            " Checking brick order."); +                ret = cli_cmd_check_brick_order (state, brick_list, brick_count, sub_count); +                if (ret) { +                        gf_log("cli", GF_LOG_INFO, "Not creating volume because of bad brick order"); +                        goto out; +                } +        }          if (proc->fn) {                  ret = proc->fn (frame, THIS, options);          } diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h index f6abfa464..1878571fa 100644 --- a/cli/src/cli-cmd.h +++ b/cli/src/cli-cmd.h @@ -25,7 +25,10 @@  #include "config.h"  #endif +#include <netdb.h> +  #include "cli.h" +#include "list.h"  typedef enum {          GF_ANSWER_YES = 1, @@ -55,6 +58,17 @@ typedef struct cli_profile_info_ {          double percentage_avg_latency;  } cli_profile_info_t; +typedef struct addrinfo_list { +        struct list_head list; +        struct addrinfo *info; +} addrinfo_list_t; + +typedef enum { +        GF_AI_COMPARE_NO_MATCH     = 0, +        GF_AI_COMPARE_MATCH        = 1, +        GF_AI_COMPARE_ERROR        = 2 +} gf_ai_compare_t; +  typedef struct cli_cmd_volume_get_ctx_ cli_cmd_volume_get_ctx_t;  int cli_cmd_volume_register (struct cli_state *state); @@ -23,7 +23,7 @@ function start_fs()      chmod 0755 $P/export;      glusterd; -    gluster volume create $V replica 2 $H:$P/export/export{1,2,3,4}; +    gluster --mode=script volume create $V replica 2 $H:$P/export/export{1,2,3,4};      gluster volume start $V;      glusterfs -s $H --volfile-id $V $M;  #    mount -t glusterfs $H:/$V $M;  | 
