From 870ea37dcd440b33418bab5c9e2c69ca67bb668e Mon Sep 17 00:00:00 2001 From: Kotresh H R Date: Wed, 8 Jan 2014 10:52:28 +0530 Subject: glusterd/geo-rep : Allow volume to stop if geo-rep is not active. In staging phase of volume stop, code is added to read the state_file for each slave of the master to which the volume belongs. If any of the geo-rep session is active with at least one slave, volume is not allowed to stop else it is allowed. Change-Id: I4a01a357fc86b872e9635b3d19998cdbd9545114 BUG: 1049727 Signed-off-by: Kotresh H R Reviewed-on: http://review.gluster.org/6663 Tested-by: Gluster Build System Reviewed-by: Vijay Bellur Reviewed-on: http://review.gluster.org/6821 --- xlators/mgmt/glusterd/src/glusterd-geo-rep.c | 152 ++++++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd-op-sm.h | 5 + xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 20 +++- 3 files changed, 176 insertions(+), 1 deletion(-) diff --git a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c index 5d724cc2a..44ab97ad9 100644 --- a/xlators/mgmt/glusterd/src/glusterd-geo-rep.c +++ b/xlators/mgmt/glusterd/src/glusterd-geo-rep.c @@ -1295,6 +1295,158 @@ glusterd_check_gsync_running (glusterd_volinfo_t *volinfo, gf_boolean_t *flag) return 0; } +/* + * is_geo_rep_active: + * This function reads the state_file and sets is_active to 1 if the + * monitor status is neither "Stopped" or "Not Started" + * + * RETURN VALUE: + * 0: On successful read of state_file. + * -1: error. + */ + +static int +is_geo_rep_active (glusterd_volinfo_t *volinfo, char *slave, + char *conf_path, int *is_active) +{ + dict_t *confd = NULL; + char *statefile = NULL; + char *master = NULL; + char monitor_status[PATH_MAX] = ""; + int ret = -1; + xlator_t *this = NULL; + + this = THIS; + GF_ASSERT (this); + + master = volinfo->volname; + + confd = dict_new (); + if (!confd) { + gf_log ("", GF_LOG_ERROR, "Not able to create dict."); + goto out; + } + + ret = glusterd_gsync_get_config (master, slave, conf_path, + confd); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get configuration data " + "for %s(master), %s(slave)", master, slave); + ret = -1; + goto out; + } + + ret = dict_get_param (confd, "state_file", &statefile); + if (ret) { + gf_log ("", GF_LOG_ERROR, "Unable to get state_file's name " + "for %s(master), %s(slave). Please check gsync " + "config file.", master, slave); + ret = -1; + goto out; + } + + ret = glusterd_gsync_read_frm_status (statefile, monitor_status, + sizeof (monitor_status)); + if (ret <= 0) { + gf_log ("", GF_LOG_ERROR, "Unable to read the status " + "file for %s(master), %s(slave)", master, slave); + strncpy (monitor_status, "defunct", sizeof (monitor_status)); + } + + if ((!strcmp(monitor_status, "Stopped")) || + (!strcmp(monitor_status, "Not Started"))) { + *is_active = 0; + } else { + *is_active = 1; + } + ret = 0; +out: + if (confd) + dict_destroy (confd); + return ret; +} + +/* + * _get_slave_status: + * Called for each slave in the volume from dict_foreach. + * It calls is_geo_rep_active to get the monitor status. + * + * RETURN VALUE: + * 0: On successful read of state_file from is_geo_rep_active. + * When it is found geo-rep is already active from previous calls. + * When there is no slave. + * -1: On error. + */ + +int +_get_slave_status (dict_t *dict, char *key, data_t *value, void *data) +{ + gsync_status_param_t *param = NULL; + char *slave = NULL; + char *slave_ip = NULL; + char *slave_vol = NULL; + char *errmsg = NULL; + char conf_path[PATH_MAX] = ""; + int ret = -1; + glusterd_conf_t *priv = NULL; + xlator_t *this = NULL; + + param = (gsync_status_param_t *)data; + + GF_ASSERT (param); + GF_ASSERT (param->volinfo); + + if (param->is_active) { + ret = 0; + goto out; + } + + this = THIS; + GF_ASSERT (this); + + 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) { + ret = 0; + goto out; + } + slave++; + + ret = glusterd_get_slave_info (slave, &slave_ip, &slave_vol, &errmsg); + if (ret) { + if (errmsg) + gf_log ("", GF_LOG_ERROR, "Unable to fetch " + "slave details. Error: %s", errmsg); + else + gf_log ("", GF_LOG_ERROR, + "Unable to fetch slave details."); + ret = -1; + goto out; + } + + ret = snprintf (conf_path, sizeof(conf_path) - 1, + "%s/"GEOREP"/%s_%s_%s/gsyncd.conf", + priv->workdir, param->volinfo->volname, + slave_ip, slave_vol); + if (ret < 0) { + gf_log ("", GF_LOG_ERROR, "Unable to assign conf_path."); + ret = -1; + goto out; + } + conf_path[ret] = '\0'; + + ret = is_geo_rep_active (param->volinfo,slave, conf_path, + ¶m->is_active); +out: + return ret; +} + static int glusterd_op_verify_gsync_running (glusterd_volinfo_t *volinfo, char *slave, char *conf_path, diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index 62f991933..1125368ce 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -165,6 +165,11 @@ typedef struct glusterd_gsync_status_temp { char *node; }glusterd_gsync_status_temp_t; +typedef struct gsync_status_param { + int is_active; + glusterd_volinfo_t *volinfo; +}gsync_status_param_t; + typedef enum cli_cmd_type_ { PER_REPLICA, ALL_REPLICA, diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index df2562ba6..db9f39c7c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -30,6 +30,8 @@ #define glusterd_op_start_volume_args_get(dict, volname, flags) \ glusterd_op_stop_volume_args_get (dict, volname, flags) +extern int +_get_slave_status (dict_t *this, char *key, data_t *value, void *data); int __glusterd_handle_create_volume (rpcsvc_request_t *req) @@ -1059,6 +1061,7 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) glusterd_volinfo_t *volinfo = NULL; char msg[2048] = {0}; xlator_t *this = NULL; + gsync_status_param_t param = {0,}; this = THIS; GF_ASSERT (this); @@ -1102,7 +1105,22 @@ glusterd_op_stage_stop_volume (dict_t *dict, char **op_errstr) if (ret && (is_run == _gf_false)) gf_log (this->name, GF_LOG_WARNING, "Unable to get the status" " of active "GEOREP" session"); - if (is_run) { + + param.volinfo = volinfo; + ret = dict_foreach (volinfo->gsync_slaves, _get_slave_status, ¶m); + + if (ret) { + gf_log (this->name, GF_LOG_WARNING, "_get_slave_satus failed"); + snprintf (msg, sizeof(msg), GEOREP" Unable to get the status " + "of active "GEOREP" session for the volume '%s'.\n" + "Please check the log file for more info. Use " + "'force' option to ignore and stop the volume.", + volname); + ret = -1; + goto out; + } + + if (is_run && param.is_active) { gf_log (this->name, GF_LOG_WARNING, GEOREP" sessions active" "for the volume %s ", volname); snprintf (msg, sizeof(msg), GEOREP" sessions are active " -- cgit