diff options
| author | Mohammed Junaid Ahmed <junaid@gluster.com> | 2011-03-15 05:36:18 +0000 | 
|---|---|---|
| committer | Vijay Bellur <vijay@dev.gluster.com> | 2011-03-16 00:04:50 -0700 | 
| commit | c5d93456dcd17ddeb189c3e1390e58f95e30b851 (patch) | |
| tree | d958423709ab10af2a7ff98591a5164dea106e4a | |
| parent | 8221c3cae1ce5c2f7d897e5637591c5437aeea69 (diff) | |
cli: QUOTA cli related changes.
Signed-off-by: Junaid <junaid@gluster.com>
Signed-off-by: Vijay Bellur <vijay@dev.gluster.com>
BUG: 2473 (Support for volume and directory level quota)
URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2473
| -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);  | 
