diff options
Diffstat (limited to 'xlators/mgmt/glusterd/src')
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 44 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.c | 211 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-store.h | 23 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 3 | ||||
| -rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.c | 10 | 
5 files changed, 287 insertions, 4 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 578881323..993ddddb2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -2127,6 +2127,32 @@ out:  }  static int +glusterd_op_commit_hook (glusterd_op_t op, dict_t *op_ctx,  glusterd_commit_hook_type_t type) +{ +        glusterd_conf_t *priv                   = NULL; +        char            hookdir[PATH_MAX]       = {0, }; +        char            scriptdir[PATH_MAX]     = {0, }; +        char            type_subdir[256]        = {0, }; +        char            *cmd_subdir             = NULL; + +        priv = THIS->private; +        if (type == GD_COMMIT_HOOK_PRE) +                strcpy (type_subdir, "pre"); +        else if (type == GD_COMMIT_HOOK_POST) +                strcpy (type_subdir, "post"); + +        cmd_subdir = glusterd_store_get_hooks_cmd_subdir (op); +        if (strlen (cmd_subdir) == 0) +                return -1; + +        GLUSTERD_GET_HOOKS_DIR (hookdir, GLUSTERD_HOOK_VER, priv); +        snprintf (scriptdir, sizeof (scriptdir), "%s/%s/%s", +                  hookdir, cmd_subdir, type_subdir); + +        return glusterd_store_run_hooks (scriptdir, op_ctx); +} + +static int  glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx)  {          int                     ret = 0; @@ -2145,12 +2171,15 @@ glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx)          priv = this->private;          GF_ASSERT (priv); -        op = glusterd_op_get_op (); +        op      = glusterd_op_get_op (); +        op_dict = glusterd_op_get_ctx (); +          ret = glusterd_op_build_payload (&dict);          if (ret)                  goto out; +        glusterd_op_commit_hook (op, op_dict, GD_COMMIT_HOOK_PRE);          ret = glusterd_op_commit_perform (op, dict, &op_errstr, NULL); //rsp_dict invalid for source          if (ret) {                  gf_log (THIS->name, GF_LOG_ERROR, "Commit failed"); @@ -2158,6 +2187,8 @@ glusterd_op_ac_send_commit_op (glusterd_op_sm_event_t *event, void *ctx)                  goto out;          } +        glusterd_op_commit_hook (op, op_dict, GD_COMMIT_HOOK_POST); +          list_for_each_entry (peerinfo, &priv->peers, uuid_list) {                  GF_ASSERT (peerinfo); @@ -2196,7 +2227,6 @@ out:          if (!opinfo.pending_count) {                  if (op == GD_OP_REPLACE_BRICK) { -                        op_dict = glusterd_op_get_ctx ();                          ret = glusterd_op_start_rb_timer (op_dict);                  } else { @@ -2579,11 +2609,11 @@ static int  glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx)  {          int                       ret        = 0; -        glusterd_req_ctx_t       *req_ctx = NULL; +        glusterd_req_ctx_t       *req_ctx    = NULL;          int32_t                   status     = 0;          char                     *op_errstr  = NULL;          dict_t                   *dict       = NULL; -        dict_t                   *rsp_dict = NULL; +        dict_t                   *rsp_dict   = NULL;          GF_ASSERT (ctx); @@ -2595,6 +2625,8 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx)          if (NULL == rsp_dict)                  return -1; +        glusterd_op_commit_hook (req_ctx->op, dict, GD_COMMIT_HOOK_PRE); +          if (GD_OP_CLEARLOCKS_VOLUME == req_ctx->op) {                  /*clear locks should be run only on                   * originator glusterd*/ @@ -2607,6 +2639,10 @@ glusterd_op_ac_commit_op (glusterd_op_sm_event_t *event, void *ctx)          if (status) {                  gf_log (THIS->name, GF_LOG_ERROR, "Commit failed: %d", status); +        } else { +                /* On successful commit */ +                glusterd_op_commit_hook (req_ctx->op, dict, +                                         GD_COMMIT_HOOK_POST);          }          ret = glusterd_op_commit_send_resp (req_ctx->req, req_ctx->op, diff --git a/xlators/mgmt/glusterd/src/glusterd-store.c b/xlators/mgmt/glusterd/src/glusterd-store.c index 56c1d9875..4cfbf5e4c 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.c +++ b/xlators/mgmt/glusterd/src/glusterd-store.c @@ -51,6 +51,39 @@  #include <inttypes.h>  #include <dirent.h> +extern int mkdir_if_missing (char *dir); + +#define EMPTY "" +char glusterd_hook_dirnames[GD_OP_MAX][256] = +{ +        [GD_OP_NONE]                    = EMPTY, +        [GD_OP_CREATE_VOLUME]           = "create", +        [GD_OP_START_BRICK]             = EMPTY, +        [GD_OP_STOP_BRICK]              = EMPTY, +        [GD_OP_DELETE_VOLUME]           = "delete", +        [GD_OP_START_VOLUME]            = "start", +        [GD_OP_STOP_VOLUME]             = "stop", +        [GD_OP_DEFRAG_VOLUME]           = EMPTY, +        [GD_OP_ADD_BRICK]               = "add-brick", +        [GD_OP_REMOVE_BRICK]            = "remove-brick", +        [GD_OP_REPLACE_BRICK]           = EMPTY, +        [GD_OP_SET_VOLUME]              = EMPTY, +        [GD_OP_RESET_VOLUME]            = EMPTY, +        [GD_OP_SYNC_VOLUME]             = EMPTY, +        [GD_OP_LOG_ROTATE]              = EMPTY, +        [GD_OP_GSYNC_SET]               = EMPTY, +        [GD_OP_PROFILE_VOLUME]          = EMPTY, +        [GD_OP_QUOTA]                   = EMPTY, +        [GD_OP_STATUS_VOLUME]           = EMPTY, +        [GD_OP_REBALANCE]               = EMPTY, +        [GD_OP_HEAL_VOLUME]             = EMPTY, +        [GD_OP_STATEDUMP_VOLUME]        = EMPTY, +        [GD_OP_LIST_VOLUME]             = EMPTY, +        [GD_OP_CLEARLOCKS_VOLUME]       = EMPTY, +        [GD_OP_DEFRAG_BRICK_VOLUME]     = EMPTY, +}; +#undef EMPTY +  static int32_t  glusterd_store_mkdir (char *path)  { @@ -2464,3 +2497,181 @@ out:          gf_log ("", GF_LOG_DEBUG, "Returning %d", ret);          return ret;  } + +static inline gf_boolean_t +glusterd_is_hook_enabled (char *script) +{ +        return (script[0] == 'S'); +} + +int +glusterd_store_create_hooks_directory (char *basedir) +{ +        int  ret                                        = -1; +        int  op                                         = GD_OP_NONE; +        int  type                                       = GD_COMMIT_HOOK_NONE; +        char version_dir[PATH_MAX]                      = {0, }; +        char path[PATH_MAX]                             = {0, }; +        char *cmd_subdir                                = NULL; +        char type_subdir[GD_COMMIT_HOOK_MAX][256]       = {{0, }, +                                                           "pre", +                                                           "post"}; +        glusterd_conf_t *priv                           = NULL; + +        priv = THIS->private; + +        snprintf (path, sizeof (path), "%s/hooks", basedir); +        ret = mkdir_if_missing (path); +        if (ret) { +                gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to create %s due" +                         "to %s", path, strerror (errno)); +                goto out; +        } + +        GLUSTERD_GET_HOOKS_DIR (version_dir, GLUSTERD_HOOK_VER, priv); +        ret = mkdir_if_missing (version_dir); +        if (ret) { +                gf_log (THIS->name, GF_LOG_CRITICAL, "Unable to create %s due " +                        "to %s", version_dir, strerror (errno)); +                goto out; +        } + +        for (op = GD_OP_NONE+1; op < GD_OP_MAX; op++) { +                cmd_subdir = glusterd_store_get_hooks_cmd_subdir (op); +                if (strlen (cmd_subdir) == 0) +                        continue; + +                snprintf (path, sizeof (path), "%s/%s", version_dir, +                          cmd_subdir); +                ret = mkdir_if_missing (path); +                if (ret) { +                        gf_log (THIS->name, GF_LOG_CRITICAL, +                                "Unable to create %s due to %s", +                                path, strerror (errno)); +                        goto out; +                } + +                for (type = GD_COMMIT_HOOK_PRE; type < GD_COMMIT_HOOK_MAX; +                     type++) { +                        snprintf (path, sizeof (path), "%s/%s/%s", +                                  version_dir, cmd_subdir, type_subdir[type]); +                        ret = mkdir_if_missing (path); +                        if (ret) { +                                gf_log (THIS->name, GF_LOG_CRITICAL, +                                        "Unable to create %s due to %s", +                                        path, strerror (errno)); +                                goto out; +                        } +                } +        } + +        ret = 0; +out: +        return ret; +} + +char* +glusterd_store_get_hooks_cmd_subdir (glusterd_op_t op) +{ +        GF_ASSERT ((op > GD_OP_NONE) && (op < GD_OP_MAX)); + +        return glusterd_hook_dirnames[op]; +} + +int +glusterd_store_run_hooks (char *hooks_path, dict_t *op_ctx) +{ +        xlator_t        *this                   = NULL; +        glusterd_conf_t *priv                   = NULL; +        runner_t        runner                  = {0, }; +        struct dirent   *entry                  = NULL; +        DIR             *hookdir                = NULL; +        char            *volname                = NULL; +        char            **lines                 = NULL; +        int             N                       = 8; /*arbitrary*/ +        int             lineno                  = 0; +        int             line_count              = 0; +        int             ret                     = -1; + +        this = THIS; +        priv = this->private; + +        ret = dict_get_str (op_ctx, "volname", &volname); +        if (ret) { +                gf_log (this->name, GF_LOG_CRITICAL, "Failed to get volname " +                        "from operation context"); +                goto out; +        } + +        hookdir = opendir (hooks_path); +        if (!hookdir) { +                ret = -1; +                gf_log (this->name, GF_LOG_ERROR, "Failed to open dir %s, due " +                        "to %s", hooks_path, strerror (errno)); +                goto out; +        } + +        lines = GF_CALLOC (1, N * sizeof (*lines), gf_gld_mt_charptr); +        if (!lines) { +                ret = -1; +                goto out; +        } + +        ret = -1; +        line_count = 0; +        glusterd_for_each_entry (entry, hookdir); +        while (entry) { +                if (line_count == N-1) { +                        N *= 2; +                        lines = GF_REALLOC (lines, N * sizeof (char *)); +                        if (!lines) +                                goto out; +                } + +                if (glusterd_is_hook_enabled (entry->d_name)) { +                        lines[line_count] = gf_strdup (entry->d_name); +                        line_count++; +                } + +                glusterd_for_each_entry (entry, hookdir); +        } + +        lines[line_count] = NULL; +        lines = GF_REALLOC (lines, (line_count + 1) * sizeof (char *)); +        if (!lines) +                goto out; + +        qsort (lines, line_count, sizeof (*lines), glusterd_compare_lines); + +        for (lineno = 0; lineno < line_count; lineno++) { + +                runinit (&runner); +                runner_argprintf (&runner, "%s/%s", hooks_path, lines[lineno]); +                /*Add future command line arguments to hook scripts below*/ +                runner_argprintf (&runner, "--volname=%s", volname); +                ret = runner_run_reuse (&runner); +                if (ret) { +                        runner_log (&runner, this->name, GF_LOG_ERROR, +                                    "Failed to execute script"); +                } else { +                        runner_log (&runner, this->name, GF_LOG_INFO, +                                    "Ran script"); +                } +                runner_end (&runner); +        } + +        ret = 0; +out: +        if (lines) { +                for (lineno = 0; lineno < line_count+1; lineno++) +                        if (lines[lineno]) +                                GF_FREE (lines[lineno]); + +                GF_FREE (lines); +        } + +        if (hookdir) +                closedir (hookdir); + +        return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-store.h b/xlators/mgmt/glusterd/src/glusterd-store.h index b381e5a0c..788949d55 100644 --- a/xlators/mgmt/glusterd/src/glusterd-store.h +++ b/xlators/mgmt/glusterd/src/glusterd-store.h @@ -30,6 +30,7 @@  #include "glusterfs.h"  #include "xlator.h" +#include "run.h"  #include "logging.h"  #include "call-stub.h"  #include "fd.h" @@ -73,6 +74,10 @@ typedef enum glusterd_store_ver_ac_{  #define GLUSTERD_STORE_KEY_PEER_HOSTNAME  "hostname"  #define GLUSTERD_STORE_KEY_PEER_STATE     "state" +#define GLUSTERD_GET_HOOKS_DIR(path, version, priv) \ +        snprintf (path, PATH_MAX, "%s/hooks/%d", priv->workdir,\ +                  version); +  #define glusterd_for_each_entry(entry, dir) \          do {\                  entry = NULL;\ @@ -85,6 +90,7 @@ typedef enum glusterd_store_ver_ac_{                  }\          } while (0); \ +  typedef enum {          GD_STORE_SUCCESS,          GD_STORE_KEY_NULL, @@ -95,6 +101,14 @@ typedef enum {          GD_STORE_STAT_FAILED  } glusterd_store_op_errno_t; +#define GLUSTERD_HOOK_VER       1 +typedef enum glusterd_commit_hook_type { +        GD_COMMIT_HOOK_NONE = 0, +        GD_COMMIT_HOOK_PRE, +        GD_COMMIT_HOOK_POST, +        GD_COMMIT_HOOK_MAX +} glusterd_commit_hook_type_t; +  int32_t  glusterd_store_volinfo (glusterd_volinfo_t *volinfo, glusterd_volinfo_ver_ac_t ac); @@ -138,4 +152,13 @@ glusterd_perform_volinfo_version_action (glusterd_volinfo_t *volinfo,                                           glusterd_volinfo_ver_ac_t ac);  gf_boolean_t  glusterd_store_is_valid_brickpath (char *volname, char *brick); + +int +glusterd_store_create_hooks_directory (char *basedir); + +char * +glusterd_store_get_hooks_cmd_subdir (glusterd_op_t op); + +int +glusterd_store_run_hooks (char *hooks_path, dict_t *op_ctx);  #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 7a784149e..6e02929f1 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -57,6 +57,9 @@ typedef struct glusterd_voldict_ctx_ {          char    *val_name;  } glusterd_voldict_ctx_t; +int +glusterd_compare_lines (const void *a, const void *b); +  typedef int (*glusterd_condition_func) (glusterd_volinfo_t *volinfo,                                          glusterd_brickinfo_t *brickinfo,                                          void *ctx); diff --git a/xlators/mgmt/glusterd/src/glusterd.c b/xlators/mgmt/glusterd/src/glusterd.c index e4f04002f..b84c141df 100644 --- a/xlators/mgmt/glusterd/src/glusterd.c +++ b/xlators/mgmt/glusterd/src/glusterd.c @@ -795,6 +795,7 @@ init (xlator_t *this)                                  " ,errno = %d", dirname, errno);                          exit (1);                  } +                  first_time = 1;          } @@ -977,6 +978,15 @@ init (xlator_t *this)          if (ret < 0)                  goto out; +        if (first_time) { +                ret = glusterd_store_create_hooks_directory (dirname); +                if (-1 == ret) { +                        gf_log (this->name, GF_LOG_CRITICAL, +                                "Unable to create hooks directory "); +                        exit (1); +                } +        } +          INIT_LIST_HEAD (&conf->mount_specs);          dict_foreach (this->options, _install_mount_spec, &ret);          if (ret)  | 
