From 93cb168fb362c7aea3c10371574a5c5566bb0222 Mon Sep 17 00:00:00 2001 From: Kaushik BV Date: Wed, 13 Apr 2011 22:14:37 +0000 Subject: mgmt/glusterd: Implementation of volume gsync status [master [slave]] Changes made in the path of gsync start/stop as well, where we maintain a list of active gsync sessions, hence gsync stop could be executed at all nodes. A new dict in glusterd_volinfo_t added to maintain an active list of gsync slaves running on each master. Signed-off-by: Kaushik BV Signed-off-by: Anand Avati BUG: 2536 (gsync service introspection) URL: http://bugs.gluster.com/cgi-bin/bugzilla3/show_bug.cgi?id=2536 --- cli/src/cli-cmd-parser.c | 49 +- cli/src/cli-rpc-ops.c | 77 +- rpc/xdr/src/cli1-xdr.c | 3 + rpc/xdr/src/cli1-xdr.h | 9 + rpc/xdr/src/cli1-xdr.x | 1 + xlators/mgmt/glusterd/src/glusterd-handler.c | 30 +- xlators/mgmt/glusterd/src/glusterd-op-sm.c | 1074 ++++++++++++++++++++++---- xlators/mgmt/glusterd/src/glusterd-op-sm.h | 15 + xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 115 ++- xlators/mgmt/glusterd/src/glusterd-store.c | 49 +- xlators/mgmt/glusterd/src/glusterd-utils.c | 8 + xlators/mgmt/glusterd/src/glusterd.h | 2 + 12 files changed, 1267 insertions(+), 165 deletions(-) diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index 1cfba3561fc..e8b0e778ae6 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1120,13 +1120,14 @@ out: int32_t cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) { - int32_t ret = 0; + int32_t ret = -1; int32_t config_type = 0; dict_t *dict = NULL; gf1_cli_gsync_set type = GF_GSYNC_OPTION_TYPE_NONE; char *append_str = NULL; size_t append_len = 0; int i = 0; + int32_t status_type = 0; GF_ASSERT (words); GF_ASSERT (options); @@ -1138,6 +1139,43 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) if (!dict) goto out; + if (wordcount < 3) + goto out; + + if ((strcmp (words[2], "status")) == 0) { + type = GF_GSYNC_OPTION_TYPE_STATUS; + + if (wordcount == 3) + status_type = GF_GSYNC_OPTION_TYPE_STATUS_ALL; + else if (wordcount == 4) + status_type = GF_GSYNC_OPTION_TYPE_STATUS_MASTER; + else if (wordcount == 5) + status_type = GF_GSYNC_OPTION_TYPE_STATUS_MST_SLV; + else + goto out; + + + ret = dict_set_int32 (dict, "status-type", status_type); + if (ret < 0) + goto out; + + if (wordcount < 4) + goto set_type; + ret = dict_set_str (dict, "master", (char *)words[3]); + if (ret < 0) + goto out; + + if (wordcount < 5) + goto set_type; + ret = dict_set_str (dict, "slave", (char *)words[4]); + if (ret < 0) + goto out; + + + + goto set_type; + } + if (wordcount < 5) goto out; @@ -1150,12 +1188,18 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) goto out; if ((strcmp (words[2], "start")) == 0) { + if (wordcount != 5) + goto out; + type = GF_GSYNC_OPTION_TYPE_START; goto set_type; } if ((strcmp (words[2], "stop")) == 0) { + if (wordcount != 5) + goto out; + type = GF_GSYNC_OPTION_TYPE_STOP; goto set_type; @@ -1219,6 +1263,9 @@ cli_cmd_gsync_set_parse (const char **words, int wordcount, dict_t **options) ret = dict_set_int32 (dict, "config_type", config_type); if (ret < 0) goto out; + } else { + ret = -1; + goto out; } set_type: diff --git a/cli/src/cli-rpc-ops.c b/cli/src/cli-rpc-ops.c index 9da2d9378f8..a6665d1ed5d 100644 --- a/cli/src/cli-rpc-ops.c +++ b/cli/src/cli-rpc-ops.c @@ -2580,6 +2580,7 @@ out: return ret; } + int gf_cli3_1_gsync_get_command (gf1_cli_gsync_set_rsp rsp) { @@ -2616,6 +2617,7 @@ gf_cli3_1_gsync_get_command (gf1_cli_gsync_set_rsp rsp) return 0; } + int gf_cli3_1_gsync_get_param_file (char *prmfile, const char *ext, char *master, char *slave, char *gl_workdir) { @@ -2673,6 +2675,55 @@ gf_cli3_1_gsync_get_param_file (char *prmfile, const char *ext, char *master, ch return ret ? -1 : 0; } +int +gf_cli3_1_gsync_out_status (dict_t *dict) +{ + 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 *mst_val = NULL; + char *slv_val = NULL; + char *sts_val = NULL; + + + ret = dict_get_int32 (dict, "gsync-count", &gsync_count); + if (ret) { + cli_out ("No Gsync sessions for the selected"); + ret = 0; + goto out; + } + + cli_out ("Gsync Status:"); + + for (i = 1; i <= gsync_count; 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, mst, &mst_val); + if (ret) + goto out; + + ret = dict_get_str (dict, slv, &slv_val); + if (ret) + goto out; + + ret = dict_get_str (dict, sts, &sts_val); + if (ret) + goto out; + + cli_out ("Master:%-20s Slave:%-50s Status:%-10s", mst_val, + slv_val, sts_val); + + } + + out: + return ret; + +} /* status: 0 when gsync is running * -1 when not running @@ -2860,6 +2911,7 @@ gf_cli3_1_gsync_set_cbk (struct rpc_req *req, struct iovec *iov, { int ret = 0; gf1_cli_gsync_set_rsp rsp = {0, }; + dict_t *dict = NULL; if (req->rpc_status == -1) { ret = -1; @@ -2873,6 +2925,20 @@ gf_cli3_1_gsync_set_cbk (struct rpc_req *req, struct iovec *iov, goto out; } + dict = dict_new (); + + if (!dict) { + ret = -1; + goto out; + } + + ret = dict_unserialize (rsp.status_dict.status_dict_val, + rsp.status_dict.status_dict_len, + &dict); + + if (ret) + goto out; + if (rsp.op_ret) { cli_out ("%s", rsp.op_errstr ? rsp.op_errstr : "command unsuccessful"); @@ -2882,10 +2948,17 @@ gf_cli3_1_gsync_set_cbk (struct rpc_req *req, struct iovec *iov, if (rsp.type == GF_GSYNC_OPTION_TYPE_START) ret = gf_cli3_1_start_gsync (rsp.master, rsp.slave, rsp.glusterd_workdir); - else if (rsp.config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL) + else if (rsp.config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL + || rsp.config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET) ret = gf_cli3_1_gsync_get_command (rsp); - else + else if (rsp.type == GF_GSYNC_OPTION_TYPE_STATUS) + ret = gf_cli3_1_gsync_out_status (dict); + else if (rsp.type == GF_GSYNC_OPTION_TYPE_STOP) + cli_out ("Gsync session stopped successfully"); + else if (!rsp.op_errstr) cli_out ("command executed successfully"); + else + cli_out (rsp.op_errstr); } out: ret = rsp.op_ret; diff --git a/rpc/xdr/src/cli1-xdr.c b/rpc/xdr/src/cli1-xdr.c index fa24ad90bbb..f1594eb9662 100644 --- a/rpc/xdr/src/cli1-xdr.c +++ b/rpc/xdr/src/cli1-xdr.c @@ -761,6 +761,9 @@ xdr_gf1_cli_gsync_set_rsp (XDR *xdrs, gf1_cli_gsync_set_rsp *objp) return FALSE; if (!xdr_string (xdrs, &objp->glusterd_workdir, ~0)) return FALSE; + if (!xdr_bytes (xdrs, (char **)&objp->status_dict.status_dict_val, + (u_int *) &objp->status_dict.status_dict_len, ~0)) + return FALSE; return TRUE; } diff --git a/rpc/xdr/src/cli1-xdr.h b/rpc/xdr/src/cli1-xdr.h index dba58349296..2002a3ae473 100644 --- a/rpc/xdr/src/cli1-xdr.h +++ b/rpc/xdr/src/cli1-xdr.h @@ -92,6 +92,11 @@ enum gf1_cli_gsync_set { GF_GSYNC_OPTION_TYPE_CONFIG_DEL = 5, GF_GSYNC_OPTION_TYPE_CONFIG_GET = 6, GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL = 7, + GF_GSYNC_OPTION_TYPE_STATUS = 8, + GF_GSYNC_OPTION_TYPE_STATUS_ALL = 9, + GF_GSYNC_OPTION_TYPE_STATUS_MASTER = 10, + GF_GSYNC_OPTION_TYPE_STATUS_MST_SLV = 11 + }; typedef enum gf1_cli_gsync_set gf1_cli_gsync_set; @@ -482,6 +487,10 @@ struct gf1_cli_gsync_set_rsp { char *slave; char *gsync_prefix; char *glusterd_workdir; + struct { + u_int status_dict_len; + char *status_dict_val; + } status_dict; }; typedef struct gf1_cli_gsync_set_rsp gf1_cli_gsync_set_rsp; diff --git a/rpc/xdr/src/cli1-xdr.x b/rpc/xdr/src/cli1-xdr.x index 035927f89e4..fc38cf7b252 100644 --- a/rpc/xdr/src/cli1-xdr.x +++ b/rpc/xdr/src/cli1-xdr.x @@ -347,6 +347,7 @@ struct gf1_cli_gsync_set_rsp { string slave<>; string gsync_prefix<>; string glusterd_workdir<>; + opaque status_dict<>; }; struct gf1_cli_stats_volume_req { diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index 3ebe5f51f42..247c655b031 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -1669,8 +1669,14 @@ glusterd_handle_gsync_set (rpcsvc_request_t *req) char *slave = NULL; char operation[256] = {0,}; int type = 0; + glusterd_conf_t *priv = NULL; + char *host_uuid = NULL; GF_ASSERT (req); + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; ret = glusterd_op_set_cli_op (cli_op); if (ret) { @@ -1701,20 +1707,32 @@ glusterd_handle_gsync_set (rpcsvc_request_t *req) } else { dict->extra_stdfree = cli_req.dict.dict_val; } + + host_uuid = gf_strdup (uuid_utoa(priv->uuid)); + if (host_uuid == NULL) { + gf_log ("glusterd", GF_LOG_ERROR, "failed to get" + "the uuid of the host machine"); + ret = -1; + goto out; + } + ret = dict_set_dynstr (dict, "host-uuid", host_uuid); + if (ret) + goto out; + } ret = dict_get_str (dict, "master", &master); if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "master not found, while handling" + gf_log ("", GF_LOG_INFO, "master not found, while handling" "gsync options"); - goto out; + master = "(No Master)"; } ret = dict_get_str (dict, "slave", &slave); if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "slave not not found, while" + gf_log ("", GF_LOG_INFO, "slave not not found, while" "handling gsync options"); - goto out; + slave = "(No Slave)"; } ret = dict_get_int32 (dict, "type", &type); @@ -1737,6 +1755,10 @@ glusterd_handle_gsync_set (rpcsvc_request_t *req) case GF_GSYNC_OPTION_TYPE_CONFIGURE: strncpy (operation, "configure", sizeof (operation)); break; + + case GF_GSYNC_OPTION_TYPE_STATUS: + strncpy (operation, "status", sizeof (operation)); + break; } gf_cmd_log ("volume gsync", " %s command on %s,%s", operation, master, diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 56ea9a19d71..ad95e340c70 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -1694,6 +1694,115 @@ volname_from_master (char *master) return gf_strdup (master+1); } +int +glusterd_gsync_get_cannonical_slave_name (char *cann, char *master, char *slave) +{ + FILE *in = NULL; + char buff[PATH_MAX] = {0, }; + char cmd[PATH_MAX] = {0, }; + char *ptr = NULL; + char buffer[PATH_MAX] = {0, }; + glusterd_conf_t *priv = NULL; + int ret = 0; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + snprintf (cmd, PATH_MAX, GSYNCD_PREFIX"/gsyncd" + " --canonicalize-url" + " %s %s", master, slave); + if (!(in = popen(cmd, "r"))) { + gf_log ("", GF_LOG_ERROR, "popen failed"); + return -1; + } + + ptr = fgets(buff, sizeof(buff), in); + if (ptr == NULL) { + ret = -1; + goto out; + } + + memset (buff, 0, PATH_MAX); + memset (buffer, 0, PATH_MAX); + + ptr = fgets(buff, sizeof(buff), in); + if (ptr) { + buff[strlen(buff)-1]='\0'; //strip off \n + strncpy (cann, buff, PATH_MAX); + } + + out: + ret |= pclose (in); + + if (ret) + gf_log ("", GF_LOG_ERROR, "popen failed"); + + return ret ? -1 : 0; + +} + +int +glusterd_gsync_get_param_file (char *prmfile, const char *ext, char *master, + char *slave, char *gl_workdir) +{ + FILE *in = NULL; + char buff[PATH_MAX] = {0, }; + char cmd[PATH_MAX] = {0, }; + char *ptr = NULL; + char prmfolder[PATH_MAX] = {0, }; + char *dotp = NULL; + int ret = 0; + + if (!(master && slave && gl_workdir)) { + GF_ASSERT (!master && !slave && !gl_workdir); + /* extension adjustment mode */ + + dotp = strrchr (prmfile, '.'); + if (!dotp++ || + /* overflow */ + dotp - prmfile + strlen (ext) + 1 > PATH_MAX) + return -1; + + strcpy (dotp, ext); + return 0; + } + + snprintf (cmd, PATH_MAX, GSYNCD_PREFIX"/gsyncd" + " --canonicalize-escape-url" + " %s %s", master, slave); + if (!(in = popen(cmd, "r"))) { + gf_log ("", GF_LOG_ERROR, "popen failed"); + return -1; + } + + ptr = fgets(buff, sizeof(buff), in); + if (ptr) { + buff[strlen(buff)-1]='\0'; //strip off \n + snprintf (prmfolder, PATH_MAX, "%s/gsync/%s", gl_workdir, buff); + } else { + ret = -1; + goto out; + } + + memset (buff, 0, PATH_MAX); + + ptr = fgets(buff, sizeof(buff), in); + if (ptr) { + buff[strlen(buff)-1]='\0'; //strip off \n + snprintf (prmfile, PATH_MAX, "%s/%s.%s", prmfolder, buff, ext); + } + + out: + ret |= pclose (in); + + if (ret) + gf_log ("", GF_LOG_ERROR, "popen failed"); + + return ret ? -1 : 0; +} + int glusterd_gsync_get_pid_file (char *pidfile, char *master, char *slave) { @@ -1752,30 +1861,34 @@ glusterd_gsync_get_pid_file (char *pidfile, char *master, char *slave) int gsync_status (char *master, char *slave, int *status) { - int ret = -1; - char pidfile[PATH_MAX] = {0,}; - FILE *file = NULL; + int ret = -1; + char pidfile[PATH_MAX] = {0,}; + FILE *file = NULL; + 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); GF_VALIDATE_OR_GOTO ("gsync", status, out); - ret = glusterd_gsync_get_pid_file (pidfile, master, slave); + ret = glusterd_gsync_get_param_file (pidfile, "pid", master, + slave, priv->workdir); if (ret == -1) { - ret = -1; gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); goto out; } + *status = -1; file = fopen (pidfile, "r+"); if (file) { ret = lockf (fileno (file), F_TEST, 0); - if (ret == 0) - *status = -1; - else + if (ret != 0) *status = 0; - } else - *status = -1; + } ret = 0; out: return ret; @@ -1875,6 +1988,93 @@ gsync_validate_config_option (dict_t *dict, int32_t config_type, return ret; } +static void +_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 master[PATH_MAX] = {0, }; + + param = (glusterd_gsync_status_temp_t *)data; + + slave = strchr(value->data, ':'); + if (slave) + slave ++; + else + return; + + master[0] = ':'; + strcat (master, param->volinfo->volname); + + ret = glusterd_get_gsync_status_mst_slv(param->volinfo, master, + slave, param->rsp_dict); + +} + +/* The return status indicates success (ret_status = 0) if the host uuid + * matches, status indicates failure (ret_status = -1) if the host uuid + * mismatches, status indicates not found if the slave is not found to be + * spawned for the given master */ +static void +_compare_host_uuid (dict_t *this, char *key, data_t *value, void *data) +{ + glusterd_gsync_slaves_t *status = NULL; + char *slave = NULL; + int uuid_len = 0; + + status = (glusterd_gsync_slaves_t *)data; + + if ((status->ret_status == -1) || (status->ret_status == 0)) + return; + slave = strchr(value->data, ':'); + if (slave) + slave ++; + + uuid_len = (slave - value->data - 1); + + if (strncmp (slave, status->slave, PATH_MAX) == 0) { + if (strncmp (value->data, status->host_uuid, uuid_len) == 0) { + status->ret_status = 0; + } else { + status->ret_status = -1; + strncpy (status->rmt_hostname, value->data, uuid_len); + status->rmt_hostname[uuid_len] = '\0'; + } + } + +} + +static void +_get_max_gsync_slave_num (dict_t *this, char *key, data_t *value, void *data) +{ + int tmp_slvnum = 0; + glusterd_gsync_slaves_t *status = NULL; + + status = (glusterd_gsync_slaves_t *)data; + + sscanf (key, "slave%d", &tmp_slvnum); + if (tmp_slvnum > status->ret_status) + status->ret_status = tmp_slvnum; +} + +static void +_remove_gsync_slave (dict_t *this, char *key, data_t *value, void *data) +{ + glusterd_gsync_slaves_t *status = NULL; + char *slave = NULL; + + + status = (glusterd_gsync_slaves_t *)data; + + slave = strchr(value->data, ':'); + if (slave) + slave ++; + + if (strncmp (slave, status->slave, PATH_MAX) == 0) + dict_del (this, key); + +} int gsync_verify_config_options (dict_t *dict, char **op_errstr) @@ -1909,41 +2109,286 @@ out: } static int -glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) +glusterd_remove_slave_in_info (glusterd_volinfo_t *volinfo, char *master, + char *slave,char *host_uuid, char **op_errstr) { - int ret = 0; - int type = 0; - int status = 0; - dict_t *ctx = NULL; - char *volname = NULL; - char *master = NULL; - char *slave = NULL; - gf_boolean_t exists = _gf_false; - glusterd_volinfo_t *volinfo = NULL; + int ret = 0; + glusterd_gsync_slaves_t status = {0, }; + char cann_slave[PATH_MAX] = {0, }; - ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); - if (!ctx) { - gf_log ("gsync", GF_LOG_DEBUG, "gsync command doesn't " - "correspond to this glusterd"); + GF_ASSERT (volinfo); + GF_ASSERT (master); + GF_ASSERT (slave); + GF_ASSERT (host_uuid); + + ret = glusterd_gsync_get_cannonical_slave_name (cann_slave, master, + slave); + if (ret) + goto out; + + status.slave = cann_slave; + status.host_uuid = host_uuid; + status.ret_status = 1; + + dict_foreach (volinfo->gsync_slaves, _remove_gsync_slave, &status); + + ret = glusterd_store_volinfo (volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) { + *op_errstr = gf_strdup ("Failed to store the Volume" + "information"); goto out; } + out: + gf_log ("", GF_LOG_DEBUG, "returning %d", ret); + return ret; - ret = dict_get_str (dict, "master", &master); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "master not found"); - *op_errstr = gf_strdup ("master not found"); +} + +static int +glusterd_gsync_get_uuid (char *master, char *slave, glusterd_volinfo_t *vol, + uuid_t uuid) +{ + + int ret = 0; + glusterd_gsync_slaves_t status = {0, }; + char cann_slave[PATH_MAX] = {0, }; + char host_uuid_str[32] = {0}; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + + + this = THIS; + GF_ASSERT (this); + priv = this->private; + GF_ASSERT (priv); + GF_ASSERT (vol); + GF_ASSERT (master); + GF_ASSERT (slave); + + uuid_utoa_r (priv->uuid, host_uuid_str); + ret = glusterd_gsync_get_cannonical_slave_name (cann_slave, master, + slave); + if (ret) + goto out; + + status.slave = cann_slave; + status.host_uuid = host_uuid_str; + status.ret_status = 1; + dict_foreach (vol->gsync_slaves, _compare_host_uuid, &status); + if (status.ret_status == 0) { + uuid_copy (uuid, priv->uuid); + } else if (status.ret_status == -1) { + uuid_parse (status.rmt_hostname, uuid); + } else { ret = -1; goto out; } + ret = 0; + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "slave not found"); - *op_errstr = gf_strdup ("slave not found"); +} + +static int +glusterd_check_gsync_running_local (char *master, char *slave, + gf_boolean_t *is_run) +{ + int ret = -1; + int ret_status = 0; + + GF_ASSERT (master); + GF_ASSERT (slave); + GF_ASSERT (is_run); + + *is_run = _gf_false; + ret = gsync_status (master, slave, &ret_status); + if (ret == 0 && ret_status == 0) { + *is_run = _gf_true; + } else if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "gsync start validation " + " failed"); + goto out; + } + ret = 0; + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + +static int +glusterd_store_slave_in_info (glusterd_volinfo_t *volinfo, char *master, + char *slave, char *host_uuid, char **op_errstr) +{ + int ret = 0; + glusterd_gsync_slaves_t status = {0, }; + char cann_slave[PATH_MAX] = {0, }; + char *value = NULL; + char key[512] = {0, }; + + + ret = glusterd_gsync_get_cannonical_slave_name (cann_slave, master, + slave); + if (ret) + goto out; + + status.slave = cann_slave; + status.host_uuid = host_uuid; + status.ret_status = 1; + dict_foreach (volinfo->gsync_slaves, _compare_host_uuid, &status); + + if (status.ret_status == -1) { + gf_log ("", GF_LOG_ERROR, "Gsync has already been invoked for " + "the %s (master) and %s (slave)" + "from a different machine", + master, slave); + *op_errstr = gf_strdup ("Gsync already running in an an" + "orhter machine"); ret = -1; goto out; } + memset (&status, 0, sizeof (status)); + + dict_foreach (volinfo->gsync_slaves, _get_max_gsync_slave_num, &status); + + gf_asprintf (&value, "%s:%s", host_uuid, cann_slave); + snprintf (key, 512, "slave%d", status.ret_status +1); + ret = dict_set_dynstr (volinfo->gsync_slaves, key, value); + + if (ret) + goto out; + ret = glusterd_store_volinfo (volinfo, + GLUSTERD_VOLINFO_VER_AC_INCREMENT); + if (ret) { + *op_errstr = gf_strdup ("Failed to store the Volume" + "information"); + goto out; + } + ret = 0; + out: + return ret; +} + + +static int +glusterd_op_verify_gsync_start_options (glusterd_volinfo_t *volinfo, + char *master, char *slave, + char **op_errstr) +{ + 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; + + this = THIS; + + GF_ASSERT (volinfo); + GF_ASSERT (master); + GF_ASSERT (slave); + GF_ASSERT (op_errstr); + GF_ASSERT (this && this->private); + + priv = this->private; + + if (GLUSTERD_STATUS_STARTED != volinfo->status) { + snprintf (msg, sizeof (msg), "Volume %s needs to be started " + "before gsync start", volinfo->volname); + 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 (master, slave, volinfo, uuid); + if ((ret == 0) && (uuid_compare (priv->uuid, uuid) == 0)) { + ret = glusterd_check_gsync_running_local (master, slave, + &is_running); + if (ret) { + snprintf (msg, sizeof (msg), "gsync start option " + "validation failed "); + goto out; + } + if (_gf_true == is_running) { + snprintf (msg, sizeof (msg), "gsync %s %s already " + "started", master, slave); + ret = -1; + goto out; + } + } + ret = 0; +out: + if (ret && (msg[0] != '\0')) { + *op_errstr = gf_strdup (msg); + } + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, + char *master, char *slave, + char **op_errstr) +{ + int ret = -1; + char msg[2048] = {0}; + uuid_t uuid = {0}; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (THIS && THIS->private); + GF_ASSERT (volinfo); + GF_ASSERT (master); + GF_ASSERT (slave); + GF_ASSERT (op_errstr); + + priv = THIS->private; + + if (GLUSTERD_STATUS_STARTED != volinfo->status) { + snprintf (msg, sizeof (msg), "Volume %s needs to be started " + "before gsync start", volinfo->volname); + goto out; + } + ret = glusterd_gsync_get_uuid (master, slave, volinfo, uuid); + if (ret == -1) { + snprintf (msg, sizeof (msg), "Gsync session is not active"); + goto out; + } + + ret = 0; +out: + if (ret && (msg[0] != '\0')) { + *op_errstr = gf_strdup (msg); + } + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +glusterd_verify_gsync_status_opts (dict_t *dict, char **op_errstr) +{ + int status_type = 0; + char *master = NULL; + char *slave = NULL; + char *volname = NULL; + char errmsg[PATH_MAX] = {0, }; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + int ret = 0; + + + ret = dict_get_int32 (dict, "status-type", &status_type); + if (ret) + goto out; + + if (status_type == GF_GSYNC_OPTION_TYPE_STATUS_ALL) + goto out; + + ret = dict_get_str (dict, "master", &master); + if (ret < 0) + goto out; + volname = volname_from_master (master); if (volname == NULL) { gf_log ("", GF_LOG_WARNING, "volname couldn't be found"); @@ -1953,82 +2398,136 @@ glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) } exists = glusterd_check_volume_exists (volname); - if (!exists) { - gf_log ("", GF_LOG_WARNING, "volname doesnot exist"); - *op_errstr = gf_strdup ("volname doesnot exist"); + 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); ret = -1; goto out; } + + if (status_type == GF_GSYNC_OPTION_TYPE_STATUS_MASTER) + goto out; + + if (status_type != GF_GSYNC_OPTION_TYPE_STATUS_MST_SLV) + goto out; + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) + goto out; + + ret = glusterd_op_verify_gsync_running (volinfo, master, + slave, op_errstr); + + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + + +static int +glusterd_op_gsync_args_get (dict_t *dict, char **op_errstr, + char **master, char **slave) +{ + + int ret = -1; + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + GF_ASSERT (master); + GF_ASSERT (slave); + + ret = dict_get_str (dict, "master", master); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "master not found"); + *op_errstr = gf_strdup ("master not found"); + goto out; + } + + ret = dict_get_str (dict, "slave", slave); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "slave not found"); + *op_errstr = gf_strdup ("slave not found"); + goto out; + } + + + ret = 0; +out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; +} + +static int +glusterd_op_stage_gsync_set (dict_t *dict, char **op_errstr) +{ + int ret = 0; + int type = 0; + char *volname = NULL; + char *master = NULL; + char *slave = NULL; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + char errmsg[PATH_MAX] = {0,}; + + ret = dict_get_int32 (dict, "type", &type); if (ret < 0) { gf_log ("", GF_LOG_WARNING, "command type not found"); *op_errstr = gf_strdup ("command unsuccessful"); - ret = -1; goto out; } - ret = glusterd_volinfo_find (volname, &volinfo); - if (ret) { - gf_log ("", GF_LOG_WARNING, "volinfo not found " - "for %s", volname); - *op_errstr = gf_strdup ("command unsuccessful"); - ret = -1; - goto out; + if (type == GF_GSYNC_OPTION_TYPE_STATUS) { + ret = glusterd_verify_gsync_status_opts (dict, op_errstr); + + goto out; } - if (type == GF_GSYNC_OPTION_TYPE_START) { - if (GLUSTERD_STATUS_STARTED != volinfo->status) { - gf_log ("", GF_LOG_WARNING, "%s volume not started", - volname); - *op_errstr = gf_strdup ("please start the volume"); - ret = -1; - goto out; - } - //check if the gsync is already started - ret = gsync_status (master, slave, &status); - if (ret == 0 && status == 0) { - gf_log ("", GF_LOG_WARNING, "gsync already started"); - *op_errstr = gf_strdup ("gsync already started"); - ret = -1; - goto out; - } else if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "gsync start validation " - " failed"); - *op_errstr = gf_strdup ("command to failed, please " - "check the log file"); - goto out; - } - ret = 0; + ret = glusterd_op_gsync_args_get (dict, op_errstr, &master, &slave); + if (ret) + goto out; + volname = volname_from_master (master); + if (volname == NULL) { + gf_log ("", GF_LOG_WARNING, "volname couldn't be found"); + *op_errstr = gf_strdup ("volname not found"); + ret = -1; goto out; } - if (type == GF_GSYNC_OPTION_TYPE_STOP) { - ret = gsync_status (master, slave, &status); - if (ret == 0 && status == -1) { - gf_log ("", GF_LOG_WARNING, "gsync not running"); - *op_errstr = gf_strdup ("gsync not running"); - glusterd_gsync_volinfo_dict_set (volinfo, - "features.marker-gsync", "off"); - ret = -1; - goto out; - } else if (ret == -1) { - gf_log ("", GF_LOG_WARNING, "gsync stop validation " - " failed"); - *op_errstr = gf_strdup ("command failed, please " - "check the log file"); - goto out; - } - ret = 0; + 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); + ret = -1; goto out; } - if (type == GF_GSYNC_OPTION_TYPE_CONFIGURE) { + switch (type) { + case GF_GSYNC_OPTION_TYPE_START: + ret = glusterd_op_verify_gsync_start_options (volinfo, master, + slave, op_errstr); + if (ret) + goto out; + break; + case GF_GSYNC_OPTION_TYPE_STOP: + ret = glusterd_op_verify_gsync_running (volinfo, master, + slave, op_errstr); + if (ret) + goto out; + break; + case GF_GSYNC_OPTION_TYPE_CONFIGURE: ret = gsync_verify_config_options (dict, op_errstr); if (ret < 0) goto out; + break; } - ret = 0; out: if (volname) @@ -3635,12 +4134,17 @@ stop_gsync (char *master, char *slave, char **op_errstr) char pidfile[PATH_MAX] = {0,}; char buf [1024] = {0,}; int i = 0; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; ret = gsync_status (master, slave, &status); if (ret == 0 && status == -1) { - gf_log ("", GF_LOG_WARNING, "gsync is not running"); - *op_errstr = gf_strdup ("gsync is not running"); - ret = -1; + gf_log ("", GF_LOG_WARNING, "Gsync is not running"); + *op_errstr = gf_strdup ("Gsync is not running"); goto out; } else if (ret == -1) { gf_log ("", GF_LOG_WARNING, "gsync stop validation " @@ -3650,10 +4154,12 @@ stop_gsync (char *master, char *slave, char **op_errstr) goto out; } - ret = glusterd_gsync_get_pid_file (pidfile, master, slave); + ret = glusterd_gsync_get_param_file (pidfile, "pid", master, + slave, priv->workdir); if (ret == -1) { - ret = -1; - gf_log ("", GF_LOG_WARNING, "failed to create the pidfile string"); + gf_log ("", GF_LOG_WARNING, "failed to create the pidfile" + " string"); + *op_errstr = gf_strdup ("Operation Failed! due to corrupt pid"); goto out; } @@ -3835,87 +4341,141 @@ out: return ret; } - int -gsync_configure (char *master, char *slave, - dict_t *dict, char **op_errstr) +glusterd_gsync_read_frm_status (char *path, char *data) { - int32_t ret = -1; - int32_t config_type = 0; + int ret = 0; + FILE *status_file = NULL; - ret = dict_get_int32 (dict, "config_type", &config_type); + GF_ASSERT (path); + GF_ASSERT (data); + status_file = fopen (path, "r"); + if (status_file == NULL) { + gf_log ("", GF_LOG_WARNING, "Unable to read the Gsync status" + " file"); + return -1; + } + ret = fread (data, PATH_MAX, 1, status_file); if (ret < 0) { - gf_log ("", GF_LOG_WARNING, "couldn't get the " - "config-type for %s %s", master, slave); - *op_errstr = gf_strdup ("configure command failed, " - "please check the log-file\n"); - goto out; + gf_log ("", GF_LOG_WARNING, "Status file of Gsync is corrupt"); + return -1; } - if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_SET) { - ret = gsync_config_set (master, slave, dict, op_errstr); + return 0; +} + +int +glusterd_read_status_file (char *master, char *slave, + dict_t *dict) +{ + glusterd_conf_t *priv = NULL; + int ret = 0; + char statusfile[PATH_MAX] = {0, }; + char buff[PATH_MAX] = {0, }; + char mst[PATH_MAX] = {0, }; + char slv[PATH_MAX] = {0, }; + char sts[PATH_MAX] = {0, }; + int gsync_count = 0; + int status = 0; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + ret = glusterd_gsync_get_param_file (statusfile, "status", master, + slave, priv->workdir); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to get the name of status" + "file for %s(master), %s(slave)", master, slave); goto out; + } - if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_DEL) { - ret = gsync_config_del (master, slave, dict, op_errstr); + ret = gsync_status (master, slave, &status); + if (ret == 0 && status == -1) { + strncpy (buff, "Corrupt\n", sizeof (buff)); + goto done; + } else if (ret == -1) { + gf_log ("", GF_LOG_WARNING, "Unable to determine " + " Gsync's status"); goto out; } - if ((config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL) || - (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET)) + ret = glusterd_gsync_read_frm_status (statusfile, buff); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Unable to read the status" + "file for %s(master), %s(slave)", master, slave); goto out; - else { - gf_log ("", GF_LOG_WARNING, "Invalid config type"); - *op_errstr = gf_strdup ("Invalid config type"); - ret = -1; + } -out: - return ret; -} + done: + ret = dict_get_int32 (dict, "gsync-count", &gsync_count); -int -gsync_command_exec (dict_t *dict, char **op_errstr) -{ - char *master = NULL; - char *slave = NULL; - int32_t ret = -1; - int32_t type = -1; + if (ret) + gsync_count = 1; + else + gsync_count++; - GF_VALIDATE_OR_GOTO ("gsync", dict, out); - GF_VALIDATE_OR_GOTO ("gsync", op_errstr, out); + snprintf (mst, sizeof (mst), "master%d", gsync_count); + ret = dict_set_dynstr (dict, mst, gf_strdup (master)); + if (ret) + goto out; - ret = dict_get_int32 (dict, "type", &type); - if (ret < 0) + snprintf (slv, sizeof (slv), "slave%d", gsync_count); + ret = dict_set_dynstr (dict, slv, gf_strdup (slave)); + if (ret) goto out; - ret = dict_get_str (dict, "master", &master); - if (ret < 0) + snprintf (sts, sizeof (slv), "status%d", gsync_count); + ret = dict_set_dynstr (dict, sts, gf_strdup (buff)); + if (ret) + goto out; + ret = dict_set_int32 (dict, "gsync-count", gsync_count); + if (ret) goto out; - ret = dict_get_str (dict, "slave", &slave); - if (ret < 0) + ret = 0; + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); + return ret; +} + +int +glusterd_gsync_configure (char *master, char *slave, + dict_t *dict, char **op_errstr) +{ + int32_t ret = -1; + int32_t config_type = 0; + + ret = dict_get_int32 (dict, "config_type", &config_type); + if (ret < 0) { + gf_log ("", GF_LOG_WARNING, "couldn't get the " + "config-type for %s %s", master, slave); + *op_errstr = gf_strdup ("configure command failed, " + "please check the log-file\n"); goto out; + } - if (type == GF_GSYNC_OPTION_TYPE_START) { - ret = 0; + if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_SET) { + ret = gsync_config_set (master, slave, dict, op_errstr); goto out; } - if (type == GF_GSYNC_OPTION_TYPE_STOP) { - ret = stop_gsync (master, slave, op_errstr); + if (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_DEL) { + ret = gsync_config_del (master, slave, dict, op_errstr); goto out; } - if (type == GF_GSYNC_OPTION_TYPE_CONFIGURE) { - ret = gsync_configure (master, slave, dict, op_errstr); + if ((config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET_ALL) || + (config_type == GF_GSYNC_OPTION_TYPE_CONFIG_GET)) goto out; - } else { + else { gf_log ("", GF_LOG_WARNING, "Invalid config type"); *op_errstr = gf_strdup ("Invalid config type"); ret = -1; } + out: return ret; } @@ -3953,6 +4513,12 @@ glusterd_set_marker_gsync (char *master) char *marker_value = NULL; gf_boolean_t marker_set = _gf_false; char *gsync_status = NULL; + glusterd_conf_t *priv = NULL; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; volname = volname_from_master (master); @@ -3997,48 +4563,244 @@ out: } + + + int -glusterd_op_gsync_set (dict_t *dict) +glusterd_get_gsync_status_mst_slv( glusterd_volinfo_t *volinfo, char *master, + char *slave, dict_t *rsp_dict) { - char *master = NULL; - int32_t ret = -1; - int32_t type = -1; - dict_t *ctx = NULL; - char *op_errstr = NULL; + uuid_t uuid = {0, }; + glusterd_conf_t *priv = NULL; + int ret = 0; + + GF_ASSERT (volinfo); + GF_ASSERT (master); + GF_ASSERT (slave); + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + + priv = THIS->private; + + ret = glusterd_gsync_get_uuid (master, slave, volinfo, uuid); + if ((ret == 0) && (uuid_compare (priv->uuid, uuid) != 0)) + goto out; + + ret = glusterd_read_status_file (master, slave, rsp_dict); + out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; +} + +static int +glusterd_get_gsync_status_mst (glusterd_volinfo_t *volinfo, dict_t *rsp_dict) +{ + glusterd_gsync_status_temp_t param = {0, }; + + GF_ASSERT (volinfo); + + param.rsp_dict = rsp_dict; + param.volinfo = volinfo; + dict_foreach (volinfo->gsync_slaves, _get_status_mst_slv, ¶m); + + return 0; +} + +static int +glusterd_get_gsync_status_all ( dict_t *rsp_dict) +{ + + int32_t ret = 0; + glusterd_conf_t *priv = NULL; + glusterd_volinfo_t *volinfo = NULL; + + GF_ASSERT (THIS); + priv = THIS->private; + + GF_ASSERT (priv); + + list_for_each_entry (volinfo, &priv->volumes, vol_list) { + ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); + if (ret) + goto out; + } + +out: + gf_log ("", GF_LOG_DEBUG, "Returning with %d", ret); + return ret; + +} + +static int +glusterd_get_gsync_status (dict_t *dict, char **op_errstr, dict_t *rsp_dict) +{ + int status_type = 0; + char *master = NULL; + char *slave = NULL; + char *volname = NULL; + char errmsg[PATH_MAX] = {0, }; + gf_boolean_t exists = _gf_false; + glusterd_volinfo_t *volinfo = NULL; + int ret = 0; + + + ret = dict_get_int32 (dict, "status-type", &status_type); + if (ret) + goto out; + + if (status_type == GF_GSYNC_OPTION_TYPE_STATUS_ALL) { + ret = glusterd_get_gsync_status_all (rsp_dict); + goto out; + } + + ret = dict_get_str (dict, "master", &master); + if (ret < 0) + goto out; + + volname = volname_from_master (master); + if (volname == NULL) { + gf_log ("", GF_LOG_WARNING, "volname couldn't be found"); + *op_errstr = gf_strdup ("volname not found"); + ret = -1; + goto out; + } + + 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); + ret = -1; + goto out; + } + + + if (status_type == GF_GSYNC_OPTION_TYPE_STATUS_MASTER) { + ret = glusterd_get_gsync_status_mst (volinfo, rsp_dict); + goto out; + } + + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) + goto out; + + ret = glusterd_get_gsync_status_mst_slv (volinfo, master, + slave, rsp_dict); + + 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) +{ + char *master = NULL; + int32_t ret = -1; + int32_t type = -1; + dict_t *ctx = NULL; + dict_t *resp_dict = NULL; + char *host_uuid = NULL; + char *slave = NULL; + char *volname = NULL; + glusterd_volinfo_t *volinfo = NULL; + glusterd_conf_t *priv = NULL; + uuid_t uuid = {0, }; + + GF_ASSERT (THIS); + GF_ASSERT (THIS->private); + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + + priv = THIS->private; ret = dict_get_int32 (dict, "type", &type); if (ret < 0) goto out; + ret = dict_get_str (dict, "host-uuid", &host_uuid); + if (ret < 0) + goto out; + + if (type == GF_GSYNC_OPTION_TYPE_STATUS) { + ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); + resp_dict = ctx ? ctx : rsp_dict; + + ret = glusterd_get_gsync_status (dict, op_errstr, resp_dict); + goto out; + + } + ret = dict_get_str (dict, "master", &master); if (ret < 0) goto out; + ret = dict_get_str (dict, "slave", &slave); + if (ret < 0) + goto out; + + volname = volname_from_master (master); + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Volinfo for %s (master) not found", + volname); + goto out; + } + if (type == GF_GSYNC_OPTION_TYPE_START) { ret = glusterd_set_marker_gsync (master); if (ret != 0) { gf_log ("", GF_LOG_WARNING, "marker start failed"); - op_errstr = gf_strdup ("gsync start failed"); + *op_errstr = gf_strdup ("gsync start failed"); ret = -1; goto out; } + ret = glusterd_store_slave_in_info(volinfo, master, slave, + host_uuid, op_errstr); + if (ret) + goto out; + } -out: - ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); - if (ctx) { - ret = gsync_command_exec (dict, &op_errstr); - if (op_errstr) { - ret = dict_set_str (ctx, "errstr", op_errstr); - if (ret) { - GF_FREE (op_errstr); - gf_log ("", GF_LOG_WARNING, "failed to set " - "error message in ctx"); - } + if (type == GF_GSYNC_OPTION_TYPE_STOP) { + + ret = glusterd_gsync_get_uuid (master, slave, volinfo, uuid); + if (ret) { + gf_log ("", GF_LOG_WARNING, "Gsync is not runing for" + "%s(master) and %s(slave)", master, slave); + *op_errstr = strdup ("Gsync is not running"); + goto out; } + + ret = glusterd_remove_slave_in_info(volinfo, master, slave, + host_uuid, op_errstr); + if (ret) + goto out; + + if (uuid_compare (priv->uuid, uuid) != 0) { + goto out; + } + + ret = stop_gsync (master, slave, op_errstr); + if (ret) + goto out; + + } + + if (type == GF_GSYNC_OPTION_TYPE_CONFIGURE) { + ret = glusterd_gsync_configure (master, slave, dict, op_errstr); + goto out; } +out: + gf_log ("", GF_LOG_DEBUG,"Returning %d", ret); return ret; } @@ -6811,7 +7573,7 @@ glusterd_op_commit_perform (glusterd_op_t op, dict_t *dict, char **op_errstr, break; case GD_OP_GSYNC_SET: - ret = glusterd_op_gsync_set (dict); + ret = glusterd_op_gsync_set (dict, op_errstr, rsp_dict); break; case GD_OP_PROFILE_VOLUME: diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index 9c322b0bffd..d10d5c1a4f9 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -163,6 +163,17 @@ typedef struct glusterd_pr_brick_rsp_conv_t { dict_t *dict; } glusterd_pr_brick_rsp_conv_t; +typedef struct glusterd_gsync_slaves { + char *slave; + char *host_uuid; + int ret_status; + char rmt_hostname[256]; +} glusterd_gsync_slaves_t; + +typedef struct glusterd_gsync_status_temp { + dict_t *rsp_dict; + glusterd_volinfo_t *volinfo; +}glusterd_gsync_status_temp_t; int glusterd_op_sm_new_event (glusterd_op_sm_event_type_t event_type, glusterd_op_sm_event_t **new_event); @@ -286,4 +297,8 @@ gf_boolean_t glusterd_are_all_volumes_stopped (); int glusterd_stop_bricks (glusterd_volinfo_t *volinfo); +int +glusterd_get_gsync_status_mst_slv( glusterd_volinfo_t *volinfo, char *master, + char *slave, dict_t *rsp_dict); + #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 8600c7b93c1..27fe5b5f8eb 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -304,7 +304,13 @@ glusterd_op_send_cli_response (glusterd_op_t op, int32_t op_ret, rsp.op_name = gf_strdup (op_name); } - } else if (op_errstr) + + ret = dict_allocate_and_serialize (ctx, + &rsp.status_dict.status_dict_val, + (size_t*)&rsp.status_dict.status_dict_len); + + } + if (op_errstr) rsp.op_errstr = op_errstr; cli_rsp = &rsp; sfunc = gf_xdr_serialize_cli_gsync_set_rsp; @@ -827,7 +833,108 @@ out: GLUSTERD_STACK_DESTROY (((call_frame_t *)myframe)); return ret; } +static int32_t +glusterd_append_status_dicts (dict_t *dst, dict_t *src) +{ + int dst_count = 0; + int src_count = 0; + int i = 0; + int ret = 0; + char mst[PATH_MAX] = {0,}; + char slv[PATH_MAX] = {0, }; + char sts[PATH_MAX] = {0, }; + char *mst_val = NULL; + char *slv_val = NULL; + char *sts_val = NULL; + + GF_ASSERT (dst); + + if (src == NULL) + goto out; + + ret = dict_get_int32 (dst, "gsync-count", &dst_count); + if (ret) + dst_count = 0; + + ret = dict_get_int32 (src, "gsync-count", &src_count); + if (ret || !src_count) { + gf_log ("", GF_LOG_DEBUG, "Source brick empty"); + ret = 0; + goto out; + } + + for (i = 1; i <= src_count; 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 (src, mst, &mst_val); + if (ret) + goto out; + + ret = dict_get_str (src, slv, &slv_val); + if (ret) + goto out; + + ret = dict_get_str (src, sts, &sts_val); + if (ret) + goto out; + + snprintf (mst, sizeof(mst), "master%d", i+dst_count); + snprintf (slv, sizeof(slv), "slave%d", i+dst_count); + snprintf (sts, sizeof(sts), "status%d", i+dst_count); + + ret = dict_set_dynstr (dst, mst, gf_strdup (mst_val)); + if (ret) + goto out; + + ret = dict_set_dynstr (dst, slv, gf_strdup (slv_val)); + if (ret) + goto out; + + ret = dict_set_dynstr (dst, sts, gf_strdup (sts_val)); + if (ret) + goto out; + + } + + ret = dict_set_int32 (dst, "gsync-count", dst_count+src_count); + + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); + return ret; + +} + +static int32_t +glusterd_gsync_use_rsp_dict (dict_t *rsp_dict, char *op_errstr) +{ + dict_t *ctx = NULL; + int ret = 0; + + ctx = glusterd_op_get_ctx (GD_OP_GSYNC_SET); + if (!ctx) { + gf_log ("", GF_LOG_ERROR, + "Operation Context is not present"); + GF_ASSERT (0); + } + + if (rsp_dict) { + ret = glusterd_append_status_dicts (ctx, rsp_dict); + if (ret) + goto out; + } + if (strcmp ("", op_errstr)) { + ret = dict_set_dynstr (ctx, "errstr", gf_strdup(op_errstr)); + if (ret) + goto out; + } + ret = 0; + out: + gf_log ("", GF_LOG_DEBUG, "Returning %d ", ret); + return ret; +} static int32_t glusterd_rb_use_rsp_dict (dict_t *rsp_dict) { @@ -1173,6 +1280,12 @@ glusterd3_1_commit_op_cbk (struct rpc_req *req, struct iovec *iov, goto out; break; + case GD_OP_GSYNC_SET: + ret = glusterd_gsync_use_rsp_dict (dict, rsp.op_errstr); + if (ret) + goto out; + break; + default: break; } diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c index 8058adcd0f9..836c9d12cf5 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -448,6 +448,40 @@ out: return ret; } +static void +_storeslaves (dict_t *this, char *key, data_t *value, void *data) +{ + int32_t ret = 0; + glusterd_store_handle_t *shandle = NULL; + + shandle = (glusterd_store_handle_t*)data; + + GF_ASSERT (shandle); + GF_ASSERT (shandle->fd > 0); + GF_ASSERT (shandle->path); + GF_ASSERT (key); + GF_ASSERT (value && value->data); + + if ((!shandle) || (shandle->fd <= 0) || (!shandle->path)) + return; + + if (!key) + return; + if (!value || !value->data) + return; + + gf_log ("", GF_LOG_DEBUG, "Storing in volinfo:key= %s, val=%s", + key, value->data); + + ret = glusterd_store_save_value (shandle->fd, key, (char*)value->data); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to write into store" + " handle for path: %s", shandle->path); + return; + } +} + + void _storeopts (dict_t *this, char *key, data_t *value, void *data) { int32_t ret = 0; @@ -587,6 +621,8 @@ glusterd_store_volinfo_write (int fd, glusterd_volinfo_t *volinfo) shandle->fd = fd; dict_foreach (volinfo->dict, _storeopts, shandle); + + dict_foreach (volinfo->gsync_slaves, _storeslaves, shandle); shandle->fd = 0; out: gf_log ("", GF_LOG_DEBUG, "Returning %d", ret); @@ -1479,7 +1515,18 @@ glusterd_store_retrieve_volume (char *volname) if (ret) gf_log ("", GF_LOG_WARNING, "failed to parse uuid"); - } else { + } else if (strstr (key, "slave")) { + ret = dict_set_str(volinfo->gsync_slaves, key, + gf_strdup (value)); + if (ret) { + gf_log ("",GF_LOG_ERROR, "Error in " + "dict_set_str"); + goto out; + } + gf_log ("", GF_LOG_DEBUG, "Parsed as Gsync-" + "skave:key=%s,value:%s", key, value); + } + else { exists = glusterd_check_option_exists (key, NULL); if (exists == -1) { ret = -1; diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 1c1873a6e9f..bd6a4ed0432 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -522,6 +522,14 @@ glusterd_volinfo_new (glusterd_volinfo_t **volinfo) goto out; } + new_volinfo->gsync_slaves = dict_new (); + if (!new_volinfo->gsync_slaves) { + if (new_volinfo) + GF_FREE (new_volinfo); + + goto out; + } + *volinfo = new_volinfo; ret = 0; diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 821a2ca46f2..9175983c7c9 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -206,6 +206,8 @@ struct glusterd_volinfo_ { uuid_t volume_id; char *logdir; + + dict_t *gsync_slaves; }; typedef struct glusterd_volinfo_ glusterd_volinfo_t; -- cgit