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"  | 
