diff options
Diffstat (limited to 'cli')
| -rw-r--r-- | cli/src/cli-cmd-parser.c | 256 | ||||
| -rw-r--r-- | cli/src/cli-cmd-system.c | 147 | ||||
| -rw-r--r-- | cli/src/cli-cmd-volume.c | 3 | ||||
| -rw-r--r-- | cli/src/cli-rpc-ops.c | 586 | 
4 files changed, 866 insertions, 126 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 484c4a34b47..c3f2cca9bb2 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1595,22 +1595,161 @@ gsyncd_glob_check (const char *w)          return !!strpbrk (w, "*?[");  } +static int +config_parse (const char **words, int wordcount, dict_t *dict, +              unsigned cmdi, unsigned glob) +{ +        int32_t            ret     = -1; +        int32_t            i       = -1; +        char               *append_str = NULL; +        size_t             append_len = 0; +        char               *subop = NULL; + +        switch ((wordcount - 1) - cmdi) { +        case 0: +                subop = gf_strdup ("get-all"); +                break; +        case 1: +                if (words[cmdi + 1][0] == '!') { +                        (words[cmdi + 1])++; +                        if (gf_asprintf (&subop, "del%s", +                                         glob ? "-glob" : "") == -1) +                                subop = NULL; +                } else +                        subop = gf_strdup ("get"); + +                ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); +                if (ret < 0) +                        goto out; +                break; +        default: +                if (gf_asprintf (&subop, "set%s", glob ? "-glob" : "") == -1) +                        subop = NULL; + +                ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); +                if (ret < 0) +                        goto out; + +                /* join the varargs by spaces to get the op_value */ + +                for (i = cmdi + 2; i < wordcount; i++) +                        append_len += (strlen (words[i]) + 1); +                /* trailing strcat will add two bytes, make space for that */ +                append_len++; + +                append_str = GF_CALLOC (1, append_len, cli_mt_append_str); +                if (!append_str) { +                        ret = -1; +                        goto out; +                } + +                for (i = cmdi + 2; i < wordcount; i++) { +                        strcat (append_str, words[i]); +                        strcat (append_str, " "); +                } +                append_str[append_len - 2] = '\0'; +                /* "checkpoint now" is special: we resolve that "now" */ +                if (strcmp (words[cmdi + 1], "checkpoint") == 0 && +                    strcmp (append_str, "now") == 0) { +                        struct timeval tv = {0,}; + +                        ret = gettimeofday (&tv, NULL); +                        if (ret == -1) +                                goto out; /* FIXME: free append_str? */ + +                        GF_FREE (append_str); +                        append_str = GF_CALLOC (1, 300, cli_mt_append_str); +                        if (!append_str) { +                                ret = -1; +                                goto out; +                        } +                        strcpy (append_str, "as of "); +                        gf_time_fmt (append_str + strlen ("as of "), +                                     300 - strlen ("as of "), +                                     tv.tv_sec, gf_timefmt_FT); +                } + +                ret = dict_set_dynstr (dict, "op_value", append_str); +        } + +        ret = -1; +        if (subop) { +                ret = dict_set_dynstr (dict, "subop", subop); +                if (!ret) +                      subop = NULL; +        } + +out: +        if (ret && append_str) +                GF_FREE (append_str); + +        GF_FREE (subop); + +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +static int32_t +force_push_pem_parse (const char **words, int wordcount, +                      dict_t *dict, unsigned *cmdi) +{ +        int32_t            ret     = 0; + +        if (!strcmp ((char *)words[wordcount-1], "force")) { +                if ((strcmp ((char *)words[wordcount-2], "start")) && +                    (strcmp ((char *)words[wordcount-2], "stop")) && +                    (strcmp ((char *)words[wordcount-2], "create")) && +                    (strcmp ((char *)words[wordcount-2], "push-pem"))) { +                        ret = -1; +                        goto out; +                } +                ret = dict_set_uint32 (dict, "force", +                                       _gf_true); +                if (ret) +                        goto out; +                (*cmdi)++; + +                if (!strcmp ((char *)words[wordcount-2], "push-pem")) { +                        if (strcmp ((char *)words[wordcount-3], "create")) { +                                ret = -1; +                                goto out; +                        } +                        ret = dict_set_int32 (dict, "push_pem", 1); +                        if (ret) +                                goto out; +                        (*cmdi)++; +                } +        } else if (!strcmp ((char *)words[wordcount-1], "push-pem")) { +                if (strcmp ((char *)words[wordcount-2], "create")) { +                        ret = -1; +                        goto out; +                } +                ret = dict_set_int32 (dict, "push_pem", 1); +                if (ret) +                        goto out; +                (*cmdi)++; +        } + +out: +        gf_log ("cli", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +  int32_t  cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options)  {          int32_t            ret     = -1;          dict_t             *dict   = NULL;          gf1_cli_gsync_set  type    = GF_GSYNC_OPTION_TYPE_NONE; -        char               *append_str = NULL; -        size_t             append_len = 0; -        char               *subop = NULL;          int                i       = 0;          unsigned           masteri = 0;          unsigned           slavei  = 0;          unsigned           glob    = 0;          unsigned           cmdi    = 0; -        char               *opwords[] = { "status", "start", "stop", "config", -                                          "log-rotate", NULL }; +        char               *opwords[] = { "create", "status", "start", "stop", +                                          "config", "force", "delete", +                                          "push-pem", NULL };          char               *w = NULL;          GF_ASSERT (words); @@ -1622,10 +1761,11 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options)          /* new syntax:           * +         * volume geo-replication $m $s create [push-pem] [force]           * volume geo-replication [$m [$s]] status           * volume geo-replication [$m] $s config [[!]$opt [$val]] -         * volume geo-replication $m $s start|stop -         * volume geo-replication $m [$s] log-rotate +         * volume geo-replication $m $s start|stop [force] +         * volume geo-replication $m $s delete           */          if (wordcount < 3) @@ -1682,7 +1822,12 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options)          if (!w)                  goto out; -        if (strcmp (w, "status") == 0) { +        if (strcmp (w, "create") == 0) { +                type = GF_GSYNC_OPTION_TYPE_CREATE; + +                if (!masteri || !slavei) +                        goto out; +        } else if (strcmp (w, "status") == 0) {                  type = GF_GSYNC_OPTION_TYPE_STATUS;                  if (slavei && !masteri) @@ -1702,14 +1847,18 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options)                  if (!masteri || !slavei)                          goto out; -        } else if (strcmp(w, "log-rotate") == 0) { -                type = GF_GSYNC_OPTION_TYPE_ROTATE; +        } else if (strcmp (w, "delete") == 0) { +                type = GF_GSYNC_OPTION_TYPE_DELETE; -                if (slavei && !masteri) +                if (!masteri || !slavei)                          goto out;          } else                  GF_ASSERT (!"opword mismatch"); +        ret = force_push_pem_parse (words, wordcount, dict, &cmdi); +        if (ret) +                goto out; +          if (type != GF_GSYNC_OPTION_TYPE_CONFIG &&              (cmdi < wordcount - 1 || glob))                  goto out; @@ -1718,97 +1867,26 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options)          ret = 0; -        if (masteri) +        if (masteri) {                  ret = dict_set_str (dict, "master", (char *)words[masteri]); +                if (!ret) +                        ret = dict_set_str (dict, "volname", +                                            (char *)words[masteri]); +        }          if (!ret && slavei)                  ret = dict_set_str (dict, "slave", (char *)words[slavei]);          if (!ret)                  ret = dict_set_int32 (dict, "type", type); -        if (!ret && type == GF_GSYNC_OPTION_TYPE_CONFIG) { -                switch ((wordcount - 1) - cmdi) { -                case 0: -                        subop = gf_strdup ("get-all"); -                        break; -                case 1: -                        if (words[cmdi + 1][0] == '!') { -                                (words[cmdi + 1])++; -                                if (gf_asprintf (&subop, "del%s", glob ? "-glob" : "") == -1) -                                        subop = NULL; -                        } else -                                subop = gf_strdup ("get"); - -                        ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); -                        if (ret < 0) -                                goto out; -                        break; -                default: -                        if (gf_asprintf (&subop, "set%s", glob ? "-glob" : "") == -1) -                                subop = NULL; - -                        ret = dict_set_str (dict, "op_name", ((char *)words[cmdi + 1])); -                        if (ret < 0) -                                goto out; - -                        /* join the varargs by spaces to get the op_value */ - -                        for (i = cmdi + 2; i < wordcount; i++) -                                append_len += (strlen (words[i]) + 1); -                        /* trailing strcat will add two bytes, make space for that */ -                        append_len++; - -                        append_str = GF_CALLOC (1, append_len, cli_mt_append_str); -                        if (!append_str) { -                                ret = -1; -                                goto out; -                        } - -                        for (i = cmdi + 2; i < wordcount; i++) { -                                strcat (append_str, words[i]); -                                strcat (append_str, " "); -                        } -                        append_str[append_len - 2] = '\0'; - -                        /* "checkpoint now" is special: we resolve that "now" */ -                        if (strcmp (words[cmdi + 1], "checkpoint") == 0 && -                            strcmp (append_str, "now") == 0) { -                                struct timeval tv = {0,}; - -                                ret = gettimeofday (&tv, NULL); -                                if (ret == -1) -                                         goto out; /* FIXME: free append_str? */ - -                                GF_FREE (append_str); -                                append_str = GF_CALLOC (1, 300, cli_mt_append_str); -                                if (!append_str) { -                                        ret = -1; -                                        goto out; -                                } -                                strcpy (append_str, "as of "); -                                gf_time_fmt (append_str + strlen ("as of "), -                                             300 - strlen ("as of "), -                                             tv.tv_sec, gf_timefmt_FT); -                        } - -                        ret = dict_set_dynstr (dict, "op_value", append_str); -                } - -                ret = -1; -                if (subop) { -                        ret = dict_set_dynstr (dict, "subop", subop); -                        if (!ret) -                                subop = NULL; -                } -        } +        if (!ret && type == GF_GSYNC_OPTION_TYPE_CONFIG) +                ret = config_parse (words, wordcount, dict, cmdi, glob);  out:          if (ret) {                  if (dict)                          dict_destroy (dict); -                GF_FREE (append_str);          } else                  *options = dict; -        GF_FREE (subop);          return ret;  } diff --git a/cli/src/cli-cmd-system.c b/cli/src/cli-cmd-system.c index f73758ae37a..8cfa5e70c3c 100644 --- a/cli/src/cli-cmd-system.c +++ b/cli/src/cli-cmd-system.c @@ -31,6 +31,12 @@ extern rpc_clnt_prog_t *cli_rpc_prog;  int cli_cmd_system_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,                               const char **words, int wordcount); +int cli_cmd_copy_file_cbk (struct cli_state *state, struct cli_cmd_word *word, +                           const char **words, int wordcount); + +int cli_cmd_sys_exec_cbk (struct cli_state *state, struct cli_cmd_word *word, +                          const char **words, int wordcount); +  int  cli_cmd_getspec_cbk (struct cli_state *state, struct cli_cmd_word *word,                       const char **words, int wordcount) @@ -423,10 +429,151 @@ struct cli_cmd cli_system_cmds[] = {             cli_cmd_system_help_cbk,             "display help for system commands"}, +        { "system:: copy file [<filename>]", +           cli_cmd_copy_file_cbk, +           "Copy file from current node's $working_dir to " +           "$working_dir of all cluster nodes"}, + +        { "system:: execute <command> <args>", +           cli_cmd_sys_exec_cbk, +           "Execute the command on all the nodes " +           "in the cluster and display their output."}, +          { NULL, NULL, NULL }  };  int +cli_cmd_sys_exec_cbk (struct cli_state *state, struct cli_cmd_word *word, +                      const char **words, int wordcount) +{ +        char                   cmd_arg_name[PATH_MAX] = ""; +        char                  *command                = NULL; +        char                  *saveptr                = NULL; +        char                  *tmp                    = NULL; +        int                    ret                    = -1; +        int                    i                      = -1; +        int                    cmd_args_count         = 0; +        int                    in_cmd_args_count      = 0; +        rpc_clnt_procedure_t  *proc                   = NULL; +        call_frame_t          *frame                  = NULL; +        dict_t                *dict                   = NULL; +        cli_local_t           *local                  = NULL; + +        if (wordcount < 3) { +                cli_usage_out (word->pattern); +                goto out; +        } + +        dict = dict_new (); +        if (!dict) +                goto out; + +        command = strtok_r ((char *)words[2], " ", &saveptr); +        do { +                tmp = strtok_r (NULL, " ", &saveptr); +                if (tmp) { +                        in_cmd_args_count++; +                        memset (cmd_arg_name, '\0', sizeof(cmd_arg_name)); +                        snprintf (cmd_arg_name, sizeof(cmd_arg_name), +                                  "cmd_arg_%d", in_cmd_args_count); +                        ret = dict_set_str (dict, cmd_arg_name, tmp); +                        if (ret) { +                                gf_log ("", GF_LOG_ERROR, "Unable to set " +                                        "%s in dict", cmd_arg_name); +                                goto out; +                        } +                } +        } while (tmp); + +        cmd_args_count = wordcount - 3; + +        ret = dict_set_str (dict, "command", command); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to set command in dict"); +                goto out; +        } + +        for (i=1; i <= cmd_args_count; i++) { +                in_cmd_args_count++; +                memset (cmd_arg_name, '\0', sizeof(cmd_arg_name)); +                snprintf (cmd_arg_name, sizeof(cmd_arg_name), +                          "cmd_arg_%d", in_cmd_args_count); +                ret = dict_set_str (dict, cmd_arg_name, +                                    (char *)words[2+i]); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to set %s in dict", +                               cmd_arg_name); +                        goto out; +                } +        } + +        ret = dict_set_int32 (dict, "cmd_args_count", in_cmd_args_count); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to set cmd_args_count in dict"); +                goto out; +        } + +        ret = dict_set_str (dict, "volname", "N/A"); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to set volname in dict"); +                goto out; +        } + +        proc = &cli_rpc_prog->proctable[GLUSTER_CLI_SYS_EXEC]; +        if (proc && proc->fn) { +                frame = create_frame (THIS, THIS->ctx->pool); +                if (!frame) +                        goto out; +                CLI_LOCAL_INIT (local, words, frame, dict); +                ret = proc->fn (frame, THIS, (void*)dict); +        } +out: +        return ret; +} + +int +cli_cmd_copy_file_cbk (struct cli_state *state, struct cli_cmd_word *word, +                       const char **words, int wordcount) +{ +        int                    ret      = -1; +        rpc_clnt_procedure_t  *proc     = NULL; +        call_frame_t          *frame    = NULL; +        char                  *filename = ""; +        dict_t                *dict     = NULL; +        cli_local_t           *local    = NULL; + +        if (wordcount != 4) { +                cli_usage_out (word->pattern); +                goto out; +        } + +        dict = dict_new (); +        if (!dict) +                goto out; + +        filename = (char*)words[3]; +        ret = dict_set_str (dict, "source", filename); +        if (ret) +                 gf_log ("", GF_LOG_ERROR, "Unable to set filename in dict"); + +        ret = dict_set_str (dict, "volname", "N/A"); +        if (ret) +                 gf_log ("", GF_LOG_ERROR, "Unable to set volname in dict"); + +        proc = &cli_rpc_prog->proctable[GLUSTER_CLI_COPY_FILE]; +        if (proc && proc->fn) { +                frame = create_frame (THIS, THIS->ctx->pool); +                if (!frame) +                        goto out; +                CLI_LOCAL_INIT (local, words, frame, dict); +                ret = proc->fn (frame, THIS, (void*)dict); +        } +out: +        return ret; +} + +int  cli_cmd_system_help_cbk (struct cli_state *state, struct cli_cmd_word *in_word,                           const char **words, int wordcount)  { diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index aa1c77553b4..97a47c2c975 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -1887,7 +1887,8 @@ struct cli_cmd volume_cmds[] = {           "reset all the reconfigured options"},  #if (SYNCDAEMON_COMPILE) -        {"volume "GEOREP" [<VOLNAME>] [<SLAVE-URL>] {start|stop|config|status|log-rotate} [options...]", +        {"volume "GEOREP" [<VOLNAME>] [<SLAVE-URL>] {create [push-pem] [force]" +         "|start [force]|stop [force]|config|status|delete} [options...]",           cli_cmd_volume_gsync_set_cbk,           "Geo-sync operations",           cli_cmd_check_gsync_exists_cbk}, diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 28b92ee2fd2..0bab5d42b2b 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -13,10 +13,6 @@  #include "config.h"  #endif -#ifndef GSYNC_CONF -#define GSYNC_CONF GEOREP"/gsyncd.conf" -#endif -  /* Widths of various columns in top read/write-perf output   * Total width of top read/write-perf should be 80 chars   * including one space between column @@ -3745,6 +3741,54 @@ out:          return ret;  } +static int +gf_cli_get_slave_volname (char *slave, char **slave_vol) +{ +        char     *tmp       = NULL; +        char     *buf       = NULL; +        char     *save_ptr  = NULL; +        char     *slave_buf = NULL; +        int32_t   ret       = -1; + +        GF_ASSERT (slave); + +        slave_buf = gf_strdup(slave); +        if (!slave_buf) { +                gf_log ("", GF_LOG_ERROR, +                        "Failed to gf_strdup"); +                ret = -1; +                goto out; +        } + +        tmp  = strtok_r (slave_buf, ":", &save_ptr); +        while (tmp) { +                buf = tmp; +                tmp  = strtok_r (NULL, ":", &save_ptr); +        } + +        if (buf) { +                *slave_vol = gf_strdup (buf); +                if (!*slave_vol) { +                        gf_log ("", GF_LOG_ERROR, +                                "Failed to gf_strdup"); +                        ret = -1; +                        goto out; +                } +                gf_log ("", GF_LOG_DEBUG, "Slave Vol : %s", *slave_vol); +                ret = 0; +         } else { +                gf_log ("", GF_LOG_ERROR, "Invalid slave name"); +                goto out; +         } + +out: +        if (slave_buf) +                GF_FREE(slave_buf); + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} +  int  gf_cli_gsync_config_command (dict_t *dict)  { @@ -3752,8 +3796,11 @@ gf_cli_gsync_config_command (dict_t *dict)          char *subop         = NULL;          char *gwd           = NULL;          char *slave         = NULL; +        char *slave_vol     = NULL;          char *master        = NULL;          char *op_name       = NULL; +        int   ret           = -1; +        char  conf_path[PATH_MAX] = "";          if (dict_get_str (dict, "subop", &subop) != 0)                  return -1; @@ -3772,9 +3819,21 @@ gf_cli_gsync_config_command (dict_t *dict)          if (dict_get_str (dict, "op_name", &op_name) != 0)                  op_name = NULL; +        ret = gf_cli_get_slave_volname (slave, &slave_vol); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to fetch slave volume name."); +                return -1; +        } + +        ret = snprintf (conf_path, sizeof(conf_path) - 1, +                        "%s/"GEOREP"/%s-%s/gsyncd.conf", +                        gwd, master, slave_vol); +        conf_path[ret] = '\0'; +          runinit (&runner);          runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, gwd); +        runner_argprintf (&runner, "%s", conf_path);          if (master)                  runner_argprintf (&runner, ":%s", master);          runner_add_arg (&runner, slave); @@ -3785,68 +3844,450 @@ gf_cli_gsync_config_command (dict_t *dict)          return runner_run (&runner);  } -int -gf_cli_gsync_out_status (dict_t *dict) +static int +gf_cli_fetch_gsyncd_health_uptime (char *status, char **health, char **uptime)  { -        int   gsync_count              = 0; -        int   i                        = 0; -        int   ret                      = 0; -        char             mst[PATH_MAX] = {0, }; -        char             slv[PATH_MAX] = {0, }; -        char             sts[PATH_MAX] = {0, }; -        char             nds[PATH_MAX] = {0, }; -        char             hyphens[100]  = {0, }; -        char *mst_val                  = NULL; -        char *slv_val                  = NULL; -        char *sts_val                  = NULL; -        char *nds_val                  = NULL; - -        cli_out ("%-20s %-20s %-50s %-10s", "NODE", "MASTER", "SLAVE", "STATUS"); - -        for (i=0; i<sizeof(hyphens)-1; i++) -                hyphens[i] = '-'; +        char     *tmp      = NULL; +        char     *save_ptr = NULL; +        int32_t   ret      = -1; +        char     *key      = NULL; +        char     *value    = NULL; -        cli_out ("%s", hyphens); +        if (!health || !uptime || !status) { +                gf_log ("", GF_LOG_ERROR, "health or uptime or status is null"); +                goto out; +        } +        tmp = strtok_r (status, "\n", &save_ptr); +        if (tmp) +                *health = gf_strdup (tmp); + +        while (tmp) { +                key = strtok_r (tmp, "=", &value); +                if ((key) && (!strcmp(key, "Uptime"))) { +                    *uptime = gf_strdup (value); +                    break; +                } +                tmp = strtok_r (NULL, ";", &save_ptr); +        } + +        if (*health) +                ret = 0; + +        if (!*uptime) +                *uptime = gf_strdup ("N/A"); +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d.", ret); +        return ret; +} + +int +gf_cli_gsync_out_status (dict_t *dict) +{ +        char    mst[PATH_MAX]  = {0, }; +        char    slv[PATH_MAX]  = {0, }; +        char    sts[PATH_MAX]  = {0, }; +        char    nds[PATH_MAX]  = {0, }; +        char    errmsg[1024]   = ""; +        char   *sts_val        = NULL; +        char   *master         = NULL; +        char   *slave          = NULL; +        char  **output_values  = NULL; +        char  **dict_values    = NULL; +        char   *hyphens        = NULL; +        char   *title_values[] = {"NODE", "MASTER", "SLAVE", +                                  "HEALTH", "UPTIME"}; +        int     gsync_count    = 0; +        int     i              = 0; +        int     j              = 0; +        int     dict_val_count = 0; +        int     ret            = 0; +        int     spacing[5]     = {0, 0, 0, 0, 10}; +        int     total_spacing  = 0; + +        /* Checks if any session is active or not */          ret = dict_get_int32 (dict, "gsync-count", &gsync_count);          if (ret) { -                gf_log ("cli", GF_LOG_INFO, "No active geo-replication sessions" -                        "present for the selected"); +                ret = dict_get_str (dict, "master", &master); + +                ret = dict_get_str (dict, "slave", &slave); + +                if (master) { +                        if (slave) +                                snprintf (errmsg, sizeof(errmsg), "No active " +                                          "geo-replication sessions between %s" +                                          " and %s", master, slave); +                        else +                                snprintf (errmsg, sizeof(errmsg), "No active " +                                          "geo-replication sessions for %s", +                                          master); +                } else +                        snprintf (errmsg, sizeof(errmsg), "No active " +                                  "geo-replication sessions"); + +                gf_log ("cli", GF_LOG_INFO, "%s", errmsg); +                cli_out ("%s", errmsg);                  ret = 0;                  goto out;          } -        for (i = 1; i <= gsync_count; i++) { +        /* (gsync_count = number of nodes reporting output * +           5 = number of fields) = total number of values to +           be fetched from dict */ +        dict_values = GF_CALLOC (gsync_count * 5, sizeof (char *), +                                 gf_common_mt_char); +        if (!dict_values) { +                gf_log ("cli", GF_LOG_ERROR, "Out Of Memory"); +                ret = -1; +                goto out; +        } + +        for (i = 1, j = 0; i <= gsync_count; i++) {                  snprintf (nds, sizeof(nds), "node%d", i);                  snprintf (mst, sizeof(mst), "master%d", i);                  snprintf (slv, sizeof(slv), "slave%d", i);                  snprintf (sts, sizeof(sts), "status%d", i); -                ret = dict_get_str (dict, nds, &nds_val); +                /* Fetching the values from dict, and calculating +                   the max length for each field */ +                ret = dict_get_str (dict, nds, &dict_values[j]);                  if (ret)                          goto out; +                if (strlen (dict_values[j]) > spacing [0]) +                        spacing[0] = strlen (dict_values[j]); +                j++; -                ret = dict_get_str (dict, mst, &mst_val); +                ret = dict_get_str (dict, mst, &dict_values[j]);                  if (ret)                          goto out; +                if (strlen (dict_values[j]) > spacing [1]) +                        spacing[1] = strlen (dict_values[j]); +                j++; -                ret = dict_get_str (dict, slv, &slv_val); +                ret = dict_get_str (dict, slv, &dict_values[j]);                  if (ret)                          goto out; +                if (strlen (dict_values[j]) > spacing [2]) +                        spacing[2] = strlen (dict_values[j]); +                j++;                  ret = dict_get_str (dict, sts, &sts_val);                  if (ret)                          goto out; -                cli_out ("%-20s %-20s %-50s %-10s", nds_val, mst_val, -                         slv_val, sts_val); +                /* Fetching health and uptime from sts_val */ +                ret = gf_cli_fetch_gsyncd_health_uptime (sts_val, +                                                         &dict_values[j], +                                                         &dict_values[j+1]); +                if (ret) +                        goto out; + +                if (strlen (dict_values[j]) > spacing [3]) +                        spacing[3] = strlen (dict_values[j]); +                j++; +                if (strlen (dict_values[j]) > spacing [4]) +                        spacing[4] = strlen (dict_values[j]); +                j++;          } - out: +        /* calculating spacing for hyphens */ +        for (i = 0; i < 5; i++) { +                spacing[i] += 3; /* Adding extra space to +                                    distinguish between fields */ +                total_spacing += spacing[i]; +        } +        total_spacing += 4; /* For the spacing between the fields */ + +        /* char pointers for each field */ +        output_values = GF_CALLOC (5, sizeof (char *), gf_common_mt_char); +        if (!output_values) +                ret = -1; +        for (i = 0; i < 5; i++) { +                output_values[i] = GF_CALLOC (spacing[i] + 1, sizeof (char), +                                              gf_common_mt_char); +                if (!output_values[i]) +                        ret = -1; +        } + +        hyphens = GF_CALLOC (total_spacing + 1, sizeof (char), +                             gf_common_mt_char); +        if (!hyphens) +                ret = -1; + +        if (ret) { +                gf_log ("cli", GF_LOG_ERROR, "Out Of Memory"); +                ret = -1; +                goto out; +        } + +        /* setting the title "NODE", "MASTER", etc. from title_values[] +           and printing the same */ +        for (j = 0; j < 5; j++) { +                memset (output_values[j], ' ', spacing[j]); +                memcpy (output_values[j], title_values[j], +                        strlen(title_values[j])); +                output_values[j][spacing[j]] = '\0'; +        } +        cli_out ("%s %s %s %s %s", output_values[0], output_values[1], +                 output_values[2], output_values[3], output_values[4]); + +        /* setting and printing the hyphens */ +        memset (hyphens, '-', total_spacing); +        hyphens[total_spacing] = '\0'; +        cli_out ("%s", hyphens); + +        for (i = 1, dict_val_count = 0; i <= gsync_count; i++) { +                /* Setting the field values for each row */ +                for (j = 0; j < 5; j++) { +                        memset (output_values[j], ' ', spacing[j]); +                        memcpy (output_values[j], dict_values[dict_val_count], +                                strlen(dict_values[dict_val_count])); +                        output_values[j][spacing[j]] = '\0'; +                        dict_val_count++; +                } +                cli_out ("%s %s %s %s %s", output_values[0], output_values[1], +                         output_values[2], output_values[3], output_values[4]); +        } +out: +        if (output_values) { +                for (i = 0; i < 5; i++) { +                        if (output_values[i]) +                                GF_FREE (output_values[i]); +                } +                GF_FREE (output_values); +        } + +        if (dict_values) +                GF_FREE (dict_values); + +        if (hyphens) +                GF_FREE (hyphens); +          return ret; +} + +static int32_t +write_contents_to_common_pem_file (dict_t *dict, int output_count) +{ +        char            *workdir                   = NULL; +        char             common_pem_file[PATH_MAX] = ""; +        char            *output                    = NULL; +        char             output_name[PATH_MAX]     = ""; +        int              bytes_writen              = 0; +        int              fd                        = -1; +        int              ret                       = -1; +        int              i                         = -1; + +        ret = dict_get_str (dict, "glusterd_workdir", &workdir); +        if (ret || !workdir) { +                gf_log ("", GF_LOG_ERROR, "Unable to fetch workdir"); +                ret = -1; +                goto out; +        } + +        snprintf (common_pem_file, sizeof(common_pem_file), +                  "%s/geo-replication/common_secret.pem.pub", +                  workdir); + +        unlink (common_pem_file); + +        fd = open (common_pem_file, O_WRONLY | O_CREAT, 0600); +        if (fd == -1) { +                gf_log ("", GF_LOG_ERROR, "Failed to open %s" +                        " Error : %s", common_pem_file, +                        strerror (errno)); +                ret = -1; +                goto out; +        } + +        for (i = 1; i <= output_count; i++) { +                memset (output_name, '\0', sizeof (output_name)); +                snprintf (output_name, sizeof (output_name), +                          "output_%d", i); +                ret = dict_get_str (dict, output_name, &output); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Failed to get %s.", +                                output_name); +                        cli_out ("Unable to fetch output."); +                } +                if (output) { +                        bytes_writen = write (fd, output, strlen(output)); +                        if (bytes_writen != strlen(output)) { +                                gf_log ("", GF_LOG_ERROR, "Failed to write " +                                        "to %s", common_pem_file); +                                ret = -1; +                                goto out; +                        } +                        /* Adding the new line character */ +                        bytes_writen = write (fd, "\n", strlen("\n")); +                        if (bytes_writen != strlen("\n")) { +                                gf_log ("", GF_LOG_ERROR, +                                        "Failed to add new line char"); +                                ret = -1; +                                goto out; +                        } +                        output = NULL; +                } +        } +        cli_out ("Common secret pub file present at %s", common_pem_file); +        ret = 0; +out: +        if (fd) +                close (fd); + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +gf_cli_sys_exec_cbk (struct rpc_req *req, struct iovec *iov, +                     int count, void *myframe) +{ +        int                     ret     = -1; +        int                     output_count     = -1; +        int                     i     = -1; +        char                   *output  = NULL; +        char                   *command = NULL; +        char                    output_name[PATH_MAX] = ""; +        gf_cli_rsp              rsp     = {0, }; +        dict_t                  *dict   = NULL; +        call_frame_t            *frame  = NULL; + +        if (req->rpc_status == -1) { +                ret = -1; +                goto out; +        } + +        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; +       } + +        dict = dict_new (); + +        if (!dict) { +                ret = -1; +                goto out; +        } + +        ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); + +        if (ret) +                goto out; + +        if (rsp.op_ret) { +                cli_err ("%s", rsp.op_errstr ? rsp.op_errstr : +                         "Command failed."); +                ret = rsp.op_ret; +                goto out; +        } + +        ret = dict_get_int32 (dict, "output_count", &output_count); +        if (ret) { +                cli_out ("Command executed successfully."); +                ret = 0; +                goto out; +        } + +        ret = dict_get_str (dict, "command", &command); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to get command from dict"); +                goto out; +        } + +        if (!strcmp (command, "gsec_create")) { +                ret = write_contents_to_common_pem_file (dict, output_count); +                if (!ret) +                        goto out; +        } + +        for (i = 1; i <= output_count; i++) { +                memset (output_name, '\0', sizeof (output_name)); +                snprintf (output_name, sizeof (output_name), +                          "output_%d", i); +                ret = dict_get_str (dict, output_name, &output); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Failed to get %s.", +                                output_name); +                        cli_out ("Unable to fetch output."); +                } +                if (output) { +                        cli_out ("%s", output); +                        output = NULL; +                } +        } + +        ret = 0; +out: +        if (dict) +                dict_unref (dict); +        cli_cmd_broadcast_response (ret); + +        free (rsp.dict.dict_val); + +        return ret; +} + +int +gf_cli_copy_file_cbk (struct rpc_req *req, struct iovec *iov, +                      int count, void *myframe) +{ +        int                     ret     = -1; +        gf_cli_rsp              rsp     = {0, }; +        dict_t                  *dict   = NULL; +        call_frame_t            *frame  = NULL; + +        if (req->rpc_status == -1) { +                ret = -1; +                goto out; +        } + +        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; +       } + +        dict = dict_new (); + +        if (!dict) { +                ret = -1; +                goto out; +        } + +        ret = dict_unserialize (rsp.dict.dict_val, rsp.dict.dict_len, &dict); + +       if (ret) +                goto out; + +        if (rsp.op_ret) { +                cli_err ("%s", rsp.op_errstr ? rsp.op_errstr : +                         "Copy unsuccessful"); +                ret = rsp.op_ret; +                goto out; +        } + +        cli_out ("Successfully copied file."); + +out: +        if (dict) +                dict_unref (dict); +        cli_cmd_broadcast_response (ret); + +        free (rsp.dict.dict_val); + +        return ret;  }  int @@ -3861,6 +4302,8 @@ gf_cli_gsync_set_cbk (struct rpc_req *req, struct iovec *iov,          char                    *slave  = NULL;          int32_t                  type   = 0;          call_frame_t            *frame  = NULL; +        gf_boolean_t             is_force = _gf_false; +          if (req->rpc_status == -1) {                  ret = -1; @@ -3897,7 +4340,9 @@ gf_cli_gsync_set_cbk (struct rpc_req *req, struct iovec *iov,                  goto out;          } -        if (rsp.op_ret) { +        is_force = dict_get_str_boolean (dict, "force", _gf_false); + +        if (rsp.op_ret && !is_force) {                  cli_err ("%s", rsp.op_errstr ? rsp.op_errstr :                           GEOREP" command unsuccessful");                  ret = rsp.op_ret; @@ -3937,7 +4382,26 @@ gf_cli_gsync_set_cbk (struct rpc_req *req, struct iovec *iov,                  case GF_GSYNC_OPTION_TYPE_STATUS:                          ret = gf_cli_gsync_out_status (dict); -                        goto out; +                break; + +                case GF_GSYNC_OPTION_TYPE_DELETE: +                        if (dict_get_str (dict, "master", &master) != 0) +                                master = "???"; +                        if (dict_get_str (dict, "slave", &slave) != 0) +                                slave = "???"; +                        cli_out ("Deleting " GEOREP " session between %s & %s" +                                 " has been successful", master, slave); +                break; + +                case GF_GSYNC_OPTION_TYPE_CREATE: +                        if (dict_get_str (dict, "master", &master) != 0) +                                master = "???"; +                        if (dict_get_str (dict, "slave", &slave) != 0) +                                slave = "???"; +                        cli_out ("Creating " GEOREP " session between %s & %s" +                                 " has been successful", master, slave); +                break; +                  default:                          cli_out (GEOREP" command executed successfully");          } @@ -3953,6 +4417,54 @@ out:  }  int32_t +gf_cli_sys_exec (call_frame_t *frame, xlator_t *this, void *data) +{ +        int                      ret    = 0; +        dict_t                  *dict   = NULL; +        gf_cli_req               req = {{0,}}; + +        if (!frame || !this || !data) { +                ret = -1; +                gf_log ("cli", GF_LOG_ERROR, "Invalid data"); +                goto out; +        } + +        dict = data; + +        ret = cli_to_glusterd (&req, frame, gf_cli_sys_exec_cbk, +                               (xdrproc_t) xdr_gf_cli_req, dict, +                               GLUSTER_CLI_SYS_EXEC, this, cli_rpc_prog, +                               NULL); +out: +        GF_FREE (req.dict.dict_val); +        return ret; +} + +int32_t +gf_cli_copy_file (call_frame_t *frame, xlator_t *this, void *data) +{ +        int                      ret    = 0; +        dict_t                  *dict   = NULL; +        gf_cli_req               req = {{0,}}; + +        if (!frame || !this || !data) { +                ret = -1; +                gf_log ("cli", GF_LOG_ERROR, "Invalid data"); +                goto out; +        } + +        dict = data; + +        ret = cli_to_glusterd (&req, frame, gf_cli_copy_file_cbk, +                               (xdrproc_t) xdr_gf_cli_req, dict, +                               GLUSTER_CLI_COPY_FILE, this, cli_rpc_prog, +                               NULL); +out: +        GF_FREE (req.dict.dict_val); +        return ret; +} + +int32_t  gf_cli_gsync_set (call_frame_t *frame, xlator_t *this,                       void *data)  { @@ -6822,6 +7334,8 @@ struct rpc_clnt_procedure gluster_cli_actors[GLUSTER_CLI_MAXVALUE] = {          [GLUSTER_CLI_STATEDUMP_VOLUME] = {"STATEDUMP_VOLUME", gf_cli_statedump_volume},          [GLUSTER_CLI_LIST_VOLUME]      = {"LIST_VOLUME", gf_cli_list_volume},          [GLUSTER_CLI_CLRLOCKS_VOLUME]  = {"CLEARLOCKS_VOLUME", gf_cli_clearlocks_volume}, +        [GLUSTER_CLI_COPY_FILE]        = {"COPY_FILE", gf_cli_copy_file}, +        [GLUSTER_CLI_SYS_EXEC]         = {"SYS_EXEC", gf_cli_sys_exec},  #ifdef HAVE_BD_XLATOR          [GLUSTER_CLI_BD_OP]            = {"BD_OP", gf_cli_bd_op},  #endif  | 
