summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cli/src/Makefile.am2
-rw-r--r--cli/src/cli-cmd-parser.c166
-rw-r--r--cli/src/cli-cmd-volume.c47
-rw-r--r--cli/src/cli-rpc-ops.c169
-rw-r--r--cli/src/cli.h3
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);