diff options
-rw-r--r-- | cli/src/Makefile.am | 2 | ||||
-rw-r--r-- | cli/src/cli-cmd-parser.c | 166 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 47 | ||||
-rw-r--r-- | cli/src/cli-rpc-ops.c | 169 | ||||
-rw-r--r-- | cli/src/cli.h | 3 |
5 files changed, 385 insertions, 2 deletions
diff --git a/cli/src/Makefile.am b/cli/src/Makefile.am index 31c70fc1c..b50b7dbca 100644 --- a/cli/src/Makefile.am +++ b/cli/src/Makefile.am @@ -17,7 +17,7 @@ AM_CFLAGS = -fPIC -Wall -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D$(GF_HOST_OS)\ -DDATADIR=\"$(localstatedir)\" \ -DCONFDIR=\"$(sysconfdir)/glusterfs\" $(GF_GLUSTERFS_CFLAGS)\ -DGSYNCD_PREFIX=\"$(libexecdir)/glusterfs\"\ - -DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) + -DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) -DGFS_PREFIX=\"$(prefix)\" CLEANFILES = diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index b38cf24fa..1dd963b66 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -362,6 +362,172 @@ out: } 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 = 0; + char key[20] = {0, }; + gf_quota_type type = GF_QUOTA_OPTION_TYPE_NONE; + + GF_ASSERT (words); + GF_ASSERT (options); + + GF_ASSERT ((strcmp (words[0], "volume")) == 0); + GF_ASSERT ((strcmp (words[1], "quota")) == 0); + + dict = dict_new (); + + if (!dict) + goto out; + + if (wordcount < 4) + goto out; + + volname = (char *)words[2]; + + if (!volname) { + ret = -1; + goto out; + } + + /* Validate the volume name here itself */ + { + if (volname[0] == '-') + goto out; + + if (!strcmp (volname, "all")) { + cli_out ("\"all\" cannot be the name of a volume."); + goto out; + } + + if (strchr (volname, '/')) + goto out; + + if (strlen (volname) > 512) + goto out; + + for (i = 0; i < strlen (volname); i++) + if (!isalnum (volname[i]) && (volname[i] != '_') && (volname[i] != '-')) + goto out; + } + + ret = dict_set_str (dict, "volname", volname); + + if (ret) + goto out; + + + if ((strcasecmp (words[3], "enable")) == 0) { + type = GF_QUOTA_OPTION_TYPE_ENABLE; + goto set_type; + } + + if (strcasecmp (words[3], "disable") == 0) { + type = GF_QUOTA_OPTION_TYPE_DISABLE; + goto set_type; + } + + if (strcasecmp (words[3], "limit-usage") == 0) { + if (wordcount != 6) { + ret = -1; + goto out; + } + + type = GF_QUOTA_OPTION_TYPE_LIMIT_USAGE; + + if (words[4][0] != '/') { + cli_out ("Please enter absolute path"); + + return -2; + } + ret = dict_set_str (dict, "path", (char *) words[4]); + + if (ret) + goto out; + + if (!words[5]) { + gf_log ("cli", GF_LOG_ERROR, "Please enter the limit value " + "to be set"); + + return -2; + } + + ret = dict_set_str (dict, "limit", (char *) words[5]); + if (ret) + goto out; + + goto set_type; + } + if (strcasecmp (words[3], "remove") == 0) { + if (wordcount != 5) { + ret = -1; + goto out; + } + + type = GF_QUOTA_OPTION_TYPE_REMOVE; + + if (words[4][0] != '/') { + cli_out ("Please enter absolute path"); + + return -2; + } + + ret = dict_set_str (dict, "path", (char *) words[4]); + if (ret) + goto out; + goto set_type; + } + + if (strcasecmp (words[3], "list") == 0) { + if (wordcount < 4) { + ret = -1; + goto out; + } + + type = GF_QUOTA_OPTION_TYPE_LIST; + + 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 (strcasecmp (words[3], "version") == 0) { + type = GF_QUOTA_OPTION_TYPE_VERSION; + + } else { + ret = -1; + goto out; + } + +set_type: + ret = dict_set_int32 (dict, "type", type); + + if (ret) + goto out; + *options = dict; +out: + if (ret) { + if (dict) + dict_destroy (dict); + } + + return ret; +} + +int32_t cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options) { dict_t *dict = NULL; diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index f53db3d80..f7f333001 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -701,6 +701,49 @@ out: return ret; } +int +cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word, + const char **words, int wordcount) +{ + + int ret = 0; + int parse_err = 0; + rpc_clnt_procedure_t *proc = NULL; + call_frame_t *frame = NULL; + dict_t *options = NULL; + + proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA]; + if (proc == NULL) { + ret = -1; + goto out; + } + + frame = create_frame (THIS, THIS->ctx->pool); + if (!frame) { + ret = -1; + goto out; + } + + ret = cli_cmd_quota_parse (words, wordcount, &options); + if (ret) { + cli_usage_out (word->pattern); + parse_err = 1; + goto out; + } + + if (proc->fn) + ret = proc->fn (frame, THIS, options); + +out: + if (options) + dict_unref (options); + + if (ret && parse_err == 0) + cli_out ("Quota command failed"); + + return ret; + +} int cli_cmd_volume_remove_brick_cbk (struct cli_state *state, @@ -1072,6 +1115,10 @@ struct cli_cmd volume_cmds[] = { cli_cmd_volume_profile_cbk, "volume profile operations"}, + { "volume quota <VOLNAME> <enable|disable|limit-usage|list|remove> [args] [path]", + cli_cmd_quota_cbk, + "quota translator specific operations"}, + { NULL, NULL, NULL } }; diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index d2b0f5cc7..7daa76341 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -1304,6 +1304,131 @@ out: return ret; } +int32_t +print_limit_list (char *volname, char *limit_list) +{ + char mount [1024] = {0, }; + char cmd_str [1024] = {0, }; + char path [1024] = {0, }; + char ret_str [1024] = {0, }; + char value [1024] = {0, }; + char umount_str [1024] = {0, }; + int64_t size = 0; + int64_t limit_value = 0; + int32_t i, j, k, len, ret; + + if (volname == NULL || limit_list == NULL) + return -1; + + snprintf (mount, sizeof (mount), "/etc/glusterd/mountlist/%s", volname); + + snprintf (cmd_str, sizeof (cmd_str), "mkdir -p %s", mount); + + snprintf (umount_str, sizeof (umount_str), "umount %s>>/dev/null 2>&1", mount); + system (umount_str); + + ret = system (cmd_str); + if (ret) { + ret = -1; + goto out; + } + + snprintf (cmd_str, sizeof (cmd_str), GFS_PREFIX "/sbin/glusterfs -s localhost " + "--volfile-id %s %s", volname, mount); + + ret = system (cmd_str); + if (ret) { + ret = -1; + goto out; + } + + len = strlen (limit_list); + + if (len == 0) { + cli_out ("quota limit not set "); + goto out; + } + + i = 0; + + cli_out ("\tpath\t\t limit_set\t size"); + cli_out ("-----------------------------------------------------------" + "-----------------------"); + while (i < len) { + j = 0; + k = 0; + + while (limit_list [i] != ':') { + path [k++] = limit_list [i++]; + } + path [k] = '\0'; + + i++; //skip ':' + + while (limit_list [i] != ',' && limit_list [i] != '\0') { + value [j++] = limit_list[i++]; + } + value [j] = '\0'; + + memset (&cmd_str, 0, 1024); + snprintf (cmd_str, sizeof (cmd_str), "%s%s", mount, path); + + ret = getxattr (cmd_str, "trusted.limit.list", (void *) ret_str, 4096); + if (ret < 0) { + cli_out ("%-20s %10s", path, value); + } else { + sscanf (ret_str, "%ld,%ld", &size, &limit_value); + cli_out ("%-20s %10ld %20ld", path, limit_value, size); + } + i++; + } +out: + system (umount_str); + + return ret; +} + +int +gf_cli3_1_quota_cbk (struct rpc_req *req, struct iovec *iov, + int count, void *myframe) +{ + gf1_cli_quota_rsp rsp = {0,}; + int ret = 0; + + if (-1 == req->rpc_status) { + goto out; + } + + ret = gf_xdr_to_cli_quota_rsp (*iov, &rsp); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "error"); + goto out; + } + + if (rsp.op_ret && + strcmp (rsp.op_errstr, "") == 0) { + cli_out ("command unsuccessful %s", rsp.op_errstr); + goto out; + } + + if (rsp.type == GF_QUOTA_OPTION_TYPE_LIST) { + if (rsp.limit_list) + print_limit_list (rsp.volname, rsp.limit_list); + } else { + gf_log ("cli", GF_LOG_NORMAL, "Received resp to quota command "); + if (rsp.op_errstr) + cli_out ("%s", rsp.op_errstr); + else + cli_out ("%s", "successful"); + } + +out: + ret = rsp.op_ret; + + cli_cmd_broadcast_response (ret); + return ret; +} + int gf_cli3_1_getspec_cbk (struct rpc_req *req, struct iovec *iov, int count, void *myframe) @@ -2257,6 +2382,46 @@ out: } int32_t +gf_cli3_1_quota (call_frame_t *frame, xlator_t *this, + void *data) +{ + gf1_cli_quota_req req = {0,}; + int ret = 0; + dict_t *dict = NULL; + + if (!frame || !this || !data) { + ret = -1; + goto out; + } + + dict = data; + + ret = dict_get_str (dict, "volname", &req.volname); + + if (ret) + goto out; + + ret = dict_allocate_and_serialize (dict, + &req.dict.dict_val, + (size_t *)&req.dict.dict_len); + if (ret < 0) { + gf_log (this->name, GF_LOG_ERROR, + "failed to get serialized length of dict"); + goto out; + } + + + ret = cli_cmd_submit (&req, frame, cli_rpc_prog, + GLUSTER_CLI_QUOTA, NULL, + gf_xdr_from_cli_quota_req, + this, gf_cli3_1_quota_cbk); + + GF_FREE (req.dict.dict_val); +out: + return ret; +} + +int32_t gf_cli3_1_pmap_b2p (call_frame_t *frame, xlator_t *this, void *data) { pmap_port_by_brick_req req = {0,}; @@ -3007,7 +3172,9 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = { [GLUSTER_CLI_RESET_VOLUME] = {"RESET_VOLUME", gf_cli3_1_reset_volume}, [GLUSTER_CLI_FSM_LOG] = {"FSM_LOG", gf_cli3_1_fsm_log}, [GLUSTER_CLI_GSYNC_SET] = {"GSYNC_SET", gf_cli3_1_gsync_set}, - [GLUSTER_CLI_PROFILE_VOLUME] = {"PROFILE_VOLUME", gf_cli3_1_profile_volume} + [GLUSTER_CLI_PROFILE_VOLUME] = {"PROFILE_VOLUME", gf_cli3_1_profile_volume}, + [GLUSTER_CLI_QUOTA] = {"QUOTA", gf_cli3_1_quota}, + }; struct rpc_clnt_program cli_prog = { diff --git a/cli/src/cli.h b/cli/src/cli.h index acfd5b539..1db78746a 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -179,6 +179,9 @@ int32_t cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **opt); int32_t +cli_cmd_quota_parse (const char **words, int wordcount, dict_t **opt); + +int32_t cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options); |