diff options
-rw-r--r-- | cli/src/cli-cmd-parser.c | 56 | ||||
-rw-r--r-- | cli/src/cli-cmd-volume.c | 51 | ||||
-rw-r--r-- | cli/src/cli-cmd.h | 2 | ||||
-rw-r--r-- | cli/src/cli.h | 4 | ||||
-rw-r--r-- | extras/hook-scripts/set/post/Makefile.am | 2 | ||||
-rwxr-xr-x | extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh | 124 | ||||
-rw-r--r-- | glusterfs.spec.in | 4 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-hooks.c | 40 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 196 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.h | 4 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-rpc-ops.c | 9 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-sm.c | 12 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-snapshot.c | 6 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 31 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 4 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 6 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 107 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 3 |
18 files changed, 588 insertions, 73 deletions
diff --git a/cli/src/cli-cmd-parser.c b/cli/src/cli-cmd-parser.c index ed86ef1428c..f3dd58528b6 100644 --- a/cli/src/cli-cmd-parser.c +++ b/cli/src/cli-cmd-parser.c @@ -1401,17 +1401,19 @@ out: } int32_t -cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options, - char **op_errstr) +cli_cmd_volume_set_parse (struct cli_state *state, const char **words, + int wordcount, dict_t **options, char **op_errstr) { - dict_t *dict = NULL; - char *volname = NULL; - int ret = -1; - int count = 0; - char *key = NULL; - char *value = NULL; - int i = 0; - char str[50] = {0,}; + dict_t *dict = NULL; + char *volname = NULL; + int ret = -1; + int count = 0; + char *key = NULL; + char *value = NULL; + int i = 0; + char str[50] = {0,}; + const char *question = NULL; + gf_answer_t answer = GF_ANSWER_NO; GF_ASSERT (words); GF_ASSERT (options); @@ -1433,6 +1435,22 @@ cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options, if (ret) goto out; + if (!strcmp (volname, "all")) { + ret = dict_set_str (dict, "globalname", "All"); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "dict set on global key failed."); + goto out; + } + + ret = dict_set_int32 (dict, "hold_global_locks", _gf_true); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, + "dict set on global key failed."); + goto out; + } + } + if ((!strcmp (volname, "help") || !strcmp (volname, "help-xml")) && wordcount == 3 ) { ret = dict_set_str (dict, volname, volname); @@ -1502,6 +1520,24 @@ cli_cmd_volume_set_parse (const char **words, int wordcount, dict_t **options, if (ret) goto out; + + if ((!strcmp (key, "cluster.enable-shared-storage")) && + (!strcmp (value, "disable"))) { + question = "Disabling cluster.enable-shared-storage " + "will delete the shared storage volume" + "(gluster_shared_storage), which is used " + "by snapshot scheduler, geo-replication " + "and NFS-Ganesha. Do you still want to " + "continue?"; + answer = cli_cmd_get_confirmation (state, question); + if (GF_ANSWER_NO == answer) { + gf_log ("cli", GF_LOG_ERROR, "Operation " + "cancelled, exiting"); + *op_errstr = gf_strdup ("Aborted by user."); + ret = -1; + goto out; + } + } } ret = dict_set_int32 (dict, "count", wordcount-3); diff --git a/cli/src/cli-cmd-volume.c b/cli/src/cli-cmd-volume.c index 3ce88394925..3793863890d 100644 --- a/cli/src/cli-cmd-volume.c +++ b/cli/src/cli-cmd-volume.c @@ -281,22 +281,28 @@ cli_cmd_volume_delete_cbk (struct cli_state *state, struct cli_cmd_word *word, goto out; } - answer = cli_cmd_get_confirmation (state, question); - - if (GF_ANSWER_NO == answer) { - ret = 0; - goto out; - } - volname = (char *)words[2]; ret = dict_set_str (dict, "volname", volname); - if (ret) { gf_log (THIS->name, GF_LOG_WARNING, "dict set failed"); goto out; } + if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) { + question = "Deleting the shared storage volume" + "(gluster_shared_storage), will affect features " + "like snapshot scheduler, geo-replication " + "and NFS-Ganesha. Do you still want to " + "continue?"; + } + + answer = cli_cmd_get_confirmation (state, question); + if (GF_ANSWER_NO == answer) { + ret = 0; + goto out; + } + CLI_LOCAL_INIT (local, words, frame, dict); if (proc->fn) { @@ -468,6 +474,14 @@ cli_cmd_volume_stop_cbk (struct cli_state *state, struct cli_cmd_word *word, goto out; } + if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) { + question = "Stopping the shared storage volume" + "(gluster_shared_storage), will affect features " + "like snapshot scheduler, geo-replication " + "and NFS-Ganesha. Do you still want to " + "continue?"; + } + if (wordcount == 4) { if (!strcmp("force", words[3])) { flags |= GF_CLI_FLAG_OP_FORCE; @@ -478,6 +492,7 @@ cli_cmd_volume_stop_cbk (struct cli_state *state, struct cli_cmd_word *word, goto out; } } + ret = dict_set_int32 (dict, "flags", flags); if (ret) { gf_log (THIS->name, GF_LOG_ERROR, @@ -727,7 +742,8 @@ cli_cmd_volume_set_cbk (struct cli_state *state, struct cli_cmd_word *word, if (!frame) goto out; - ret = cli_cmd_volume_set_parse (words, wordcount, &options, &op_errstr); + ret = cli_cmd_volume_set_parse (state, words, wordcount, + &options, &op_errstr); if (ret) { if (op_errstr) { cli_err ("%s", op_errstr); @@ -1607,6 +1623,7 @@ cli_cmd_volume_remove_brick_cbk (struct cli_state *state, int parse_error = 0; int need_question = 0; cli_local_t *local = NULL; + char *volname = NULL; const char *question = "Removing brick(s) can result in data loss. " "Do you want to Continue?"; @@ -1623,6 +1640,22 @@ cli_cmd_volume_remove_brick_cbk (struct cli_state *state, goto out; } + ret = dict_get_str (options, "volname", &volname); + if (ret || !volname) { + gf_log ("cli", GF_LOG_ERROR, "Failed to fetch volname"); + ret = -1; + goto out; + } + + if (!strcmp (volname, GLUSTER_SHARED_STORAGE)) { + question = "Removing brick from the shared storage volume" + "(gluster_shared_storage), will affect features " + "like snapshot scheduler, geo-replication " + "and NFS-Ganesha. Do you still want to " + "continue?"; + need_question = _gf_true; + } + if (!(state->mode & GLUSTER_MODE_SCRIPT) && need_question) { /* we need to ask question only in case of 'commit or force' */ answer = cli_cmd_get_confirmation (state, question); diff --git a/cli/src/cli-cmd.h b/cli/src/cli-cmd.h index 9a4426a3a7d..27f385fab85 100644 --- a/cli/src/cli-cmd.h +++ b/cli/src/cli-cmd.h @@ -15,6 +15,8 @@ #include "cli.h" #include "list.h" +#define GLUSTER_SHARED_STORAGE "gluster_shared_storage" + #define CLI_LOCAL_INIT(local, words, frame, dictionary) \ do { \ local = cli_local_get (); \ diff --git a/cli/src/cli.h b/cli/src/cli.h index be9fd961804..965ce3f9ee4 100644 --- a/cli/src/cli.h +++ b/cli/src/cli.h @@ -243,8 +243,8 @@ int32_t cli_cmd_bitrot_parse (const char **words, int wordcount, dict_t **opt); int32_t -cli_cmd_volume_set_parse (const char **words, int wordcount, - dict_t **options, char **op_errstr); +cli_cmd_volume_set_parse (struct cli_state *state, const char **words, + int wordcount, dict_t **options, char **op_errstr); int32_t cli_cmd_ganesha_parse (struct cli_state *state, const char **words, int wordcount, dict_t **options, char **op_errstr); diff --git a/extras/hook-scripts/set/post/Makefile.am b/extras/hook-scripts/set/post/Makefile.am index 3ec25d94134..99dfaa3eafb 100644 --- a/extras/hook-scripts/set/post/Makefile.am +++ b/extras/hook-scripts/set/post/Makefile.am @@ -1 +1 @@ -EXTRA_DIST = S30samba-set.sh S31ganesha-set.sh +EXTRA_DIST = S30samba-set.sh S31ganesha-set.sh S32gluster_enable_shared_storage.sh diff --git a/extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh b/extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh new file mode 100755 index 00000000000..28fa0e53316 --- /dev/null +++ b/extras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh @@ -0,0 +1,124 @@ +#!/bin/bash + +key=`echo $3 | cut -d '=' -f 1` +val=`echo $3 | cut -d '=' -f 2` +if [ "$key" != "cluster.enable-shared-storage" ]; then + exit; +fi +if [ "$val" != 'enable' ]; then + if [ "$val" != 'disable' ]; then + exit; + fi +fi + +option=$val + +key_val_pair1=`echo $4 | cut -d ',' -f 1` +key_val_pair2=`echo $4 | cut -d ',' -f 2` + +key=`echo $key_val_pair1 | cut -d '=' -f 1` +val=`echo $key_val_pair1 | cut -d '=' -f 2` +if [ "$key" != "is_originator" ]; then + exit; +fi +is_originator=$val; + +key=`echo $key_val_pair2 | cut -d '=' -f 1` +val=`echo $key_val_pair2 | cut -d '=' -f 2` +if [ "$key" != "local_node_hostname" ]; then + exit; +fi +local_node_hostname=$val; + +# Read gluster peer status to find the peers +# which are in 'Peer in Cluster' mode and +# are connected. + +number_of_connected_peers=0 +while read -r line +do + # Already got two connected peers. Including the current node + # we have 3 peers which is enough to create a shared storage + # with replica 3 + if [ "$number_of_connected_peers" == "2" ]; then + break; + fi + + key=`echo $line | cut -d ':' -f 1` + if [ "$key" == "Hostname" ]; then + hostname=`echo $line | cut -d ':' -f 2 | xargs` + fi + + if [ "$key" == "State" ]; then + peer_state=`echo $line | cut -d ':' -f 2 | cut -d '(' -f 1 | xargs` + conn_state=`echo $line | cut -d '(' -f 2 | cut -d ')' -f 1 | xargs` + + if [ "$peer_state" == "Peer in Cluster" ]; then + if [ "$conn_state" == "Connected" ]; then + ((number_of_connected_peers++)) + connected_peer[$number_of_connected_peers]=$hostname + fi + fi + fi + +done < <(gluster peer status) + +# Include current node in connected peer list +((number_of_connected_peers++)) +connected_peer[$number_of_connected_peers]=$local_node_hostname + +# forming the create vol command +create_cmd="gluster --mode=script --wignore volume create \ + gluster_shared_storage replica $number_of_connected_peers" + +# Adding the brick names in the command +for i in "${connected_peer[@]}" +do + create_cmd=$create_cmd" "$i:/var/run/gluster/ss_brick +done + +if [ "$option" == "disable" ]; then + # Unmount the volume on all the nodes + umount /var/run/gluster/shared_storage +fi + +if [ "$is_originator" == 1 ]; then + if [ "$option" == "enable" ]; then + # Create and start the volume + $create_cmd + gluster --mode=script --wignore volume start gluster_shared_storage + fi + + if [ "$option" == "disable" ]; then + # Stop and delete the volume + gluster --mode=script --wignore volume stop gluster_shared_storage + gluster --mode=script --wignore volume delete gluster_shared_storage + fi +fi + +function check_volume_status() +{ + status=`gluster volume info gluster_shared_storage | grep Status | cut -d ':' -f 2 | xargs` + echo $status +} + +mount_cmd="mount -t glusterfs "$local_node_hostname":/gluster_shared_storage \ + /var/run/gluster/shared_storage" + +if [ "$option" == "enable" ]; then + retry=0; + # Wait for volume to start before mounting + status=$(check_volume_status) + while [ "$status" != "Started" ]; do + sleep 5; + ((retry++)) + if [ "$retry" == 3 ]; then + break; + fi + status = check_volume_status; + done + # Mount the volume on all the nodes + umount /var/run/gluster/shared_storage + mkdir -p /var/run/gluster/shared_storage + $mount_cmd +fi diff --git a/glusterfs.spec.in b/glusterfs.spec.in index b9e2d689340..59daab4cf38 100644 --- a/glusterfs.spec.in +++ b/glusterfs.spec.in @@ -1135,6 +1135,7 @@ fi %config %{_sharedstatedir}/glusterd/hooks/1/add-brick/pre/S28Quota-enable-root-xattr-heal.sh %config %{_sharedstatedir}/glusterd/hooks/1/set/post/S30samba-set.sh %config %{_sharedstatedir}/glusterd/hooks/1/set/post/S31ganesha-set.sh +%config %{_sharedstatedir}/glusterd/hooks/1/set/post/S32gluster_enable_shared_storage.sh %config %{_sharedstatedir}/glusterd/hooks/1/start/post/S29CTDBsetup.sh %config %{_sharedstatedir}/glusterd/hooks/1/start/post/S30samba-start.sh %config %{_sharedstatedir}/glusterd/hooks/1/stop/pre/S30samba-stop.sh @@ -1238,6 +1239,9 @@ fi * Wed May 20 2015 Anand Nekkunti <anekkunt@redhat.com> - glusterd.socket file cleanup during post run upgrade (#1210404) +* Tue May 19 2015 Avra Sengupta <asengupt@redhat.com> +- Added S32gluster_enable_shared_storage.sh as volume set hook script (#1222013) + * Mon May 18 2015 Milind Changire <mchangir@redhat.com> - Move file peer_add_secret_pub to the server RPM to support glusterfind (#1221544) diff --git a/xlators/mgmt/glusterd/src/glusterd-hooks.c b/xlators/mgmt/glusterd/src/glusterd-hooks.c index fa9cff711ad..e3c2ee0ad78 100644 --- a/xlators/mgmt/glusterd/src/glusterd-hooks.c +++ b/xlators/mgmt/glusterd/src/glusterd-hooks.c @@ -157,6 +157,34 @@ glusterd_hooks_add_hooks_version (runner_t* runner) runner_argprintf (runner, "--version=%d", GLUSTERD_HOOK_VER); } +static void +glusterd_hooks_add_custom_args (dict_t *dict, runner_t *runner) +{ + char *hooks_args = NULL; + int32_t ret = -1; + xlator_t *this = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO ("glusterd", this, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + GF_VALIDATE_OR_GOTO (this->name, runner, out); + + ret = dict_get_str (dict, "hooks_args", &hooks_args); + if (ret) + gf_log (this->name, GF_LOG_DEBUG, + "No Hooks Arguments."); + else + gf_log (this->name, GF_LOG_DEBUG, + "Hooks Args = %s", hooks_args); + + if (hooks_args) + runner_argprintf (runner, "%s", hooks_args); + +out: + return; +} + + int glusterd_hooks_set_volume_args (dict_t *dict, runner_t *runner) { @@ -191,6 +219,8 @@ glusterd_hooks_set_volume_args (dict_t *dict, runner_t *runner) runner_argprintf (runner, "%s=%s", key, value); } + glusterd_hooks_add_custom_args (dict, runner); + ret = 0; out: return ret; @@ -258,15 +288,7 @@ glusterd_hooks_add_op_args (runner_t *runner, glusterd_op_t op, 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); + glusterd_hooks_add_custom_args (op_ctx, runner); break; case GD_OP_ADD_BRICK: diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index d22b0c571db..01244409146 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -51,11 +51,36 @@ #include <signal.h> #include <sys/wait.h> +extern char ss_brick_path[PATH_MAX]; +extern char local_node_hostname[PATH_MAX]; +static int +glusterd_set_shared_storage (dict_t *dict, char *key, char *value, + char **op_errstr); + +/* Valid options for all volumes to be listed in the * + * valid_all_vol_opts table. To add newer options to * + * all volumes, we can just add more entries to this * + * table * + */ +glusterd_all_vol_opts valid_all_vol_opts[] = { + { GLUSTERD_QUORUM_RATIO_KEY }, + { GLUSTERD_SHARED_STORAGE_KEY }, + { NULL }, +}; + #define ALL_VOLUME_OPTION_CHECK(volname, key, ret, op_errstr, label) \ do { \ - gf_boolean_t _all = !strcmp ("all", volname); \ - gf_boolean_t _ratio = !strcmp (key, \ - GLUSTERD_QUORUM_RATIO_KEY); \ + gf_boolean_t _all = !strcmp ("all", volname); \ + gf_boolean_t _ratio = _gf_false; \ + int32_t i = 0; \ + \ + for (i = 0; valid_all_vol_opts[i].option; i++) { \ + if (!strcmp (key, valid_all_vol_opts[i].option)) { \ + _ratio = _gf_true; \ + break; \ + } \ + } \ + \ if (_all && !_ratio) { \ ret = -1; \ *op_errstr = gf_strdup ("Not a valid option for all " \ @@ -678,6 +703,71 @@ out: } static int +glusterd_validate_shared_storage (char *key, char *value, char *errstr) +{ + int32_t ret = -1; + int32_t exists = -1; + int32_t count = -1; + xlator_t *this = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO ("glusterd", this, out); + GF_VALIDATE_OR_GOTO (this->name, key, out); + GF_VALIDATE_OR_GOTO (this->name, value, out); + GF_VALIDATE_OR_GOTO (this->name, errstr, out); + + ret = 0; + + if (strcmp (key, GLUSTERD_SHARED_STORAGE_KEY)) { + goto out; + } + + if ((strcmp (value, "enable")) && + (strcmp (value, "disable"))) { + snprintf (errstr, PATH_MAX, + "Invalid option(%s). Valid options " + "are 'enable' and 'disable'", value); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); + ret = -1; + goto out; + } + + if (strcmp (value, "enable")) { + goto out; + } + + exists = glusterd_check_volume_exists (GLUSTER_SHARED_STORAGE); + if (exists) { + snprintf (errstr, PATH_MAX, + "Shared storage volume("GLUSTER_SHARED_STORAGE + ") already exists."); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); + ret = -1; + goto out; + } + + ret = glusterd_count_connected_peers (&count); + if (ret) { + snprintf (errstr, PATH_MAX, + "Failed to calculate number of connected peers."); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + if (count <= 1) { + snprintf (errstr, PATH_MAX, + "More than one node should " + "be up/present in the cluster to enable this option"); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); + ret = -1; + goto out; + } + +out: + return ret; +} + +static int glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) { int ret = -1; @@ -692,7 +782,7 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) int trash_path_len = 0; int count = 0; int dict_count = 0; - char errstr[2048] = {0, }; + char errstr[PATH_MAX] = {0, }; glusterd_volinfo_t *volinfo = NULL; glusterd_brickinfo_t *brickinfo = NULL; dict_t *val_dict = NULL; @@ -996,6 +1086,14 @@ glusterd_op_stage_set_volume (dict_t *dict, char **op_errstr) } } + ret = glusterd_validate_shared_storage (key, value, errstr); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to validate shared " + "storage volume options"); + goto out; + } + if (!strcmp(key, "features.trash-dir") && trash_enabled) { if (strchr (value, '/')) { snprintf (errstr, sizeof (errstr), @@ -1921,7 +2019,8 @@ out: } static int -glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict) +glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict, + char **op_errstr) { char *key = NULL; char *key_fixed = NULL; @@ -1945,6 +2044,7 @@ glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict) "invalid key,value pair in 'volume set'"); goto out; } + ret = glusterd_check_option_exists (key, &key_fixed); if (ret <= 0) { gf_log (this->name, GF_LOG_ERROR, "Invalid key %s", key); @@ -1955,6 +2055,13 @@ glusterd_op_set_all_volume_options (xlator_t *this, dict_t *dict) if (key_fixed) key = key_fixed; + ret = glusterd_set_shared_storage (dict, key, value, op_errstr); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Failed to set shared storage option"); + goto out; + } + /* If the key is cluster.op-version, set conf->op_version to the value * if needed and save it. */ @@ -2033,6 +2140,82 @@ out: } static int +glusterd_set_shared_storage (dict_t *dict, char *key, char *value, + char **op_errstr) +{ + int32_t ret = -1; + int32_t exists = -1; + int32_t count = -1; + char hooks_args[PATH_MAX] = {0, }; + char errstr[PATH_MAX] = {0, }; + xlator_t *this = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO ("glusterd", this, out); + GF_VALIDATE_OR_GOTO (this->name, dict, out); + GF_VALIDATE_OR_GOTO (this->name, key, out); + GF_VALIDATE_OR_GOTO (this->name, value, out); + GF_VALIDATE_OR_GOTO (this->name, op_errstr, out); + + ret = 0; + + if (strcmp (key, GLUSTERD_SHARED_STORAGE_KEY)) { + goto out; + } + + /* Re-create the brick path so as to be * + * able to re-use it * + */ + ret = recursive_rmdir (ss_brick_path); + if (ret) { + snprintf (errstr, PATH_MAX, + "Failed to remove shared " + "storage brick(%s). " + "Reason: %s", ss_brick_path, + strerror (errno)); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); + ret = -1; + goto out; + } + + ret = mkdir_p (ss_brick_path, 0777, _gf_true); + if (-1 == ret) { + snprintf (errstr, PATH_MAX, + "Failed to create shared " + "storage brick(%s). " + "Reason: %s", ss_brick_path, + strerror (errno)); + gf_log (this->name, GF_LOG_ERROR, "%s", errstr); + goto out; + } + + if (is_origin_glusterd (dict)) { + snprintf(hooks_args, sizeof(hooks_args), + "is_originator=1,local_node_hostname=%s", + local_node_hostname); + } else { + snprintf(hooks_args, sizeof(hooks_args), + "is_originator=0,local_node_hostname=%s", + local_node_hostname); + } + + ret = dict_set_dynstr_with_alloc (dict, "hooks_args", hooks_args); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to set" + " hooks_args in dict."); + goto out; + } + +out: + if (ret && strlen(errstr)) { + *op_errstr = gf_strdup (errstr); + } + + return ret; +} + + +static int glusterd_op_set_volume (dict_t *dict, char **errstr) { int ret = 0; @@ -2086,7 +2269,8 @@ glusterd_op_set_volume (dict_t *dict, char **errstr) } if (strcasecmp (volname, "all") == 0) { - ret = glusterd_op_set_all_volume_options (this, dict); + ret = glusterd_op_set_all_volume_options (this, dict, + &op_errstr); goto out; } diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.h b/xlators/mgmt/glusterd/src/glusterd-op-sm.h index 749e3806ca6..42b4252c73b 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.h +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.h @@ -163,6 +163,10 @@ typedef enum cli_cmd_type_ { ALL_HEAL_XL, } cli_cmd_type; +typedef struct glusterd_all_volume_options { + char *option; +} glusterd_all_vol_opts; + int glusterd_op_sm_new_event (glusterd_op_sm_event_type_t event_type, glusterd_op_sm_event_t **new_event); diff --git a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c index 447fce561c0..098e489d7ae 100644 --- a/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-rpc-ops.c @@ -1467,6 +1467,15 @@ glusterd_rpc_friend_add (call_frame_t *frame, xlator_t *this, goto out; } + ret = dict_set_dynstr_with_alloc (peer_data, + "hostname_in_cluster", + peerinfo->hostname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to add hostname of the peer"); + goto out; + } + if (priv->op_version >= GD_OP_VERSION_3_6_0) { ret = glusterd_add_missed_snaps_to_export_dict (peer_data); if (ret) { diff --git a/xlators/mgmt/glusterd/src/glusterd-sm.c b/xlators/mgmt/glusterd/src/glusterd-sm.c index cabe4335416..a3de0c30ac4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-sm.c @@ -34,6 +34,8 @@ #include "glusterd-snapshot-utils.h" #include "glusterd-server-quorum.h" +char local_node_hostname[PATH_MAX] = {0, }; + static struct cds_list_head gd_friend_sm_queue; static char *glusterd_friend_sm_state_names[] = { @@ -729,6 +731,7 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) int32_t op_ret = -1; int32_t op_errno = 0; xlator_t *this = NULL; + char *hostname = NULL; this = THIS; GF_ASSERT (this); @@ -833,6 +836,15 @@ glusterd_ac_handle_friend_add_req (glusterd_friend_sm_event_t *event, void *ctx) new_event->ctx = new_ev_ctx; + ret = dict_get_str (ev_ctx->vols, "hostname_in_cluster", + &hostname); + if (ret || !hostname) { + gf_log (this->name, GF_LOG_DEBUG, + "Unable to fetch local hostname from peer"); + } else + strncpy (local_node_hostname, hostname, + sizeof(local_node_hostname)); + glusterd_friend_sm_inject_event (new_event); new_event = NULL; diff --git a/xlators/mgmt/glusterd/src/glusterd-snapshot.c b/xlators/mgmt/glusterd/src/glusterd-snapshot.c index ce63bd2079b..7825031f706 100644 --- a/xlators/mgmt/glusterd/src/glusterd-snapshot.c +++ b/xlators/mgmt/glusterd/src/glusterd-snapshot.c @@ -62,7 +62,7 @@ #include "lvm-defaults.h" -char snap_mount_folder[PATH_MAX]; +char snap_mount_dir[PATH_MAX]; struct snap_create_args_ { xlator_t *this; dict_t *dict; @@ -4604,7 +4604,7 @@ glusterd_snap_brick_create (glusterd_volinfo_t *snap_volinfo, GF_ASSERT (brickinfo); snprintf (snap_brick_mount_path, sizeof (snap_brick_mount_path), - "%s/%s/brick%d", snap_mount_folder, snap_volinfo->volname, + "%s/%s/brick%d", snap_mount_dir, snap_volinfo->volname, brick_count + 1); ret = mkdir_p (snap_brick_mount_path, 0777, _gf_true); @@ -4794,7 +4794,7 @@ glusterd_add_brick_to_snap_volume (dict_t *dict, dict_t *rsp_dict, * <snap-uuid>/<original-brick#>/snap-brick-dir * */ snprintf (snap_brick_path, sizeof(snap_brick_path), - "%s/%s/brick%d%s", snap_mount_folder, + "%s/%s/brick%d%s", snap_mount_dir, snap_vol->volname, brick_count+1, snap_brick_dir); diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 0ff70bdfd78..5e99ee99550 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -9759,3 +9759,34 @@ glusterd_disallow_op_for_tier (glusterd_volinfo_t *volinfo, glusterd_op_t op, out: return ret; } + +int32_t +glusterd_count_connected_peers (int32_t *count) +{ + glusterd_peerinfo_t *peerinfo = NULL; + glusterd_conf_t *conf = NULL; + int32_t ret = -1; + xlator_t *this = NULL; + + this = THIS; + GF_VALIDATE_OR_GOTO ("glusterd", this, out); + conf = this->private; + GF_VALIDATE_OR_GOTO (this->name, conf, out); + GF_VALIDATE_OR_GOTO (this->name, count, out); + + *count = 1; + + rcu_read_lock (); + cds_list_for_each_entry_rcu (peerinfo, &conf->peers, uuid_list) { + /* Find peer who is connected and is a friend */ + if ((peerinfo->connected) && + (peerinfo->state.state == GD_FRIEND_STATE_BEFRIENDED)) { + (*count)++; + } + } + rcu_read_unlock (); + + ret = 0; +out: + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 57eecca8fb1..69f16a29edc 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -657,4 +657,8 @@ glusterd_defrag_rpc_get (glusterd_defrag_info_t *defrag); struct rpc_clnt* glusterd_defrag_rpc_put (glusterd_defrag_info_t *defrag); + +int32_t +glusterd_count_connected_peers (int32_t *count); + #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index ec107b55bf7..3e49fab37d4 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -1740,6 +1740,12 @@ struct volopt_map_entry glusterd_volopt_map[] = { .voltype = "features/trash", .op_version = GD_OP_VERSION_3_7_0, }, + { .key = GLUSTERD_SHARED_STORAGE_KEY, + .voltype = "mgmt/glusterd", + .value = "disable", + .type = GLOBAL_DOC, + .op_version = GD_OP_VERSION_3_7_1, + }, #if USE_GFDB /* no GFDB means tiering is disabled */ /* tier translator - global tunables */ diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index 5bdeb753f4a..407089af493 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -62,7 +62,8 @@ extern struct rpcsvc_program gd_svc_cli_trusted_progs; extern struct rpc_clnt_program gd_brick_prog; extern struct rpcsvc_program glusterd_mgmt_hndsk_prog; -extern char snap_mount_folder[PATH_MAX]; +extern char snap_mount_dir[PATH_MAX]; +char ss_brick_path[PATH_MAX]; rpcsvc_cbk_program_t glusterd_cbk_prog = { .progname = "Gluster Callback", @@ -1115,18 +1116,18 @@ glusterd_stop_uds_listener (xlator_t *this) } static int -glusterd_init_snap_folder (xlator_t *this) +glusterd_find_correct_var_run_dir (xlator_t *this, char *var_run_dir) { int ret = -1; struct stat buf = {0,}; - GF_ASSERT (this); + GF_VALIDATE_OR_GOTO ("glusterd", this, out); + GF_VALIDATE_OR_GOTO (this->name, var_run_dir, out); - /* Snapshot volumes are mounted under /var/run/gluster/snaps folder. - * But /var/run is normally a symbolic link to /run folder, which + /* /var/run is normally a symbolic link to /run dir, which * creates problems as the entry point in the mtab for the mount point * and glusterd maintained entry point will be different. Therefore - * identify the correct run folder and use it for snap volume mounting. + * identify the correct run dir and use it */ ret = lstat (GLUSTERD_VAR_RUN_DIR, &buf); if (ret != 0) { @@ -1136,20 +1137,38 @@ glusterd_init_snap_folder (xlator_t *this) goto out; } - /* If /var/run is symlink then use /run folder */ + /* If /var/run is symlink then use /run dir */ if (S_ISLNK (buf.st_mode)) { - strcpy (snap_mount_folder, GLUSTERD_RUN_DIR); + strcpy (var_run_dir, GLUSTERD_RUN_DIR); } else { - strcpy (snap_mount_folder, GLUSTERD_VAR_RUN_DIR); + strcpy (var_run_dir, GLUSTERD_VAR_RUN_DIR); } - strcat (snap_mount_folder, GLUSTERD_DEFAULT_SNAPS_BRICK_DIR); + ret = 0; +out: + return ret; +} + +static int +glusterd_init_var_run_dirs (xlator_t *this, char *var_run_dir, + char *dir_to_be_created) +{ + int ret = -1; + struct stat buf = {0,}; + char abs_path[PATH_MAX] = {0, }; + + GF_VALIDATE_OR_GOTO ("glusterd", this, out); + GF_VALIDATE_OR_GOTO (this->name, var_run_dir, out); + GF_VALIDATE_OR_GOTO (this->name, dir_to_be_created, out); + + snprintf (abs_path, sizeof(abs_path), "%s%s", + var_run_dir, dir_to_be_created); - ret = stat (snap_mount_folder, &buf); + ret = stat (abs_path, &buf); if ((ret != 0) && (ENOENT != errno)) { gf_log (this->name, GF_LOG_ERROR, "stat fails on %s, exiting. (errno = %d)", - snap_mount_folder, errno); + abs_path, errno); ret = -1; goto out; } @@ -1157,19 +1176,19 @@ glusterd_init_snap_folder (xlator_t *this) if ((!ret) && (!S_ISDIR(buf.st_mode))) { gf_log (this->name, GF_LOG_CRITICAL, "Provided snap path %s is not a directory," - "exiting", snap_mount_folder); + "exiting", abs_path); ret = -1; goto out; } if ((-1 == ret) && (ENOENT == errno)) { - /* Create missing folders */ - ret = mkdir_p (snap_mount_folder, 0777, _gf_true); + /* Create missing dirs */ + ret = mkdir_p (abs_path, 0777, _gf_true); if (-1 == ret) { gf_log (this->name, GF_LOG_CRITICAL, "Unable to create directory %s" - " ,errno = %d", snap_mount_folder, errno); + " ,errno = %d", abs_path, errno); goto out; } } @@ -1246,21 +1265,22 @@ out: int init (xlator_t *this) { - int32_t ret = -1; - rpcsvc_t *rpc = NULL; - rpcsvc_t *uds_rpc = NULL; - glusterd_conf_t *conf = NULL; - data_t *dir_data = NULL; - struct stat buf = {0,}; - char storedir [PATH_MAX] = {0,}; - char workdir [PATH_MAX] = {0,}; - char cmd_log_filename [PATH_MAX] = {0,}; - int first_time = 0; - char *mountbroker_root = NULL; - int i = 0; - int total_transport = 0; - char *valgrind_str = NULL; - char *transport_type = NULL; + int32_t ret = -1; + rpcsvc_t *rpc = NULL; + rpcsvc_t *uds_rpc = NULL; + glusterd_conf_t *conf = NULL; + data_t *dir_data = NULL; + struct stat buf = {0,}; + char storedir[PATH_MAX] = {0,}; + char workdir[PATH_MAX] = {0,}; + char cmd_log_filename[PATH_MAX] = {0,}; + int first_time = 0; + char *mountbroker_root = NULL; + int i = 0; + int total_transport = 0; + char *valgrind_str = NULL; + char *transport_type = NULL; + char var_run_dir[PATH_MAX] = {0,}; #ifndef GF_DARWIN_HOST_OS { @@ -1322,14 +1342,35 @@ init (xlator_t *this) gf_log (this->name, GF_LOG_INFO, "Using %s as working directory", workdir); - ret = glusterd_init_snap_folder (this); + ret = glusterd_find_correct_var_run_dir (this, var_run_dir); + if (ret) { + gf_log (this->name, GF_LOG_CRITICAL, "Unable to find " + "the correct var run dir"); + exit (1); + } + + ret = glusterd_init_var_run_dirs (this, var_run_dir, + GLUSTERD_DEFAULT_SNAPS_BRICK_DIR); + if (ret) { + gf_log (this->name, GF_LOG_CRITICAL, "Unable to create " + "snap backend dir"); + exit (1); + } + snprintf (snap_mount_dir, sizeof(snap_mount_dir), "%s%s", + var_run_dir, GLUSTERD_DEFAULT_SNAPS_BRICK_DIR); + + ret = glusterd_init_var_run_dirs (this, var_run_dir, + GLUSTER_SHARED_STORAGE_BRICK_DIR); if (ret) { gf_log (this->name, GF_LOG_CRITICAL, "Unable to create " - "snap backend folder"); + "shared storage brick"); exit (1); } + snprintf (ss_brick_path, sizeof(ss_brick_path), "%s%s", + var_run_dir, GLUSTER_SHARED_STORAGE_BRICK_DIR); + snprintf (cmd_log_filename, PATH_MAX, "%s/cmd_history.log", DEFAULT_LOG_FILE_DIRECTORY); ret = gf_cmd_log_init (cmd_log_filename); diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index a4b0bfdf1a1..7e3c8129a94 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -47,6 +47,8 @@ #define GEO_CONF_MAX_OPT_VALS 6 #define GLUSTERD_CREATE_HOOK_SCRIPT "/hooks/1/gsync-create/post/" \ "S56glusterd-geo-rep-create-post.sh" +#define GLUSTER_SHARED_STORAGE "gluster_shared_storage" +#define GLUSTERD_SHARED_STORAGE_KEY "cluster.enable-shared-storage" #define GANESHA_HA_CONF CONFDIR "/ganesha-ha.conf" #define GLUSTERD_SNAPS_MAX_HARD_LIMIT 256 @@ -507,6 +509,7 @@ typedef enum { #define GLUSTERD_VOL_SNAP_DIR_PREFIX "snaps" #define GLUSTERD_DEFAULT_SNAPS_BRICK_DIR "/gluster/snaps" +#define GLUSTER_SHARED_STORAGE_BRICK_DIR "/gluster/ss_brick" #define GLUSTERD_VAR_RUN_DIR "/var/run" #define GLUSTERD_RUN_DIR "/run" |