diff options
Diffstat (limited to 'xlators/mgmt/glusterd')
-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 5788813235b..993ddddb2b4 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 56c1d98754a..4cfbf5e4c3d 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 b381e5a0cce..788949d55fc 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 7a784149e0a..6e02929f1ec 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 e4f04002f09..b84c141df9a 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) |