summaryrefslogtreecommitdiffstats
path: root/cli/src/cli-cmd-volume.c
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/cli-cmd-volume.c')
-rw-r--r--cli/src/cli-cmd-volume.c270
1 files changed, 206 insertions, 64 deletions
diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c
index 17663091..adad8442 100644
--- a/cli/src/cli-cmd-volume.c
+++ b/cli/src/cli-cmd-volume.c
@@ -1096,16 +1096,193 @@ print_quota_list_header (void)
}
int
-cli_get_soft_limit (call_frame_t *frame, cli_local_t *local, dict_t *options,
- const char **words)
+cli_get_soft_limit (dict_t *options, const char **words, dict_t *xdata)
{
- rpc_clnt_procedure_t *proc = NULL;
- int ret = -1;
+ call_frame_t *frame = NULL;
+ cli_local_t *local = NULL;
+ rpc_clnt_procedure_t *proc = NULL;
+ char *default_sl = NULL;
+ char *default_sl_dup = NULL;
+ int ret = -1;
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame) {
+ ret = -1;
+ goto out;
+ }
+
+ //We need a ref on @options to prevent CLI_STACK_DESTROY
+ //from destroying it prematurely.
+ dict_ref (options);
CLI_LOCAL_INIT (local, words, frame, options);
proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA];
ret = proc->fn (frame, THIS, options);
+ ret = dict_get_str (options, "default-soft-limit", &default_sl);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get default soft limit");
+ goto out;
+ }
+
+ default_sl_dup = gf_strdup (default_sl);
+ if (!default_sl_dup) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = dict_set_dynstr (xdata, "default-soft-limit", default_sl_dup);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set default soft limit");
+ GF_FREE (default_sl_dup);
+ goto out;
+ }
+
+out:
+ CLI_STACK_DESTROY (frame);
+ return ret;
+}
+
+#define QUOTA_CONF_HEADER \
+ "GlusterFS Quota conf | version: v%d.%d\n"
+int
+cli_cmd_quota_conf_skip_header (int fd)
+{
+ char buf[PATH_MAX] = {0,};
+
+ snprintf (buf, sizeof(buf)-1, QUOTA_CONF_HEADER, 1, 1);
+ return gf_skip_header_section (fd, strlen (buf));
+}
+
+int
+cli_cmd_quota_handle_list_all (const char **words, dict_t *options)
+{
+ int all_failed = 1;
+ int count = 0;
+ int ret = -1;
+ rpc_clnt_procedure_t *proc = NULL;
+ cli_local_t *local = NULL;
+ call_frame_t *frame = NULL;
+ dict_t *xdata = NULL;
+ char *gfid_str = NULL;
+ char *volname = NULL;
+ char *volname_dup = NULL;
+ unsigned char buf[16] = {0};
+ int fd = -1;
+ char quota_conf_file[PATH_MAX] = {0};
+
+ xdata = dict_new ();
+ if (!xdata) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = dict_get_str (options, "volname", &volname);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name");
+ goto out;
+ }
+
+ ret = cli_get_soft_limit (options, words, xdata);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to fetch default "
+ "soft-limit");
+ goto out;
+ }
+
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame) {
+ ret = -1;
+ goto out;
+ }
+
+ volname_dup = gf_strdup (volname);
+ if (!volname_dup) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = dict_set_dynstr (xdata, "volume-uuid", volname_dup);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set volume-uuid");
+ GF_FREE (volname_dup);
+ goto out;
+ }
+
+ //TODO: fix hardcoding; Need to perform an RPC call to glusterd
+ //to fetch working directory
+ sprintf (quota_conf_file, "/var/lib/glusterd/vols/%s/quota.conf",
+ volname);
+ fd = open (quota_conf_file, O_RDONLY);
+ if (fd == -1) {
+ //This may because no limits were yet set on the volume
+ gf_log ("cli", GF_LOG_TRACE, "Unable to open "
+ "quota.conf");
+ ret = 0;
+ goto out;
+ }
+
+ ret = cli_cmd_quota_conf_skip_header (fd);
+ if (ret) {
+ goto out;
+ }
+ CLI_LOCAL_INIT (local, words, frame, xdata);
+ proc = &cli_quotad_clnt.proctable[GF_AGGREGATOR_GETLIMIT];
+
+ print_quota_list_header ();
+ gfid_str = GF_CALLOC (1, gf_common_mt_char, 64);
+ if (!gfid_str) {
+ ret = -1;
+ goto out;
+ }
+ for (count = 0;; count++) {
+ ret = read (fd, (void*) buf, 16);
+ if (ret <= 0) {
+ //Finished reading all entries in the conf file
+ break;
+ }
+ if (ret < 16) {
+ //This should never happen. We must have a multiple of
+ //entry_sz bytes in our configuration file.
+ gf_log (THIS->name, GF_LOG_CRITICAL, "Quota "
+ "configuration store may be corrupt.");
+ goto out;
+ }
+ uuid_utoa_r (buf, gfid_str);
+ ret = dict_set_str (xdata, "gfid", gfid_str);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to set gfid");
+ goto out;
+ }
+
+ ret = proc->fn (frame, THIS, xdata);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Failed to get quota "
+ "limits for %s", uuid_utoa ((unsigned char*)buf));
+ }
+
+ dict_del (xdata, "gfid");
+ all_failed = all_failed && ret;
+ }
+
+ if (count > 0) {
+ ret = all_failed? 0: -1;
+ } else {
+ ret = 0;
+ }
+out:
+ if (count == 0) {
+ cli_out ("quota: No quota configured on volume %s", volname);
+ }
+ if (fd != -1) {
+ close (fd);
+ }
+
+ GF_FREE (gfid_str);
+ if (ret) {
+ gf_log ("cli", GF_LOG_ERROR, "Couldn't fetch quota limits "
+ "for even one of the directories configured");
+ }
+ CLI_STACK_DESTROY (frame);
return ret;
}
@@ -1124,26 +1301,11 @@ cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,
cli_local_t *local = NULL;
int sent = 0;
char *volname = NULL;
- dict_t *xdata = NULL;
- char buf[256] = {0};
- FILE *fp = NULL;
const char *question = "Disabling quota will delete all the quota "
"configuration. Do you want to continue?";
- 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;
- }
-
+ //parse **words into options dictionary
ret = cli_cmd_quota_parse (words, wordcount, &options);
-
if (ret < 0) {
cli_usage_out (word->pattern);
parse_err = 1;
@@ -1155,10 +1317,21 @@ cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,
gf_log ("cli", GF_LOG_ERROR, "Failed to get opcode");
goto out;
}
- if (type == GF_QUOTA_OPTION_TYPE_DISABLE) {
+
+ //handle quota-disable and quota-list-all different from others
+ switch (type) {
+ case GF_QUOTA_OPTION_TYPE_DISABLE:
answer = cli_cmd_get_confirmation (state, question);
if (answer == GF_ANSWER_NO)
goto out;
+ break;
+ case GF_QUOTA_OPTION_TYPE_LIST:
+ if (wordcount != 4)
+ break;
+ ret = cli_cmd_quota_handle_list_all (words, options);
+ goto out;
+ default:
+ break;
}
ret = dict_get_str (options, "volname", &volname);
@@ -1166,59 +1339,29 @@ cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,
gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name");
goto out;
}
- if (type == GF_QUOTA_OPTION_TYPE_LIST && wordcount == 4) {
- ret = cli_get_soft_limit (frame, local, options, words);
- if (ret) {
- gf_log ("cli", GF_LOG_ERROR, "Failed to fetch default "
- "soft-limit");
- goto out;
- }
- proc = &cli_quotad_clnt.proctable[GF_AGGREGATOR_GETLIMIT];
- xdata = dict_new ();
- if (!xdata) {
- ret = -1;
- goto out;
- }
- ret = dict_set_str (xdata, "volume-uuid", volname);
- if (ret)
- goto out;
-
- char quota_conf_file[PATH_MAX] = {0};
- //TODO: fix hardcoding
- sprintf (quota_conf_file, "/var/lib/glusterd/vols/%s/quota.conf",
- volname);
- fp = fopen (quota_conf_file, "r");
- if (!fp) {
- gf_log ("cli", GF_LOG_ERROR, "Failed to open quota.conf");
- goto out;
- }
-
- print_quota_list_header ();
- while (fscanf (fp, "%s", buf) != EOF) {
-
- ret = dict_set_str (xdata, "gfid", buf);
- if (ret)
- goto out;
- //Given the path, get the gfi
- ret = proc->fn (frame, THIS, xdata);
- dict_del (xdata, "gfid");
-
- }
- goto out;
- }
+ //create auxillary mount need for quota commands that operate on path
ret = cli_stage_quota_op (volname, type);
if (ret)
goto out;
+ frame = create_frame (THIS, THIS->ctx->pool);
+ if (!frame) {
+ ret = -1;
+ goto out;
+ }
+
CLI_LOCAL_INIT (local, words, frame, options);
+ proc = &cli_rpc_prog->proctable[GLUSTER_CLI_QUOTA];
+ if (proc == NULL) {
+ ret = -1;
+ goto out;
+ }
if (proc->fn)
ret = proc->fn (frame, THIS, options);
out:
- if (fp)
- fclose (fp);
if (ret) {
cli_cmd_sent_status_get (&sent);
if (sent == 0 && parse_err == 0)
@@ -1227,7 +1370,6 @@ out:
}
CLI_STACK_DESTROY (frame);
-
return ret;
}