diff options
| author | Avra Sengupta <asengupt@redhat.com> | 2013-07-10 17:32:41 +0530 | 
|---|---|---|
| committer | Vijay Bellur <vbellur@redhat.com> | 2013-07-26 13:19:18 -0700 | 
| commit | 5757ed2727990fd2c3aaff420003638f1eec6b92 (patch) | |
| tree | 6cb26130cc08b04cf85b467d03146d2c21ba1f80 | |
| parent | b13c483dca20e4015b958f8959328e665a357f60 (diff) | |
glusterd/cli changes for distributed geo-rep
Commands:
gluster system:: execute gsec_create
gluster volume geo-rep <master> <slave-url> create [push-pem] [force]
gluster volume geo-rep <master> <slave-url> start [force]
gluster volume geo-rep <master> <slave-url> stop [force]
gluster volume geo-rep <master> <slave-url> delete
gluster volume geo-rep <master> <slave-url> config
gluster volume geo-rep <master> <slave-url> status
The geo-replication is distributed. The session will be created, and
gsyncd will be spawned on all relevant nodes, instead of only one
node.
geo-rep: Collecting status detail related data
Added persistent store for saving information about
TotalFilesSynced, TotalSyncTime, TotalBytesSynced
Changes in the status information in socket:
Existing(Ex):
FilesSynced=2;BytesSynced=2507;Uptime=00:26:01;
New(Ex):
FilesSynced=2;BytesSynced=2507;Uptime=00:26:01;SyncTime=0.69978;
TotalSyncTime=2.890044;TotalFilesSynced=6;TotalBytesSynced=143640;
Persistent details stored in
/var/lib/glusterd/geo-replication/${mastervol}/${eSlave}-detail.status
Change-Id: I1db7fc13ffca2e415c05200b0109b1254067f111
BUG: 847839
Original Author: Avra Sengupta <asengupt@redhat.com>
Original Author: Venky Shankar <vshankar@redhat.com>
Original Author: Aravinda VK <avishwan@redhat.com>
Original Author: Amar Tumballi <amarts@redhat.com>
Original Author: Csaba Henk <csaba@redhat.com>
Signed-off-by: Avra Sengupta <asengupt@redhat.com>
Reviewed-on: http://review.gluster.org/5132
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Tested-by: Vijay Bellur <vbellur@redhat.com>
31 files changed, 3630 insertions, 718 deletions
diff --git a/.gitignore b/.gitignore index bac9ab97d2c..d3e1a01dd68 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ glusterfsd/src/glusterfsd  libglusterfs/src/spec.lex.c  libglusterfs/src/y.tab.c  libglusterfs/src/y.tab.h +libgfchangelog.pc
\ No newline at end of file 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 diff --git a/configure.ac b/configure.ac index a1a52eebd8e..0aefdd283cc 100644 --- a/configure.ac +++ b/configure.ac @@ -30,6 +30,7 @@ AC_CONFIG_FILES([Makefile                  libglusterfs/Makefile                  libglusterfs/src/Makefile                  geo-replication/src/peer_gsec_create +                geo-replication/src/peer_add_secret_pub                  glusterfsd/Makefile                  glusterfsd/src/Makefile                  rpc/Makefile diff --git a/extras/hook-scripts/Makefile.am b/extras/hook-scripts/Makefile.am index edfa5a6ac87..f6bded20cbe 100644 --- a/extras/hook-scripts/Makefile.am +++ b/extras/hook-scripts/Makefile.am @@ -1 +1 @@ -EXTRA_DIST = S29CTDBsetup.sh S30samba-start.sh S30samba-stop.sh S30samba-set.sh Sglusterd-geo-rep-create-post.sh +EXTRA_DIST = S29CTDBsetup.sh S30samba-start.sh S30samba-stop.sh S30samba-set.sh S56glusterd-geo-rep-create-post.sh diff --git a/extras/hook-scripts/S56glusterd-geo-rep-create-post.sh b/extras/hook-scripts/S56glusterd-geo-rep-create-post.sh new file mode 100755 index 00000000000..71e44b6ed13 --- /dev/null +++ b/extras/hook-scripts/S56glusterd-geo-rep-create-post.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +key_val_pair1=`echo $2 | cut -d ' ' -f 1` +key_val_pair2=`echo $2 | cut -d ' ' -f 2` +key_val_pair3=`echo $2 | cut -d ' ' -f 3` + +key=`echo $key_val_pair1 | cut -d '=' -f 1` +val=`echo $key_val_pair1 | cut -d '=' -f 2` +if [ "$key" != "is_push_pem" ]; then +    exit; +fi +if [ "$val" != '1' ]; then +    exit; +fi + +key=`echo $key_val_pair2 | cut -d '=' -f 1` +val=`echo $key_val_pair2 | cut -d '=' -f 2` +if [ "$key" != "pub_file" ]; then +    exit; +fi +if [ "$val" == "" ]; then +    exit; +fi +pub_file=`echo $val` + +key=`echo $key_val_pair3 | cut -d '=' -f 1` +val=`echo $key_val_pair3 | cut -d '=' -f 2` +if [ "$key" != "slave_ip" ]; then +    exit; +fi +if [ "$val" == "" ]; then +    exit; +fi +slave_ip=`echo $val` + +if [ -f $pub_file ]; then +    ssh $slave_ip "\rm -rf $pub_file" +    scp $pub_file $slave_ip:$pub_file &> /dev/null +    ssh $slave_ip "gluster system:: copy file /geo-replication/common_secret.pem.pub > /dev/null" +    ssh $slave_ip "gluster system:: execute add_secret_pub > /dev/null" +fi diff --git a/geo-replication/src/Makefile.am b/geo-replication/src/Makefile.am index 6feeda8e68c..324d8869f8b 100644 --- a/geo-replication/src/Makefile.am +++ b/geo-replication/src/Makefile.am @@ -3,9 +3,9 @@ gsyncddir = $(libexecdir)/glusterfs  gsyncd_SCRIPTS = gverify.sh peer_add_secret_pub peer_gsec_create -# peer_gsec_create is not added to EXTRA_DIST as it's derived -# from a .in file -EXTRA_DIST = gverify.sh peer_add_secret_pub +# peer_gsec_create and peer_add_secret_pub are not added to +# EXTRA_DIST as it's derived from a .in file +EXTRA_DIST = gverify.sh  gsyncd_PROGRAMS = gsyncd diff --git a/geo-replication/src/gsyncd.c b/geo-replication/src/gsyncd.c index 68446d9ad34..0830e7f9bcc 100644 --- a/geo-replication/src/gsyncd.c +++ b/geo-replication/src/gsyncd.c @@ -37,7 +37,7 @@  #define _GLUSTERD_CALLED_ "_GLUSTERD_CALLED_"  #define _GSYNCD_DISPATCHED_ "_GSYNCD_DISPATCHED_" -#define GSYNCD_CONF "geo-replication/gsyncd.conf" +#define GSYNCD_CONF_TEMPLATE "geo-replication/gsyncd_template.conf"  #define GSYNCD_PY "gsyncd.py"  #define RSYNC "rsync" @@ -127,11 +127,11 @@ invoke_gsyncd (int argc, char **argv)                          gluster_workdir_len = len - 1;                  if (gluster_workdir_len) { -                        if (gluster_workdir_len + 1 + strlen (GSYNCD_CONF) + 1 > +                        if (gluster_workdir_len + 1 + strlen (GSYNCD_CONF_TEMPLATE) + 1 >                              PATH_MAX)                                  goto error;                          config_file[gluster_workdir_len] = '/'; -                        strcat (config_file, GSYNCD_CONF); +                        strcat (config_file, GSYNCD_CONF_TEMPLATE);                  } else                          goto error; diff --git a/geo-replication/src/peer_add_secret_pub b/geo-replication/src/peer_add_secret_pub deleted file mode 100644 index 1ce040d4419..00000000000 --- a/geo-replication/src/peer_add_secret_pub +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -cat $1 >> ~/.ssh/authorized_keys diff --git a/geo-replication/src/peer_add_secret_pub.in b/geo-replication/src/peer_add_secret_pub.in new file mode 100644 index 00000000000..c036cf33416 --- /dev/null +++ b/geo-replication/src/peer_add_secret_pub.in @@ -0,0 +1,9 @@ +#!/bin/bash + +if [ ! -d ~/.ssh ]; then +        mkdir ~/.ssh; +        chmod 700 ~/.ssh +        chown root:root ~/.ssh +fi + +cat "$GLUSTERD_WORKING_DIR"/geo-replication/common_secret.pem.pub >> ~/.ssh/authorized_keys diff --git a/geo-replication/syncdaemon/README.md b/geo-replication/syncdaemon/README.md index 0eb15fa7170..67f346ace5a 100644 --- a/geo-replication/syncdaemon/README.md +++ b/geo-replication/syncdaemon/README.md @@ -39,7 +39,7 @@ The config file format matches the following syntax:        <option2>: <value2>        # comment -By default (unless specified by the option `-c`), gsyncd looks for config file at _conf/gsyncd.conf_ +By default (unless specified by the option `-c`), gsyncd looks for config file at _conf/gsyncd_template.conf_  in the source tree.  USAGE diff --git a/geo-replication/syncdaemon/gsyncd.py b/geo-replication/syncdaemon/gsyncd.py index ad498c39cdc..67ba0737087 100644 --- a/geo-replication/syncdaemon/gsyncd.py +++ b/geo-replication/syncdaemon/gsyncd.py @@ -346,10 +346,9 @@ def main_i():              for name in rmap[x]:                  for j in range(3):                      namedict[mods[j](name)] = pa[j][i] -                if x.scheme == 'gluster': -                    namedict[name + 'vol'] = x.volume +                namedict[name + 'vol'] = x.volume      if not 'config_file' in rconf: -        rconf['config_file'] = os.path.join(os.path.dirname(sys.argv[0]), "conf/gsyncd.conf") +        rconf['config_file'] = os.path.join(os.path.dirname(sys.argv[0]), "conf/gsyncd_template.conf")      gcnf = GConffile(rconf['config_file'], canon_peers, defaults.__dict__, opts.__dict__, namedict)      checkpoint_change = False @@ -399,6 +398,8 @@ def main_i():          if getattr(gconf, 'state_socket_unencoded', None):              cleanup_paths.append(gconf.state_socket_unencoded) +        cleanup_paths.append(rconf['config_file'][:-11] + "*"); +          # Cleanup changelog working dirs          if getattr(gconf, 'working_dir', None):              try: diff --git a/geo-replication/syncdaemon/resource.py b/geo-replication/syncdaemon/resource.py index 52989fe28cc..4b0183b981d 100644 --- a/geo-replication/syncdaemon/resource.py +++ b/geo-replication/syncdaemon/resource.py @@ -1056,6 +1056,7 @@ class SSH(AbstractUrl, SlaveRemote):          self.remote_addr, inner_url = sup(self, path,                                            '^((?:%s@)?%s):(.+)' % tuple([ r.pattern for r in (UserRX, HostRX) ]))          self.inner_rsc = parse_url(inner_url) +        self.volume = inner_url[1:]      @staticmethod      def parse_ssh_address(addr): diff --git a/glusterfs.spec.in b/glusterfs.spec.in index e92cd6e0a80..b5f2d45f9ce 100644 --- a/glusterfs.spec.in +++ b/glusterfs.spec.in @@ -431,7 +431,7 @@ sed -i 's|option working-directory /etc/glusterd|option working-directory %{_sha  %if ( 0%{!?_without_georeplication:1} )  # geo-rep ghosts  %{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/geo-replication -touch %{buildroot}%{_sharedstatedir}/glusterd/geo-replication/gsyncd.conf +touch %{buildroot}%{_sharedstatedir}/glusterd/geo-replication/gsyncd_template.conf  %endif  # the rest of the ghosts @@ -460,6 +460,12 @@ touch %{buildroot}%{_sharedstatedir}/glusterd/options  %{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/delete  %{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/delete/post  %{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/delete/pre +%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/copy-file +%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/copy-file/post +%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/copy-file/pre +%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/gsync-create +%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/gsync-create/post +%{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/hooks/1/gsync-create/pre  %{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/glustershd  %{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/peers  %{__mkdir_p} %{buildroot}%{_sharedstatedir}/glusterd/vols @@ -521,8 +527,10 @@ fi  %{_libexecdir}/glusterfs/gsyncd  %{_libexecdir}/glusterfs/python/syncdaemon/*  %{_libexecdir}/glusterfs/gverify.sh +%{_libexecdir}/glusterfs/peer_add_secret_pub +%{_libexecdir}/glusterfs/peer_gsec_create  %ghost %dir %attr(0755,-,-) %{_sharedstatedir}/glusterd/geo-replication -%ghost %attr(0644,-,-) %{_sharedstatedir}/glusterd/geo-replication/gsyncd.conf +%ghost %attr(0644,-,-) %{_sharedstatedir}/glusterd/geo-replication/gsyncd_template.conf  %endif  %files fuse @@ -697,6 +705,9 @@ if [ $1 -ge 1 ]; then  fi  %changelog +* Thu Jul 25 2013 Csaba Henk <csaba@redhat.com> +- Added peer_add_secret_pub and peer_gsec_create to %{_libexecdir}/glusterfs +  * Thu Jul 25 2013 Aravinda VK <avishwan@redhat.com>  - Added gverify.sh to %{_libexecdir}/glusterfs directory. diff --git a/rpc/rpc-lib/src/protocol-common.h b/rpc/rpc-lib/src/protocol-common.h index b80a52bb670..704b1540a52 100644 --- a/rpc/rpc-lib/src/protocol-common.h +++ b/rpc/rpc-lib/src/protocol-common.h @@ -158,6 +158,8 @@ enum gluster_cli_procnum {          GLUSTER_CLI_UUID_RESET,          GLUSTER_CLI_BD_OP,          GLUSTER_CLI_UUID_GET, +        GLUSTER_CLI_COPY_FILE, +        GLUSTER_CLI_SYS_EXEC,          GLUSTER_CLI_MAXVALUE,  }; diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index e80d6f70c4b..20787c494a0 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -121,6 +121,8 @@ enum gf1_cli_gsync_set {  	GF_GSYNC_OPTION_TYPE_CONFIG = 3,  	GF_GSYNC_OPTION_TYPE_STATUS = 4,  	GF_GSYNC_OPTION_TYPE_ROTATE = 5, +	GF_GSYNC_OPTION_TYPE_CREATE = 6, +	GF_GSYNC_OPTION_TYPE_DELETE = 7,  };  typedef enum gf1_cli_gsync_set gf1_cli_gsync_set; diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 0bee1967914..b85ecf87ab2 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -51,7 +51,8 @@ enum gf_quota_type {  };  enum gf1_cli_friends_list { -        GF_CLI_LIST_ALL = 1 +        GF_CLI_LIST_PEERS = 1, +        GF_CLI_LIST_POOL_NODES = 2  } ;  enum gf1_cli_get_volume { @@ -74,7 +75,9 @@ enum gf1_cli_gsync_set {          GF_GSYNC_OPTION_TYPE_STOP,          GF_GSYNC_OPTION_TYPE_CONFIG,          GF_GSYNC_OPTION_TYPE_STATUS, -        GF_GSYNC_OPTION_TYPE_ROTATE +        GF_GSYNC_OPTION_TYPE_ROTATE, +        GF_GSYNC_OPTION_TYPE_DELETE, +        GF_GSYNC_OPTION_TYPE_CREATE  };  enum gf1_cli_stats_op { diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c index 6440efa153e..29a20f50760 100644 --- a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c @@ -25,6 +25,24 @@  #include <signal.h> +static int +dict_get_param (dict_t *dict, char *key, char **param); + +static int +glusterd_get_statefile_name (glusterd_volinfo_t *volinfo, char *slave, +                             char *conf_path, char **statefile); + +static int +glusterd_get_slave_details_confpath (glusterd_volinfo_t *volinfo, dict_t *dict, +                                     char **slave_ip, char **slave_vol, +                                     char **conf_path); + +static int +glusterd_get_slave_info (dict_t *dict, char **slave_ip, char **slave_vol); + +static int +glusterd_gsync_read_frm_status (char *path, char *buf, size_t blen); +  static char *gsync_reserved_opts[] = {          "gluster-command-dir",          "pid-file", @@ -41,6 +59,148 @@ static char *gsync_reserved_opts[] = {  };  int +__glusterd_handle_sys_exec (rpcsvc_request_t *req) +{ +        int32_t                 ret     = 0; +        dict_t                  *dict   = NULL; +        gf_cli_req              cli_req = {{0},}; +        glusterd_op_t           cli_op = GD_OP_SYS_EXEC; +        glusterd_conf_t         *priv   = NULL; +        char                    *host_uuid = NULL; +        char                    err_str[2048] = {0,}; +        xlator_t                *this = NULL; + +        GF_ASSERT (req); + +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT (priv); + +        ret = xdr_to_generic (req->msg[0], &cli_req, +                              (xdrproc_t)xdr_gf_cli_req); +        if (ret < 0) { +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        if (cli_req.dict.dict_len) { +                dict = dict_new (); +                if (!dict) +                        goto out; + + +                ret = dict_unserialize (cli_req.dict.dict_val, +                                        cli_req.dict.dict_len, +                                        &dict); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to " +                                "unserialize req-buffer to dictionary"); +                        snprintf (err_str, sizeof (err_str), "Unable to decode " +                                  "the command"); +                        goto out; +               } else { +                        dict->extra_stdfree = cli_req.dict.dict_val; +                } + +                host_uuid = gf_strdup (uuid_utoa(MY_UUID)); +                if (host_uuid == NULL) { +                        snprintf (err_str, sizeof (err_str), "Failed to get " +                                  "the uuid of local glusterd"); +                        ret = -1; +                        goto out; +                } + +                ret = dict_set_dynstr (dict, "host-uuid", host_uuid); +                if (ret) +                        goto out; +        } + +        ret = glusterd_op_begin_synctask (req, cli_op, dict); + +out: +        if (ret) { +                if (err_str[0] == '\0') +                        snprintf (err_str, sizeof (err_str), +                                  "Operation failed"); +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     dict, err_str); +        } +        return ret; +} + +int +__glusterd_handle_copy_file (rpcsvc_request_t *req) +{ +        int32_t                 ret     = 0; +        dict_t                  *dict   = NULL; +        gf_cli_req              cli_req = {{0},}; +        glusterd_op_t           cli_op = GD_OP_COPY_FILE; +        glusterd_conf_t         *priv   = NULL; +        char                    *host_uuid = NULL; +        char                    err_str[2048] = {0,}; +        xlator_t                *this = NULL; + +        GF_ASSERT (req); + +        this = THIS; +        GF_ASSERT (this); +        priv = this->private; +        GF_ASSERT (priv); + +        ret = xdr_to_generic (req->msg[0], &cli_req, +                              (xdrproc_t)xdr_gf_cli_req); +        if (ret < 0) { +                req->rpc_err = GARBAGE_ARGS; +                goto out; +        } + +        if (cli_req.dict.dict_len) { +                dict = dict_new (); +                if (!dict) +                        goto out; + + +                ret = dict_unserialize (cli_req.dict.dict_val, +                                        cli_req.dict.dict_len, +                                        &dict); +                if (ret < 0) { +                        gf_log (this->name, GF_LOG_ERROR, "failed to " +                                "unserialize req-buffer to dictionary"); +                        snprintf (err_str, sizeof (err_str), "Unable to decode " +                                  "the command"); +                        goto out; +               } else { +                        dict->extra_stdfree = cli_req.dict.dict_val; +                } + +                host_uuid = gf_strdup (uuid_utoa(MY_UUID)); +                if (host_uuid == NULL) { +                        snprintf (err_str, sizeof (err_str), "Failed to get " +                                  "the uuid of local glusterd"); +                        ret = -1; +                        goto out; +                } + +                ret = dict_set_dynstr (dict, "host-uuid", host_uuid); +                if (ret) +                        goto out; +        } + +        ret = glusterd_op_begin_synctask (req, cli_op, dict); + +out: +        if (ret) { +                if (err_str[0] == '\0') +                        snprintf (err_str, sizeof (err_str), +                                  "Operation failed"); +                ret = glusterd_op_send_cli_response (cli_op, ret, 0, req, +                                                     dict, err_str); +        } +        return ret; +} + +int  __glusterd_handle_gsync_set (rpcsvc_request_t *req)  {          int32_t                 ret     = 0; @@ -104,13 +264,13 @@ __glusterd_handle_gsync_set (rpcsvc_request_t *req)          ret = dict_get_str (dict, "master", &master);          if (ret < 0) {                  gf_log (this->name, GF_LOG_INFO, "master not found, while " -                        "handling"GEOREP" options"); +                        "handling "GEOREP" options");                  master = "(No Master)";          }          ret = dict_get_str (dict, "slave", &slave);          if (ret < 0) { -                gf_log (this->name, GF_LOG_INFO, "slave not not found, while" +                gf_log (this->name, GF_LOG_INFO, "slave not found, while"                          "handling "GEOREP" options");                  slave = "(No Slave)";          } @@ -124,6 +284,10 @@ __glusterd_handle_gsync_set (rpcsvc_request_t *req)          }          switch (type) { +        case GF_GSYNC_OPTION_TYPE_CREATE: +                strncpy (operation, "create", sizeof (operation)); +                cli_op = GD_OP_GSYNC_CREATE; +                break;          case GF_GSYNC_OPTION_TYPE_START:                  strncpy (operation, "start", sizeof (operation)); @@ -140,12 +304,9 @@ __glusterd_handle_gsync_set (rpcsvc_request_t *req)          case GF_GSYNC_OPTION_TYPE_STATUS:                  strncpy (operation, "status", sizeof (operation));                  break; -        case GF_GSYNC_OPTION_TYPE_ROTATE: -                strncpy (operation, "rotate", sizeof(operation)); -                break;          } -        ret = glusterd_op_begin_synctask (req, GD_OP_GSYNC_SET, dict); +        ret = glusterd_op_begin_synctask (req, cli_op, dict);  out:          if (ret) { @@ -158,6 +319,17 @@ out:          return ret;  } +int +glusterd_handle_sys_exec (rpcsvc_request_t *req) +{ +        return glusterd_big_locked_handler (req, __glusterd_handle_sys_exec); +} + +int +glusterd_handle_copy_file (rpcsvc_request_t *req) +{ +        return glusterd_big_locked_handler (req, __glusterd_handle_copy_file); +}  int  glusterd_handle_gsync_set (rpcsvc_request_t *req) @@ -448,7 +620,7 @@ _fcbk_conftodict (char *resbuf, size_t blen, FILE *fp, void *data)  }  static int -glusterd_gsync_get_config (char *master, char *slave, char *gl_workdir, dict_t *dict) +glusterd_gsync_get_config (char *master, char *slave, char *conf_path, dict_t *dict)  {          /* key + value, where value must be able to accommodate a path */          char resbuf[256 + PATH_MAX] = {0,}; @@ -456,7 +628,7 @@ glusterd_gsync_get_config (char *master, char *slave, char *gl_workdir, dict_t *          runinit (&runner);          runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); +        runner_argprintf (&runner, "%s", conf_path);          runner_argprintf (&runner, ":%s", master);          runner_add_args  (&runner, slave, "--config-get-all", NULL); @@ -466,13 +638,13 @@ glusterd_gsync_get_config (char *master, char *slave, char *gl_workdir, dict_t *  static int  glusterd_gsync_get_param_file (char *prmfile, const char *param, char *master, -                               char *slave, char *gl_workdir) +                               char *slave, char *conf_path)  {          runner_t            runner = {0,};          runinit (&runner);          runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); +        runner_argprintf (&runner, "%s", conf_path);          runner_argprintf (&runner, ":%s", master);          runner_add_args  (&runner, slave, "--config-get", NULL);          runner_argprintf (&runner, "%s-file", param); @@ -481,83 +653,14 @@ glusterd_gsync_get_param_file (char *prmfile, const char *param, char *master,  }  static int -glusterd_gsync_get_session_owner (char *master, char *slave, char *session_owner, -                                  char *gl_workdir) -{ -        runner_t runner = {0,}; - -        runinit(&runner); -        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); -        runner_argprintf (&runner, ":%s", master); -        runner_add_args  (&runner, slave, "--config-get", "session-owner", -                          NULL); - -        return glusterd_query_extutil (session_owner, &runner); -} - -/* check whether @slave is local or remote. normalized - * urls starting with ssh are considered to be remote - * @returns - *    1 if slave is remote - *    0 is slave is local - */ -static int -glusterd_gsync_slave_is_remote (char *slave) -{ -        int   ret     = 0; -        char *ssh_pos = NULL; - -        ssh_pos = strstr(slave, "ssh://"); -        if ( ssh_pos && ((ssh_pos - slave) == 0) ) -                ret = 1; - -        return ret; -} - -static int -glusterd_gsync_get_slave_log_file (char *master, char *slave, char *log_file) -{ -        int              ret        = -1; -        runner_t         runner     = {0,}; -        char uuid_str[64]           = {0,}; -        glusterd_conf_t *priv       = NULL; -        char            *gl_workdir = NULL; - -        GF_ASSERT(THIS); -        GF_ASSERT(THIS->private); - -        priv = THIS->private; - -        GF_VALIDATE_OR_GOTO("gsyncd", master, out); -        GF_VALIDATE_OR_GOTO("gsyncd", slave, out); - -        gl_workdir = priv->workdir; - -        /* get the session owner for the master-slave session */ -        ret = glusterd_gsync_get_session_owner (master, slave, uuid_str, -                                                gl_workdir); -        if (ret) -                goto out; - -        /* get the log file for the slave */ -        runinit(&runner); -        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, gl_workdir); -        runner_argprintf (&runner, "--session-owner=%s", uuid_str); -        runner_add_args  (&runner, slave, "--config-get", "log-file", NULL); - -        ret = glusterd_query_extutil (log_file, &runner); - - out: -        return ret; -} - -static int -gsyncd_getpidfile (char *master, char *slave, char *pidfile) +gsyncd_getpidfile (char *master, char *slave, char *pidfile, char *conf_path)  {          int                ret             = -1;          glusterd_conf_t    *priv  = NULL; +        char               *confpath = NULL; +        char                conf_buf[PATH_MAX] = ""; +        struct stat         stbuf = {0,}; +          GF_ASSERT (THIS);          GF_ASSERT (THIS->private); @@ -567,8 +670,22 @@ gsyncd_getpidfile (char *master, char *slave, char *pidfile)          GF_VALIDATE_OR_GOTO ("gsync", master, out);          GF_VALIDATE_OR_GOTO ("gsync", slave, out); +        ret = lstat (conf_path, &stbuf); +        if (!ret) { +                gf_log ("", GF_LOG_DEBUG, "Using passed config template(%s).", +                        conf_path); +                confpath = conf_path; +        } else { +                ret = snprintf (conf_buf, sizeof(conf_buf) - 1, +                                "%s/"GSYNC_CONF_TEMPLATE, priv->workdir); +                conf_buf[ret] = '\0'; +                confpath = conf_buf; +                gf_log ("", GF_LOG_DEBUG, "Using default config template(%s).", +                        confpath); +        } +          ret = glusterd_gsync_get_param_file (pidfile, "pid", master, -                                              slave, priv->workdir); +                                              slave, confpath);          if (ret == -1) {                  ret = -2;                  gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); @@ -582,32 +699,6 @@ gsyncd_getpidfile (char *master, char *slave, char *pidfile)  }  static int -glusterd_gsyncd_getlogfile (char *master, char *slave, char *log_file) -{ -        int                ret             = -1; -        glusterd_conf_t    *priv  = NULL; - -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; - -        GF_VALIDATE_OR_GOTO ("gsync", master, out); -        GF_VALIDATE_OR_GOTO ("gsync", slave, out); - -        ret = glusterd_gsync_get_param_file (log_file, "log", master, -                                              slave, priv->workdir); -        if (ret == -1) { -                ret = -2; -                gf_log ("", GF_LOG_WARNING, "failed to gsyncd logfile"); -                goto out; -        } - - out: -        return ret; -} - -static int  gsync_status_byfd (int fd)  {          GF_ASSERT (fd >= -1); @@ -624,12 +715,12 @@ gsync_status_byfd (int fd)   * return -1 when not running   */  int -gsync_status (char *master, char *slave, int *status) +gsync_status (char *master, char *slave, char *conf_path, int *status)  {          char pidfile[PATH_MAX] = {0,};          int  fd                = -1; -        fd = gsyncd_getpidfile (master, slave, pidfile); +        fd = gsyncd_getpidfile (master, slave, pidfile, conf_path);          if (fd == -2)                  return -1; @@ -666,10 +757,38 @@ out:  }  static int -gsync_verify_config_options (dict_t *dict, char **op_errstr) +glusterd_verify_gsyncd_spawn (char *master, char *slave) +{ +        int                 ret = 0; +        runner_t            runner = {0,}; + +        runinit (&runner); +        runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", +                         "--verify", "spawning", NULL); +        runner_argprintf (&runner, ":%s", master); +        runner_add_args  (&runner, slave, NULL); +        runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); +        ret = runner_start (&runner); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "spawning child failed"); +                ret = -1; +                goto out; +        } + +        if (runner_end (&runner) != 0) +                ret = -1; + +out: +        gf_log ("", GF_LOG_DEBUG, "returning %d", ret); +        return ret; +} + +static int +gsync_verify_config_options (dict_t *dict, char **op_errstr, char *volname)  {          char  **resopt    = NULL;          int     i         = 0; +        int     ret       = -1;          char   *subop     = NULL;          char   *slave     = NULL;          char   *op_name   = NULL; @@ -699,6 +818,12 @@ gsync_verify_config_options (dict_t *dict, char **op_errstr)          }          if (runcmd (GSYNCD_PREFIX"/gsyncd", "--config-check", op_name, NULL)) { +                ret = glusterd_verify_gsyncd_spawn (volname, slave); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to spawn gsyncd"); +                        return 0; +                } +                  gf_log ("", GF_LOG_WARNING, "Invalid option %s", op_name);                  *op_errstr = gf_strdup ("Invalid option"); @@ -748,30 +873,76 @@ gsync_verify_config_options (dict_t *dict, char **op_errstr)  static int  glusterd_get_gsync_status_mst_slv (glusterd_volinfo_t *volinfo, -                                   char *slave, dict_t *rsp_dict, char *node); +                                   char *slave, char *conf_path, +                                   dict_t *rsp_dict, char *node);  static int  _get_status_mst_slv (dict_t *this, char *key, data_t *value, void *data)  {          glusterd_gsync_status_temp_t  *param = NULL;          char                          *slave = NULL; -        int                           ret = 0; +        char                          *slave_buf = NULL; +        char                          *slave_vol = NULL; +        char                          *tmp       = NULL; +        char                          *save_ptr  = NULL; +        char                           conf_path[PATH_MAX] = ""; +        int                           ret = -1; +        glusterd_conf_t              *priv = NULL;          param = (glusterd_gsync_status_temp_t *)data;          GF_ASSERT (param);          GF_ASSERT (param->volinfo); +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                goto out; +        } +          slave = strchr(value->data, ':'); -        if (slave) +        if (slave) {                  slave ++; -        else +                slave_buf = gf_strdup (slave); +                if (!slave_buf) { +                        gf_log ("", GF_LOG_ERROR, +                                "Failed to gf_strdup"); +                        ret = -1; +                        goto out; +                } +        } else                  return 0; +        tmp  = strtok_r (slave_buf, ":", &save_ptr); +        while (tmp) { +                slave_vol = tmp; +                tmp  = strtok_r (NULL, ":", &save_ptr); +        } + +        if (!slave_vol) { +                gf_log ("", GF_LOG_ERROR, "Invalid slave name"); +                ret = -1; +                goto out; +        } + +        ret = snprintf (conf_path, sizeof(conf_path) - 1, +                        "%s/"GEOREP"/%s-%s/gsyncd.conf", +                        priv->workdir, param->volinfo->volname, +                        slave_vol); +        conf_path[ret] = '\0'; +          ret = glusterd_get_gsync_status_mst_slv(param->volinfo, -                                                slave, param->rsp_dict, +                                                slave, conf_path, +                                                param->rsp_dict,                                                  param->node); -        return 0; +out: + +        if (slave_buf) +                GF_FREE(slave_buf); + +        gf_log ("", GF_LOG_DEBUG, "Returning %d.", ret); +        return ret;  } @@ -792,19 +963,22 @@ static int  glusterd_remove_slave_in_info (glusterd_volinfo_t *volinfo, char *slave,                                 char **op_errstr)  { +        int   zero_slave_entries = _gf_true;          int   ret = 0;          char *slavekey = NULL;          GF_ASSERT (volinfo);          GF_ASSERT (slave); -        ret = glusterd_get_slave (volinfo, slave, &slavekey); -        if (ret < 0) { -                ret++; -                goto out; -        } - -        dict_del (volinfo->gsync_slaves, slavekey); +        do { +                ret = glusterd_get_slave (volinfo, slave, &slavekey); +                if (ret < 0 && zero_slave_entries) { +                        ret++; +                        goto out; +                } +                zero_slave_entries = _gf_false; +                dict_del (volinfo->gsync_slaves, slavekey); +        } while (ret >= 0);          ret = glusterd_store_volinfo (volinfo,                                        GLUSTERD_VOLINFO_VER_AC_INCREMENT); @@ -859,6 +1033,7 @@ glusterd_gsync_get_uuid (char *slave, glusterd_volinfo_t *vol,  static int  glusterd_check_gsync_running_local (char *master, char *slave, +                                    char *conf_path,                                      gf_boolean_t *is_run)  {          int                 ret    = -1; @@ -869,7 +1044,7 @@ glusterd_check_gsync_running_local (char *master, char *slave,          GF_ASSERT (is_run);          *is_run = _gf_false; -        ret = gsync_status (master, slave, &ret_status); +        ret = gsync_status (master, slave, conf_path, &ret_status);          if (ret == 0 && ret_status == 0) {                  *is_run = _gf_true;          } else if (ret == -1) { @@ -886,7 +1061,8 @@ glusterd_check_gsync_running_local (char *master, char *slave,  static int  glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave, -                              char *host_uuid, char **op_errstr) +                              char *host_uuid, char **op_errstr, +                              gf_boolean_t is_force)  {          int    ret = 0;          int    maxslv = 0; @@ -909,7 +1085,8 @@ glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave,          case -1:                                  break;          default: -                GF_ASSERT (ret > 0); +                if (!is_force) +                        GF_ASSERT (ret > 0);                  ret = dict_get_str (volinfo->gsync_slaves, slavekey, &slaveentry);                  GF_ASSERT (ret == 0); @@ -918,13 +1095,23 @@ glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave,                   * assert an uuid mismatch                   */                  t = strtail (slaveentry, host_uuid); -                GF_ASSERT (!t || *t != ':'); +                if (!is_force) +                        GF_ASSERT (!t || *t != ':'); + +                if (is_force) { +                        gf_log ("", GF_LOG_DEBUG, GEOREP" has already been " +                                "invoked for the %s (master) and %s (slave)." +                                " Allowing without saving info again due to" +                                " force command.", volinfo->volname, slave); +                        ret = 0; +                        goto out; +                }                  gf_log ("", GF_LOG_ERROR, GEOREP" has already been invoked for "                                            "the %s (master) and %s (slave) "                                            "from a different machine",                                             volinfo->volname, slave); -                *op_errstr = gf_strdup (GEOREP" already running in an an" +                *op_errstr = gf_strdup (GEOREP" already running in "                                          "another machine");                  ret = -1;                  goto out; @@ -957,23 +1144,26 @@ glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *slave,          return ret;  } -  static int  glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo, -                                        char *slave, char **op_errstr) +                                        char *slave, char *conf_path, +                                        char *statefile, char **op_errstr, +                                        gf_boolean_t is_force)  {          int                     ret = -1;          gf_boolean_t            is_running = _gf_false;          char                    msg[2048] = {0};          uuid_t                  uuid = {0}; -        glusterd_conf_t         *priv = NULL; -        xlator_t                *this = NULL; +        glusterd_conf_t        *priv = NULL; +        xlator_t               *this = NULL; +        struct stat             stbuf = {0,};          this = THIS;          GF_ASSERT (volinfo);          GF_ASSERT (slave);          GF_ASSERT (op_errstr); +        GF_ASSERT (conf_path);          GF_ASSERT (this && this->private);          priv  = this->private; @@ -983,26 +1173,56 @@ glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo,                            "before "GEOREP" start", volinfo->volname);                  goto out;          } + +        ret = lstat (statefile, &stbuf); +        if (ret) { +                snprintf (msg, sizeof (msg), "Session between %s and %s has" +                          " not been created. Please create session and retry.", +                          volinfo->volname, slave); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                *op_errstr = gf_strdup (msg); +                goto out; +        } + +        /* Check if the gsync slave info is stored. If not +         * session has not been created */ +        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); +        if (ret) { +                snprintf (msg, sizeof (msg), "Session between %s and %s has" +                          " not been created. Please create session and retry.", +                          volinfo->volname, slave); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                goto out; +        } + +        if (is_force) { +                ret = 0; +                goto out; +        } +          /*Check if the gsync is already started in cmd. inited host           * If so initiate add it into the glusterd's priv*/ -        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -        if ((ret == 0) && (uuid_compare (MY_UUID, uuid) == 0)) { -                ret = glusterd_check_gsync_running_local (volinfo->volname, -                                                          slave, &is_running); -                if (ret) { -                        snprintf (msg, sizeof (msg), GEOREP" start option " -                                  "validation failed "); -                        goto out; -                } -                if (_gf_true == is_running) { -                        snprintf (msg, sizeof (msg), GEOREP " session between" -                                  " %s & %s already started", volinfo->volname, -                                  slave); -                        ret = -1; -                        goto out; -                } +        ret = glusterd_check_gsync_running_local (volinfo->volname, +                                                  slave, conf_path, +                                                  &is_running); +        if (ret) { +                snprintf (msg, sizeof (msg), GEOREP" start option " +                          "validation failed "); +                goto out; +        } +        if (_gf_true == is_running) { +                snprintf (msg, sizeof (msg), GEOREP " session between" +                          " %s & %s already started", volinfo->volname, +                          slave); +                ret = -1; +                goto out; +        } + +        ret = glusterd_verify_gsyncd_spawn (volinfo->volname, slave); +        if (ret) { +                snprintf (msg, sizeof (msg), "Unable to spawn gsyncd"); +                gf_log ("", GF_LOG_ERROR, "%s", msg);          } -        ret = 0;  out:          if (ret && (msg[0] != '\0')) {                  *op_errstr = gf_strdup (msg); @@ -1028,11 +1248,13 @@ glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag)  static int  glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, -                                  char *slave, char **op_errstr) +                                  char *slave, char *conf_path, +                                  char **op_errstr)  { -        int                     ret = -1; -        char                    msg[2048] = {0}; -        uuid_t                  uuid = {0}; +        int        pfd               = -1; +        int        ret               = -1; +        char       msg[2048]         = {0}; +        char       pidfile[PATH_MAX] = {0,};          GF_ASSERT (THIS && THIS->private);          GF_ASSERT (volinfo); @@ -1045,12 +1267,25 @@ glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo,                  goto out;          } -        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -        if (ret == -1) { -                snprintf (msg, sizeof (msg), GEOREP" session between %s & %s" -                          " not active", volinfo->volname, slave); + +        pfd = gsyncd_getpidfile (volinfo->volname, slave, pidfile, conf_path); +        if (pfd == -2) { +                gf_log ("", GF_LOG_ERROR, GEOREP" stop validation " +                        "failed for %s & %s", volinfo->volname, slave); +                ret = -1;                  goto out;          } +        if (gsync_status_byfd (pfd) == -1) { +                snprintf (msg, sizeof (msg), GEOREP" session b/w %s & %s is not" +                          " running on this node.", volinfo->volname, slave); +                gf_log ("", GF_LOG_ERROR, "%s", msg); +                ret = -1; +                /* monitor gsyncd already dead */ +                goto out; +        } + +        if (pfd < 0) +                goto out;          ret = 0;  out: @@ -1070,6 +1305,18 @@ glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr)          gf_boolean_t       exists = _gf_false;          glusterd_volinfo_t *volinfo = NULL;          int                ret = 0; +        char               *conf_path = NULL; +        char               *slave_ip = NULL; +        char               *slave_vol = NULL; +        glusterd_conf_t    *priv = NULL; + +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                *op_errstr = gf_strdup ("glusterd defunct"); +                goto out; +        }          ret = dict_get_str (dict, "master", &volname);          if (ret < 0) { @@ -1094,7 +1341,17 @@ glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr)                  goto out;          } - out: +        ret = glusterd_get_slave_details_confpath (volinfo, dict, &slave_ip, +                                                   &slave_vol, &conf_path); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), +                          "Unable to fetch slave  or confpath details."); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                ret = -1; +                goto out; +        } + +out:          gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret; @@ -1103,7 +1360,7 @@ glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr)  int  glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, -                            char **master, char **slave) +                            char **master, char **slave, char **host_uuid)  {          int             ret = -1; @@ -1128,9 +1385,460 @@ glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr,                  }          } +        if (host_uuid) { +                ret = dict_get_str (dict, "host-uuid", host_uuid); +                if (ret < 0) { +                        gf_log ("", GF_LOG_WARNING, "host_uuid not found"); +                        *op_errstr = gf_strdup ("host_uuid not found"); +                        goto out; +                } +        } + +        ret = 0; +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_op_stage_sys_exec (dict_t *dict, char **op_errstr) +{ +        char             errmsg[PATH_MAX]          = ""; +        char            *command                   = NULL; +        char             command_path[PATH_MAX]    = ""; +        struct stat      st                        = {0,}; +        int              ret                       = -1; + +        ret = dict_get_str (dict, "command", &command); +        if (ret) { +                strcpy (errmsg, "internal error"); +                gf_log ("", GF_LOG_ERROR, +                        "Unable to get command from dict"); +                goto out; +        } + +        /* enforce local occurrence of the command */ +        if (strchr (command, '/')) { +                strcpy (errmsg, "invalid command name"); +                ret = -1; +                goto out; +        } + +        sprintf (command_path, GSYNCD_PREFIX"/peer_%s", command); +        /* check if it's executable */ +        ret = access (command_path, X_OK); +        if (!ret) +                /* check if it's a regular file */ +                ret = stat (command_path, &st); +        if (!ret && !S_ISREG (st.st_mode)) +                ret = -1; + +out: +        if (ret) { +                if (errmsg[0] == '\0') +                        snprintf (errmsg, sizeof (errmsg), "%s not found.", +                                  command); +                *op_errstr = gf_strdup (errmsg); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +        } + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_op_stage_copy_file (dict_t *dict, char **op_errstr) +{ +        char             abs_filename[PATH_MAX] = ""; +        char             errmsg[PATH_MAX]       = ""; +        char            *filename               = NULL; +        char            *host_uuid              = NULL; +        char             uuid_str [64]          = {0}; +        int              ret                    = -1; +        glusterd_conf_t *priv                   = NULL; +        struct stat      stbuf                  = {0,}; + +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                *op_errstr = gf_strdup ("glusterd defunct"); +                goto out; +        } + +        ret = dict_get_str (dict, "host-uuid", &host_uuid); +        if (ret < 0) { +                gf_log ("", GF_LOG_ERROR, "Unable to fetch" +                        " host-uuid from dict."); +                goto out; +        } + +        uuid_utoa_r (MY_UUID, uuid_str); +        if (!strcmp (uuid_str, host_uuid)) { +                ret = dict_get_str (dict, "source", &filename); +                if (ret < 0) { +                        gf_log ("", GF_LOG_ERROR, "Unable to fetch" +                                " filename from dict."); +                        *op_errstr = gf_strdup ("command unsuccessful"); +                        goto out; +                } +                snprintf (abs_filename, sizeof(abs_filename), +                          "%s/%s", priv->workdir, filename); + +                ret = lstat (abs_filename, &stbuf); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Source file" +                                  " does not exist in %s", priv->workdir); +                        *op_errstr = gf_strdup (errmsg); +                        goto out; +                } + +                if (!S_ISREG(stbuf.st_mode)) { +                        snprintf (errmsg, sizeof (errmsg), "Source file" +                                 " is not a regular file."); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        ret = -1; +                        goto out; +                } +        } + +        ret = 0; +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +static int +glusterd_get_statefile_name (glusterd_volinfo_t *volinfo, char *slave, +                             char *conf_path, char **statefile) +{ +        glusterd_conf_t *priv = NULL; +        int              ret = -1; +        char            *master    = NULL; +        char            *buf       = NULL; +        dict_t          *confd = NULL; +        char            *confpath = NULL; +        char             conf_buf[PATH_MAX] = ""; +        struct stat      stbuf = {0,}; + +        GF_ASSERT (THIS); +        GF_ASSERT (THIS->private); +        GF_ASSERT (volinfo); + +        master = volinfo->volname; + +        confd = dict_new (); +        if (!confd) { +                gf_log ("", GF_LOG_ERROR, "Unable to create new dict"); +                goto out; +        } + +        priv = THIS->private; + +        ret = lstat (conf_path, &stbuf); +        if (!ret) { +                gf_log ("", GF_LOG_DEBUG, "Using passed config template(%s).", +                        conf_path); +                confpath = conf_path; +        } else { +                ret = snprintf (conf_buf, sizeof(conf_buf) - 1, +                                "%s/"GSYNC_CONF_TEMPLATE, priv->workdir); +                conf_buf[ret] = '\0'; +                confpath = conf_buf; +                gf_log ("", GF_LOG_DEBUG, "Using default config template(%s).", +                        confpath); +        } + +        ret = glusterd_gsync_get_config (master, slave, confpath, +                                         confd); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get configuration data" +                        "for %s(master), %s(slave)", master, slave); +                goto out; + +        } + +        ret = dict_get_param (confd, "state_file", &buf); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to get state_file's name."); +                goto out; +        } + +        *statefile = gf_strdup(buf); +        if (!*statefile) { +                gf_log ("", GF_LOG_ERROR, "Unable to gf_strdup."); +                ret = -1; +                goto out; +        } + +        ret = 0; + out: +        if (confd) +                dict_destroy (confd); + +        gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); +        return ret; +} + +static int +glusterd_create_status_file (char *master, char *slave, +                             char *slave_vol, char *status) +{ +        int                ret    = -1; +        runner_t           runner = {0,}; +        glusterd_conf_t   *priv   = NULL; + +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                goto out; +        } + +        if (!status) { +                gf_log ("", GF_LOG_ERROR, "Status Empty"); +                goto out; +        } +        gf_log ("", GF_LOG_DEBUG, "slave = %s", slave); + +        runinit (&runner); +        runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "--create", +                         status, "-c", NULL); +        runner_argprintf (&runner, "%s/"GEOREP"/%s-%s/gsyncd.conf", +                          priv->workdir, master, slave_vol); +        runner_argprintf (&runner, ":%s", master); +        runner_add_args  (&runner, slave, NULL); +        synclock_unlock (&priv->big_lock); +        ret = runner_run (&runner); +        synclock_lock (&priv->big_lock); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Creating status file failed."); +                ret = -1; +                goto out; +        } + +        ret = 0; +out: +        gf_log ("", GF_LOG_DEBUG, "returning %d", ret); +        return ret; +} + +static int +glusterd_verify_slave (char *volname, char *slave_ip, char *slave, +                       char **op_errstr) +{ +        int32_t         ret     = -1; +        runner_t        runner    = {0,}; +        glusterd_conf_t *priv   = NULL; +        char            log_file_path[PATH_MAX] = ""; +        char            buf[PATH_MAX]           = ""; + +        GF_ASSERT (volname); +        GF_ASSERT (slave_ip); +        GF_ASSERT (slave); + +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                goto out; +        } + +        snprintf (log_file_path, sizeof(log_file_path), +                  DEFAULT_LOG_FILE_DIRECTORY"/create_verify_log"); + +        runinit (&runner); +        runner_add_args  (&runner, GSYNCD_PREFIX"/gverify.sh", NULL); +        runner_argprintf (&runner, "%s", volname); +        runner_argprintf (&runner, "%s", slave_ip); +        runner_argprintf (&runner, "%s", slave); +        runner_argprintf (&runner, "%s", log_file_path); +        runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); +        synclock_unlock (&priv->big_lock); +        ret = runner_run (&runner); +        synclock_lock (&priv->big_lock); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Not a valid slave"); +                ret = glusterd_gsync_read_frm_status (log_file_path, +                                                      buf, sizeof(buf)); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to read from %s", +                                log_file_path); +                        goto out; +                } +                *op_errstr = gf_strdup (buf); +                ret = -1; +                goto out; +        } +        ret = 0; +out: +        unlink (log_file_path); +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int +glusterd_op_stage_gsync_create (dict_t *dict, char **op_errstr) +{ +        char               *down_peerstr              = NULL; +        char               *slave                     = NULL; +        char               *volname                   = NULL; +        char               *host_uuid                 = NULL; +        char               *statefile                 = NULL; +        char               *slave_ip                  = NULL; +        char               *slave_vol                 = NULL; +        char               *conf_path                 = NULL; +        char                errmsg[PATH_MAX]          = ""; +        char                common_pem_file[PATH_MAX] = ""; +        char                uuid_str [64]             = ""; +        int                 ret                       = -1; +        int                 is_pem_push               = -1; +        gf_boolean_t        is_force                  = -1; +        gf_boolean_t        exists                    = _gf_false; +        glusterd_conf_t    *conf                      = NULL; +        glusterd_volinfo_t *volinfo                   = NULL; +        struct stat         stbuf                     = {0,}; +        xlator_t           *this                      = NULL; + +        this = THIS; +        GF_ASSERT (this); +        conf = this->private; +        GF_ASSERT (conf); + +        ret = glusterd_op_gsync_args_get (dict, op_errstr, &volname, +                                          &slave, &host_uuid); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to fetch arguments"); +                gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +                return -1; +        } + +        exists = glusterd_check_volume_exists (volname); +        ret = glusterd_volinfo_find (volname, &volinfo); +        if ((ret) || (!exists)) { +                gf_log ("", GF_LOG_WARNING, "volume name does not exist"); +                snprintf (errmsg, sizeof(errmsg), "Volume name %s does not" +                          " exist", volname); +                *op_errstr = gf_strdup (errmsg); +                gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +                return -1; +        } + +        is_force = dict_get_str_boolean (dict, "force", _gf_false); + +        ret = glusterd_get_slave_details_confpath (volinfo, dict, &slave_ip, +                                                   &slave_vol, &conf_path); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), +                          "Unable to fetch slave  or confpath details."); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                ret = -1; +                goto out; +        } + +        uuid_utoa_r (MY_UUID, uuid_str); +        if (!strcmp (uuid_str, host_uuid)) { +                ret = glusterd_are_vol_all_peers_up (volinfo, +                                                     &conf->peers, +                                                     &down_peerstr); +                if (ret == _gf_false) { +                        snprintf (errmsg, sizeof (errmsg), "Peer %s," +                                  " which is a part of %s volume, is" +                                  " down. Please bring up the peer and" +                                  " retry.", down_peerstr, +                                  volinfo->volname); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        *op_errstr = gf_strdup (errmsg); +                        GF_FREE (down_peerstr); +                        down_peerstr = NULL; +                        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +                        return -1; +                } + +                ret = glusterd_verify_slave (volname, slave_ip, slave_vol, +                                             op_errstr); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, +                                "%s is not a valid slave volume.", +                                slave); +                        ret = -1; +                        goto out; +                } + +                ret = dict_get_int32 (dict, "push_pem", &is_pem_push); +                if (!ret && is_pem_push) { +                        snprintf (common_pem_file, sizeof(common_pem_file), +                                  "%s"GLUSTERD_COMMON_PEM_PUB_FILE, +                                  conf->workdir); + +                        ret = lstat (common_pem_file, &stbuf); +                        if (ret) { +                                snprintf (errmsg, sizeof (errmsg), "%s" +                                          " required for push-pem is" +                                          " not present.", common_pem_file); +                                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                                ret = -1; +                                goto out; +                        } + +                        if (!S_ISREG(stbuf.st_mode)) { +                                snprintf (errmsg, sizeof (errmsg), "%s" +                                          " required for push-pem is" +                                          " not a regular file.", +                                          common_pem_file); +                                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                                ret = -1; +                                goto out; +                        } +                } +        } + +        ret = glusterd_get_statefile_name (volinfo, slave, conf_path, &statefile); +        if (ret) { +                if (!strstr(slave, "::")) +                        snprintf (errmsg, sizeof (errmsg), +                                  "%s is not a valid slave url.", slave); +                else +                        snprintf (errmsg, sizeof (errmsg), "Unable to get " +                                  "statefile's name"); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out; +        } + +        ret = lstat (statefile, &stbuf); +        if (!ret) { +                snprintf (errmsg, sizeof (errmsg), "Session between %s" +                          " and %s is already created.", +                          volinfo->volname, slave); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                ret = -1; +                goto out; +        } + +        ret = dict_set_str (dict, "statefile", statefile); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to store statefile path"); +                goto out; +        } + +        ret = glusterd_verify_gsyncd_spawn (volinfo->volname, slave); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), "Unable to spawn gsyncd"); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out; +        }          ret = 0;  out: + +        if (is_force) +                ret = 0; + +        if (ret && errmsg[0] != '\0') +                *op_errstr = gf_strdup (errmsg); +          gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret;  } @@ -1142,11 +1850,29 @@ glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr)          int                     type    = 0;          char                    *volname = NULL;          char                    *slave   = NULL; +        char                    *slave_ip = NULL; +        char                    *slave_vol = NULL; +        char                    *down_peerstr = NULL; +        char                    *statefile    = NULL; +        char                    *path_list    = NULL; +        char                    *conf_path    = NULL;          gf_boolean_t            exists   = _gf_false;          glusterd_volinfo_t      *volinfo = NULL;          char                    errmsg[PATH_MAX] = {0,};          dict_t                  *ctx = NULL; +        gf_boolean_t            is_force = 0; +        gf_boolean_t            is_running = _gf_false; +        uuid_t                  uuid = {0}; +        char                    uuid_str [64] = {0}; +        char                    *host_uuid = NULL; +        xlator_t                *this = NULL; +        glusterd_conf_t         *conf = NULL; +        struct stat             stbuf = {0,}; +        this = THIS; +        GF_ASSERT (this); +        conf = this->private; +        GF_ASSERT (conf);          ret = dict_get_int32 (dict, "type", &type);          if (ret < 0) { @@ -1155,23 +1881,13 @@ glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr)                  goto out;          } -        switch (type) { -        case GF_GSYNC_OPTION_TYPE_STATUS: +        if (type == GF_GSYNC_OPTION_TYPE_STATUS) {                  ret = glusterd_verify_gsync_status_opts (dict, op_errstr); - -                goto out; -        case GF_GSYNC_OPTION_TYPE_CONFIG: -                ret = gsync_verify_config_options (dict, op_errstr); - -                goto out; - -        case GF_GSYNC_OPTION_TYPE_ROTATE: -                /* checks same as status mode */ -                ret = glusterd_verify_gsync_status_opts(dict, op_errstr);                  goto out;          } -        ret = glusterd_op_gsync_args_get (dict, op_errstr, &volname, &slave); +        ret = glusterd_op_gsync_args_get (dict, op_errstr, +                                          &volname, &slave, NULL);          if (ret)                  goto out; @@ -1186,12 +1902,86 @@ glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr)                  goto out;          } +        ret = glusterd_get_slave_details_confpath (volinfo, dict, &slave_ip, +                                                   &slave_vol, &conf_path); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), +                          "Unable to fetch slave or confpath details."); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                ret = -1; +                goto out; +        } + +        ret = glusterd_get_statefile_name (volinfo, slave, conf_path, &statefile); +        if (ret) { +                if (!strstr(slave, "::")) +                        snprintf (errmsg, sizeof (errmsg), +                                  "%s is not a valid slave url.", slave); +                else +                        snprintf (errmsg, sizeof (errmsg), +                                  "Unable to get statefile's name"); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                ret = -1; +                goto out; +        } + +        ret = dict_set_str (dict, "statefile", statefile); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to store statefile path"); +                goto out; +        } + +        if ((type == GF_GSYNC_OPTION_TYPE_CONFIG) || +            (type == GF_GSYNC_OPTION_TYPE_DELETE)) { +                ret = lstat (statefile, &stbuf); +                if (ret) { +                        snprintf (errmsg, sizeof(errmsg), "Geo-replication" +                                  " session between %s and %s does not exist.", +                                  volinfo->volname, slave); +                        gf_log ("", GF_LOG_ERROR, "%s. statefile = %s", +                                errmsg, statefile); +                        *op_errstr = gf_strdup (errmsg); +                        ret = -1; +                        goto out; +                } +        } + +        is_force = dict_get_str_boolean (dict, "force", _gf_false); + +        /* Check if all peers that are a part of the volume are up or not */ +        if ((type == GF_GSYNC_OPTION_TYPE_DELETE) || +            ((type == GF_GSYNC_OPTION_TYPE_STOP) && !is_force)) { +                ret = dict_get_str (dict, "host-uuid", &host_uuid); +                if (ret < 0) +                        goto out; + +                uuid_utoa_r (MY_UUID, uuid_str); +                if (!strcmp (uuid_str, host_uuid)) { +                        ret = glusterd_are_vol_all_peers_up (volinfo, +                                                             &conf->peers, +                                                             &down_peerstr); +                        if (ret == _gf_false) { +                                snprintf (errmsg, sizeof (errmsg), "Peer %s," +                                          " which is a part of %s volume, is" +                                          " down. Please bring up the peer and" +                                          " retry.", down_peerstr, +                                          volinfo->volname); +                                *op_errstr = gf_strdup (errmsg); +                                ret = -1; +                                GF_FREE (down_peerstr); +                                down_peerstr = NULL; +                                goto out; +                        } +                } +        } +          switch (type) {          case GF_GSYNC_OPTION_TYPE_START:                  /* don't attempt to start gsync if replace-brick is                   * in progress */                  if (glusterd_is_rb_ongoing (volinfo)) { -                        snprintf (errmsg, sizeof(errmsg),"replace-brick is in" +                        snprintf (errmsg, sizeof(errmsg), "replace-brick is in"                                     " progress, not starting geo-replication");                          *op_errstr = gf_strdup (errmsg);                          ret = -1; @@ -1199,16 +1989,18 @@ glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr)                  }                  ret = glusterd_op_verify_gsync_start_options (volinfo, slave, -                                                              op_errstr); +                                                              conf_path, statefile, +                                                              op_errstr, is_force);                  if (ret)                          goto out;                  ctx = glusterd_op_get_ctx();                  if (ctx) { -                        /*gsyncd does a fuse mount to start the geo-rep session*/ +                        /* gsyncd does a fuse mount to start +                         * the geo-rep session */                          if (!glusterd_is_fuse_available ()) { -                                gf_log ("glusterd", GF_LOG_ERROR, "Unable to open" -                                        " /dev/fuse (%s), geo-replication start" -                                        " failed", strerror (errno)); +                                gf_log ("glusterd", GF_LOG_ERROR, "Unable to " +                                        "open /dev/fuse (%s), geo-replication " +                                        "start failed", strerror (errno));                                  snprintf (errmsg, sizeof(errmsg),                                            "fuse unvailable");                                  *op_errstr = gf_strdup (errmsg); @@ -1219,17 +2011,72 @@ glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr)                  break;          case GF_GSYNC_OPTION_TYPE_STOP: -                ret = glusterd_op_verify_gsync_running (volinfo, slave, -                                                        op_errstr); +                if (!is_force) { +                        ret = glusterd_op_verify_gsync_running (volinfo, slave, +                                                                conf_path, +                                                                op_errstr); +                        if (ret) { +                                ret = glusterd_get_local_brickpaths (volinfo, +                                                                     &path_list); +                                if (path_list) +                                        ret = -1; +                        } +                } +                break; + +        case GF_GSYNC_OPTION_TYPE_CONFIG: +                ret = gsync_verify_config_options (dict, op_errstr, volname); +                goto out; +                break; + +        case GF_GSYNC_OPTION_TYPE_DELETE: +                /* Check if the gsync session is still running +                 * If so ask the user to stop geo-replication first.*/ +                ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); +                if (ret) { +                        snprintf (errmsg, sizeof(errmsg), "Geo-replication" +                                  " session between %s and %s does not exist.", +                                  volinfo->volname, slave); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        *op_errstr = gf_strdup (errmsg); +                        ret = -1; +                        goto out; +                } else { +                        ret = glusterd_check_gsync_running_local (volinfo->volname, +                                                                  slave, conf_path, +                                                                  &is_running); +                        if (_gf_true == is_running) { +                                snprintf (errmsg, sizeof (errmsg), GEOREP +                                          " session between %s & %s is " +                                          "still active. Please stop the " +                                          "session and retry.", +                                          volinfo->volname, slave); +                                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                                *op_errstr = gf_strdup (errmsg); +                                ret = -1; +                                goto out; +                        } +                } + +                ret = glusterd_verify_gsyncd_spawn (volinfo->volname, slave); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), +                                  "Unable to spawn gsyncd"); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                } +                  break;          }  out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret;  }  static int -stop_gsync (char *master, char *slave, char **msg) +stop_gsync (char *master, char *slave, char **msg, +            char *conf_path, gf_boolean_t is_force)  {          int32_t         ret     = 0;          int             pfd     = -1; @@ -1241,19 +2088,16 @@ stop_gsync (char *master, char *slave, char **msg)          GF_ASSERT (THIS);          GF_ASSERT (THIS->private); -        pfd = gsyncd_getpidfile (master, slave, pidfile); -        if (pfd == -2) { +        pfd = gsyncd_getpidfile (master, slave, pidfile, conf_path); +        if (pfd == -2 && !is_force) {                  gf_log ("", GF_LOG_ERROR, GEOREP" stop validation "                          " failed for %s & %s", master, slave);                  ret = -1;                  goto out;          } -        if (gsync_status_byfd (pfd) == -1) { +        if (gsync_status_byfd (pfd) == -1 && !is_force) {                  gf_log ("", GF_LOG_ERROR, "gsyncd b/w %s & %s is not"                          " running", master, slave); -                if (msg) -                        *msg = gf_strdup ("Warning: "GEOREP" session was " -                                          "defunct at stop time");                  /* monitor gsyncd already dead */                  goto out;          } @@ -1288,16 +2132,21 @@ stop_gsync (char *master, char *slave, char **msg)  out:          sys_close (pfd); + +        if (is_force) +                ret = 0;          return ret;  }  static int  glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, -                                      dict_t *resp_dict); +                                      dict_t *resp_dict, char *path_list, +                                      char *conf_path, gf_boolean_t is_force);  static int  glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave, -                          dict_t *dict, dict_t *resp_dict, char **op_errstr) +                          char *path_list, dict_t *dict, +                          dict_t *resp_dict, char **op_errstr)  {          int32_t         ret     = -1;          char            *op_name = NULL; @@ -1306,6 +2155,9 @@ glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave,          glusterd_conf_t *priv   = NULL;          char            *subop  = NULL;          char            *master = NULL; +        char            *conf_path = NULL; +        char            *slave_vol = NULL; +        struct stat      stbuf     = {0, };          GF_ASSERT (slave);          GF_ASSERT (op_errstr); @@ -1340,10 +2192,17 @@ glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave,                  goto out;          } +        ret = dict_get_str (dict, "conf_path", &conf_path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to fetch conf file path."); +                goto out; +        } +          master = "";          runinit (&runner);          runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); +        runner_argprintf (&runner, "%s", conf_path);          if (volinfo) {                  master = volinfo->volname;                  runner_argprintf (&runner, ":%s", master); @@ -1366,13 +2225,39 @@ glusterd_gsync_configure (glusterd_volinfo_t *volinfo, char *slave,                  goto out;          } + +        if (!strcmp (op_name, "state_file")) { + +                ret = lstat (op_value, &stbuf); +                if (ret) { +                        ret = dict_get_str (dict, "slave_vol", &slave_vol); +                        if (ret) { +                                gf_log ("", GF_LOG_ERROR, +                                        "Unable to fetch slave volume name."); +                                goto out; +                        } + +                        ret = glusterd_create_status_file (volinfo->volname, slave, +                                                           slave_vol, +                                                           "Switching Status File"); +                        if (ret || lstat (op_value, &stbuf)) { +                                gf_log ("", GF_LOG_ERROR, "Unable to create %s" +                                        ". Error : %s", op_value, +                                        strerror (errno)); +                                ret = -1; +                                goto out; +                        } +                } +        } +          ret = 0;          gf_asprintf (op_errstr, "config-%s successful", subop);  out:          if (!ret && volinfo) {                  ret = glusterd_check_restart_gsync_session (volinfo, slave, -                                                            resp_dict); +                                                            resp_dict, path_list, +                                                            conf_path, 0);                  if (ret)                          *op_errstr = gf_strdup ("internal error");          } @@ -1498,12 +2383,13 @@ dict_get_param (dict_t *dict, char *key, char **param)  }  static int -glusterd_read_status_file (char *master, char *slave, -                           dict_t *dict, char *node) +glusterd_read_status_file (glusterd_volinfo_t *volinfo, char *slave, +                           char *conf_path, dict_t *dict, char *node)  {          glusterd_conf_t *priv = NULL;          int              ret = 0;          char            *statefile = NULL; +        char            *master    = NULL;          char             buf[1024] = {0, };          char             nds[1024] = {0, };          char             mst[1024] = {0, }; @@ -1514,16 +2400,21 @@ glusterd_read_status_file (char *master, char *slave,          int              gsync_count = 0;          int              status = 0;          char *dyn_node = NULL; +        char *path_list = NULL;          GF_ASSERT (THIS);          GF_ASSERT (THIS->private); +        GF_ASSERT (volinfo); + +        master = volinfo->volname;          confd = dict_new ();          if (!dict)                  return -1;          priv = THIS->private; -        ret = glusterd_gsync_get_config (master, slave, priv->workdir, + +        ret = glusterd_gsync_get_config (master, slave, conf_path,                                           confd);          if (ret) {                  gf_log ("", GF_LOG_ERROR, "Unable to get configuration data" @@ -1532,13 +2423,6 @@ glusterd_read_status_file (char *master, char *slave,          } -        ret = gsync_status (master, slave, &status); -        if (ret == 0 && status == -1) { -                strncpy (buf, "defunct", sizeof (buf)); -                goto done; -        } else if (ret == -1) -                goto out; -          ret = dict_get_param (confd, "state_file", &statefile);          if (ret)                  goto out; @@ -1549,7 +2433,17 @@ glusterd_read_status_file (char *master, char *slave,                  strncpy (buf, "defunct", sizeof (buf));                  goto done;          } -        if (strcmp (buf, "OK") != 0) + +        ret = gsync_status (master, slave, conf_path, &status); +        if (ret == 0 && status == -1) { +                if ((strcmp (buf, "Not Started")) && +                    (strcmp (buf, "Stopped"))) +                    strncpy (buf, "defunct", sizeof (buf)); +                goto done; +        } else if (ret == -1) +                goto out; + +        if (strcmp (buf, "Stable") != 0)                  goto done;          ret = dict_get_param (confd, "state_socket_unencoded", &statefile); @@ -1575,6 +2469,19 @@ glusterd_read_status_file (char *master, char *slave,          }   done: +        if ((!strcmp (buf, "defunct")) || +            (!strcmp (buf, "Not Started")) || +            (!strcmp (buf, "Stopped"))) { +                ret = glusterd_get_local_brickpaths (volinfo, &path_list); +                if (!path_list) { +                        gf_log ("", GF_LOG_DEBUG, "This node not being part of" +                                " volume should not be running gsyncd. Hence" +                                " shouldn't display status for this node."); +                        ret = 0; +                        goto out; +                } +        } +          ret = dict_get_int32 (dict, "gsync-count", &gsync_count);          if (ret) @@ -1635,13 +2542,14 @@ glusterd_read_status_file (char *master, char *slave,  static int  glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave, -                                      dict_t *resp_dict) +                                      dict_t *resp_dict, char *path_list, +                                      char *conf_path, gf_boolean_t is_force)  {          int                    ret = 0; -        uuid_t                 uuid = {0, };          glusterd_conf_t        *priv = NULL;          char                   *status_msg = NULL; +        gf_boolean_t           is_running = _gf_false;          GF_ASSERT (volinfo);          GF_ASSERT (slave); @@ -1650,18 +2558,22 @@ glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave,          priv = THIS->private; -        if (glusterd_gsync_get_uuid (slave, volinfo, uuid)) -                /* session does not exist, nothing to do */ +        ret = glusterd_check_gsync_running_local (volinfo->volname, +                                                  slave, conf_path, +                                                  &is_running); +        if (!ret && (_gf_true != is_running)) +                /* gsynd not running, nothing to do */                  goto out; -        if (uuid_compare (MY_UUID, uuid) == 0) { -                ret = stop_gsync (volinfo->volname, slave, &status_msg); -                if (ret == 0 && status_msg) -                        ret = dict_set_str (resp_dict, "gsync-status", -                                            status_msg); -                if (ret == 0) -                        ret = glusterd_start_gsync (volinfo, slave, -                                                    uuid_utoa(MY_UUID), NULL); -        } + +        ret = stop_gsync (volinfo->volname, slave, &status_msg, +                          conf_path, is_force); +        if (ret == 0 && status_msg) +                ret = dict_set_str (resp_dict, "gsync-status", +                                    status_msg); +        if (ret == 0) +                ret = glusterd_start_gsync (volinfo, slave, path_list, +                                            conf_path, uuid_utoa(MY_UUID), +                                            NULL);   out:          gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); @@ -1669,7 +2581,7 @@ glusterd_check_restart_gsync_session (glusterd_volinfo_t *volinfo, char *slave,  }  static int32_t -glusterd_marker_create_volfile (glusterd_volinfo_t *volinfo) +glusterd_marker_changelog_create_volfile (glusterd_volinfo_t *volinfo)  {          int32_t          ret     = 0; @@ -1693,58 +2605,73 @@ out:  }  static int -glusterd_set_marker_gsync (glusterd_volinfo_t *volinfo) +glusterd_set_gsync_knob (glusterd_volinfo_t *volinfo, char *key, int *vc)  { -        int                      ret     = -1; -        int                      marker_set = _gf_false; -        char                    *gsync_status = NULL; +        int   ret          = -1; +        int   conf_enabled = _gf_false; +        char *knob_on      = NULL;          GF_ASSERT (THIS);          GF_ASSERT (THIS->private); -        marker_set = glusterd_volinfo_get_boolean (volinfo, VKEY_MARKER_XTIME); -        if (marker_set == -1) { -                gf_log ("", GF_LOG_ERROR, "failed to get the marker status"); -                ret = -1; +        conf_enabled = glusterd_volinfo_get_boolean (volinfo, key); +        if (conf_enabled == -1) { +                gf_log ("", GF_LOG_ERROR, +                        "failed to get key %s from volinfo", key);                  goto out;          } -        if (marker_set == _gf_false) { -                gsync_status = gf_strdup ("on"); -                if (gsync_status == NULL) { +        ret = 0; +        if (conf_enabled == _gf_false) { +                *vc = 1; +                knob_on = gf_strdup ("on"); +                if (knob_on == NULL) {                          ret = -1;                          goto out;                  }                  ret = glusterd_gsync_volinfo_dict_set (volinfo, -                                                       VKEY_MARKER_XTIME, gsync_status); -                if (ret < 0) -                        goto out; - -                ret = glusterd_marker_create_volfile (volinfo); -                if (ret) { -                        gf_log ("", GF_LOG_ERROR, "Setting dict failed"); -                        goto out; -                } +                                                       key, knob_on);          } -        ret = 0; -out: + out:          gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret;  } +static int +glusterd_set_gsync_confs (glusterd_volinfo_t *volinfo) +{ +        int ret             = -1; +        int volfile_changed = 0; + +        ret = glusterd_set_gsync_knob (volinfo, +                                       VKEY_MARKER_XTIME, &volfile_changed); +        if (ret) +                goto out; + +        ret = glusterd_set_gsync_knob (volinfo, +                                       VKEY_CHANGELOG, &volfile_changed); +        if (ret) +                goto out; +        if (volfile_changed) +                ret = glusterd_marker_changelog_create_volfile (volinfo); + out: +        return ret; +}  static int  glusterd_get_gsync_status_mst_slv (glusterd_volinfo_t *volinfo, -                                   char *slave, dict_t *rsp_dict, -                                   char *node) +                                   char *slave, char *conf_path, +                                   dict_t *rsp_dict, char *node)  { +        char              *statefile = NULL;          uuid_t             uuid = {0, };          glusterd_conf_t    *priv = NULL;          int                ret = 0; +        struct stat        stbuf = {0, };          GF_ASSERT (volinfo);          GF_ASSERT (slave); @@ -1754,19 +2681,38 @@ glusterd_get_gsync_status_mst_slv (glusterd_volinfo_t *volinfo,          priv = THIS->private;          ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -        if ((ret == 0) && (uuid_compare (MY_UUID, uuid) != 0)) -                goto out; -          if (ret) { -                ret = 0;                  gf_log ("", GF_LOG_INFO, "geo-replication status %s %s :"                          "session is not active", volinfo->volname, slave); -                goto out; + +                ret = glusterd_get_statefile_name (volinfo, slave, +                                                   conf_path, &statefile); +                if (ret) { +                        if (!strstr(slave, "::")) +                                gf_log ("", GF_LOG_INFO, +                                        "%s is not a valid slave url.", slave); +                        else +                                gf_log ("", GF_LOG_INFO, "Unable to get" +                                        " statefile's name"); +                        ret = 0; +                        goto out; +                } + +                ret = lstat (statefile, &stbuf); +                if (ret) { +                        gf_log ("", GF_LOG_INFO, "%s statefile not present.", +                                statefile); +                        ret = 0; +                        goto out; +                }          } -        ret = glusterd_read_status_file (volinfo->volname, -                                         slave, rsp_dict, node); - out: +        ret = glusterd_read_status_file (volinfo, slave, conf_path, +                                         rsp_dict, node); +out: +        if (statefile) +                GF_FREE (statefile); +          gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret);          return ret;  } @@ -1817,6 +2763,7 @@ glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict)  {          char               *slave  = NULL;          char               *volname = NULL; +        char               *conf_path = NULL;          char               errmsg[PATH_MAX] = {0, };          gf_boolean_t       exists = _gf_false;          glusterd_volinfo_t *volinfo = NULL; @@ -1854,7 +2801,14 @@ glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict)                  goto out;          } -        ret = glusterd_get_gsync_status_mst_slv (volinfo, slave, +        ret = dict_get_str (dict, "conf_path", &conf_path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to fetch conf file path."); +                goto out; +        } + +        ret = glusterd_get_gsync_status_mst_slv (volinfo, slave, conf_path,                                                   rsp_dict, my_hostname);   out: @@ -1863,300 +2817,405 @@ glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict)  }  static int -glusterd_send_sigstop (pid_t pid) -{ -        int ret = 0; -        ret = kill (pid, SIGSTOP); -        if (ret) -                gf_log ("", GF_LOG_ERROR, GEOREP"failed to send SIGSTOP signal"); -        return ret; -} - -static int -glusterd_send_sigcont (pid_t pid) -{ -        int ret = 0; -        ret = kill (pid, SIGCONT); -        if (ret) -                gf_log ("", GF_LOG_ERROR, GEOREP"failed to send SIGCONT signal"); -        return ret; -} - -/* - * Log rotations flow is something like this: - * - Send SIGSTOP to process group (this will stop monitor/worker process - *   and also the slave if it's local) - * - Rotate log file for monitor/worker - * - Rotate log file for slave if it's local - * - Send SIGCONT to the process group. Monitor wakes up, kills the worker - *   (this is done in the SIGCONT handler), which results in the termination - *   of the slave (local/remote). After returning from signal handler, - *   monitor detects absence of worker and starts it again, which in-turn - *   starts the slave. - */ -static int -glusterd_send_log_rotate_signal (pid_t pid, char *logfile1, char *logfile2) +glusterd_gsync_delete (glusterd_volinfo_t *volinfo, char *slave, +                       char *slave_vol, char *path_list, dict_t *dict, +                       dict_t *resp_dict, char **op_errstr)  { -        int         ret         = 0; -        char rlogfile[PATH_MAX] = {0,}; -        time_t      rottime     = 0; - -        ret = glusterd_send_sigstop (-pid); -        rottime = time (NULL); +        int32_t         ret     = -1; +        runner_t        runner    = {0,}; +        glusterd_conf_t *priv   = NULL; +        char            *master = NULL; +        char            *gl_workdir = NULL; +        char             geo_rep_dir[PATH_MAX] = ""; +        char            *conf_path = NULL; -        snprintf (rlogfile, sizeof (rlogfile), "%s.%"PRIu64, logfile1, -                  (uint64_t) rottime); -        ret = rename (logfile1, rlogfile); -        if (ret) -                gf_log ("", GF_LOG_ERROR, "rename failed for geo-rep log file"); +        GF_ASSERT (slave); +        GF_ASSERT (slave_vol); +        GF_ASSERT (op_errstr); +        GF_ASSERT (dict); +        GF_ASSERT (resp_dict); -        if (!*logfile2) { -                gf_log ("", GF_LOG_DEBUG, "Slave is not local," -                        " skipping rotation"); -                ret = 0; +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                *op_errstr = gf_strdup ("glusterd defunct");                  goto out;          } -        (void) snprintf (rlogfile, sizeof (rlogfile), "%s.%"PRIu64, logfile2, -                         (uint64_t) rottime); -        ret = rename (logfile2, rlogfile); -        if (ret) -                gf_log ("", GF_LOG_ERROR, "rename failed for geo-rep slave" -                        " log file"); +        ret = dict_get_str (dict, "conf_path", &conf_path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to fetch conf file path."); +                goto out; +        } - out: -        ret = glusterd_send_sigcont (-pid); +        gl_workdir = priv->workdir; +        master = ""; +        runinit (&runner); +        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", +                          "--delete", "-c", NULL); +        runner_argprintf (&runner, "%s", conf_path); -        return ret; -} +        if (volinfo) { +                master = volinfo->volname; +                runner_argprintf (&runner, ":%s", master); +        } +        runner_add_arg (&runner, slave); +        runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); +        synclock_unlock (&priv->big_lock); +        ret = runner_run (&runner); +        synclock_lock (&priv->big_lock); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "gsyncd failed to " +                        "delete session info for %s and %s peers", +                        master, slave); -static int -glusterd_get_pid_from_file (char *master, char *slave, pid_t *pid) -{ -        int ret                = -1; -        int pfd                = 0; -        char pidfile[PATH_MAX] = {0,}; -        char buff[1024]        = {0,}; +                gf_asprintf (op_errstr, "gsyncd failed to " +                             "delete session info for %s and %s peers", +                             master, slave); -        pfd = gsyncd_getpidfile (master, slave, pidfile); -        if (pfd == -2) { -                gf_log ("", GF_LOG_ERROR, GEOREP" log-rotate validation " -                        " failed for %s & %s", master, slave); -                goto out; -        } -        if (gsync_status_byfd (pfd) == -1) { -                gf_log ("", GF_LOG_ERROR, "gsyncd b/w %s & %s is not" -                        " running", master, slave);                  goto out;          } -        if (pfd < 0) -                goto out; +        ret = snprintf (geo_rep_dir, sizeof(geo_rep_dir) - 1, +                        "%s/"GEOREP"/%s-%s", gl_workdir, +                        volinfo->volname, slave_vol); +        geo_rep_dir[ret] = '\0'; -        ret = read (pfd, buff, 1024); -        if (ret < 0) { -                gf_log ("", GF_LOG_ERROR, GEOREP" cannot read pid from pid-file"); -                goto out; +        ret = rmdir (geo_rep_dir); +        if (ret) { +                if (errno == ENOENT) +                        gf_log ("", GF_LOG_DEBUG, "Geo Rep Dir(%s) Not Present.", +                                geo_rep_dir); +                else { +                        gf_log ("", GF_LOG_ERROR, "Unable to delete " +                                "Geo Rep Dir(%s). Error: %s", geo_rep_dir, +                                strerror (errno)); +                        goto out; +                }          } - -        *pid = strtol (buff, NULL, 10);          ret = 0; +        gf_asprintf (op_errstr, "delete successful"); +  out: -        sys_close(pfd); +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret;  } -static int -glusterd_do_gsync_log_rotate (char *master, char *slave, uuid_t *uuid, char **op_errstr) +int +glusterd_op_sys_exec (dict_t *dict, char **op_errstr, dict_t *rsp_dict)  { -        int              ret     = 0; -        glusterd_conf_t *priv    = NULL; -        pid_t            pid     = 0; -        char log_file1[PATH_MAX] = {0,}; -        char log_file2[PATH_MAX] = {0,}; +        char                   buf[PATH_MAX]          = ""; +        char                   cmd_arg_name[PATH_MAX] = ""; +        char                   output_name[PATH_MAX]  = ""; +        char                   errmsg[PATH_MAX]       = ""; +        char                  *ptr                    = NULL; +        char                  *bufp                   = NULL; +        char                  *command                = NULL; +        char                 **cmd_args               = NULL; +        int                    ret                    = -1; +        int                    i                      = -1; +        int                    cmd_args_count         = 0; +        int                    output_count           = 0; +        glusterd_conf_t       *priv                   = NULL; +        runner_t               runner                 = {0,}; -        GF_ASSERT (THIS); -        GF_ASSERT (THIS->private); - -        priv = THIS->private; +        GF_ASSERT (dict); +        GF_ASSERT (op_errstr); +        GF_ASSERT (rsp_dict); -        ret = glusterd_get_pid_from_file (master, slave, &pid); -        if (ret) +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                *op_errstr = gf_strdup ("glusterd defunct");                  goto out; +        } -        /* log file */ -        ret = glusterd_gsyncd_getlogfile (master, slave, log_file1); -        if (ret) +        ret = dict_get_str (dict, "command", &command); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to get command from dict");                  goto out; +        } -        /* check if slave is local or remote */ -        ret = glusterd_gsync_slave_is_remote (slave); -        if (ret) -                goto do_rotate; - -        /* slave log file - slave is local and it's log can be rotated */ -        ret = glusterd_gsync_get_slave_log_file (master, slave, log_file2); +        ret = dict_get_int32 (dict, "cmd_args_count", &cmd_args_count);          if (ret) -                goto out; - - do_rotate: -        ret = glusterd_send_log_rotate_signal (pid, log_file1, log_file2); - - out: -        if (ret && op_errstr) -                *op_errstr = gf_strdup("Error rotating log file"); -        return ret; -} - -static int -glusterd_do_gsync_log_rotation_mst_slv (glusterd_volinfo_t *volinfo, char *slave, -                                        char **op_errstr) -{ -        uuid_t           uuid = {0, }; -        glusterd_conf_t *priv = NULL; -        int              ret  = 0; -        char             errmsg[1024] = {0,}; -        xlator_t        *this    = NULL; +                gf_log ("", GF_LOG_INFO, "No cmd_args_count"); + +        if (cmd_args_count) { +                cmd_args = GF_CALLOC (cmd_args_count, sizeof (char*), +                                      gf_common_mt_char); +                if (!cmd_args) { +                        gf_log ("", GF_LOG_ERROR, "Unable to calloc. " +                                "Errno = %s", strerror(errno)); +                        goto out; +                } -        GF_ASSERT (volinfo); -        GF_ASSERT (slave); -        GF_ASSERT (THIS); -        this = THIS; -        GF_ASSERT (this->private); -        priv = this->private; +                for (i=1; i <= cmd_args_count; i++) { +                        memset (cmd_arg_name, '\0', sizeof(cmd_arg_name)); +                        snprintf (cmd_arg_name, sizeof(cmd_arg_name), +                                  "cmd_arg_%d", i); +                        ret = dict_get_str (dict, cmd_arg_name, &cmd_args[i-1]); +                        if (ret) { +                                gf_log ("", GF_LOG_ERROR, +                                        "Unable to get %s in dict", +                                        cmd_arg_name); +                                goto out; +                        } +                } +        } -        ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -        if ((ret == 0) && (uuid_compare (MY_UUID, uuid) != 0)) +        runinit (&runner); +        runner_argprintf (&runner, GSYNCD_PREFIX"/peer_%s", command); +        for (i=0; i < cmd_args_count; i++) +                runner_add_arg (&runner, cmd_args[i]); +        runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); +        synclock_unlock (&priv->big_lock); +        ret = runner_start (&runner); +        if (ret == -1) { +                snprintf (errmsg, sizeof (errmsg), "Unable to " +                          "execute command. Error : %s", +                          strerror (errno)); +                *op_errstr = gf_strdup (errmsg); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                ret = -1; +                synclock_lock (&priv->big_lock);                  goto out; +        } + +        ptr = fgets(buf, sizeof(buf), runner_chio (&runner, STDOUT_FILENO)); +        if (ptr) { +                ret = dict_get_int32 (rsp_dict, "output_count", &output_count); +                if (ret) +                        output_count = 1; +                else +                        output_count++; +                memset (output_name, '\0', sizeof (output_name)); +                snprintf (output_name, sizeof (output_name), +                          "output_%d", output_count); +                if (buf[strlen(buf) - 1] == '\n') +                        buf[strlen(buf) - 1] = '\0'; +                bufp = gf_strdup (buf); +                if (!bufp) +                        gf_log ("", GF_LOG_ERROR, "gf_strdup failed."); +                ret = dict_set_dynstr (rsp_dict, output_name, bufp); +                if (ret) { +                        GF_FREE (bufp); +                        gf_log ("", GF_LOG_ERROR, "output set failed."); +                } +                ret = dict_set_int32 (rsp_dict, "output_count", output_count); +                if (ret) +                        gf_log ("", GF_LOG_ERROR, "output_count set failed."); +        } +        ret = runner_end (&runner);          if (ret) { -                snprintf(errmsg, sizeof(errmsg), "geo-replication session b/w %s %s not active", -                         volinfo->volname, slave); -                gf_log (this->name, GF_LOG_WARNING, "%s", errmsg); -                if (op_errstr) -                        *op_errstr = gf_strdup(errmsg); +                snprintf (errmsg, sizeof (errmsg), "Unable to " +                          "end. Error : %s", +                          strerror (errno)); +                *op_errstr = gf_strdup (errmsg); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                ret = -1; +                synclock_lock (&priv->big_lock);                  goto out;          } +        synclock_lock (&priv->big_lock); -        ret = glusterd_do_gsync_log_rotate (volinfo->volname, slave, &uuid, op_errstr); +        ret = 0; +out: +        if (cmd_args) { +                GF_FREE (cmd_args); +                cmd_args = NULL; +        } - out: -        gf_log (this->name, GF_LOG_DEBUG, "Returning with %d", ret); +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret;  } -static int -_iterate_log_rotate_mst_slv (dict_t *this, char *key, data_t *value, void *data) +int +glusterd_op_copy_file (dict_t *dict, char **op_errstr)  { -        glusterd_gsync_status_temp_t  *param = NULL; -        char                          *slave = NULL; +        char             abs_filename[PATH_MAX] = ""; +        char             errmsg[PATH_MAX]       = ""; +        char            *filename               = NULL; +        char            *host_uuid              = NULL; +        char             uuid_str [64]          = {0}; +        char            *contents               = NULL; +        char             buf[1024]              = ""; +        int              ret                    = -1; +        int              fd                     = -1; +        int              bytes_writen           = 0; +        int              bytes_read             = 0; +        int              contents_size          = -1; +        int              file_mode              = -1; +        glusterd_conf_t *priv                   = NULL; +        struct stat      stbuf                  = {0,}; -        param = (glusterd_gsync_status_temp_t *) data; -        GF_ASSERT (param); -        GF_ASSERT (param->volinfo); - -        slave = strchr (value->data, ':'); -        if (slave) -                slave++; -        else { -                gf_log ("", GF_LOG_ERROR, "geo-replication log-rotate: slave (%s) " -                        "not conforming to format", slave); -                return -1; +        if (THIS) +                priv = THIS->private; +        if (priv == NULL) { +                gf_log ("", GF_LOG_ERROR, "priv of glusterd not present"); +                *op_errstr = gf_strdup ("glusterd defunct"); +                goto out;          } -        (void) glusterd_do_gsync_log_rotation_mst_slv (param->volinfo, slave, NULL); -        return 0; -} +        ret = dict_get_str (dict, "host-uuid", &host_uuid); +        if (ret < 0) +                goto out; -static int -glusterd_do_gsync_log_rotation_mst (glusterd_volinfo_t *volinfo) -{ -        glusterd_gsync_status_temp_t  param = {0, }; +        ret = dict_get_str (dict, "source", &filename); +        if (ret < 0) { +               gf_log ("", GF_LOG_ERROR, "Unable to fetch" +                       " filename from dict."); +               *op_errstr = gf_strdup ("command unsuccessful"); +               goto out; +        } +        snprintf (abs_filename, sizeof(abs_filename), +                  "%s/%s", priv->workdir, filename); -        GF_ASSERT (volinfo); +        uuid_utoa_r (MY_UUID, uuid_str); +        if (!strcmp (uuid_str, host_uuid)) { +                ret = lstat (abs_filename, &stbuf); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Source file" +                                 " does not exist in %s", priv->workdir); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        goto out; +                } -        param.volinfo = volinfo; -        dict_foreach (volinfo->gsync_slaves, _iterate_log_rotate_mst_slv, ¶m); -        return 0; -} +                contents = GF_CALLOC(1, stbuf.st_size+1, gf_common_mt_char); +                if (!contents) { +                        snprintf (errmsg, sizeof (errmsg), +                                  "Unable to allocate memory"); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        ret = -1; +                        goto out; +                } -static int -glusterd_rotate_gsync_all () -{ -        int32_t             ret     = 0; -        glusterd_conf_t    *priv    = NULL; -        glusterd_volinfo_t *volinfo = NULL; +                fd = open (abs_filename, O_RDONLY); +                if (fd < 0) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to open %s", +                                  abs_filename); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        ret = -1; +                        goto out; +                } -        GF_ASSERT (THIS); -        priv = THIS->private; +                do { +                        ret = read (fd, buf, sizeof(buf)); +                        if (ret > 0) { +                                memcpy (contents+bytes_read, buf, ret); +                                bytes_read += ret; +                                memset (buf, '\0', sizeof(buf)); +                        } +                } while (ret > 0); -        GF_ASSERT (priv); +                if (bytes_read != stbuf.st_size) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to read all " +                                  "the data from %s", abs_filename); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        ret = -1; +                        goto out; +                } -        list_for_each_entry (volinfo, &priv->volumes, vol_list) { -                ret = glusterd_do_gsync_log_rotation_mst (volinfo); -                if (ret) +                ret = dict_set_int32 (dict, "contents_size", stbuf.st_size); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to set" +                                  " contents size in dict."); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg);                          goto out; -        } +                } - out: -        gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); -        return ret; -} +                ret = dict_set_int32 (dict, "file_mode", +                                      (int32_t)stbuf.st_mode); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to set" +                                  " file mode in dict."); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        goto out; +                } -static int -glusterd_rotate_gsync_logs (dict_t *dict, char **op_errstr, dict_t *rsp_dict) -{ -        char                *slave   = NULL; -        char                *volname = NULL; -        char errmsg[1024]            = {0,}; -        gf_boolean_t         exists  = _gf_false; -        glusterd_volinfo_t  *volinfo = NULL; -        char               **linearr = NULL; -        int                  ret     = 0; +                ret = dict_set_bin (dict, "common_pem_contents", +                                    contents, stbuf.st_size); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to set" +                                  " pem contents in dict."); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        goto out; +                } +                close (fd); +        } else { +                ret = dict_get_bin (dict, "common_pem_contents", +                                    (void **) &contents); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to get" +                                  " pem contents in dict."); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        goto out; +                } -        ret = dict_get_str (dict, "master", &volname); -        if (ret < 0) { -                ret = glusterd_rotate_gsync_all (); -                goto out; -        } +                ret = dict_get_int32 (dict, "contents_size", &contents_size); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to set" +                                  " contents size in dict."); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        goto out; +                } -        exists = glusterd_check_volume_exists (volname); -        ret = glusterd_volinfo_find (volname, &volinfo); -        if ((ret) || (!exists)) { -                snprintf (errmsg, sizeof(errmsg), "Volume %s does not" -                          " exist", volname); -                gf_log ("", GF_LOG_WARNING, "%s", errmsg); -                *op_errstr = gf_strdup (errmsg); -                ret = -1; -                goto out; -        } +                ret = dict_get_int32 (dict, "file_mode", &file_mode); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to get" +                                  " file mode in dict."); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        goto out; +                } -        ret = dict_get_str (dict, "slave", &slave); -        if (ret < 0) { -                ret = glusterd_do_gsync_log_rotation_mst (volinfo); -                goto out; -        } +                fd = open (abs_filename, O_WRONLY | O_TRUNC | O_CREAT, 0600); +                if (fd < 0) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to open %s", +                                  abs_filename); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        ret = -1; +                        goto out; +                } -        /* for the given slave use the normalized url */ -        ret = glusterd_urltransform_single (slave, "normalize", &linearr); -        if (ret == -1) -                goto out; +                bytes_writen = write (fd, contents, contents_size); -        ret = glusterd_do_gsync_log_rotation_mst_slv (volinfo, linearr[0], -                                                      op_errstr); -        if (ret) -                gf_log ("gsyncd", GF_LOG_ERROR, "gsyncd log-rotate failed for" -                        " %s & %s", volname, slave); +                if (bytes_writen != contents_size) { +                        snprintf (errmsg, sizeof (errmsg), "Failed to write" +                                  " to %s", abs_filename); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        ret = -1; +                        goto out; +                } -        glusterd_urltransform_free (linearr, 1); - out: +                fchmod (fd, file_mode); +                close (fd); +        } + +        ret = 0; +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret;  } -  int  glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict)  { @@ -2166,11 +3225,15 @@ glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict)          dict_t             *resp_dict = NULL;          char               *host_uuid = NULL;          char               *slave  = NULL; +        char               *slave_vol = NULL;          char               *volname = NULL; +        char               *path_list = NULL;          glusterd_volinfo_t *volinfo = NULL;          glusterd_conf_t    *priv = NULL; +        gf_boolean_t        is_force = _gf_false;          char               *status_msg = NULL; -        uuid_t              uuid = {0, }; +        gf_boolean_t        is_running = _gf_false; +        char               *conf_path = NULL;          GF_ASSERT (THIS);          GF_ASSERT (THIS->private); @@ -2196,15 +3259,22 @@ glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict)                  goto out;          } -        if (type == GF_GSYNC_OPTION_TYPE_ROTATE) { -                ret = glusterd_rotate_gsync_logs (dict, op_errstr, resp_dict); +        ret = dict_get_str (dict, "slave", &slave); +        if (ret < 0)                  goto out; +        ret = dict_get_str (dict, "slave_vol", &slave_vol); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Unable to fetch slave volume name."); +                goto out;          } -        ret = dict_get_str (dict, "slave", &slave); -        if (ret < 0) +        ret = dict_get_str (dict, "conf_path", &conf_path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to fetch conf file path.");                  goto out; +        }          if (dict_get_str (dict, "master", &volname) == 0) {                  ret = glusterd_volinfo_find (volname, &volinfo); @@ -2213,11 +3283,24 @@ glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict)                                  volname);                          goto out;                  } + +                ret = glusterd_get_local_brickpaths (volinfo, &path_list);          }          if (type == GF_GSYNC_OPTION_TYPE_CONFIG) { -                ret = glusterd_gsync_configure (volinfo, slave, dict, resp_dict, -                                                op_errstr); +                ret = glusterd_gsync_configure (volinfo, slave, path_list, +                                                dict, resp_dict, op_errstr); +                goto out; +        } + +        if (type == GF_GSYNC_OPTION_TYPE_DELETE) { +                ret = glusterd_remove_slave_in_info(volinfo, slave, op_errstr); +                if (ret && !is_force && path_list) +                        goto out; + +                ret = glusterd_gsync_delete (volinfo, slave, slave_vol, +                                             path_list, dict, resp_dict, +                                             op_errstr);                  goto out;          } @@ -2226,48 +3309,636 @@ glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict)                  goto out;          } +        is_force = dict_get_str_boolean (dict, "force", _gf_false); +          if (type == GF_GSYNC_OPTION_TYPE_START) { -                ret = glusterd_set_marker_gsync (volinfo); +                ret = glusterd_set_gsync_confs (volinfo);                  if (ret != 0) { -                        gf_log ("", GF_LOG_WARNING, "marker start failed"); +                        gf_log ("", GF_LOG_WARNING, "marker/changelog start failed");                          *op_errstr = gf_strdup ("failed to initialize indexing");                          ret = -1;                          goto out;                  } -                ret = glusterd_store_slave_in_info(volinfo, slave, -                                                   host_uuid, op_errstr); -                if (ret) -                        goto out; -                ret = glusterd_start_gsync (volinfo, slave, host_uuid, -                                            op_errstr); +                ret = glusterd_start_gsync (volinfo, slave, path_list, +                                            conf_path, host_uuid, op_errstr);          }          if (type == GF_GSYNC_OPTION_TYPE_STOP) { - -                ret = glusterd_gsync_get_uuid (slave, volinfo, uuid); -                if (ret) { +                ret = glusterd_check_gsync_running_local (volinfo->volname, +                                                          slave, conf_path, +                                                          &is_running); +                if (!ret && !is_force && path_list && +                    (_gf_true != is_running)) {                          gf_log ("", GF_LOG_WARNING, GEOREP" is not set up for"                                  "%s(master) and %s(slave)", volname, slave);                          *op_errstr = strdup (GEOREP" is not set up");                          goto out;                  } -                ret = glusterd_remove_slave_in_info(volinfo, slave, op_errstr); -                if (ret) +                ret = stop_gsync (volname, slave, &status_msg, conf_path, is_force); +                if (ret == 0 && status_msg) +                        ret = dict_set_str (resp_dict, "gsync-status", +                                            status_msg); +                if (ret != 0 && !is_force && path_list) +                        *op_errstr = gf_strdup ("internal error"); + +                if (!ret) { +                        ret = glusterd_create_status_file (volinfo->volname, +                                                           slave, slave_vol, "Stopped"); +                        if (ret) { +                                gf_log ("", GF_LOG_ERROR, "Unable to update" +                                        "state_file. Error : %s", +                                        strerror (errno)); +                        } +                } +        } + +out: +        if (path_list) { +                GF_FREE (path_list); +                path_list = NULL; +        } + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +static int +glusterd_get_slave_details_confpath (glusterd_volinfo_t *volinfo, dict_t *dict, +                                     char **slave_ip, char **slave_vol, +                                     char **conf_path) +{ +        int                ret                = -1; +        char               confpath[PATH_MAX] = ""; +        glusterd_conf_t   *priv               = NULL; + +        GF_ASSERT (THIS); +        priv = THIS->private; +        GF_ASSERT (priv); + +        ret = glusterd_get_slave_info (dict, slave_ip, slave_vol); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to fetch slave details."); +                ret = -1; +                goto out; +        } + +        ret = snprintf (confpath, sizeof(confpath) - 1, +                        "%s/"GEOREP"/%s-%s/gsyncd.conf", +                        priv->workdir, volinfo->volname, *slave_vol); +        confpath[ret] = '\0'; +        *conf_path = gf_strdup (confpath); +        if (!(*conf_path)) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to gf_strdup. Error: %s", strerror (errno)); +                ret = -1; +                goto out; +        } + +        ret = dict_set_str (dict, "conf_path", *conf_path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to store conf_path"); +                goto out; +        } + +out: +        gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); +        return ret; + +} + +static int +glusterd_get_slave_info (dict_t *dict, char **slave_ip, char **slave_vol) +{ +        char     *tmp       = NULL; +        char     *save_ptr  = NULL; +        char     *slave     = NULL; +        char    **linearr   = NULL; +        int32_t   ret       = -1; + +        GF_ASSERT (dict); + +        ret = dict_get_str (dict, "slave", &slave); +        if (slave) { +                ret = glusterd_urltransform_single (slave, "normalize", +                                                    &linearr); +                if (ret == -1) { +                        gf_log ("", GF_LOG_ERROR, "Failed to normalize url"); +                        goto out; +                } + +                tmp = strtok_r (linearr[0], "/", &save_ptr); +                tmp = strtok_r (NULL, "/", &save_ptr); +                slave = strtok_r (tmp, ":", &save_ptr); +                if (slave) { +                        *slave_ip = gf_strdup (slave); +                        if (!*slave_ip) { +                                gf_log ("", GF_LOG_ERROR, +                                        "Failed to gf_strdup"); +                                ret = -1; +                                goto out; +                        } +                        gf_log ("", GF_LOG_DEBUG, "Slave IP : %s", *slave_ip); +                        ret = 0; +                } else { +                        gf_log ("", GF_LOG_ERROR, "Invalid slave name");                          goto out; +                } -                if (uuid_compare (MY_UUID, uuid) != 0) { +                slave = strtok_r (NULL, ":", &save_ptr); +                if (slave) { +                        *slave_vol = gf_strdup (slave); +                        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;                  } -                ret = stop_gsync (volname, slave, &status_msg); -                if (ret == 0 && status_msg) -                        ret = dict_set_str (resp_dict, "gsync-status", -                                            status_msg); -                if (ret != 0) -                        *op_errstr = gf_strdup ("internal error"); +                ret = dict_set_str (dict, "slave_ip", *slave_ip); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, +                                "Unable to store slave IP."); +                        goto out; +                } + +                ret = dict_set_str (dict, "slave_vol", *slave_vol); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, +                                "Unable to store slave volume name."); +                        goto out; +                } +        } else +                gf_log ("", GF_LOG_ERROR, "Unable to fetch slave from dict"); + +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +static void +runinit_gsyncd_setrx (runner_t *runner, char *conf_path) +{ +        runinit (runner); +        runner_add_args (runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); +        runner_argprintf (runner, "%s", conf_path); +        runner_add_arg (runner, "--config-set-rx"); +} + +static int +glusterd_check_gsync_present (int *valid_state) +{ +        char                buff[PATH_MAX] = {0, }; +        runner_t            runner = {0,}; +        char               *ptr = NULL; +        int                 ret = 0; + +        runinit (&runner); +        runner_add_args (&runner, GSYNCD_PREFIX"/gsyncd", "--version", NULL); +        runner_redir (&runner, STDOUT_FILENO, RUN_PIPE); +        ret = runner_start (&runner); +        if (ret == -1) { +                if (errno == ENOENT) { +                        gf_log ("glusterd", GF_LOG_INFO, GEOREP +                                 " module not installed in the system"); +                        *valid_state = 0; +                } +                else { +                        gf_log ("glusterd", GF_LOG_ERROR, GEOREP +                                  " module not working as desired"); +                        *valid_state = -1; +                } +                goto out; +        } + +        ptr = fgets(buff, sizeof(buff), runner_chio (&runner, STDOUT_FILENO)); +        if (ptr) { +                if (!strstr (buff, "gsyncd")) { +                        ret = -1; +                        gf_log ("glusterd", GF_LOG_ERROR, GEOREP" module not " +                                 "working as desired"); +                        *valid_state = -1; +                        goto out; +                } +        } else { +                ret = -1; +                gf_log ("glusterd", GF_LOG_ERROR, GEOREP" module not " +                         "working as desired"); +                *valid_state = -1; +                goto out; +        } + +        ret = 0; + out: + +        runner_end (&runner); + +        gf_log ("glusterd", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; + +} + +static int +create_conf_file (glusterd_conf_t *conf, char *conf_path) +#define RUN_GSYNCD_CMD do {                                                          \ +        ret = runner_run_reuse (&runner);                                            \ +        if (ret == -1) {                                                             \ +                runner_log (&runner, "glusterd", GF_LOG_ERROR, "command failed");    \ +                runner_end (&runner);                                                \ +                goto out;                                                            \ +        }                                                                            \ +        runner_end (&runner);                                                        \ +} while (0) +{ +        int ret = 0; +        runner_t runner = {0,}; +        char georepdir[PATH_MAX] = {0,}; +        int valid_state = 0; + +        valid_state = -1; +        ret = glusterd_check_gsync_present (&valid_state); +        if (-1 == ret) { +                ret = valid_state; +                goto out; +        } + +        ret = snprintf (georepdir, sizeof(georepdir) - 1, "%s/"GEOREP, +                        conf->workdir); +        georepdir[ret] = '\0'; + +        /************ +         * master pre-configuration +         ************/ + +        /* remote-gsyncd */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "remote-gsyncd", GSYNCD_PREFIX"/gsyncd", ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "remote-gsyncd", "/nonexistent/gsyncd", +                         ".", "^ssh:", NULL); +        RUN_GSYNCD_CMD; + +        /* gluster-command-dir */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "gluster-command-dir", SBIN_DIR"/", +                         ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* gluster-params */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "gluster-params", +                         "aux-gfid-mount xlator-option=*-dht.assert-no-child-down=true", +                         ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* ssh-command */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_arg (&runner, "ssh-command"); +        runner_argprintf (&runner, +                          "ssh -oPasswordAuthentication=no " +                           "-oStrictHostKeyChecking=no " +                           "-i %s/secret.pem", georepdir); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* pid-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_arg (&runner, "pid-file"); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}.pid", georepdir); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* state-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_arg (&runner, "state-file"); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}.status", georepdir); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* state-detail-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_arg (&runner, "state-detail-file"); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}-detail.status", georepdir); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* state-socket */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_arg (&runner, "state-socket-unencoded"); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}.socket", georepdir); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* socketdir */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "socketdir", GLUSTERD_SOCK_DIR, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* log-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, +                         "log-file", +                         DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"/${mastervol}/${eSlave}.log", +                         ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* gluster-log-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, +                         "gluster-log-file", +                         DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"/${mastervol}/${eSlave}${local_id}.gluster.log", +                         ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* ignore-deletes */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "ignore-deletes", "true", ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* special-sync-mode */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "special-sync-mode", "partial", ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* change-detector == changelog */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args(&runner, "change-detector", "changelog", ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_arg(&runner, "working-dir"); +        runner_argprintf(&runner, "%s/${mastervol}/${eSlave}", +                         DEFAULT_VAR_RUN_DIRECTORY); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /************ +         * slave pre-configuration +         ************/ + +        /* gluster-command-dir */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "gluster-command-dir", SBIN_DIR"/", +                         ".", NULL); +        RUN_GSYNCD_CMD; + +        /* gluster-params */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, "gluster-params", +                         "aux-gfid-mount xlator-option=*-dht.assert-no-child-down=true", +                         ".", NULL); +        RUN_GSYNCD_CMD; + +        /* log-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, +                         "log-file", +                         DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${eSlave}.log", +                         ".", NULL); +        RUN_GSYNCD_CMD; + +        /* MountBroker log-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, +                         "log-file-mbr", +                         DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/mbr/${session_owner}:${eSlave}.log", +                         ".", NULL); +        RUN_GSYNCD_CMD; + +        /* gluster-log-file */ +        runinit_gsyncd_setrx (&runner, conf_path); +        runner_add_args (&runner, +                         "gluster-log-file", +                         DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"-slaves/${session_owner}:${eSlave}.gluster.log", +                         ".", NULL); +        RUN_GSYNCD_CMD; + + out: +        return ret ? -1 : 0; +} + +static int +glusterd_create_essential_dir_files (glusterd_volinfo_t *volinfo, dict_t *dict, char *slave, char *slave_vol, char **op_errstr) +{ +        int                ret              = -1; +        char              *conf_path        = NULL; +        char              *statefile        = NULL; +        char               buf[PATH_MAX]    = ""; +        char               errmsg[PATH_MAX] = ""; +        glusterd_conf_t   *conf             = NULL; +        struct stat        stbuf            = {0,}; + +        GF_ASSERT (THIS); +        conf = THIS->private; + +        ret = dict_get_str (dict, "conf_path", &conf_path); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), +                          "Unable to fetch conf file path."); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out; +        } + +        ret = dict_get_str (dict, "statefile", &statefile); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), +                          "Unable to fetch statefile path."); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out; +        } + +        ret = snprintf (buf, sizeof(buf) - 1, "%s/"GEOREP"/%s-%s", +                        conf->workdir, volinfo->volname, slave_vol); +        buf[ret] = '\0'; +        ret = mkdir_p (buf, 0777, _gf_true); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), "Unable to create %s" +                          ". Error : %s", buf, strerror (errno)); +                *op_errstr = gf_strdup (errmsg); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out; +        } + +        ret = snprintf (buf, PATH_MAX, DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"/%s", +                        volinfo->volname); +        buf[ret] = '\0'; +        ret = mkdir_p (buf, 0777, _gf_true); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), "Unable to create %s" +                          ". Error : %s", buf, strerror (errno)); +                *op_errstr = gf_strdup (errmsg); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out; +        } + +        ret = lstat (conf_path, &stbuf); +        if (!ret) { +                gf_log ("", GF_LOG_DEBUG, "Session already running." +                        " Not creating config file again."); +        } else { +                ret = create_conf_file (conf, conf_path); +                if (ret || lstat (conf_path, &stbuf)) { +                        snprintf (errmsg, sizeof (errmsg), "Failed to create" +                                  " config file(%s).", conf_path); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        goto out; +                } +        } + +        ret = lstat (statefile, &stbuf); +        if (!ret) { +                gf_log ("", GF_LOG_DEBUG, "Session already running." +                        " Not creating status file again."); +                goto out; +        } else { +                ret = glusterd_create_status_file (volinfo->volname, slave, slave_vol, +                                                   "Not Started"); +                if (ret || lstat (statefile, &stbuf)) { +                        snprintf (errmsg, sizeof (errmsg), "Unable to create %s" +                                  ". Error : %s", statefile, strerror (errno)); +                        *op_errstr = gf_strdup (errmsg); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        ret = -1; +                        goto out; +                } +        } + +out: +        gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); +        return ret; +} + +int +glusterd_op_gsync_create (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ +        char                common_pem_file[PATH_MAX] = ""; +        char                errmsg[PATH_MAX]          = ""; +        char                hooks_args[PATH_MAX]      = ""; +        char                uuid_str [64]             = ""; +        char               *host_uuid                 = NULL; +        char               *slave_ip                  = NULL; +        char               *slave_vol                 = NULL; +        char               *arg_buf                   = NULL; +        char               *volname                   = NULL; +        char               *slave                     = NULL; +        int32_t             ret                       = -1; +        int32_t             is_pem_push               = -1; +        gf_boolean_t        is_force                  = -1; +        glusterd_conf_t    *conf                      = NULL; +        glusterd_volinfo_t *volinfo                   = NULL; + +        GF_ASSERT (THIS); +        conf = THIS->private; +        GF_ASSERT (conf); +        GF_ASSERT (dict); +        GF_ASSERT (op_errstr); + +        ret = glusterd_op_gsync_args_get (dict, op_errstr, +                                          &volname, &slave, &host_uuid); +        if (ret) +                goto out; + +        snprintf (common_pem_file, sizeof(common_pem_file), +                  "%s"GLUSTERD_COMMON_PEM_PUB_FILE, conf->workdir); + +        ret = glusterd_volinfo_find (volname, &volinfo); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Volinfo for %s" +                        " (master) not found", volname); +                goto out; +        } + +        ret = dict_get_str (dict, "slave_vol", &slave_vol); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), +                          "Unable to fetch slave volume name."); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out; +        } + +        is_force = dict_get_str_boolean (dict, "force", _gf_false); + +        uuid_utoa_r (MY_UUID, uuid_str); +        if (!strcmp (uuid_str, host_uuid)) { +                ret = dict_get_str (dict, "slave_ip", &slave_ip); +                if (ret) { +                        snprintf (errmsg, sizeof (errmsg), +                                  "Unable to fetch slave IP." +                                  " No Hooks Arguments."); +                        gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                        if (is_force) { +                                ret = 0; +                                goto create_essentials; +                        } +                        ret = -1; +                        goto out; +                } + +                ret = dict_get_int32 (dict, "push_pem", &is_pem_push); +                if (!ret && is_pem_push) { +                        gf_log ("", GF_LOG_DEBUG, "Trying to setup" +                                " pem files in slave"); +                        is_pem_push = 1; +                } else +                        is_pem_push = 0; + +                snprintf(hooks_args, sizeof(hooks_args), +                         "is_push_pem=%d pub_file=%s slave_ip=%s", +                         is_pem_push, common_pem_file, slave_ip); + +        } else +                snprintf(hooks_args, sizeof(hooks_args), +                         "This argument will stop the hooks script"); + +        arg_buf = gf_strdup (hooks_args); +        if (!arg_buf) { +                gf_log ("", GF_LOG_ERROR, "Failed to" +                        " gf_strdup"); +                if (is_force) { +                        ret = 0; +                        goto create_essentials; +                } +                ret = -1; +                goto out; +        } + +        ret = dict_set_str (dict, "hooks_args", arg_buf); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, "Failed to set" +                        " hooks_args in dict."); +                if (is_force) { +                        ret = 0; +                        goto create_essentials; +                } +                goto out; +        } + +create_essentials: + +        ret = glusterd_create_essential_dir_files (volinfo, dict, slave, slave_vol, op_errstr); +        if (ret) +                goto out; + +        ret = glusterd_store_slave_in_info (volinfo, slave, +                                            host_uuid, op_errstr, +                                            is_force); +        if (ret) { +                snprintf (errmsg, sizeof (errmsg), "Unable to store" +                          " slave info."); +                gf_log ("", GF_LOG_ERROR, "%s", errmsg); +                goto out;          }  out: diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 480ee01b0ce..38427d82292 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -3922,6 +3922,8 @@ rpcsvc_actor_t gd_svc_cli_actors[] = {  #ifdef HAVE_BD_XLATOR          [GLUSTER_CLI_BD_OP]              = {"BD_OP",              GLUSTER_CLI_BD_OP,            glusterd_handle_cli_bd_op,             NULL, 0, DRC_NA},  #endif +        [GLUSTER_CLI_COPY_FILE]     = {"COPY_FILE", GLUSTER_CLI_COPY_FILE, glusterd_handle_copy_file, NULL, 0, DRC_NA}, +        [GLUSTER_CLI_SYS_EXEC]      = {"SYS_EXEC", GLUSTER_CLI_SYS_EXEC, glusterd_handle_sys_exec, NULL, 0, DRC_NA},  };  struct rpcsvc_program gd_svc_cli_prog = { diff --git a/xlators/mgmt/glusterd/src/glusterd-hooks.c b/xlators/mgmt/glusterd/src/glusterd-hooks.c index a61e1e85f2d..2b43a452e0c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-hooks.c +++ b/xlators/mgmt/glusterd/src/glusterd-hooks.c @@ -49,6 +49,7 @@ char glusterd_hook_dirnames[GD_OP_MAX][256] =          [GD_OP_RESET_VOLUME]            = EMPTY,          [GD_OP_SYNC_VOLUME]             = EMPTY,          [GD_OP_LOG_ROTATE]              = EMPTY, +        [GD_OP_GSYNC_CREATE]            = "gsync-create",          [GD_OP_GSYNC_SET]               = EMPTY,          [GD_OP_PROFILE_VOLUME]          = EMPTY,          [GD_OP_QUOTA]                   = EMPTY, @@ -185,6 +186,7 @@ static int  glusterd_hooks_add_op_args (runner_t *runner, glusterd_op_t op,                              dict_t *op_ctx, glusterd_commit_hook_type_t type)  { +        char                   *hooks_args       = NULL;          int                     vol_count        = 0;          gf_boolean_t            truth            = _gf_false;          glusterd_volinfo_t      *voliter         = NULL; @@ -236,6 +238,18 @@ glusterd_hooks_add_op_args (runner_t *runner, glusterd_op_t op,                          ret = glusterd_hooks_set_volume_args (op_ctx, runner);                          break; +                case GD_OP_GSYNC_CREATE: +                        ret = dict_get_str (op_ctx, "hooks_args", &hooks_args); +                        if (ret) +                                gf_log ("", GF_LOG_DEBUG, +                                        "No Hooks Arguments."); +                        else +                                gf_log ("", GF_LOG_DEBUG, +                                        "Hooks Args = %s", hooks_args); +                        if (hooks_args) +                                runner_argprintf (runner, "%s", hooks_args); +                        break; +                  default:                          break; diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index fb8d1f17efb..1774b133b93 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -2504,12 +2504,13 @@ glusterd_op_build_payload (dict_t **req, char **op_errstr, dict_t *op_ctx)                          }                          break; +                case GD_OP_GSYNC_CREATE:                  case GD_OP_GSYNC_SET:                          {                                  ret = glusterd_op_gsync_args_get (dict,                                                                    &errstr,                                                                    &volname, -                                                                  NULL); +                                                                  NULL, NULL);                                  if (ret == 0) {                                          ret = glusterd_dict_set_volid                                                  (dict, volname, op_errstr); @@ -2622,6 +2623,18 @@ glusterd_op_build_payload (dict_t **req, char **op_errstr, dict_t *op_ctx)                          }                          break; +                case GD_OP_COPY_FILE: +                        { +                                dict_copy (dict, req_dict); +                                break; +                        } + +                case GD_OP_SYS_EXEC: +                        { +                                dict_copy (dict, req_dict); +                                break; +                        } +                  default:                          break;          } @@ -3755,6 +3768,10 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr,                          ret = glusterd_op_stage_sync_volume (dict, op_errstr);                          break; +                case GD_OP_GSYNC_CREATE: +                        ret = glusterd_op_stage_gsync_create (dict, op_errstr); +                        break; +                  case GD_OP_GSYNC_SET:                          ret = glusterd_op_stage_gsync_set (dict, op_errstr);                          break; @@ -3793,13 +3810,21 @@ glusterd_op_stage_validate (glusterd_op_t op, dict_t *dict, char **op_errstr,                          ret = glusterd_op_stage_bd (dict, op_errstr);                          break;  #endif + +                case GD_OP_COPY_FILE: +                        ret = glusterd_op_stage_copy_file (dict, op_errstr); +                        break; + +                case GD_OP_SYS_EXEC: +                        ret = glusterd_op_stage_sys_exec (dict, op_errstr); +                        break; +                  default:                          gf_log (this->name, GF_LOG_ERROR, "Unknown op %s",                                  gd_op_list[op]);          } -        gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); - +        gf_log (this->name, GF_LOG_DEBUG, "OP = %d. Returning %d", op, ret);          return ret;  } @@ -3857,6 +3882,11 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr,                          ret = glusterd_op_sync_volume (dict, op_errstr, rsp_dict);                          break; +                case GD_OP_GSYNC_CREATE: +                        ret = glusterd_op_gsync_create (dict, op_errstr, +                                                        rsp_dict); +                        break; +                  case GD_OP_GSYNC_SET:                          ret = glusterd_op_gsync_set (dict, op_errstr, rsp_dict);                          break; @@ -3896,6 +3926,15 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr,                          ret = 0;                          break;  #endif + +                case GD_OP_COPY_FILE: +                        ret = glusterd_op_copy_file (dict, op_errstr); +                        break; + +                case GD_OP_SYS_EXEC: +                        ret = glusterd_op_sys_exec (dict, op_errstr, rsp_dict); +                        break; +                  default:                          gf_log (this->name, GF_LOG_ERROR, "Unknown op %s",                                  gd_op_list[op]); @@ -3904,8 +3943,8 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr,          if (ret == 0)              glusterd_op_commit_hook (op, dict, GD_COMMIT_HOOK_POST); -        gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret); +        gf_log (this->name, GF_LOG_DEBUG, "Returning %d", ret);          return ret;  } diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index df8b8c1410e..321c5c484f5 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -15,8 +15,8 @@  #include "config.h"  #endif -#ifndef GSYNC_CONF -#define GSYNC_CONF GEOREP"/gsyncd.conf" +#ifndef GSYNC_CONF_TEMPLATE +#define GSYNC_CONF_TEMPLATE GEOREP"/gsyncd_template.conf"  #endif  #include <pthread.h> @@ -270,7 +270,7 @@ glusterd_are_all_volumes_stopped ();  int  glusterd_stop_bricks (glusterd_volinfo_t *volinfo);  int -gsync_status (char *master, char *slave, int *status); +gsync_status (char *master, char *slave, char *conf_path, int *status);  int  glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag); diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 18a74349487..2d8d381bf26 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -84,6 +84,7 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret,                  }                  break;          } +        case GD_OP_GSYNC_CREATE:          case GD_OP_GSYNC_SET:          {                 if (ctx) { @@ -146,6 +147,21 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret,                  /*nothing specific to be done*/                  break;          } +        case GD_OP_COPY_FILE: +        { +               if (ctx) +                        ret = dict_get_str (ctx, "errstr", &errstr); +               break; +        } +        case GD_OP_SYS_EXEC: +        { +               if (ctx) { +                        ret = dict_get_str (ctx, "errstr", &errstr); +                        ret = dict_set_str (ctx, "glusterd_workdir", +                                            conf->workdir); +               } +               break; +        }          }          rsp.op_ret = op_ret; diff --git a/xlators/mgmt/glusterd/src/glusterd-syncop.c b/xlators/mgmt/glusterd/src/glusterd-syncop.c index 7b0c28baf1a..a694cae84d1 100644 --- a/xlators/mgmt/glusterd/src/glusterd-syncop.c +++ b/xlators/mgmt/glusterd/src/glusterd-syncop.c @@ -32,14 +32,77 @@ gd_synctask_barrier_wait (struct syncargs *args, int count)  static void  gd_collate_errors (struct syncargs *args, int op_ret, int op_errno, -                   char *op_errstr) +                   char *op_errstr, int op_code, +                   glusterd_peerinfo_t *peerinfo, u_char *uuid)  { -        if (args->op_ret) -                return; -        args->op_ret = op_ret; -        args->op_errno = op_errno; -        if (op_ret && op_errstr && strcmp (op_errstr, "")) -                args->errstr = gf_strdup (op_errstr); +        char     err_str[PATH_MAX] = "Please check log file for details."; +        char     op_err[PATH_MAX] = ""; +        int      len               = -1; +        char    *peer_str      = NULL; + +        if (op_ret) { +                args->op_ret = op_ret; +                args->op_errno = op_errno; + +                if (peerinfo) +                        peer_str = peerinfo->hostname; +                else +                        peer_str = uuid_utoa (uuid); + +                if (op_errstr && strcmp (op_errstr, "")) { +                        len = snprintf (err_str, sizeof(err_str) - 1, +                                        "Error: %s", op_errstr); +                        err_str[len] = '\0'; +                } + +                switch (op_code){ +                        case GLUSTERD_MGMT_CLUSTER_LOCK : +                        { +                                len = snprintf (op_err, sizeof(op_err) - 1, +                                                "Locking failed on %s. %s", +                                                peer_str, err_str); +                                break; +                        } +                        case GLUSTERD_MGMT_CLUSTER_UNLOCK : +                        { +                                len = snprintf (op_err, sizeof(op_err) - 1, +                                                "Unlocking failed on %s. %s", +                                                peer_str, err_str); +                                break; +                        } +                        case GLUSTERD_MGMT_STAGE_OP : +                        { +                                len = snprintf (op_err, sizeof(op_err) - 1, +                                                "Staging failed on %s. %s", +                                                peer_str, err_str); +                                break; +                        } +                        case GLUSTERD_MGMT_COMMIT_OP : +                        { +                                len = snprintf (op_err, sizeof(op_err) - 1, +                                                "Commit failed on %s. %s", +                                                peer_str, err_str); +                                break; +                        } +                } +                op_err[len] = '\0'; + +                if (args->errstr) { +                        len = snprintf (err_str, sizeof(err_str) - 1, +                                        "%s\n%s", args->errstr, +                                        op_err); +                        GF_FREE (args->errstr); +                        args->errstr = NULL; +                } else +                        len = snprintf (err_str, sizeof(err_str) - 1, +                                        "%s", op_err); +                err_str[len] = '\0'; + +                gf_log ("", GF_LOG_ERROR, "%s", op_err); +                args->errstr = gf_strdup (err_str); +        } + +        return;  }  static void @@ -169,6 +232,9 @@ glusterd_syncop_aggr_rsp_dict (glusterd_op_t op, dict_t *aggr, dict_t *rsp)                          goto out;          break; +        case GD_OP_GSYNC_CREATE: +        break; +          case GD_OP_GSYNC_SET:                  ret = glusterd_gsync_use_rsp_dict (aggr, rsp, NULL);                  if (ret) @@ -203,6 +269,12 @@ glusterd_syncop_aggr_rsp_dict (glusterd_op_t op, dict_t *aggr, dict_t *rsp)          break; +        case GD_OP_SYS_EXEC: +                ret = glusterd_sys_exec_output_rsp_dict (aggr, rsp); +                if (ret) +                        goto out; +        break; +          default:          break;          } @@ -246,7 +318,8 @@ _gd_syncop_mgmt_lock_cbk (struct rpc_req *req, struct iovec *iov,          op_ret = rsp.op_ret;          op_errno = rsp.op_errno;  out: -        gd_collate_errors (args, op_ret, op_errno, NULL); +        gd_collate_errors (args, op_ret, op_errno, NULL, +                           GLUSTERD_MGMT_CLUSTER_LOCK, peerinfo, rsp.uuid);          STACK_DESTROY (frame->root);          synctask_barrier_wake(args);          return 0; @@ -312,7 +385,8 @@ _gd_syncop_mgmt_unlock_cbk (struct rpc_req *req, struct iovec *iov,          op_ret = rsp.op_ret;          op_errno = rsp.op_errno;  out: -        gd_collate_errors (args, op_ret, op_errno, NULL); +        gd_collate_errors (args, op_ret, op_errno, NULL, +                           GLUSTERD_MGMT_CLUSTER_UNLOCK, peerinfo, rsp.uuid);          STACK_DESTROY (frame->root);          synctask_barrier_wake(args);          return 0; @@ -356,6 +430,7 @@ _gd_syncop_stage_op_cbk (struct rpc_req *req, struct iovec *iov,          xlator_t                    *this       = NULL;          dict_t                      *rsp_dict   = NULL;          call_frame_t                *frame      = NULL; +        glusterd_peerinfo_t         *peerinfo   = NULL;          int                         op_ret      = -1;          int                         op_errno    = -1; @@ -389,6 +464,15 @@ _gd_syncop_stage_op_cbk (struct rpc_req *req, struct iovec *iov,                  }          } +        ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); +        if (ret) { +                gf_log (this->name, GF_LOG_CRITICAL, "Staging response " +                        "for 'Volume %s' received from unknown " +                        "peer: %s", gd_op_list[rsp.op], +                        uuid_utoa (rsp.uuid)); +                goto out; +        } +          uuid_copy (args->uuid, rsp.uuid);          if (rsp.op == GD_OP_REPLACE_BRICK) {                  pthread_mutex_lock (&args->lock_dict); @@ -407,7 +491,9 @@ _gd_syncop_stage_op_cbk (struct rpc_req *req, struct iovec *iov,          op_errno = rsp.op_errno;  out: -        gd_collate_errors (args, op_ret, op_errno, rsp.op_errstr); +        gd_collate_errors (args, op_ret, op_errno, rsp.op_errstr, +                           GLUSTERD_MGMT_STAGE_OP, peerinfo, rsp.uuid); +          if (rsp_dict)                  dict_unref (rsp_dict); @@ -588,14 +674,15 @@ int32_t  _gd_syncop_commit_op_cbk (struct rpc_req *req, struct iovec *iov,                            int count, void *myframe)  { -        int                         ret         = -1; -        gd1_mgmt_commit_op_rsp      rsp         = {{0},}; -        struct syncargs             *args       = NULL; -        xlator_t                    *this       = NULL; -        dict_t                      *rsp_dict   = NULL; -        call_frame_t                *frame      = NULL; -        int                         op_ret      = -1; -        int                         op_errno    = -1; +        int                          ret           = -1; +        gd1_mgmt_commit_op_rsp       rsp           = {{0},}; +        struct syncargs             *args          = NULL; +        xlator_t                    *this          = NULL; +        dict_t                      *rsp_dict      = NULL; +        call_frame_t                *frame         = NULL; +        glusterd_peerinfo_t         *peerinfo      = NULL; +        int                          op_ret        = -1; +        int                          op_errno      = -1;          this  = THIS;          frame = myframe; @@ -628,6 +715,15 @@ _gd_syncop_commit_op_cbk (struct rpc_req *req, struct iovec *iov,                  }          } +        ret = glusterd_friend_find (rsp.uuid, NULL, &peerinfo); +        if (ret) { +                gf_log (this->name, GF_LOG_CRITICAL, "Commit response " +                        "for 'Volume %s' received from unknown " +                        "peer: %s", gd_op_list[rsp.op], +                        uuid_utoa (rsp.uuid)); +                goto out; +        } +          uuid_copy (args->uuid, rsp.uuid);          pthread_mutex_lock (&args->lock_dict);          { @@ -642,8 +738,10 @@ _gd_syncop_commit_op_cbk (struct rpc_req *req, struct iovec *iov,          op_ret = rsp.op_ret;          op_errno = rsp.op_errno; +  out: -        gd_collate_errors (args, op_ret, op_errno, rsp.op_errstr); +        gd_collate_errors (args, op_ret, op_errno, rsp.op_errstr, +                           GLUSTERD_MGMT_COMMIT_OP, peerinfo, rsp.uuid);          if (rsp_dict)                  dict_unref (rsp_dict); @@ -816,12 +914,16 @@ stage_done:                  peer_cnt++;          }          gd_synctask_barrier_wait((&args), peer_cnt); -        ret = args.op_ret; -        if (dict_get_str (op_ctx, "errstr", &errstr) == 0) + +        if (args.errstr) +                 *op_errstr = gf_strdup (args.errstr); +        else if (dict_get_str (op_ctx, "errstr", &errstr) == 0)                  *op_errstr = gf_strdup (errstr); -        else if (args.errstr) -                *op_errstr = gf_strdup (args.errstr); +        ret = args.op_ret; + +        gf_log (this->name, GF_LOG_DEBUG, "Sent stage op req for 'Volume %s' " +                "to %d peers", gd_op_list[op], peer_cnt);  out:          if (rsp_dict)                  dict_unref (rsp_dict); @@ -881,6 +983,7 @@ commit_done:                  ret = 0;                  goto out;          } +          gd_syncargs_init (&args, op_ctx);          synctask_barrier_init((&args));          peer_cnt = 0; @@ -892,17 +995,23 @@ commit_done:          }          gd_synctask_barrier_wait((&args), peer_cnt);          ret = args.op_ret; -        if (dict_get_str (op_ctx, "errstr", &errstr) == 0) +        if (args.errstr) +                 *op_errstr = gf_strdup (args.errstr); +        else if (dict_get_str (op_ctx, "errstr", &errstr) == 0)                  *op_errstr = gf_strdup (errstr); -        else if (args.errstr) -                *op_errstr = gf_strdup (args.errstr); +        gf_log (this->name, GF_LOG_DEBUG, "Sent commit op req for 'Volume %s' " +                "to %d peers", gd_op_list[op], peer_cnt);  out:          if (!ret)                  glusterd_op_modify_op_ctx (op, op_ctx);          if (rsp_dict)                  dict_unref (rsp_dict); + +        GF_FREE (args.errstr); +        args.errstr = NULL; +          return ret;  } @@ -1108,8 +1217,10 @@ out:          if (req_dict)                  dict_unref (req_dict); -        if (op_errstr) +        if (op_errstr) {                  GF_FREE (op_errstr); +                op_errstr = NULL; +        }          return;  } diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index be5941830f8..6a760087c12 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -3969,10 +3969,13 @@ glusterd_restart_bricks (glusterd_conf_t *conf)  int  _local_gsyncd_start (dict_t *this, char *key, data_t *value, void *data)  { +        char                        *path_list = NULL;          char                        *slave = NULL;          int                          uuid_len = 0; +        int                          ret = 0;          char                         uuid_str[64] = {0};          glusterd_volinfo_t           *volinfo = NULL; +        char                         *conf_path = NULL;          volinfo = data;          GF_ASSERT (volinfo); @@ -3984,9 +3987,24 @@ _local_gsyncd_start (dict_t *this, char *key, data_t *value, void *data)          uuid_len = (slave - value->data - 1);          strncpy (uuid_str, (char*)value->data, uuid_len); -        glusterd_start_gsync (volinfo, slave, uuid_str, NULL); -        return 0; +        ret = glusterd_get_local_brickpaths (volinfo, &path_list); + +        ret = dict_get_str (this, "conf_path", &conf_path); +        if (ret) { +                gf_log ("", GF_LOG_ERROR, +                        "Unable to fetch conf file path."); +                goto out; +        } + +        glusterd_start_gsync (volinfo, slave, path_list, conf_path, +                              uuid_str, NULL); + +        GF_FREE (path_list); +        path_list = NULL; + +out: +        return ret;  }  int @@ -5425,12 +5443,92 @@ glusterd_delete_all_bricks (glusterd_volinfo_t* volinfo)  }  int +glusterd_get_local_brickpaths (glusterd_volinfo_t *volinfo, char **pathlist) +{ +        char                 **path_tokens  = NULL; +        char                  *tmp_path_list = NULL; +        char                   path[PATH_MAX] = ""; +        int32_t                count          = 0; +        int32_t                pathlen        = 0; +        int32_t                total_len      = 0; +        int32_t                ret            = 0; +        int                    i              = 0; +        glusterd_brickinfo_t  *brickinfo      = NULL; + +        if ((!volinfo) || (!pathlist)) +            goto out; + +        path_tokens = GF_CALLOC (sizeof(char*), volinfo->brick_count, +                                 gf_gld_mt_charptr); +        if (!path_tokens) { +                gf_log ("", GF_LOG_DEBUG, "Could not allocate memory."); +                ret = -1; +                goto out; +        } + +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +                if (uuid_compare (brickinfo->uuid, MY_UUID)) +                        continue; + +                 pathlen = snprintf (path, sizeof(path), +                                     "--path=%s ", brickinfo->path); +                 if (pathlen < sizeof(path)) +                        path[pathlen] = '\0'; +                 else +                        path[sizeof(path)-1] = '\0'; +                 path_tokens[count] = gf_strdup (path); +                 if (!path_tokens[count]) { +                        gf_log ("", GF_LOG_DEBUG, +                                "Could not allocate memory."); +                        ret = -1; +                        goto out; +                 } +                 count++; +                 total_len += pathlen; +        } + +        tmp_path_list = GF_CALLOC (sizeof(char), total_len + 1, +                                   gf_gld_mt_char); +        if (!tmp_path_list) { +                gf_log ("", GF_LOG_DEBUG, "Could not allocate memory."); +                ret = -1; +                goto out; +        } + +        for (i = 0; i < count; i++) +                strcat (tmp_path_list, path_tokens[i]); + +        if (count) +                *pathlist = tmp_path_list; + +        ret = count; +out: +        for (i = 0; i < count; i++) { +                GF_FREE (path_tokens[i]); +                path_tokens[i] = NULL; +        } + +        GF_FREE (path_tokens); +        path_tokens = NULL; + +        if (ret == 0) { +                gf_log ("", GF_LOG_DEBUG, "No Local Bricks Present."); +                GF_FREE (tmp_path_list); +                tmp_path_list = NULL; +        } + +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int  glusterd_start_gsync (glusterd_volinfo_t *master_vol, char *slave, -                      char *glusterd_uuid_str, char **op_errstr) +                      char *path_list, char *conf_path, +                      char *glusterd_uuid_str, +                      char **op_errstr)  {          int32_t         ret     = 0;          int32_t         status  = 0; -        char            buf[PATH_MAX]   = {0,};          char            uuid_str [64] = {0};          runner_t        runner = {0,};          xlator_t        *this = NULL; @@ -5443,32 +5541,23 @@ glusterd_start_gsync (glusterd_volinfo_t *master_vol, char *slave,          GF_ASSERT (priv);          uuid_utoa_r (MY_UUID, uuid_str); -        if (strcmp (uuid_str, glusterd_uuid_str)) -                goto out; - -        ret = gsync_status (master_vol->volname, slave, &status); -        if (status == 0) -                goto out; -        snprintf (buf, PATH_MAX, "%s/"GEOREP"/%s", priv->workdir, master_vol->volname); -        ret = mkdir_p (buf, 0777, _gf_true); -        if (ret) { -                errcode = -1; +        if (!path_list) { +                ret = 0; +                gf_log ("", GF_LOG_DEBUG, "No Bricks in this node." +                        " Not starting gsyncd.");                  goto out;          } -        snprintf (buf, PATH_MAX, DEFAULT_LOG_FILE_DIRECTORY"/"GEOREP"/%s", -                  master_vol->volname); -        ret = mkdir_p (buf, 0777, _gf_true); -        if (ret) { -                errcode = -1; +        ret = gsync_status (master_vol->volname, slave, conf_path, &status); +        if (status == 0)                  goto out; -        }          uuid_utoa_r (master_vol->volume_id, uuid_str);          runinit (&runner); -        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); +        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", +                          path_list, "-c", NULL); +        runner_argprintf (&runner, "%s", conf_path);          runner_argprintf (&runner, ":%s", master_vol->volname);          runner_add_args  (&runner, slave, "--config-set", "session-owner",                            uuid_str, NULL); @@ -5481,9 +5570,12 @@ glusterd_start_gsync (glusterd_volinfo_t *master_vol, char *slave,          }          runinit (&runner); -        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", "--monitor", "-c", NULL); -        runner_argprintf (&runner, "%s/"GSYNC_CONF, priv->workdir); +        runner_add_args  (&runner, GSYNCD_PREFIX"/gsyncd", +                          path_list, "--monitor", "-c", NULL); +        runner_argprintf (&runner, "%s", conf_path);          runner_argprintf (&runner, ":%s", master_vol->volname); +        runner_argprintf (&runner, "--glusterd-uuid=%s", +                          uuid_utoa (priv->uuid));          runner_add_arg   (&runner, slave);          synclock_unlock (&priv->big_lock);          ret = runner_run (&runner); @@ -5499,7 +5591,7 @@ glusterd_start_gsync (glusterd_volinfo_t *master_vol, char *slave,  out:          if ((ret != 0) && errcode == -1) {                  if (op_errstr) -                        *op_errstr = gf_strdup ("internal error, cannot start" +                        *op_errstr = gf_strdup ("internal error, cannot start "                                                  "the " GEOREP " session");          } @@ -6853,6 +6945,61 @@ out:  }  int +glusterd_sys_exec_output_rsp_dict (dict_t *dst, dict_t *src) +{ +        char           output_name[PATH_MAX] = ""; +        char          *output = NULL; +        int            ret      = 0; +        int            i      = 0; +        int            len    = 0; +        int            src_output_count      = 0; +        int            dst_output_count      = 0; + +        if (!dst || !src) { +                gf_log ("", GF_LOG_ERROR, "Source or Destination " +                        "dict is empty."); +                goto out; +        } + +        ret = dict_get_int32 (dst, "output_count", &dst_output_count); + +        ret = dict_get_int32 (src, "output_count", &src_output_count); +        if (ret) { +                gf_log ("", GF_LOG_DEBUG, "No output from source"); +                ret = 0; +                goto out; +        } + +        for (i = 1; i <= src_output_count; i++) { +                len = snprintf (output_name, sizeof(output_name) - 1, +                                "output_%d", i); +                output_name[len] = '\0'; +                ret = dict_get_str (src, output_name, &output); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to fetch %s", +                                output_name); +                        goto out; +                } + +                len = snprintf (output_name, sizeof(output_name) - 1, +                                "output_%d", i+dst_output_count); +                output_name[len] = '\0'; +                ret = dict_set_dynstr (dst, output_name, gf_strdup (output)); +                if (ret) { +                        gf_log ("", GF_LOG_ERROR, "Unable to set %s", +                                output_name); +                        goto out; +                } +        } + +        ret = dict_set_int32 (dst, "output_count", +                              dst_output_count+src_output_count); +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} + +int  glusterd_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict)  {          int            ret      = 0; @@ -7404,3 +7551,39 @@ gd_is_remove_brick_committed (glusterd_volinfo_t *volinfo)          return _gf_true;  } + +gf_boolean_t +glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, +                               struct list_head *peers, +                               char **down_peerstr) +{ +        glusterd_peerinfo_t   *peerinfo  = NULL; +        glusterd_brickinfo_t  *brickinfo = NULL; +        gf_boolean_t           ret       = _gf_false; + +        list_for_each_entry (brickinfo, &volinfo->bricks, brick_list) { +                if (!uuid_compare (brickinfo->uuid, MY_UUID)) +                        continue; + +                list_for_each_entry (peerinfo, peers, uuid_list) { +                        if (uuid_compare (peerinfo->uuid, brickinfo->uuid)) +                                continue; + +                        /*Found peer who owns the brick, return false +                         * if peer is not connected or not friend */ +                        if (!(peerinfo->connected) || +                           (peerinfo->state.state != +                             GD_FRIEND_STATE_BEFRIENDED)) { +                                *down_peerstr = gf_strdup (peerinfo->hostname); +                                gf_log ("", GF_LOG_DEBUG, "Peer %s is down. ", +                                        peerinfo->hostname); +                                goto out; +                        } +                } +       } + +        ret = _gf_true; +out: +        gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); +        return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 912b394b497..818b3f4faed 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -367,7 +367,13 @@ int  glusterd_restart_gsyncds (glusterd_conf_t *conf);  int  glusterd_start_gsync (glusterd_volinfo_t *master_vol, char *slave, -                      char *glusterd_uuid_str, char **op_errstr); +                      char *path_list, char *conf_path, +                      char *glusterd_uuid_str, +                      char **op_errstr); +int +glusterd_get_local_brickpaths (glusterd_volinfo_t *volinfo, +                               char **pathlist); +  int32_t  glusterd_recreate_bricks (glusterd_conf_t *conf);  int32_t @@ -471,6 +477,8 @@ int  glusterd_volume_heal_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict);  int  glusterd_use_rsp_dict (dict_t *aggr, dict_t *rsp_dict); +int +glusterd_sys_exec_output_rsp_dict (dict_t *aggr, dict_t *rsp_dict);  int32_t  glusterd_handle_node_rsp (dict_t *req_ctx, void *pending_entry,                            glusterd_op_t op, dict_t *rsp_dict, dict_t *op_ctx, @@ -487,6 +495,11 @@ glusterd_profile_volume_brick_rsp (void *pending_entry,                                     dict_t *rsp_dict, dict_t *op_ctx,                                     char **op_errstr, gd_node_type type); +gf_boolean_t +glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, +                               struct list_head *peers, +                               char **down_peerstr); +  /* Should be used only when an operation is in progress, as that is the only   * time a lock_owner is set   */ @@ -531,4 +544,9 @@ gd_peer_uuid_str (glusterd_peerinfo_t *peerinfo);  gf_boolean_t  gd_is_remove_brick_committed (glusterd_volinfo_t *volinfo); + +gf_boolean_t +glusterd_are_vol_all_peers_up (glusterd_volinfo_t *volinfo, +                               struct list_head *peers, +                               char **down_peerstr);  #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h index 6a41f47c16c..4ff899f4aad 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.h +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h @@ -23,6 +23,7 @@  #define VKEY_DIAG_LAT_MEASUREMENT "diagnostics.latency-measurement"  #define VKEY_FEATURES_LIMIT_USAGE "features.limit-usage"  #define VKEY_MARKER_XTIME         GEOREP".indexing" +#define VKEY_CHANGELOG            "changelog.changelog"  #define VKEY_FEATURES_QUOTA       "features.quota"  #define AUTH_ALLOW_MAP_KEY "auth.allow" diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index 53ca33ef92a..a43c8d54207 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -94,6 +94,9 @@ const char *gd_op_list[GD_OP_MAX + 1] = {          [GD_OP_LIST_VOLUME]             = "Lists",          [GD_OP_CLEARLOCKS_VOLUME]       = "Clear locks",          [GD_OP_DEFRAG_BRICK_VOLUME]     = "Rebalance", +        [GD_OP_COPY_FILE]               = "Copy File", +        [GD_OP_SYS_EXEC]                = "Execute system commands", +        [GD_OP_GSYNC_CREATE]            = "Geo-replication Create",          [GD_OP_MAX]                     = "Invalid op"  }; @@ -519,7 +522,7 @@ runinit_gsyncd_setrx (runner_t *runner, glusterd_conf_t *conf)  {          runinit (runner);          runner_add_args (runner, GSYNCD_PREFIX"/gsyncd", "-c", NULL); -        runner_argprintf (runner, "%s/"GSYNC_CONF,conf->workdir); +        runner_argprintf (runner, "%s/"GSYNC_CONF_TEMPLATE, conf->workdir);          runner_add_arg (runner, "--config-set-rx");  } @@ -581,7 +584,7 @@ configure_syncdaemon (glusterd_conf_t *conf)          /* gluster-params */          runinit_gsyncd_setrx (&runner, conf);          runner_add_args (&runner, "gluster-params", -                         "xlator-option=*-dht.assert-no-child-down=true", +                         "aux-gfid-mount xlator-option=*-dht.assert-no-child-down=true",                           ".", ".", NULL);          RUN_GSYNCD_CMD; @@ -598,14 +601,30 @@ configure_syncdaemon (glusterd_conf_t *conf)          /* pid-file */          runinit_gsyncd_setrx (&runner, conf);          runner_add_arg (&runner, "pid-file"); -        runner_argprintf (&runner, "%s/${mastervol}/${eSlave}.pid", georepdir); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}.pid", georepdir);          runner_add_args (&runner, ".", ".", NULL);          RUN_GSYNCD_CMD;          /* state-file */          runinit_gsyncd_setrx (&runner, conf);          runner_add_arg (&runner, "state-file"); -        runner_argprintf (&runner, "%s/${mastervol}/${eSlave}.status", georepdir); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}.status", georepdir); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* state-detail-file */ +        runinit_gsyncd_setrx (&runner, conf); +        runner_add_arg (&runner, "state-detail-file"); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}-detail.status", +                          georepdir); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        /* state-detail-file */ +        runinit_gsyncd_setrx (&runner, conf); +        runner_add_arg (&runner, "state-detail-file"); +        runner_argprintf (&runner, "%s/${mastervol}-${slavevol}/${eSlave}-detail.status", +                          georepdir);          runner_add_args (&runner, ".", ".", NULL);          RUN_GSYNCD_CMD; @@ -647,6 +666,18 @@ configure_syncdaemon (glusterd_conf_t *conf)          runner_add_args (&runner, "special-sync-mode", "partial", ".", ".", NULL);          RUN_GSYNCD_CMD; +        /* change-detector == changelog */ +        runinit_gsyncd_setrx (&runner, conf); +        runner_add_args(&runner, "change-detector", "changelog", ".", ".", NULL); +        RUN_GSYNCD_CMD; + +        runinit_gsyncd_setrx (&runner, conf); +        runner_add_arg(&runner, "working-dir"); +        runner_argprintf(&runner, "%s/${mastervol}/${eSlave}", +                         DEFAULT_VAR_RUN_DIRECTORY); +        runner_add_args (&runner, ".", ".", NULL); +        RUN_GSYNCD_CMD; +          /************           * slave pre-configuration           ************/ @@ -660,7 +691,7 @@ configure_syncdaemon (glusterd_conf_t *conf)          /* gluster-params */          runinit_gsyncd_setrx (&runner, conf);          runner_add_args (&runner, "gluster-params", -                         "xlator-option=*-dht.assert-no-child-down=true", +                         "aux-gfid-mount xlator-option=*-dht.assert-no-child-down=true",                           ".", NULL);          RUN_GSYNCD_CMD; @@ -967,6 +998,7 @@ init (xlator_t *this)                  first_time = 1;          } +        setenv ("GLUSTERD_WORKING_DIR", workdir, 1);          gf_log (this->name, GF_LOG_INFO, "Using %s as working directory",                  workdir); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 6bd9431e83e..ccdf1c435e9 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -47,6 +47,7 @@  #define GLUSTERD_QUORUM_TYPE_KEY        "cluster.server-quorum-type"  #define GLUSTERD_QUORUM_RATIO_KEY       "cluster.server-quorum-ratio"  #define GLUSTERD_GLOBAL_OPT_VERSION     "global-option-version" +#define GLUSTERD_COMMON_PEM_PUB_FILE    "/geo-replication/common_secret.pem.pub"  #define GLUSTERD_SERVER_QUORUM "server" @@ -95,6 +96,9 @@ typedef enum glusterd_op_ {          GD_OP_CLEARLOCKS_VOLUME,          GD_OP_DEFRAG_BRICK_VOLUME,          GD_OP_BD_OP, +        GD_OP_COPY_FILE, +        GD_OP_SYS_EXEC, +        GD_OP_GSYNC_CREATE,          GD_OP_MAX,  } glusterd_op_t; @@ -602,6 +606,12 @@ int  glusterd_handle_reset_volume (rpcsvc_request_t *req);  int +glusterd_handle_copy_file (rpcsvc_request_t *req); + +int +glusterd_handle_sys_exec (rpcsvc_request_t *req); + +int  glusterd_handle_gsync_set (rpcsvc_request_t *req);  int @@ -685,6 +695,12 @@ int glusterd_op_stage_heal_volume (dict_t *dict, char **op_errstr);  int glusterd_op_heal_volume (dict_t *dict, char **op_errstr);  int glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr);  int glusterd_op_gsync_set (dict_t *dict, char **op_errstr, dict_t *rsp_dict); +int glusterd_op_stage_copy_file (dict_t *dict, char **op_errstr); +int glusterd_op_copy_file (dict_t *dict, char **op_errstr); +int glusterd_op_stage_sys_exec (dict_t *dict, char **op_errstr); +int glusterd_op_sys_exec (dict_t *dict, char **op_errstr, dict_t *rsp_dict); +int glusterd_op_stage_gsync_create (dict_t *dict, char **op_errstr); +int glusterd_op_gsync_create (dict_t *dict, char **op_errstr, dict_t *rsp_dict);  int glusterd_op_quota (dict_t *dict, char **op_errstr, dict_t *rsp_dict);  int glusterd_op_stage_quota (dict_t *dict, char **op_errstr);  int glusterd_op_stage_replace_brick (dict_t *dict, char **op_errstr, @@ -726,7 +742,7 @@ int glusterd_op_statedump_volume_args_get (dict_t *dict, char **volname,                                             char **options, int *option_cnt);  int glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, -                                char **master, char **slave); +                                char **master, char **slave, char **host_uuid);  /* Synctask part */  int32_t glusterd_op_begin_synctask (rpcsvc_request_t *req, glusterd_op_t op,                                      void *dict);  | 
