diff options
Diffstat (limited to 'cli')
| -rw-r--r-- | cli/src/Makefile.am | 4 | ||||
| -rw-r--r-- | cli/src/cli-cmd-parser.c | 129 | ||||
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 354 | ||||
| -rw-r--r-- | cli/src/cli-cmd.c | 4 | ||||
| -rw-r--r-- | cli/src/cli-cmd.h | 2 | ||||
| -rw-r--r-- | cli/src/cli-quotad-client.c | 154 | ||||
| -rw-r--r-- | cli/src/cli-quotad-client.h | 33 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 509 | ||||
| -rw-r--r-- | cli/src/cli.c | 48 | ||||
| -rw-r--r-- | cli/src/cli.h | 9 | 
10 files changed, 1065 insertions, 181 deletions
diff --git a/cli/src/Makefile.am b/cli/src/Makefile.am index d5189da5e8c..6370c2203bb 100644 --- a/cli/src/Makefile.am +++ b/cli/src/Makefile.am @@ -2,7 +2,7 @@ sbin_PROGRAMS = gluster  gluster_SOURCES = cli.c registry.c input.c cli-cmd.c cli-rl.c \  	 cli-cmd-volume.c cli-cmd-peer.c cli-rpc-ops.c cli-cmd-parser.c\ -	 cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c +	 cli-cmd-system.c cli-cmd-misc.c cli-xml-output.c cli-quotad-client.c  gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD)\  		$(RLLIBS) $(top_builddir)/rpc/xdr/src/libgfxdr.la \ @@ -10,7 +10,7 @@ gluster_LDADD = $(top_builddir)/libglusterfs/src/libglusterfs.la $(GF_LDADD)\  		$(GF_GLUSTERFS_LIBS) $(XML_LIBS)  gluster_LDFLAGS = $(GF_LDFLAGS) -noinst_HEADERS = cli.h cli-mem-types.h cli-cmd.h +noinst_HEADERS = cli.h cli-mem-types.h cli-cmd.h cli-quotad-client.h  AM_CPPFLAGS = $(GF_CPPFLAGS) \  	-I$(top_srcdir)/libglusterfs/src -I$(top_srcdir)/rpc/rpc-lib/src\ diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index cd0370acc78..dd7b11bccd4 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -485,8 +485,12 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)          uint64_t         value   = 0;          gf_quota_type    type    = GF_QUOTA_OPTION_TYPE_NONE;          char           *opwords[] = { "enable", "disable", "limit-usage", -                                      "remove", "list", "version", NULL }; +                                      "remove", "list", "alert-time", +                                      "soft-timeout", "hard-timeout", +                                      "default-soft-limit", NULL};          char            *w       = NULL; +        uint32_t         time    = 0; +        double           percent = 0;          GF_ASSERT (words);          GF_ASSERT (options); @@ -558,7 +562,8 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)          }          if (strcmp (w, "limit-usage") == 0) { -                if (wordcount != 6) { + +                if (wordcount < 6 || wordcount > 7) {                          ret = -1;                          goto out;                  } @@ -567,8 +572,8 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)                  if (words[4][0] != '/') {                          cli_err ("Please enter absolute path"); - -                        return -2; +                        ret = -1; +                        goto out;                  }                  ret = dict_set_str (dict, "path", (char *) words[4]);                  if (ret) @@ -576,20 +581,34 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)                  if (!words[5]) {                          cli_err ("Please enter the limit value to be set"); - -                        return -2; +                        ret = -1; +                        goto out;                  }                  ret = gf_string2bytesize (words[5], &value);                  if (ret != 0) {                          cli_err ("Please enter a correct value"); -                        return -1; +                        goto out;                  } -                ret = dict_set_str (dict, "limit", (char *) words[5]); +                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) { +                                cli_err ("Please enter a correct value"); +                                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) { @@ -602,8 +621,8 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)                  if (words[4][0] != '/') {                          cli_err ("Please enter absolute path"); - -                        return -2; +                        ret = -1; +                        goto out;                  }                  ret = dict_set_str (dict, "path", (char *) words[4]); @@ -636,8 +655,75 @@ cli_cmd_quota_parse (const char **words, int wordcount, dict_t **options)                  goto set_type;          } -        if (strcmp (w, "version") == 0) { -                type = GF_QUOTA_OPTION_TYPE_VERSION; + +        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");          } @@ -2225,6 +2311,8 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,                                          cmd |= GF_CLI_STATUS_NFS;                                  } else if (!strcmp (words[3], "shd")) {                                          cmd |= GF_CLI_STATUS_SHD; +                                } else if (!strcmp (words[3], "quotad")) { +                                        cmd |= GF_CLI_STATUS_QUOTAD;                                  } else {                                          cmd = GF_CLI_STATUS_BRICK;                                          ret = dict_set_str (dict, "brick", @@ -2280,6 +2368,17 @@ cli_cmd_volume_status_parse (const char **words, int wordcount,                                  goto out;                          }                          cmd |= GF_CLI_STATUS_SHD; +                } else if (!strcmp (words[3], "quotad")) { +                        if (cmd == GF_CLI_STATUS_FD || +                            cmd == GF_CLI_STATUS_CLIENTS || +                            cmd == GF_CLI_STATUS_DETAIL || +                            cmd == GF_CLI_STATUS_INODE) { +                                cli_err ("Detail/FD/Clients/Inode status not " +                                         "available for Quota Daemon"); +                                ret = -1; +                                goto out; +                        } +                        cmd |= GF_CLI_STATUS_QUOTAD;                  } else {                          if (cmd == GF_CLI_STATUS_TASKS) {                                  cli_err ("Tasks status not available for " @@ -2317,7 +2416,7 @@ cli_cmd_validate_dumpoption (const char *arg, char **option)  {          char    *opwords[] = {"all", "nfs", "mem", "iobuf", "callpool", "priv",                                "fd", "inode", "history", "inodectx", "fdctx", -                              NULL}; +                              "quotad", NULL};          char    *w = NULL;          w = str_getunamb (arg, opwords); @@ -2349,6 +2448,10 @@ cli_cmd_volume_statedump_options_parse (const char **words, int wordcount,                  strncat (option_str, option, strlen (option));                  strncat (option_str, " ", 1);          } +        if((strstr (option_str, "nfs")) && strstr (option_str, "quotad")) { +                ret = -1; +                goto out; +        }          dict = dict_new ();          if (!dict) diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 100be0b7337..9bc11d2dbb4 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -30,8 +30,10 @@  #include "run.h"  extern struct rpc_clnt *global_rpc; +extern struct rpc_clnt *global_quotad_rpc;  extern rpc_clnt_prog_t *cli_rpc_prog; +extern rpc_clnt_prog_t cli_quotad_clnt;  int  cli_cmd_volume_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word, @@ -1007,6 +1009,283 @@ out:          return ret;  } +static int +gf_cli_create_auxiliary_mount (char *volname) +{ +        int      ret                     = -1; +        char     mountdir[PATH_MAX]      = {0,}; +        char     pidfile_path[PATH_MAX]  = {0,}; +        char     logfile[PATH_MAX]       = {0,}; + +        GLUSTERFS_GET_AUX_MOUNT_PIDFILE (pidfile_path, volname); + +        if (gf_is_service_running (pidfile_path, NULL)) { +                gf_log ("cli", GF_LOG_DEBUG, "Aux mount of volume %s is running" +                        " already", volname); +                ret = 0; +                goto out; +        } + +        snprintf (mountdir, sizeof (mountdir)-1, "/tmp/%s", volname); +        ret = mkdir (mountdir, 0777); +        if (ret && errno != EEXIST) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to create auxiliary mount " +                        "directory %s. Reason : %s", mountdir, +                        strerror (errno)); +                goto out; +        } + +        snprintf (logfile, PATH_MAX-1, "%s/quota-mount-%s.log", +                  DEFAULT_LOG_FILE_DIRECTORY, volname); + +        ret = runcmd (SBIN_DIR"/glusterfs", +                      "-s", "localhost", +                      "--volfile-id", volname, +                      "-l", logfile, +                      "-p", pidfile_path, +                      mountdir, +                      "--client-pid", "-42", NULL); + +        if (ret) { +                gf_log ("cli", GF_LOG_WARNING, "failed to mount glusterfs " +                        "client. Please check the log file %s for more details", +                        logfile); +                ret = -1; +                goto out; +        } + +        ret = 0; + +out: +        return ret; +} + +static int +cli_stage_quota_op (char *volname, int op_code) +{ +        int ret = -1; + +        switch (op_code) { +                case GF_QUOTA_OPTION_TYPE_ENABLE: +                case GF_QUOTA_OPTION_TYPE_LIMIT_USAGE: +                case GF_QUOTA_OPTION_TYPE_REMOVE: +                case GF_QUOTA_OPTION_TYPE_LIST: +                        ret = gf_cli_create_auxiliary_mount (volname); +                        if (ret) +                                goto out; +                        ret = 0; +                        break; + +                default: +                        ret = 0; +                        break; +        } + +out: +        return ret; +} + +static void +print_quota_list_header (void) +{ +        //Header +        cli_out ("                  Path                   Hard-limit " +                 "Soft-limit   Used  Available"); +        cli_out ("-----------------------------------------------------" +                 "---------------------------"); +} + +int +cli_get_soft_limit (dict_t *options, const char **words, dict_t *xdata) +{ +        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; +} +  int  cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,                     const char **words, int wordcount) @@ -1020,47 +1299,78 @@ cli_cmd_quota_cbk (struct cli_state *state, struct cli_cmd_word *word,          dict_t                  *options   = NULL;          gf_answer_t              answer    = GF_ANSWER_NO;          cli_local_t             *local     = NULL; +        int                      sent      = 0; +        char                    *volname   = 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; +        //parse **words into options dictionary +        ret = cli_cmd_quota_parse (words, wordcount, &options); +        if (ret < 0) { +                cli_usage_out (word->pattern); +                parse_err = 1;                  goto out;          } -        frame = create_frame (THIS, THIS->ctx->pool); -        if (!frame) { -                ret = -1; +        ret = dict_get_int32 (options, "type", &type); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get opcode");                  goto out;          } -        ret = cli_cmd_quota_parse (words, wordcount, &options); - -        if (ret < 0) { -                cli_usage_out (word->pattern); -                parse_err = 1; -                goto out; -        } else if (dict_get_int32 (options, "type", &type) == 0 && -                   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); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get volume name"); +                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 (ret && parse_err == 0) -                cli_out ("Quota command failed"); +        if (ret) { +                cli_cmd_sent_status_get (&sent); +                if (sent == 0 && parse_err == 0) +                        cli_out ("Quota command failed. Please check the cli " +                                 "logs for more details"); +        }          CLI_STACK_DESTROY (frame); -          return ret; -  }  int @@ -1906,7 +2216,9 @@ struct cli_cmd volume_cmds[] = {             cli_cmd_volume_profile_cbk,             "volume profile operations"}, -        { "volume quota <VOLNAME> <enable|disable|limit-usage|list|remove> [path] [value]", +        { "volume quota <VOLNAME> {enable|disable|list [<path> ...]|remove <path>| default-soft-limit <percent>} |\n" +          "volume quota <VOLNAME> {limit-usage <path> <size> [<percent>]} |\n" +          "volume quota <VOLNAME> {alert-time|soft-timeout|hard-timeout} {<time>}",            cli_cmd_quota_cbk,            "quota translator specific operations"}, @@ -1915,7 +2227,7 @@ struct cli_cmd volume_cmds[] = {             cli_cmd_volume_top_cbk,             "volume top operations"}, -        { "volume status [all | <VOLNAME> [nfs|shd|<BRICK>]]" +        { "volume status [all | <VOLNAME> [nfs|shd|<BRICK>|quotad]]"            " [detail|clients|mem|inode|fd|callpool|tasks]",            cli_cmd_volume_status_cbk,            "display status of all or specified volume(s)/brick"}, @@ -1924,7 +2236,7 @@ struct cli_cmd volume_cmds[] = {            cli_cmd_volume_heal_cbk,            "self-heal commands on volume specified by <VOLNAME>"}, -        {"volume statedump <VOLNAME> [nfs] [all|mem|iobuf|callpool|priv|fd|" +        {"volume statedump <VOLNAME> [nfs|quotad] [all|mem|iobuf|callpool|priv|fd|"           "inode|history]...",           cli_cmd_volume_statedump_cbk,           "perform statedump on bricks"}, diff --git a/cli/src/cli-cmd.c b/cli/src/cli-cmd.c index 1045f34f0f5..63b939282fa 100644 --- a/cli/src/cli-cmd.c +++ b/cli/src/cli-cmd.c @@ -352,7 +352,7 @@ cli_cmd_broadcast_connected ()  }  int -cli_cmd_submit (void *req, call_frame_t *frame, +cli_cmd_submit (struct rpc_clnt* rpc, void *req, call_frame_t *frame,                  rpc_clnt_prog_t *prog,                  int procnum, struct iobref *iobref,                  xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc) @@ -368,7 +368,7 @@ cli_cmd_submit (void *req, call_frame_t *frame,          cli_cmd_lock ();          cmd_sent = 0; -        ret = cli_submit_request (req, frame, prog, +        ret = cli_submit_request (rpc, req, frame, prog,                                    procnum, NULL, this, cbkfn, xdrproc);          if (!ret) { diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h index 06a1ed32aac..52396bbf755 100644 --- a/cli/src/cli-cmd.h +++ b/cli/src/cli-cmd.h @@ -110,7 +110,7 @@ int cli_cmd_lock ();  int cli_cmd_unlock ();  int -cli_cmd_submit (void *req, call_frame_t *frame, +cli_cmd_submit (struct rpc_clnt *rpc, void *req, call_frame_t *frame,                  rpc_clnt_prog_t *prog,                  int procnum, struct iobref *iobref,                  xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc); diff --git a/cli/src/cli-quotad-client.c b/cli/src/cli-quotad-client.c new file mode 100644 index 00000000000..f0efc8640bd --- /dev/null +++ b/cli/src/cli-quotad-client.c @@ -0,0 +1,154 @@ +/* +   Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.com> +   This file is part of GlusterFS. + +   This file is licensed to you under your choice of the GNU Lesser +   General Public License, version 3 or any later version (LGPLv3 or +   later), or the GNU General Public License, version 2 (GPLv2), in all +   cases as published by the Free Software Foundation. +*/ +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + + +#include "cli-quotad-client.h" + +extern struct rpc_clnt global_quotad_rpc; +extern struct rpc_clnt_program cli_quotad_clnt; + +int +cli_quotad_submit_request (void *req, call_frame_t *frame, +                           rpc_clnt_prog_t *prog, +                           int procnum, struct iobref *iobref, +                           xlator_t *this, fop_cbk_fn_t cbkfn, +                           xdrproc_t xdrproc) +{ +        int           ret        = -1; +        int           count      = 0; +        struct iovec  iov        = {0, }; +        struct iobuf *iobuf      = NULL; +        char          new_iobref = 0; +        ssize_t       xdr_size   = 0; + +        GF_ASSERT (this); + +        if (req) { +                xdr_size = xdr_sizeof (xdrproc, req); +                iobuf = iobuf_get2 (this->ctx->iobuf_pool, xdr_size); +                if (!iobuf) { +                        goto out; +                }; + +                if (!iobref) { +                        iobref = iobref_new (); +                        if (!iobref) { +                                goto out; +                        } + +                        new_iobref = 1; +                } + +                iobref_add (iobref, iobuf); + +                iov.iov_base = iobuf->ptr; +                iov.iov_len  = iobuf_size (iobuf); + +                /* Create the xdr payload */ +                ret = xdr_serialize_generic (iov, req, xdrproc); +                if (ret == -1) { +                        goto out; +                } +                iov.iov_len = ret; +                count = 1; +        } + +        /* Send the msg */ +        ret = rpc_clnt_submit (&global_quotad_rpc, prog, procnum, cbkfn, +                               &iov, count, +                               NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL); +        ret = 0; + +out: +        if (new_iobref) +                iobref_unref (iobref); +        if (iobuf) +                iobuf_unref (iobuf); + +        return ret; +} + +int +cli_quotad_notify (struct rpc_clnt *rpc, void *mydata, +                   rpc_clnt_event_t event, void *data) +{ +        xlator_t                *this = NULL; +        int                     ret = 0; + +        this = mydata; + +        switch (event) { +        case RPC_CLNT_CONNECT: +        { +                gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_CONNECT"); +                break; +        } + +        case RPC_CLNT_DISCONNECT: +        { +                gf_log (this->name, GF_LOG_TRACE, "got RPC_CLNT_DISCONNECT"); +                break; +        } + +        default: +                gf_log (this->name, GF_LOG_TRACE, +                        "got some other RPC event %d", event); +                ret = 0; +                break; +        } + +        return ret; +} + +struct rpc_clnt * +cli_quotad_clnt_init (xlator_t *this, dict_t *options) +{ +        struct rpc_clnt *rpc  = NULL; +        int              ret  = -1; + + +        ret = dict_set_str (options, "transport.address-family", "unix"); +        if (ret) +                goto out; + +        ret = dict_set_str (options, "transport-type", "socket"); +        if (ret) +                goto out; + +        ret = dict_set_str (options, "transport.socket.connect-path", +                            "/tmp/quotad.socket"); +        if (ret) +                goto out; + +        rpc = rpc_clnt_new (options, this->ctx, this->name, 16); +        if (!rpc) +                goto out; + +        ret = rpc_clnt_register_notify (rpc, cli_quotad_notify, this); +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "failed to register notify"); +                goto out; +        } + +        rpc_clnt_start (rpc); +out: +        if (ret) { +                if (rpc) +                        rpc_clnt_unref (rpc); +                rpc = NULL; +        } + +        return rpc; +} + diff --git a/cli/src/cli-quotad-client.h b/cli/src/cli-quotad-client.h new file mode 100644 index 00000000000..aa0b42af38d --- /dev/null +++ b/cli/src/cli-quotad-client.h @@ -0,0 +1,33 @@ +/* +   Copyright (c) 2010-2013 Red Hat, Inc. <http://www.redhat.com> +   This file is part of GlusterFS. + +   This file is licensed to you under your choice of the GNU Lesser +   General Public License, version 3 or any later version (LGPLv3 or +   later), or the GNU General Public License, version 2 (GPLv2), in all +   cases as published by the Free Software Foundation. +*/ +#include "cli.h" +#include "compat-errno.h" +#include "compat.h" +#include "cli-cmd.h" +#include "cli1-xdr.h" +#include "xdr-generic.h" +#include "protocol-common.h" +#include "cli-mem-types.h" + + +int +cli_quotad_submit_request (void *req, call_frame_t *frame, +                           rpc_clnt_prog_t *prog, +                           int procnum, struct iobref *iobref, +                           xlator_t *this, fop_cbk_fn_t cbkfn, +                           xdrproc_t xdrproc); + +struct rpc_clnt * +cli_quotad_clnt_init (xlator_t *this, dict_t *options); + +int +cli_quotad_notify (struct rpc_clnt *rpc, void *mydata, +                   rpc_clnt_event_t event, void *data); + diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 208f7a281f0..07c081affcc 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -37,9 +37,13 @@  #include "syscall.h"  #include "glusterfs3.h"  #include "portmap-xdr.h" +#include "byte-order.h" +#include "cli-quotad-client.h"  #include "run.h" +extern struct rpc_clnt *global_quotad_rpc; +extern rpc_clnt_prog_t cli_quotad_clnt;  extern rpc_clnt_prog_t *cli_rpc_prog;  extern int              cli_op_ret;  extern int              connected; @@ -2281,137 +2285,346 @@ out:          return ret;  } -int32_t -gf_cli_print_limit_list (char *volname, char *limit_list, -                            char *op_errstr) +static int +print_quota_list_output (char *mountdir, char *default_sl, char *path)  { -        int64_t  size            = 0; -        int64_t  limit_value     = 0; -        int32_t  i, j; -        int32_t  len = 0, ret    = -1; -        char     *size_str       = NULL; -        char     path [PATH_MAX] = {0, }; -        char     ret_str [1024]  = {0, }; -        char     value [1024]    = {0, }; -        char     mountdir []     = "/tmp/mntXXXXXX"; -        char     abspath [PATH_MAX] = {0, }; -        char     *colon_ptr      = NULL; -        runner_t runner          = {0,}; +        uint64_t used_space       = 0; +        uint64_t avail            = 0; +        char    *used_str         = NULL; +        char    *avail_str        = NULL; +        int     ret               = -1; +        char    *sl_final         = NULL; +        char     percent_str[20]  = {0,}; +        char    *hl_str           = NULL; + +        struct quota_limit { +                int64_t hl; +                int64_t sl; +        } __attribute__ ((__packed__)) existing_limits; + +        ret = sys_lgetxattr (mountdir, "trusted.glusterfs.quota.limit-set", +                             (void *)&existing_limits, +                             sizeof (existing_limits)); +        if (ret < 0) { +                gf_log ("cli", GF_LOG_ERROR, "Failed to get the xattr " +                        "trusted.glusterfs.quota.limit-set on %s. Reason : %s", +                        mountdir, strerror (errno)); +                goto out; +        } -        GF_VALIDATE_OR_GOTO ("cli", volname, out); -        GF_VALIDATE_OR_GOTO ("cli", limit_list, out); +        existing_limits.hl = ntoh64 (existing_limits.hl); +        existing_limits.sl = ntoh64 (existing_limits.sl); -        if (!connected) +        hl_str = gf_uint64_2human_readable (existing_limits.hl); + +        if (existing_limits.sl < 0) { +                sl_final = default_sl; +        } else { +                snprintf (percent_str, sizeof (percent_str), "%"PRIu64"%%", +                          existing_limits.sl); +                sl_final = percent_str; +        } + +        ret = sys_lgetxattr (mountdir, "trusted.glusterfs.quota.size", +                             &used_space, sizeof (used_space)); + +        if (ret < 0) { +                cli_out ("%-40s %7s %9s %11s %7s", path, hl_str, sl_final, +                         "N/A", "N/A"); +        } else { +                used_space = ntoh64 (used_space); + +                used_str = gf_uint64_2human_readable (used_space); + +                if (existing_limits.hl > used_space) +                        avail = existing_limits.hl - used_space; +                else +                        avail = 0; + +                avail_str = gf_uint64_2human_readable (avail); +                if (used_str == NULL) +                        cli_out ("%-40s %7s %9s %11"PRIu64 +                                                 "%9"PRIu64, path, hl_str, +                                                 sl_final, used_space, avail); +                else +                        cli_out ("%-40s %7s %9s %11s %7s", path, hl_str, +                                 sl_final, used_str, avail_str); +        } + +out: +        GF_FREE (used_str); +        GF_FREE (avail_str); +        GF_FREE (hl_str); +        return ret; +} + +int +gf_cli_print_limit_list_from_dict (char *volname, dict_t *dict, +                                   char *default_sl, int count, char *op_errstr) +{ +        int  ret               = -1; +        int  i                 = 0; +        char key[1024]         = {0,}; +        char mountdir[PATH_MAX] = {0,}; +        char *path              = NULL; + +        if (!dict|| count <= 0)                  goto out; -        len = strlen (limit_list); -        if (len == 0) { -                cli_err ("%s", op_errstr?op_errstr:"quota limit not set "); +        /*To-Do: +         * Proper error reporting to handle the case where none of the given +         * path arguments are present or have their limits set. +         */ + +        cli_out ("                  Path                   Hard-limit " +                 "Soft-limit   Used  Available"); +        cli_out ("-----------------------------------------------------" +                 "---------------------------"); + +        while (count--) { +                snprintf (key, sizeof (key), "path%d", i++); + +                ret = dict_get_str (dict, key, &path); +                if (ret < 0) { +                        gf_log ("cli", GF_LOG_DEBUG, "Path not present in limit" +                                " list"); +                        continue; +                } + +                ret = gf_canonicalize_path (path); +                if (ret) +                        goto out; +                snprintf (mountdir, sizeof (mountdir), "/tmp/%s%s", volname, +                          path); + +                ret = print_quota_list_output (mountdir, default_sl, path); + +        } +out: +        return ret; +} + +int +print_quota_list_from_quotad (call_frame_t *frame, dict_t *rsp_dict) +{ +        int64_t used_space    = 0; +        int64_t avail         = 0; +        int64_t *limit         = NULL; +        char    *used_str      = NULL; +        char    *avail_str     = NULL; +        char    percent_str[20]= {0}; +        char    *hl_str        = NULL; +        char    *sl_final      = NULL; +        char    *path          = NULL; +        char    *default_sl = NULL; +        int     ret            = -1; +        cli_local_t *local     = NULL; +        dict_t *gd_rsp_dict    = NULL; + +        local = frame->local; +        gd_rsp_dict = local->dict; + +        struct quota_limit { +                int64_t hl; +                int64_t sl; +        } __attribute__ ((__packed__)) *existing_limits = NULL; + +        ret = dict_get_str (rsp_dict, GET_ANCESTRY_PATH_KEY, &path); +        if (ret) { +                gf_log ("cli", GF_LOG_WARNING, "path key is not present " +                        "in dict");                  goto out;          } -        if (mkdtemp (mountdir) == NULL) { -                gf_log ("cli", GF_LOG_WARNING, "failed to create a temporary " -                        "mount directory"); -                ret = -1; +        ret = dict_get_bin (rsp_dict, QUOTA_LIMIT_KEY, (void**)&limit); +        if (ret) { +                gf_log ("cli", GF_LOG_WARNING, +                        "limit key not present in dict");                  goto out;          } -        /* Mount a temporary client to fetch the disk usage -         * of the directory on which the limit is set. -         */ -        ret = runcmd (SBIN_DIR"/glusterfs", "-s", -                      "localhost", "--volfile-id", volname, "-l", -                      DEFAULT_LOG_FILE_DIRECTORY"/quota-list.log", -                      mountdir, NULL); +        ret = dict_get_str (gd_rsp_dict, "default-soft-limit", &default_sl);          if (ret) { -                gf_log ("cli", GF_LOG_WARNING, "failed to mount glusterfs client"); -                ret = -1; -                goto rm_dir; +                gf_log (frame->this->name, GF_LOG_ERROR, "failed to " +                        "get default soft limit"); +                goto out;          } +        existing_limits = (struct quota_limit *)limit; +        existing_limits->hl = ntoh64 (existing_limits->hl); +        existing_limits->sl = ntoh64 (existing_limits->sl); -        len = strlen (limit_list); -        if (len == 0) { -                cli_err ("quota limit not set "); -                goto unmount; +        hl_str = gf_uint64_2human_readable (existing_limits->hl); + +        if (existing_limits->sl < 0) { +                sl_final = default_sl; +        } else { +                snprintf (percent_str, sizeof (percent_str), "%"PRIu64"%%", +                          existing_limits->sl); +                sl_final = percent_str;          } -        i = 0; +        ret = dict_get_bin (rsp_dict, QUOTA_SIZE_KEY, (void**)&limit); +        if (ret < 0) { +                gf_log ("cli", GF_LOG_WARNING, +                        "size key not present in dict"); +                cli_out ("%-40s %7s %9s %11s %7s", path, hl_str, sl_final, +                         "N/A", "N/A"); +        } else { +                used_space = *limit; +                used_space = ntoh64 (used_space); +                used_str = gf_uint64_2human_readable (used_space); -        cli_out ("\tpath\t\t  limit_set\t     size"); -        cli_out ("-----------------------------------------------------------" -                 "-----------------------"); -        while (i < len) { -                j = 0; +                if (existing_limits->hl > used_space) +                        avail = existing_limits->hl - used_space; +                else +                        avail = 0; -                while (limit_list [i] != ',' && limit_list [i] != '\0') { -                        path [j++] = limit_list[i++]; -                } -                path [j] = '\0'; -                //here path[] contains both path and limit value +                avail_str = gf_uint64_2human_readable (avail); +                if (used_str == NULL) +                        cli_out ("%-40s %7s %9s %11"PRIu64 +                                                 "%9"PRIu64, path, hl_str, +                                                 sl_final, used_space, avail); +                else +                        cli_out ("%-40s %7s %9s %11s %7s", path, hl_str, +                                 sl_final, used_str, avail_str); +        } + +        ret = 0; +out: +        GF_FREE (used_str); +        GF_FREE (avail_str); +        GF_FREE (hl_str); +        return ret; +} + +int +cli_quotad_getlimit_cbk (struct rpc_req *req, struct iovec *iov, +                          int count, void *myframe) +{ +    //TODO: we need to gather the path, hard-limit, soft-limit and used space +        gf_cli_rsp         rsp         = {0,}; +        int                ret         = -1; +        dict_t            *dict        = NULL; +        call_frame_t      *frame       = NULL; -                colon_ptr = strrchr (path, ':'); -                *colon_ptr = '\0'; -                strcpy (value, ++colon_ptr); +        if (-1 == req->rpc_status) { +                goto out; +        } -                snprintf (abspath, sizeof (abspath), "%s/%s", mountdir, path); +        frame = myframe; + +        ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp); +        if (ret < 0) { +                gf_log (frame->this->name, GF_LOG_ERROR, +                        "Failed to decode xdr response"); +                goto out; +        } + +        if (rsp.op_ret && strcmp (rsp.op_errstr, "") == 0) { +                cli_err ("quota command : failed"); +                goto out; + +        } else if (strcmp (rsp.op_errstr, "")) +                        cli_err ("quota command failed : %s", rsp.op_errstr); + +        if (rsp.dict.dict_len) { +                /* Unserialize the dictionary */ +                dict  = dict_new (); -                ret = sys_lgetxattr (abspath, "trusted.limit.list", (void *) ret_str, 4096); +                ret = dict_unserialize (rsp.dict.dict_val, +                                        rsp.dict.dict_len, +                                        &dict);                  if (ret < 0) { -                        cli_out ("%-20s %10s", path, value); -                } else { -                        sscanf (ret_str, "%"PRId64",%"PRId64, &size, -                                &limit_value); -                        size_str = gf_uint64_2human_readable ((uint64_t) size); -                        if (size_str == NULL) { -                                cli_out ("%-20s %10s %20"PRId64, path, -                                         value, size); -                        } else { -                                cli_out ("%-20s %10s %20s", path, -                                         value, size_str); -                                GF_FREE (size_str); -                        } +                        gf_log ("cli", GF_LOG_ERROR, +                                "failed to " +                                "unserialize req-buffer to dictionary"); +                        goto out;                  } -                i++; +                print_quota_list_from_quotad (frame, dict);          } -unmount: +out: +        cli_cmd_broadcast_response (ret); +        if (dict) +                dict_unref (dict); -        runinit (&runner); -        runner_add_args (&runner, "umount", -#if GF_LINUX_HOST_OS -                         "-l", -#endif -                         mountdir, NULL); -        ret = runner_run_reuse (&runner); -        if (ret) -                runner_log (&runner, "cli", GF_LOG_WARNING, "error executing"); -        runner_end (&runner); +        free (rsp.dict.dict_val); +        return ret; +} + +int +cli_quotad_getlimit (call_frame_t *frame, xlator_t *this, void *data) +{ +        gf_cli_req          req = {{0,}}; +        int                 ret = 0; +        dict_t             *dict = NULL; + +        if (!frame || !this ||  !data) { +                ret = -1; +                goto out; +        } + +        dict = data; +        ret = dict_allocate_and_serialize (dict, &req.dict.dict_val, +                                           &req.dict.dict_len); +        if (ret < 0) { +                gf_log (this->name, GF_LOG_ERROR, +                        "failed to serialize the data"); + +                goto out; +        } + +        ret = cli_cmd_submit (global_quotad_rpc, &req, frame, &cli_quotad_clnt, +                              GF_AGGREGATOR_GETLIMIT, NULL, +                              this, cli_quotad_getlimit_cbk, +                              (xdrproc_t) xdr_gf_cli_req); -rm_dir: -        rmdir (mountdir);  out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret);          return ret; + + +} + +void +gf_cli_quota_list (char *volname, dict_t *dict, int count, char *op_errstr, +                   char *default_sl) +{ +        GF_VALIDATE_OR_GOTO ("cli", volname, out); + +        if (!connected) +                goto out; + +        if (count > 0) +                gf_cli_print_limit_list_from_dict (volname, dict, default_sl, +                                                   count, op_errstr); +out: +        return;  }  int  gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,                       int count, void *myframe)  { -        gf_cli_rsp         rsp        = {0,}; -        int                ret        = -1; -        dict_t            *dict       = NULL; -        char              *volname    = NULL; -        char              *limit_list = NULL; -        int32_t            type       = 0; -        char               msg[1024]  = {0,}; -        call_frame_t      *frame      = NULL; - +        gf_cli_rsp         rsp         = {0,}; +        int                ret         = -1; +        dict_t            *dict        = NULL; +        char              *volname     = NULL; +        int32_t            type        = 0; +        call_frame_t      *frame       = NULL; +        char              *default_sl  = NULL; +        char              *limit_list  = NULL; +        cli_local_t       *local       = NULL; +        dict_t            *aggr        = NULL; +        char              *default_sl_dup  = NULL; +        int32_t            entry_count      = 0;          if (-1 == req->rpc_status) {                  goto out;          }          frame = myframe; +        local = frame->local; +        aggr  = local->dict;          ret = xdr_to_generic (*iov, &rsp, (xdrproc_t)xdr_gf_cli_rsp);          if (ret < 0) { @@ -2420,15 +2633,14 @@ gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,                  goto out;          } -        if (rsp.op_ret && -            strcmp (rsp.op_errstr, "") == 0) { -                snprintf (msg, sizeof (msg), "command unsuccessful %s", -                          rsp.op_errstr); +        if (rsp.op_ret && strcmp (rsp.op_errstr, "") == 0) { +                cli_err ("quota command : failed");                  if (global_state->mode & GLUSTER_MODE_XML)                          goto xml_output;                  goto out; -        } +        } else if (strcmp (rsp.op_errstr, "")) +                        cli_err ("quota command failed : %s", rsp.op_errstr);          if (rsp.dict.dict_len) {                  /* Unserialize the dictionary */ @@ -2438,28 +2650,51 @@ gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,                                          rsp.dict.dict_len,                                          &dict);                  if (ret < 0) { -                        gf_log ("glusterd", GF_LOG_ERROR, +                        gf_log ("cli", GF_LOG_ERROR,                                  "failed to "                                  "unserialize req-buffer to dictionary");                          goto out;                  }          } +        gf_log ("cli", GF_LOG_DEBUG, "Received resp to quota command"); +          ret = dict_get_str (dict, "volname", &volname);          if (ret) -                gf_log (frame->this->name, GF_LOG_TRACE, +                gf_log (frame->this->name, GF_LOG_ERROR,                          "failed to get volname"); -        ret = dict_get_str (dict, "limit_list", &limit_list); +        ret = dict_get_str (dict, "default-soft-limit", &default_sl);          if (ret) -                gf_log (frame->this->name, GF_LOG_TRACE, -                        "failed to get limit_list"); +                gf_log (frame->this->name, GF_LOG_TRACE, "failed to get " +                        "default soft limit"); + +        // default-soft-limit is part of rsp_dict only iff we sent +        // GLUSTER_CLI_QUOTA with type being GF_QUOTA_OPTION_TYPE_LIST +        if (default_sl) { +                default_sl_dup = gf_strdup (default_sl); +                if (!default_sl_dup) { +                        ret = -1; +                        goto out; +                } +                ret = dict_set_dynstr (aggr, "default-soft-limit", +                                       default_sl_dup); +                if (ret) { +                        gf_log (frame->this->name, GF_LOG_TRACE, +                                "failed to set default soft limit"); +                        GF_FREE (default_sl_dup); +                } +        }          ret = dict_get_int32 (dict, "type", &type);          if (ret)                  gf_log (frame->this->name, GF_LOG_TRACE,                          "failed to get type"); +        ret = dict_get_int32 (dict, "count", &entry_count); +        if (ret) +                gf_log (frame->this->name, GF_LOG_TRACE, "failed to get count"); +          if (type == GF_QUOTA_OPTION_TYPE_LIST) {                  if (global_state->mode & GLUSTER_MODE_XML) {                          ret = cli_xml_output_vol_quota_limit_list @@ -2469,31 +2704,15 @@ gf_cli_quota_cbk (struct rpc_req *req, struct iovec *iov,                                  gf_log ("cli", GF_LOG_ERROR,                                          "Error outputting to xml");                          goto out; -                  } -                if (limit_list) { -                        gf_cli_print_limit_list (volname, -                                                    limit_list, -                                                    rsp.op_errstr); -                } else { -                        gf_log ("cli", GF_LOG_INFO, "Received resp to quota " -                                "command "); -                        if (rsp.op_errstr) -                                snprintf (msg, sizeof (msg), "%s", -                                          rsp.op_errstr); -                } -        } else { -                gf_log ("cli", GF_LOG_INFO, "Received resp to quota command "); -                if (rsp.op_errstr) -                        snprintf (msg, sizeof (msg), "%s", rsp.op_errstr); -                else -                        snprintf (msg, sizeof (msg), "successful"); +                gf_cli_quota_list (volname, dict, entry_count, rsp.op_errstr, +                                   default_sl);          }  xml_output:          if (global_state->mode & GLUSTER_MODE_XML) { -                ret = cli_xml_output_str ("volQuota", msg, rsp.op_ret, +                ret = cli_xml_output_str ("volQuota", NULL, rsp.op_ret,                                            rsp.op_errno, rsp.op_errstr);                  if (ret)                          gf_log ("cli", GF_LOG_ERROR, @@ -2501,12 +2720,8 @@ xml_output:                  goto out;          } -        if (strlen (msg) > 0) { -                if (rsp.op_ret) -                        cli_err ("%s", msg); -                else -                        cli_out ("%s", msg); -        } +        if (!rsp.op_ret && type != GF_QUOTA_OPTION_TYPE_LIST) +                cli_out ("volume quota : success");          ret = rsp.op_ret;  out: @@ -2700,7 +2915,7 @@ gf_cli_list_friends (call_frame_t *frame, xlator_t *this,          flags = (long)data;          req.flags = flags;          frame->local = (void*)flags; -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_LIST_FRIENDS, NULL,                                this, gf_cli_list_friends_cbk,                                (xdrproc_t) xdr_gf1_cli_peer_list_req); @@ -2814,7 +3029,7 @@ gf_cli_get_volume (call_frame_t *frame, xlator_t *this,          ret = dict_allocate_and_serialize (dict, &req.dict.dict_val,                                             &req.dict.dict_len); -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_GET_VOLUME, NULL,                                this, gf_cli_get_volume_cbk,                                (xdrproc_t) xdr_gf_cli_req); @@ -3033,7 +3248,7 @@ gf_cli_rename_volume (call_frame_t *frame, xlator_t *this,          } -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_RENAME_VOLUME, NULL,                                this, gf_cli_rename_volume_cbk,                                (xdrproc_t) xdr_gf_cli_req); @@ -3385,7 +3600,7 @@ gf_cli_getspec (call_frame_t *frame, xlator_t *this,                  goto out;          } -        ret = cli_cmd_submit (&req, frame, &cli_handshake_prog, +        ret = cli_cmd_submit (NULL, &req, frame, &cli_handshake_prog,                                GF_HNDSK_GETSPEC, NULL,                                this, gf_cli_getspec_cbk,                                (xdrproc_t) xdr_gf_getspec_req); @@ -3442,7 +3657,7 @@ gf_cli_pmap_b2p (call_frame_t *frame, xlator_t *this, void *data)          if (ret)                  goto out; -        ret = cli_cmd_submit (&req, frame, &cli_pmap_prog, +        ret = cli_cmd_submit (NULL, &req, frame, &cli_pmap_prog,                                GF_PMAP_PORTBYBRICK, NULL,                                this, gf_cli_pmap_b2p_cbk,                                (xdrproc_t) xdr_pmap_port_by_brick_req); @@ -3557,7 +3772,7 @@ gf_cli_fsm_log (call_frame_t *frame, xlator_t *this, void *data)          if (!frame || !this || !data)                  goto out;          req.name = data; -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_FSM_LOG, NULL,                                this, gf_cli_fsm_log_cbk,                                (xdrproc_t) xdr_gf1_cli_fsm_log_req); @@ -5125,7 +5340,7 @@ gf_cli_getwd (call_frame_t *frame, xlator_t *this, void *data)          if (!frame || !this)                  goto out; -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_GETWD, NULL,                                this, gf_cli_getwd_cbk,                                (xdrproc_t) xdr_gf1_cli_getwd_req); @@ -6329,7 +6544,8 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,                  goto out;          } -        if ((cmd & GF_CLI_STATUS_NFS) || (cmd & GF_CLI_STATUS_SHD)) +        if ((cmd & GF_CLI_STATUS_NFS) || (cmd & GF_CLI_STATUS_SHD) || +            (cmd & GF_CLI_STATUS_QUOTAD))                  notbrick = _gf_true;          if (global_state->mode & GLUSTER_MODE_XML) { @@ -6444,7 +6660,8 @@ gf_cli_status_cbk (struct rpc_req *req, struct iovec *iov,                   */                  memset (status.brick, 0, PATH_MAX + 255);                  if (!strcmp (hostname, "NFS Server") || -                    !strcmp (hostname, "Self-heal Daemon")) +                    !strcmp (hostname, "Self-heal Daemon") || +                    !strcmp (hostname, "Quota Daemon"))                          snprintf (status.brick, PATH_MAX + 255, "%s on %s",                                    hostname, path);                  else @@ -6694,7 +6911,7 @@ gf_cli_mount (call_frame_t *frame, xlator_t *this, void *data)                  goto out;          } -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_MOUNT, NULL,                                this, gf_cli_mount_cbk,                                (xdrproc_t)xdr_gf1_cli_mount_req); @@ -6757,7 +6974,7 @@ gf_cli_umount (call_frame_t *frame, xlator_t *this, void *data)                  goto out;          } -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_UMOUNT, NULL,                                this, gf_cli_umount_cbk,                                (xdrproc_t)xdr_gf1_cli_umount_req); @@ -7326,7 +7543,7 @@ gf_cli_list_volume (call_frame_t *frame, xlator_t *this, void *data)          if (!frame || !this)                  goto out; -        ret = cli_cmd_submit (&req, frame, cli_rpc_prog, +        ret = cli_cmd_submit (NULL, &req, frame, cli_rpc_prog,                                GLUSTER_CLI_LIST_VOLUME, NULL,                                this, gf_cli_list_volume_cbk,                                (xdrproc_t)xdr_gf_cli_req); @@ -7499,7 +7716,7 @@ cli_to_glusterd (gf_cli_req *req, call_frame_t *frame,                  goto out;          } -        ret = cli_cmd_submit (req, frame, prog, procnum, iobref, this, +        ret = cli_cmd_submit (NULL, req, frame, prog, procnum, iobref, this,                                cbkfn, (xdrproc_t) xdrproc);  out: @@ -7556,3 +7773,17 @@ struct rpc_clnt_program cli_prog = {          .numproc   = GLUSTER_CLI_MAXVALUE,          .proctable = gluster_cli_actors,  }; + +struct rpc_clnt_procedure cli_quotad_procs[GF_AGGREGATOR_MAXVALUE] = { +        [GF_AGGREGATOR_NULL]     = {"NULL", NULL}, +        [GF_AGGREGATOR_LOOKUP]   = {"LOOKUP", NULL}, +        [GF_AGGREGATOR_GETLIMIT]   = {"GETLIMIT", cli_quotad_getlimit}, +}; + +struct rpc_clnt_program cli_quotad_clnt = { +        .progname  = "CLI Quotad client", +        .prognum   = GLUSTER_AGGREGATOR_PROGRAM, +        .progver   = GLUSTER_AGGREGATOR_VERSION, +        .numproc   = GF_AGGREGATOR_MAXVALUE, +        .proctable = cli_quotad_procs, +}; diff --git a/cli/src/cli.c b/cli/src/cli.c index 91b315ff169..67f1ad25793 100644 --- a/cli/src/cli.c +++ b/cli/src/cli.c @@ -45,6 +45,7 @@  #endif  #include "cli.h" +#include "cli-quotad-client.h"  #include "cli-cmd.h"  #include "cli-mem-types.h" @@ -82,6 +83,7 @@ const char *argp_program_bug_address = "<" PACKAGE_BUGREPORT ">"; +struct rpc_clnt *global_quotad_rpc;  struct rpc_clnt *global_rpc;  rpc_clnt_prog_t *cli_rpc_prog; @@ -184,7 +186,7 @@ logging_init (glusterfs_ctx_t *ctx, struct cli_state *state)  }  int -cli_submit_request (void *req, call_frame_t *frame, +cli_submit_request (struct rpc_clnt *rpc, void *req, call_frame_t *frame,                      rpc_clnt_prog_t *prog,                      int procnum, struct iobref *iobref,                      xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc) @@ -229,8 +231,10 @@ cli_submit_request (void *req, call_frame_t *frame,                  count = 1;          } +        if (!rpc) +                rpc = global_rpc;          /* Send the msg */ -        ret = rpc_clnt_submit (global_rpc, prog, procnum, cbkfn, +        ret = rpc_clnt_submit (rpc, prog, procnum, cbkfn,                                 &iov, count,                                 NULL, 0, iobref, frame, NULL, 0, NULL, 0, NULL);          ret = 0; @@ -491,6 +495,42 @@ _cli_out (const char *fmt, ...)  }  struct rpc_clnt * +cli_quotad_clnt_rpc_init (void) +{ +        struct rpc_clnt *rpc = NULL; +        dict_t          *rpc_opts = NULL; +        int             ret = -1; + +        rpc_opts = dict_new (); +        if (!rpc_opts) { +                        ret = -1; +                        goto out; +                } + +        ret = dict_set_str (rpc_opts, "transport.address-family", "unix"); +        if (ret) +                goto out; + +        ret = dict_set_str (rpc_opts, "transport-type", "socket"); +        if (ret) +                goto out; + +        ret = dict_set_str (rpc_opts, "transport.socket.connect-path", +                                            "/tmp/quotad.socket"); +        if (ret) +                goto out; + +        rpc = cli_quotad_clnt_init (THIS, rpc_opts); +        if (!rpc) +                goto out; + +        global_quotad_rpc = rpc; +out: +        dict_unref (rpc_opts); +        return rpc; +} + +struct rpc_clnt *  cli_rpc_init (struct cli_state *state)  {          struct rpc_clnt         *rpc = NULL; @@ -634,6 +674,10 @@ main (int argc, char *argv[])          if (!global_rpc)                  goto out; +        global_quotad_rpc = cli_quotad_clnt_rpc_init (); +        if (!global_quotad_rpc) +                goto out; +          ret = cli_cmds_register (&state);          if (ret)                  goto out; diff --git a/cli/src/cli.h b/cli/src/cli.h index bc71ee2b4f0..b71140a810b 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -45,6 +45,13 @@ enum argp_option_keys {  #define GLUSTER_MODE_SCRIPT    (1 << 0)  #define GLUSTER_MODE_ERR_FATAL (1 << 1)  #define GLUSTER_MODE_XML       (1 << 2) + + +#define GLUSTERFS_GET_AUX_MOUNT_PIDFILE(pidfile,volname) {               \ +                snprintf (pidfile, PATH_MAX-1,                             \ +                          DEFAULT_VAR_RUN_DIRECTORY"/%s.pid", volname);  \ +        } +  struct cli_state;  struct cli_cmd_word;  struct cli_cmd_tree; @@ -212,7 +219,7 @@ int _cli_err (const char *fmt, ...);          } while (0)  int -cli_submit_request (void *req, call_frame_t *frame, +cli_submit_request (struct rpc_clnt *rpc, void *req, call_frame_t *frame,                      rpc_clnt_prog_t *prog,                      int procnum, struct iobref *iobref,                      xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc);  | 
