summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaushal M <kaushal@gluster.com>2011-08-03 18:12:21 +0530
committerVijay Bellur <vijay@gluster.com>2011-09-18 23:46:09 -0700
commite378778686fca24934e76c41e6496b12162a5420 (patch)
treeb917a0af19eed73e3f600cf92982aa9760ad73ee
parent46a7adafe94b14778328d77a7f743fbce17341e3 (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.c186
-rw-r--r--cli/src/cli-cmd.h14
-rwxr-xr-xsmoke.sh2
3 files changed, 200 insertions, 2 deletions
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 16dc32328d2..ec578417606 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 f6abfa4645f..1878571fa34 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);
diff --git a/smoke.sh b/smoke.sh
index 3226b74f172..612f6400851 100755
--- a/smoke.sh
+++ b/smoke.sh
@@ -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;