summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/cli-cmd-parser.c245
-rw-r--r--cli/src/cli-cmd-volume.c2
-rw-r--r--tests/basic/glusterd/disperse-create.t81
3 files changed, 226 insertions, 102 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c
index d7c1ddeb041..9c887fa78a5 100644
--- a/cli/src/cli-cmd-parser.c
+++ b/cli/src/cli-cmd-parser.c
@@ -177,24 +177,58 @@ out:
}
int32_t
-cli_cmd_create_disperse_check(struct cli_state * state, int * disperse,
- int * redundancy, int count)
+cli_cmd_create_disperse_check (struct cli_state *state, int *disperse,
+ int *redundancy, int *data, int count)
{
int i = 0;
int tmp = 0;
gf_answer_t answer = GF_ANSWER_NO;
char question[128];
- const char * question1 = "There isn't an optimal redundancy value "
- "for this configuration. Do you want to "
- "create the volume with redundancy 1 ?";
+ const char *question1 = "There isn't an optimal redundancy value "
+ "for this configuration. Do you want to "
+ "create the volume with redundancy 1 ?";
- const char * question2 = "The optimal redundancy for this "
- "configuration is %d. Do you want to create "
- "the volume with this value ?";
+ const char *question2 = "The optimal redundancy for this "
+ "configuration is %d. Do you want to create "
+ "the volume with this value ?";
- const char * question3 = "This configuration is not optimal on most "
- "workloads. Do you want to use it ?";
+ const char *question3 = "This configuration is not optimal on most "
+ "workloads. Do you want to use it ?";
+
+ const char *question4 = "Redundancy for this configuration is %d. "
+ "Do you want to create "
+ "the volume with this value ?";
+
+ if (*data > 0) {
+ if (*disperse > 0 && *redundancy > 0) {
+ if (*disperse != (*data + *redundancy)) {
+ cli_err ("Disperse count(%d) should be equal "
+ "to sum of disperse-data count(%d) and "
+ "redundancy count(%d)", *disperse,
+ *data, *redundancy);
+ return -1;
+ }
+ } else if (*redundancy > 0) {
+ *disperse = *data + *redundancy;
+ } else if (*disperse > 0) {
+ *redundancy = *disperse - *data;
+ } else {
+ if ((count - *data) >= *data) {
+ cli_err ("Please provide redundancy count "
+ "along with disperse-data count");
+ return -1;
+ } else {
+ sprintf (question, question4, count - *data);
+ answer = cli_cmd_get_confirmation (state,
+ question);
+ if (answer == GF_ANSWER_NO)
+ return -1;
+ *redundancy = count - *data;
+ *disperse = count;
+ }
+ }
+ }
if (*disperse <= 0) {
if (count < 3) {
@@ -206,7 +240,7 @@ cli_cmd_create_disperse_check(struct cli_state * state, int * disperse,
*disperse = count;
}
- if (*redundancy == 0) {
+ if (*redundancy == -1) {
tmp = *disperse - 1;
for (i = tmp / 2;
(i > 0) && ((tmp & -tmp) != tmp);
@@ -232,8 +266,7 @@ cli_cmd_create_disperse_check(struct cli_state * state, int * disperse,
}
tmp = 0;
- }
- else {
+ } else {
tmp = *disperse - *redundancy;
}
@@ -254,6 +287,87 @@ cli_cmd_create_disperse_check(struct cli_state * state, int * disperse,
return 0;
}
+static int32_t
+cli_validate_disperse_volume (char *word, gf1_cluster_type type,
+ const char **words, int32_t wordcount,
+ int32_t index, int32_t *disperse_count,
+ int32_t *redundancy_count,
+ int32_t *data_count)
+{
+ int ret = -1;
+
+ switch (type) {
+ case GF_CLUSTER_TYPE_NONE:
+ case GF_CLUSTER_TYPE_DISPERSE:
+ if (strcmp (word, "disperse") == 0) {
+ if (*disperse_count >= 0) {
+ cli_err ("disperse option given twice");
+ goto out;
+ }
+ if (wordcount < (index+2)) {
+ goto out;
+ }
+ ret = gf_string2int (words[index + 1], disperse_count);
+ if (ret == -1 && errno == EINVAL) {
+ *disperse_count = 0;
+ ret = 1;
+ } else if (ret == -1) {
+ goto out;
+ } else {
+ if (*disperse_count < 3) {
+ cli_err ("disperse count must "
+ "be greater than 2");
+ goto out;
+ }
+ ret = 2;
+ }
+ } else if (strcmp (word, "disperse-data") == 0) {
+ if (*data_count >= 0) {
+ cli_err ("disperse-data option given twice");
+ goto out;
+ }
+ if (wordcount < (index+2)) {
+ goto out;
+ }
+ ret = gf_string2int (words[index+1], data_count);
+ if (ret == -1 || *data_count < 2) {
+ cli_err ("disperse-data must be greater than 1");
+ goto out;
+ }
+ ret = 2;
+ } else if (strcmp (word, "redundancy") == 0) {
+ if (*redundancy_count >= 0) {
+ cli_err ("redundancy option given twice");
+ goto out;
+ }
+ if (wordcount < (index+2)) {
+ goto out;
+ }
+ ret = gf_string2int (words[index+1], redundancy_count);
+ if (ret == -1 || *redundancy_count < 1) {
+ cli_err ("redundancy must be greater than 0");
+ goto out;
+ }
+ ret = 2;
+ }
+ break;
+ case GF_CLUSTER_TYPE_STRIPE_REPLICATE:
+ cli_err ("striped-replicated-dispersed volume "
+ "is not supported");
+ goto out;
+ case GF_CLUSTER_TYPE_STRIPE:
+ cli_err ("striped-dispersed volume is not "
+ "supported");
+ goto out;
+ case GF_CLUSTER_TYPE_REPLICATE:
+ cli_err ("replicated-dispersed volume is not "
+ "supported");
+ goto out;
+ }
+out:
+ return ret;
+}
+
int32_t
cli_cmd_volume_create_parse (struct cli_state *state, const char **words,
int wordcount, dict_t **options)
@@ -271,7 +385,7 @@ cli_cmd_volume_create_parse (struct cli_state *state, const char **words,
char *bricks = NULL;
int32_t brick_count = 0;
char *opwords[] = { "replica", "stripe", "transport", "disperse",
- "redundancy", NULL };
+ "redundancy", "disperse-data", NULL };
char *invalid_volnames[] = {"volume", "type", "subvolumes", "option",
"end-volume", "all", "volume_not_in_ring",
@@ -285,7 +399,8 @@ cli_cmd_volume_create_parse (struct cli_state *state, const char **words,
int32_t replica_count = 1;
int32_t stripe_count = 1;
int32_t disperse_count = -1;
- int32_t redundancy_count = 0;
+ int32_t redundancy_count = -1;
+ int32_t disperse_data_count = -1;
gf_boolean_t is_force = _gf_false;
int wc = wordcount;
@@ -440,90 +555,17 @@ cli_cmd_volume_create_parse (struct cli_state *state, const char **words,
}
index += 2;
- } else if ((strcmp (w, "disperse")) == 0) {
- switch (type) {
- case GF_CLUSTER_TYPE_DISPERSE:
- if (disperse_count >= 0) {
- cli_err ("disperse option given "
- "twice");
- goto out;
- }
- break;
- case GF_CLUSTER_TYPE_NONE:
- type = GF_CLUSTER_TYPE_DISPERSE;
- break;
- case GF_CLUSTER_TYPE_STRIPE_REPLICATE:
- cli_err ("striped-replicated-dispersed volume "
- "is not supported");
- goto out;
- case GF_CLUSTER_TYPE_STRIPE:
- cli_err ("striped-dispersed volume is not "
- "supported");
- goto out;
- case GF_CLUSTER_TYPE_REPLICATE:
- cli_err ("replicated-dispersed volume is not "
- "supported");
- goto out;
- }
-
- if (wordcount >= (index+2)) {
- disperse_count = strtol (words[index + 1],
- &ptr, 0);
- if (*ptr != 0)
- disperse_count = 0;
- else {
- if (disperse_count < 3) {
- cli_err ("disperse count must "
- "be greater than 2");
- ret = -1;
- goto out;
- }
- index++;
- }
- }
-
- index++;
-
- } else if ((strcmp (w, "redundancy")) == 0) {
- switch (type) {
- case GF_CLUSTER_TYPE_NONE:
- type = GF_CLUSTER_TYPE_DISPERSE;
- break;
- case GF_CLUSTER_TYPE_DISPERSE:
- if (redundancy_count > 0) {
- cli_err ("redundancy option given "
- "twice");
- goto out;
- }
- break;
- case GF_CLUSTER_TYPE_STRIPE_REPLICATE:
- cli_err ("striped-replicated-dispersed volume "
- "is not supported");
- goto out;
- case GF_CLUSTER_TYPE_STRIPE:
- cli_err ("striped-dispersed volume is not "
- "supported");
- goto out;
- case GF_CLUSTER_TYPE_REPLICATE:
- cli_err ("replicated-dispersed volume is not "
- "supported");
- goto out;
- }
-
- if (wordcount < (index+2)) {
- ret = -1;
- goto out;
- }
- redundancy_count = strtol (words[index+1], NULL, 0);
- if (redundancy_count < 1) {
- cli_err ("redundancy must be greater than 0");
- ret = -1;
+ } else if ((strcmp (w, "disperse") == 0) ||
+ (strcmp (w, "redundancy") == 0) ||
+ (strcmp (w, "disperse-data") == 0)) {
+ ret = cli_validate_disperse_volume (w, type, words,
+ wordcount, index, &disperse_count,
+ &redundancy_count, &disperse_data_count);
+ if (ret < 0)
goto out;
- }
-
- index += 2;
-
- } else {
+ index += ret;
+ type = GF_CLUSTER_TYPE_DISPERSE;
+ } else {
GF_ASSERT (!"opword mismatch");
ret = -1;
goto out;
@@ -563,9 +605,10 @@ cli_cmd_volume_create_parse (struct cli_state *state, const char **words,
}
if (type == GF_CLUSTER_TYPE_DISPERSE) {
- ret = cli_cmd_create_disperse_check(state, &disperse_count,
- &redundancy_count,
- brick_count);
+ ret = cli_cmd_create_disperse_check (state, &disperse_count,
+ &redundancy_count,
+ &disperse_data_count,
+ brick_count);
if (!ret)
ret = dict_set_int32 (dict, "disperse-count",
disperse_count);
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index f87e6e24e7e..1b235bade6f 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -2305,7 +2305,7 @@ struct cli_cmd volume_cmds[] = {
"list information of all volumes"},
{ "volume create <NEW-VOLNAME> [stripe <COUNT>] [replica <COUNT>] "
- "[disperse [<COUNT>]] [redundancy <COUNT>] "
+ "[disperse [<COUNT>]] [disperse-data <COUNT>] [redundancy <COUNT>] "
"[transport <tcp|rdma|tcp,rdma>] <NEW-BRICK>"
#ifdef HAVE_BD_XLATOR
"?<vg_name>"
diff --git a/tests/basic/glusterd/disperse-create.t b/tests/basic/glusterd/disperse-create.t
new file mode 100644
index 00000000000..e5ce74c12b2
--- /dev/null
+++ b/tests/basic/glusterd/disperse-create.t
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+. $(dirname $0)/../../include.rc
+. $(dirname $0)/../../volume.rc
+
+# This command tests the volume create command validation for disperse volumes.
+
+cleanup;
+TEST glusterd
+TEST pidof glusterd
+TEST $CLI volume create $V0 disperse $H0:$B0/b1 $H0:$B0/b2 $H0:$B0/b3
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+TEST $CLI volume delete $V0
+TEST $CLI volume create $V0 disperse 3 $H0:$B0/b4 $H0:$B0/b5 $H0:$B0/b6
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+TEST $CLI volume delete $V0
+TEST $CLI volume create $V0 disperse 3 redundancy 1 $H0:$B0/b7 $H0:$B0/b8 $H0:$B0/b9
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+TEST $CLI volume delete $V0
+TEST $CLI volume create $V0 redundancy 1 $H0:$B0/b10 $H0:$B0/b11 $H0:$B0/b12
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+TEST $CLI volume delete $V0
+TEST $CLI volume create $V0 disperse-data 2 redundancy 1 $H0:$B0/b11 $H0:$B0/b12 $H0:$B0/b13
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+TEST $CLI volume delete $V0
+TEST $CLI volume create $V0 disperse-data 2 redundancy 1 $H0:$B0/b11 $H0:$B0/b12 $H0:$B0/b13
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+TEST $CLI volume delete $V0
+TEST $CLI volume create $V0 disperse 3 disperse-data 2 $H0:$B0/b14 $H0:$B0/b15 $H0:$B0/b16
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+TEST $CLI volume delete $V0
+TEST $CLI volume create $V0 disperse 3 disperse-data 2 redundancy 1 $H0:$B0/b17 $H0:$B0/b18 $H0:$B0/b19
+EXPECT "1 x \(2 \+ 1\) = 3" volinfo_field $V0 "Number of Bricks"
+
+# -ve test cases
+#Key-words appearing more than once
+TEST ! $CLI volume create $V0 disperse 3 disperse 3 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 disperse-data 2 disperse-data 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 redundancy 1 redundancy 1 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+
+#Minimum counts test
+TEST ! $CLI volume create $V0 disperse 2 $H0:$B0/b20 $H0:$B0/b22
+TEST ! $CLI volume create $V0 disperse-data 1 redundancy 0 $H0:$B0/b20 $H0:$B0/b22
+TEST ! $CLI volume create $V0 redundancy 0 $H0:$B0/b20 $H0:$B0/b22
+
+#Wrong count n != k+m
+TEST ! $CLI volume create $V0 disperse 4 disperse-data 4 redundancy 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+#Num bricks is not multiple of disperse count
+TEST ! $CLI volume create $V0 disperse 6 disperse-data 4 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+#Redundancy > data
+TEST ! $CLI volume create $V0 disperse 6 disperse-data 2 redundancy 4 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 disperse 4 disperse-data 2 redundancy 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+#Replica + Disperse
+TEST ! $CLI volume create $V0 disperse 4 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 disperse-data 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23
+TEST ! $CLI volume create $V0 redundancy 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 replica 2 disperse 4 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 replica 2 disperse-data 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23
+TEST ! $CLI volume create $V0 replica 2 redundancy 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+#Stripe + Disperse
+TEST ! $CLI volume create $V0 disperse 4 stripe 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 disperse-data 2 stripe 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23
+TEST ! $CLI volume create $V0 redundancy 2 stripe 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 stripe 2 disperse 4 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 stripe 2 disperse-data 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23
+TEST ! $CLI volume create $V0 stripe 2 redundancy 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+#Stripe + Replicate + Disperse, It is failing with striped-dispersed volume.
+TEST ! $CLI volume create $V0 disperse 4 stripe 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 disperse-data 2 stripe 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23
+TEST ! $CLI volume create $V0 redundancy 2 stripe 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 stripe 2 disperse 4 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+TEST ! $CLI volume create $V0 stripe 2 disperse-data 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22 $H0:$B0/b23
+TEST ! $CLI volume create $V0 stripe 2 redundancy 2 replica 2 $H0:$B0/b20 $H0:$B0/b21 $H0:$B0/b22
+cleanup