summaryrefslogtreecommitdiffstats
path: root/tests/basic/gfapi/mandatory-lock-optimal.t
diff options
context:
space:
mode:
Diffstat (limited to 'tests/basic/gfapi/mandatory-lock-optimal.t')
0 files changed, 0 insertions, 0 deletions
= -1; cli_err ("Found duplicate" " exports %s",words[brick_index]); goto out; } tmp_list = tmpptr; j++; } strcat (brick_list, words[brick_index]); strcat (brick_list, " "); brick_list_len += (strlen (words[brick_index]) + 1); ++(*brick_count); ++brick_index; } *bricks = gf_strdup (brick_list); if (!*bricks) ret = -1; out: GF_FREE (free_list_ptr); return ret; } int32_t 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 *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 *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) { cli_err ("number of bricks must be greater " "than 2"); return -1; } *disperse = count; } if (*redundancy == -1) { tmp = *disperse - 1; for (i = tmp / 2; (i > 0) && ((tmp & -tmp) != tmp); i--, tmp--); if (i == 0) { answer = cli_cmd_get_confirmation(state, question1); if (answer == GF_ANSWER_NO) return -1; *redundancy = 1; } else { *redundancy = *disperse - tmp; if (*redundancy > 1) { sprintf(question, question2, *redundancy); answer = cli_cmd_get_confirmation(state, question); if (answer == GF_ANSWER_NO) return -1; } } tmp = 0; } else { tmp = *disperse - *redundancy; } if (*redundancy > (*disperse - 1) / 2) { cli_err ("redundancy must be less than %d for a " "disperse %d volume", (*disperse + 1) / 2, *disperse); return -1; } if ((tmp & -tmp) != tmp) { answer = cli_cmd_get_confirmation(state, question3); if (answer == GF_ANSWER_NO) return -1; } 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_TIER: cli_err ("tier-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; default: cli_err ("Invalid type given"); break; } out: return ret; } int32_t cli_validate_volname (const char *volname) { int32_t ret = -1; int32_t i = -1; static const char * const invalid_volnames[] = { "volume", "type", "subvolumes", "option", "end-volume", "all", "volume_not_in_ring", "description", "force", "snap-max-hard-limit", "snap-max-soft-limit", "auto-delete", "activate-on-create", NULL}; if (volname[0] == '-') goto out; for (i = 0; invalid_volnames[i]; i++) { if (!strcmp (volname, invalid_volnames[i])) { cli_err ("\"%s\" cannot be the name of a volume.", volname); goto out; } } if (strchr (volname, '/')) goto out; if (strlen (volname) > GD_VOLUME_NAME_MAX) { cli_err("Volume name exceeds %d characters.", GD_VOLUME_NAME_MAX); goto out; } for (i = 0; i < strlen (volname); i++) { if (!isalnum (volname[i]) && (volname[i] != '_') && (volname[i] != '-')) { cli_err ("Volume name should not contain \"%c\"" " character.\nVolume names can only" "contain alphanumeric, '-' and '_' " "characters.", volname[i]); goto out; } } ret = 0; out: return ret; } int32_t cli_cmd_volume_create_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **brick_list) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; gf1_cluster_type type = GF_CLUSTER_TYPE_NONE; int sub_count = 1; int brick_index = 0; char *trans_type = NULL; int32_t index = 0; char *bricks = NULL; int32_t brick_count = 0; char *opwords[] = { "replica", "stripe", "transport", "disperse", "redundancy", "disperse-data", "arbiter", NULL }; char *w = NULL; int op_count = 0; int32_t replica_count = 1; int32_t arbiter_count = 0; int32_t stripe_count = 1; int32_t disperse_count = -1; int32_t redundancy_count = -1; int32_t disperse_data_count = -1; gf_boolean_t is_force = _gf_false; int wc = wordcount; gf_answer_t answer = GF_ANSWER_NO; const char *question = NULL; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 3) goto out; volname = (char *)words[2]; GF_ASSERT (volname); /* Validate the volume name here itself */ if (cli_validate_volname (volname) < 0) goto out; if (wordcount < 4) { ret = -1; goto out; } type = GF_CLUSTER_TYPE_NONE; index = 3; while (op_count < 3) { ret = -1; w = str_getunamb (words[index], opwords); if (!w) { break; } else if ((strcmp (w, "replica")) == 0) { switch (type) { case GF_CLUSTER_TYPE_STRIPE_REPLICATE: case GF_CLUSTER_TYPE_REPLICATE: cli_err ("replica option given twice"); goto out; case GF_CLUSTER_TYPE_NONE: type = GF_CLUSTER_TYPE_REPLICATE; break; case GF_CLUSTER_TYPE_STRIPE: type = GF_CLUSTER_TYPE_STRIPE_REPLICATE; break; case GF_CLUSTER_TYPE_TIER: cli_err ("replicated-tiered volume is not " "supported"); goto out; break; case GF_CLUSTER_TYPE_DISPERSE: cli_err ("replicated-dispersed volume is not " "supported"); goto out; default: cli_err ("Invalid type given"); goto out; } if (wordcount < (index+2)) { ret = -1; goto out; } replica_count = strtol (words[index+1], NULL, 0); if (replica_count < 2) { cli_err ("replica count should be greater" " than 1"); ret = -1; goto out; } if (replica_count == 2) { question = "Replica 2 volumes are prone to " "split-brain. Use Arbiter or Replica" " 3 to avoid this. See: " " https://gluster.readthedocs.io/en/latest/Administrator%20Guide/Split%20brain%20and%20ways%20to%20deal%20with%20it/." "\nDo you still want to continue?\n"; answer = cli_cmd_get_confirmation (state, question); if (GF_ANSWER_NO == answer) { gf_log ("cli", GF_LOG_ERROR, "Volume create cancelled, " "exiting"); ret = -1; goto out; } } ret = dict_set_int32 (dict, "replica-count", replica_count); if (ret) goto out; index += 2; if (words[index]) { if (!strcmp (words[index], "arbiter")) { ret = gf_string2int (words[index+1], &arbiter_count); if (ret == -1 || arbiter_count != 1 || replica_count != 3) { cli_err ("For arbiter " "configuration, " "replica count must be" " 3 and arbiter count " "must be 1. The 3rd " "brick of the replica " "will be the arbiter"); ret = -1; goto out; } ret = dict_set_int32 (dict, "arbiter-count", arbiter_count); if (ret) goto out; index += 2; } } } else if ((strcmp (w, "stripe")) == 0) { switch (type) { case GF_CLUSTER_TYPE_STRIPE_REPLICATE: case GF_CLUSTER_TYPE_STRIPE: cli_err ("stripe option given twice"); goto out; case GF_CLUSTER_TYPE_NONE: type = GF_CLUSTER_TYPE_STRIPE; break; case GF_CLUSTER_TYPE_REPLICATE: type = GF_CLUSTER_TYPE_STRIPE_REPLICATE; break; case GF_CLUSTER_TYPE_DISPERSE: cli_err ("striped-dispersed volume is not " "supported"); goto out; case GF_CLUSTER_TYPE_TIER: cli_err ("striped-tier volume is not " "supported"); goto out; default: cli_err ("Invalid type given"); goto out; } if (wordcount < (index + 2)) { ret = -1; goto out; } stripe_count = strtol (words[index+1], NULL, 0); if (stripe_count < 2) { cli_err ("stripe count should be greater" " than 1"); ret = -1; goto out; } ret = dict_set_int32 (dict, "stripe-count", stripe_count); if (ret) goto out; index += 2; } else if ((strcmp (w, "transport")) == 0) { if (trans_type) { cli_err ("'transport' option given more" " than one time"); goto out; } if ((strcasecmp (words[index+1], "tcp") == 0)) { trans_type = gf_strdup ("tcp"); } else if ((strcasecmp (words[index+1], "rdma") == 0)) { trans_type = gf_strdup ("rdma"); } else if ((strcasecmp (words[index+1], "tcp,rdma") == 0) || (strcasecmp (words[index+1], "rdma,tcp") == 0)) { trans_type = gf_strdup ("tcp,rdma"); } else { gf_log ("", GF_LOG_ERROR, "incorrect transport" " protocol specified"); ret = -1; goto out; } index += 2; } 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 += ret; type = GF_CLUSTER_TYPE_DISPERSE; } else if ((strcmp (w, "arbiter") == 0)) { cli_err ("arbiter option must be preceded by replica " "option."); ret = -1; goto out; } else { GF_ASSERT (!"opword mismatch"); ret = -1; goto out; } op_count++; } if (!trans_type) trans_type = gf_strdup ("tcp"); if (index >= wordcount) { ret = -1; goto out; } brick_index = index; if (strcmp (words[wordcount - 1], "force") == 0) { is_force = _gf_true; wc = wordcount - 1; } ret = cli_cmd_bricks_parse (words, wc, brick_index, &bricks, &brick_count); if (ret) goto out; /* If brick-count is not valid when replica or stripe is given, exit here */ if (!brick_count) { cli_err ("No bricks specified"); ret = -1; goto out; } if (type == GF_CLUSTER_TYPE_DISPERSE) { 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); if (!ret) ret = dict_set_int32 (dict, "redundancy-count", redundancy_count); if (ret) goto out; sub_count = disperse_count; } else sub_count = stripe_count * replica_count; if (brick_count % sub_count) { if (type == GF_CLUSTER_TYPE_STRIPE) cli_err ("number of bricks is not a multiple of " "stripe count"); else if (type == GF_CLUSTER_TYPE_REPLICATE) cli_err ("number of bricks is not a multiple of " "replica count"); else if (type == GF_CLUSTER_TYPE_DISPERSE) cli_err ("number of bricks is not a multiple of " "disperse count"); else cli_err ("number of bricks given doesn't match " "required count"); ret = -1; goto out; } /* Everything is parsed fine. start setting info in dict */ ret = dict_set_str (dict, "volname", volname); if (ret) goto out; ret = dict_set_int32 (dict, "type", type); if (ret) goto out; ret = dict_set_dynstr (dict, "transport", trans_type); if (ret) goto out; trans_type = NULL; ret = dict_set_dynstr (dict, "bricks", bricks); if (ret) goto out; ret = dict_set_int32 (dict, "count", brick_count); if (ret) goto out; ret = dict_set_int32 (dict, "force", is_force); if (ret) goto out; *options = dict; *brick_list = bricks; out: if (ret) { gf_log ("cli", GF_LOG_ERROR, "Unable to parse create volume CLI"); if (dict) dict_unref (dict); } GF_FREE (trans_type); return ret; } int32_t cli_cmd_volume_reset_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) goto out; if (wordcount < 3) goto out; if (wordcount > 5) goto out; volname = (char *)words[2]; if (!volname) { ret = -1; goto out; } ret = dict_set_str (dict, "volname", volname); if (ret) goto out; if (wordcount == 3) { ret = dict_set_str (dict, "key", "all"); if (ret) goto out; } if (wordcount >= 4) { if (!strcmp ("force", (char*)words[3])) { ret = dict_set_int32 (dict, "force", 1); if (ret) goto out; ret = dict_set_str (dict, "key", "all"); if (ret) goto out; } else { ret = dict_set_str (dict, "key", (char *)words[3]); if (ret) goto out; } } if (wordcount == 5) { if (strcmp ("force", (char*)words[4])) { ret = -1; goto out; } else { ret = dict_set_int32 (dict, "force", 1); if (ret) goto out; } } *options = dict; out: if (ret && dict) { dict_unref (dict); } return ret; } int32_t cli_cmd_get_state_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **op_errstr) { dict_t *dict = NULL; int ret = -1; char *odir = NULL; char *filename = NULL; char *daemon_name = NULL; int count = 0; uint32_t cmd = 0; GF_VALIDATE_OR_GOTO ("cli", options, out); GF_VALIDATE_OR_GOTO ("cli", words, out); dict = dict_new (); if (!dict) goto out; if (wordcount < 1 || wordcount > 7) { *op_errstr = gf_strdup ("Problem parsing arguments." " Check usage."); goto out; } if (wordcount >= 1) { gf_asprintf (&daemon_name, "%s", "glusterd"); for (count = 1; count < wordcount; count++) { if (strcmp (words[count], "odir") == 0 || strcmp (words[count], "file") == 0) { if (strcmp (words[count], "odir") == 0) { if (++count < wordcount) { odir = (char *) words[count]; continue; } else { ret = -1; goto out; } } else if (strcmp (words[count], "file") == 0) { if (++count < wordcount) { filename = (char *) words[count]; continue; } else { ret = -1; goto out; } } } else { if (count > 1) { if (count == wordcount-1) { if (strcmp (words[count], "detail") == 0) { cmd = GF_CLI_GET_STATE_DETAIL; continue; } else if (strcmp (words[count], "volumeoptions") == 0) { cmd = GF_CLI_GET_STATE_VOLOPTS; continue; } } else { *op_errstr = gf_strdup ("Problem" " parsing arguments. " "Check usage."); ret = -1; goto out; } } if (strcmp (words[count], "glusterd") == 0) { continue; } else { if (count == wordcount-1) { if (strcmp (words[count], "detail") == 0) { cmd = GF_CLI_GET_STATE_DETAIL; continue; } else if (strcmp (words[count], "volumeoptions") == 0) { cmd = GF_CLI_GET_STATE_VOLOPTS; continue; } } *op_errstr = gf_strdup ("glusterd is " "the only supported daemon."); ret = -1; goto out; } } } ret = dict_set_str (dict, "daemon", daemon_name); if (ret) { *op_errstr = gf_strdup ("Command failed. Please check " " log file for more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting daemon name to dictionary failed"); goto out; } if (odir) { ret = dict_set_str (dict, "odir", odir); if (ret) { *op_errstr = gf_strdup ("Command failed. Please" " check log file for" " more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting output directory to" "dictionary failed"); goto out; } } if (filename) { ret = dict_set_str (dict, "filename", filename); if (ret) { *op_errstr = gf_strdup ("Command failed. Please" " check log file for" " more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting filename to dictionary failed"); goto out; } } if (cmd) { ret = dict_set_uint32 (dict, "getstate-cmd", cmd); if (ret) { *op_errstr = gf_strdup ("Command failed. Please" " check log file for" " more details."); gf_log (THIS->name, GF_LOG_ERROR, "Setting " "get-state command type to dictionary " "failed"); goto out; } } } out: if (dict) *options = dict; if (ret && dict) dict_unref (dict); return ret; } int32_t cli_cmd_inode_quota_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) { gf_log ("cli", GF_LOG_ERROR, "dict_new failed"); goto out; } if (wordcount != 4) goto out; volname = (char *)words[2]; if (!volname) { ret = -1; goto out; } /* Validate the volume name here itself */ if (cli_validate_volname (volname) < 0) goto out; ret = dict_set_str (dict, "volname", volname); if (ret < 0) goto out; if (strcmp (words[3], "enable") != 0) { cli_out ("Invalid quota option : %s", words[3]); ret = -1; goto out; } ret = dict_set_int32 (dict, "type", GF_QUOTA_OPTION_TYPE_ENABLE_OBJECTS); if (ret < 0) goto out; *options = dict; out: if (ret < 0) { if (dict) dict_unref (dict); } return ret; } int32_t cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; int i = -1; char key[20] = {0, }; int64_t value = 0; gf_quota_type type = GF_QUOTA_OPTION_TYPE_NONE; char *opwords[] = { "enable", "disable", "limit-usage", "remove", "list", "alert-time", "soft-timeout", "hard-timeout", "default-soft-limit", "limit-objects", "list-objects", "remove-objects", NULL}; char *w = NULL; uint32_t time = 0; double percent = 0; char *end_ptr = NULL; int64_t limit = 0; GF_ASSERT (words); GF_ASSERT (options); dict = dict_new (); if (!dict) { gf_log ("cli", GF_LOG_ERROR, "dict_new failed"); goto out; } if (wordcount < 4) goto out; volname = (char *)words[2]; if (!volname) { ret = -1; goto out; } /* Validate the volume name here itself */ if (cli_validate_volname (volname) < 0) goto out; ret = dict_set_str (dict, "volname", volname); if (ret < 0) goto out; w = str_getunamb (words[3], opwords); if (!w) { cli_out ("Invalid quota option : %s", words[3]); ret = - 1; goto out; } if (strcmp (w, "enable") == 0) { if (wordcount == 4) { type = GF_QUOTA_OPTION_TYPE_ENABLE; ret = 0; goto set_type; } else { ret = -1; goto out; } } if (strcmp (w, "disable") == 0) { if (wordcount == 4) { type = GF_QUOTA_OPTION_TYPE_DISABLE; ret = 0; goto set_type; } else { ret = -1; goto out; } } if (strcmp (w, "limit-usage") == 0) { type = GF_QUOTA_OPTION_TYPE_LIMIT_USAGE; } else if (strcmp (w, "limit-objects") == 0) { type = GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS; } if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE || type == GF_QUOTA_OPTION_TYPE_LIMIT_OBJECTS) { if (wordcount < 6 || wordcount > 7) { ret = -1; goto out; } if (words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } ret = dict_set_str (dict, "path", (char *) words[4]); if (ret) goto out; if (!words[5]) { cli_err ("Please enter the limit value to be set"); ret = -1; goto out; } if (type == GF_QUOTA_OPTION_TYPE_LIMIT_USAGE) { ret = gf_string2bytesize_int64 (words[5], &value); if (ret != 0 || value <= 0) { if (errno == ERANGE || value <= 0) { ret = -1; cli_err ("Please enter an integer " "value in the range of " "(1 - %"PRId64 ")", INT64_MAX); } else cli_err ("Please enter a correct " "value"); goto out; } } else { errno = 0; limit = strtol (words[5], &end_ptr, 10); if (errno == ERANGE || errno == EINVAL || limit <= 0 || strcmp (end_ptr, "") != 0) { ret = -1; cli_err ("Please enter an integer value in " "the range 1 - %"PRId64, INT64_MAX); goto out; } } ret = dict_set_str (dict, "hard-limit", (char *) words[5]); if (ret < 0) goto out; if (wordcount == 7) { ret = gf_string2percent (words[6], &percent); if (ret != 0 || percent > 100) { ret = -1; cli_err ("Please enter a correct value " "in the range of 0 to 100"); goto out; } ret = dict_set_str (dict, "soft-limit", (char *) words[6]); if (ret < 0) goto out; } goto set_type; } if (strcmp (w, "remove") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_REMOVE; if (words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } ret = dict_set_str (dict, "path", (char *) words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "remove-objects") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_REMOVE_OBJECTS; if (words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } ret = dict_set_str (dict, "path", (char *) words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp (w, "list") == 0) { type = GF_QUOTA_OPTION_TYPE_LIST; if (words[4] && words[4][0] != '/') { cli_err ("Please enter absolute path"); ret = -1; goto out; } i = 4; while (i < wordcount) { snprintf (key, 20, "path%d", i-4); ret = dict_set_str (dict, key, (char *) words [i++]); if (ret < 0)