summaryrefslogtreecommitdiffstats
path: root/cli/src
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src')
0 files changed, 0 insertions, 0 deletions
f_log("cli", GF_LOG_ERROR, "Out of memory"); goto out; } *bricks = bricks_str; *bricks_str = ' '; bricks_str++; while (!list_empty(&brick_list)) { brick = list_first_entry(&brick_list, cli_brick_t, list); list_del_init(&brick->list); memcpy(bricks_str, brick->name, brick->len); bricks_str[brick->len] = ' '; bricks_str += brick->len + 1; GF_FREE(brick); } *bricks_str = 0; out: while (!list_empty(&brick_list)) { brick = list_first_entry(&brick_list, cli_brick_t, list); list_del_init(&brick->list); GF_FREE(brick); } 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 < 1) || (*redundancy > (*disperse - 1) / 2)) { cli_err( "redundancy must be greater than or equal to 1 and " "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_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; int volname_len; 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; volname_len = strlen(volname); if (volname_len > GD_VOLUME_NAME_MAX) { cli_err("Volume name exceeds %d characters.", GD_VOLUME_NAME_MAX); goto out; } for (i = 0; i < volname_len; 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: cli_err("stripe option not supported"); goto out; 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; } index += 2; if (words[index]) { if (!strcmp(words[index], "arbiter")) { ret = gf_string2int(words[index + 1], &arbiter_count); if ((ret == -1) || (arbiter_count != 1)) { cli_err( "For arbiter " "configuration, " "replica count must be" " 2 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; } } /* Do this to keep glusterd happy with sending "replica 3 arbiter 1" options to server */ if ((arbiter_count == 1) && (replica_count == 2)) replica_count += arbiter_count; if (replica_count == 2) { if (strcmp(words[wordcount - 1], "force")) { question = "Replica 2 volumes are prone" " to split-brain. Use " "Arbiter or Replica 3 to " "avoid this. See: " "http://docs.gluster.org/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; } else if ((strcmp(w, "stripe")) == 0) { cli_err("stripe option not supported"); goto out; } 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 (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_FREE(bricks); 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_dynstr(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; } daemon_name = NULL; 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); GF_FREE(daemon_name); 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) { if ((wordcount == 3) && !(strcmp(words[2], "help"))) { ret = 1; } 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) goto out; } ret = dict_set_int32(dict, "count", i - 4); if (ret < 0) goto out; goto set_type; } if (strcmp(w, "list-objects") == 0) { type = GF_QUOTA_OPTION_TYPE_LIST_OBJECTS; i = 4; while (i < wordcount) { snprintf(key, 20, "path%d", i - 4); ret = dict_set_str(dict, key, (char *)words[i++]); if (ret < 0) { gf_log("cli", GF_LOG_ERROR, "Failed to set " "quota patch in request dictionary"); goto out; } } ret = dict_set_int32(dict, "count", i - 4); if (ret < 0) { gf_log("cli", GF_LOG_ERROR, "Failed to set quota " "limit count in request dictionary"); goto out; } goto set_type; } if (strcmp(w, "alert-time") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_ALERT_TIME; ret = gf_string2time(words[4], &time); if (ret) { cli_err( "Invalid argument %s. Please enter a valid " "string", words[4]); goto out; } ret = dict_set_str(dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp(w, "soft-timeout") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_SOFT_TIMEOUT; ret = gf_string2time(words[4], &time); if (ret) { cli_err( "Invalid argument %s. Please enter a valid " "string", words[4]); goto out; } ret = dict_set_str(dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp(w, "hard-timeout") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_HARD_TIMEOUT; ret = gf_string2time(words[4], &time); if (ret) { cli_err( "Invalid argument %s. Please enter a valid " "string", words[4]); goto out; } ret = dict_set_str(dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } if (strcmp(w, "default-soft-limit") == 0) { if (wordcount != 5) { ret = -1; goto out; } type = GF_QUOTA_OPTION_TYPE_DEFAULT_SOFT_LIMIT; ret = dict_set_str(dict, "value", (char *)words[4]); if (ret < 0) goto out; goto set_type; } else { GF_ASSERT(!"opword mismatch"); } set_type: ret = dict_set_int32(dict, "type", type); if (ret < 0) goto out; *options = dict; out: if (ret < 0) { if (dict) dict_unref(dict); } return ret; } static gf_boolean_t cli_is_key_spl(char *key) { return (strcmp(key, "group") == 0); } static int32_t cli_add_key_group_value(dict_t *dict, const char *name, const char *value, int32_t id, char **op_errstr) { char *key = NULL; char *data = NULL; int32_t ret = -1; ret = gf_asprintf(&key, "%s%d", name, id); if (ret < 0) { goto out; } data = gf_strdup(value); if (data == NULL) { gf_log(THIS->name, GF_LOG_ERROR, "Failed to allocate memory for data"); ret = -1; goto out; } ret = dict_set_dynstr(dict, key, data); if (ret == 0) { data = NULL; } out: GF_FREE(key); GF_FREE(data); if ((ret != 0) && (op_errstr != NULL)) { *op_errstr = gf_strdup("Failed to allocate memory"); } return ret; } static int cli_add_key_group(dict_t *dict, char *key, char *value, char **op_errstr) { int ret = -1; int opt_count = 0; char *saveptr = NULL; char *tok_key = NULL; char *tok_val = NULL; char *tagpath = NULL; char line[PATH_MAX + 256] = { 0, }; FILE *fp = NULL; ret = gf_asprintf(&tagpath, "%s/groups/%s", GLUSTERD_DEFAULT_WORKDIR, value); if (ret == -1) { tagpath = NULL; goto out; } fp = fopen(tagpath, "r"); if (!fp) { ret = -1; if (op_errstr) { gf_asprintf(op_errstr, "Unable to open file '%s'. " "Error: %s", tagpath, strerror(errno)); } goto out; } opt_count = 0; while (fgets(line, sizeof(line), fp) != NULL) { if (strlen(line) >= sizeof(line) - 1) { ret = -1; if (op_errstr != NULL) { *op_errstr = gf_strdup("Line too long"); } goto out; } opt_count++; tok_key = strtok_r(line, "=", &saveptr); tok_val = strtok_r(NULL, "\r\n", &saveptr); if (!tok_key || !tok_val) { ret = -1; if (op_errstr) { gf_asprintf(op_errstr, "'%s' file format " "not valid.", tagpath); } goto out; } ret = cli_add_key_group_value(dict, "key", tok_key, opt_count, op_errstr); if (ret != 0) { goto out; } ret = cli_add_key_group_value(dict, "value", tok_val, opt_count, op_errstr); if (ret != 0) { goto out; } } if (!opt_count) { ret = -1; if (op_errstr) { gf_asprintf(op_errstr, "'%s' file format not valid.", tagpath); } goto out; } ret = dict_set_int32(dict, "count", opt_count); out: GF_FREE(tagpath); if (fp) fclose(fp); return ret; } int32_t cli_cmd_volume_set_parse(struct cli_state *state, const char **words, int wordcount, dict_t **options, char **op_errstr) { dict_t *dict = NULL; char *volname = NULL; int ret = -1; int count = 0; char *key = NULL; char *value = NULL; int i = 0; char str[50] = { 0, }; const char *question = NULL; gf_answer_t answer = GF_ANSWER_NO; 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); ret = dict_set_str(dict, "volname", volname); if (ret) goto out; if (!strcmp(volname, "all")) { ret = dict_set_str(dict, "globalname", "All"); if (ret) { gf_log(THIS->name, GF_LOG_ERROR, "dict set on global key failed."); goto out; } ret = dict_set_int32(dict, "hold_global_locks", _gf_true); if (ret) { gf_log(THIS->name, GF_LOG_ERROR, "dict set on global key failed."); goto out; } } if ((!strcmp(volname, "help") || !strcmp(volname, "help-xml")) &&