diff options
author | Varun Shastry <vshastry@redhat.com> | 2014-05-06 12:39:20 +0000 |
---|---|---|
committer | Krishnan Parthasarathi <kparthas@redhat.com> | 2014-06-03 00:08:29 -0700 |
commit | 0fe5ab5b9215b8f0ecfb8bc4ba15a5370850654a (patch) | |
tree | 713e00bd047e1703848a0e8529b5592e35638101 /xlators/mgmt/glusterd/src | |
parent | 15f7b4de1124a37a53c7ddb5635b005322b23025 (diff) |
glusterd: Changes to provide interface for USS
The changes which consists of the translators for the USS (User Servicable
Snapshots) is submitted as a separate patch. Current patch provides the
CLI access to the feature.
Change-Id: I6b98a42fcfa82f0870d8048fe0bb53141565e9c6
BUG: 1094815
Signed-off-by: Varun Shastry <vshastry@redhat.com>
Reviewed-on: http://review.gluster.org/7705
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Atin Mukherjee <amukherj@redhat.com>
Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com>
Tested-by: Krishnan Parthasarathi <kparthas@redhat.com>
Diffstat (limited to 'xlators/mgmt/glusterd/src')
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handler.c | 59 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-handshake.c | 14 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-op-sm.c | 10 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.c | 463 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-utils.h | 54 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.c | 456 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volgen.h | 1 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-ops.c | 9 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd-volume-set.c | 9 | ||||
-rw-r--r-- | xlators/mgmt/glusterd/src/glusterd.h | 12 |
10 files changed, 913 insertions, 174 deletions
diff --git a/xlators/mgmt/glusterd/src/glusterd-handler.c b/xlators/mgmt/glusterd/src/glusterd-handler.c index e203e5af01f..733bea236ed 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handler.c +++ b/xlators/mgmt/glusterd/src/glusterd-handler.c @@ -4138,6 +4138,65 @@ glusterd_brick_rpc_notify (struct rpc_clnt *rpc, void *mydata, } int +__glusterd_snapd_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, void *data) +{ + xlator_t *this = NULL; + glusterd_conf_t *conf = NULL; + glusterd_volinfo_t *volinfo = NULL; + int ret = 0; + + this = THIS; + GF_ASSERT (this); + conf = this->private; + GF_ASSERT (conf); + + volinfo = mydata; + if (!volinfo) + return 0; + + switch (event) { + case RPC_CLNT_CONNECT: + gf_log (this->name, GF_LOG_DEBUG, "got RPC_CLNT_CONNECT"); + + (void) glusterd_snapd_set_online_status (volinfo, _gf_true); + + break; + + case RPC_CLNT_DISCONNECT: + if (glusterd_is_snapd_online (volinfo)) { + gf_msg (this->name, GF_LOG_INFO, 0, + GD_MSG_NODE_DISCONNECTED, + "snapd for volume %s has disconnected from " + "glusterd.", volinfo->volname); + + (void) glusterd_snapd_set_online_status + (volinfo, _gf_false); + } + break; + + case RPC_CLNT_DESTROY: + glusterd_volinfo_unref (volinfo); + break; + + default: + gf_log (this->name, GF_LOG_TRACE, + "got some other RPC event %d", event); + break; + } + + return ret; +} + +int +glusterd_snapd_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, void *data) +{ + return glusterd_big_locked_notify (rpc, mydata, event, data, + __glusterd_snapd_rpc_notify); +} + +int __glusterd_nodesvc_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, void *data) { diff --git a/xlators/mgmt/glusterd/src/glusterd-handshake.c b/xlators/mgmt/glusterd/src/glusterd-handshake.c index 2901b98d847..115dd8bd145 100644 --- a/xlators/mgmt/glusterd/src/glusterd-handshake.c +++ b/xlators/mgmt/glusterd/src/glusterd-handshake.c @@ -162,6 +162,7 @@ build_volfile_path (const char *volname, char *path, const char *volname_ptr = NULL; char path_prefix [PATH_MAX] = {0,}; xlator_t *this = NULL; + char *volname_tmp = NULL; this = THIS; GF_ASSERT (this); @@ -170,7 +171,18 @@ build_volfile_path (const char *volname, char *path, GF_ASSERT (volname); GF_ASSERT (path); - if (strstr (volname, "gluster/")) { + if (strstr (volname, "snapd/")) { + volname_tmp = strchr (volname, '/') + 1; + ret = glusterd_volinfo_find (volname_tmp, &volinfo); + if (ret == -1) { + gf_log (this->name, GF_LOG_ERROR, + "Couldn't find volinfo"); + goto out; + } + glusterd_get_snapd_volfile (volinfo, path, path_len); + ret = 1; + goto out; + } else if (strstr (volname, "gluster/")) { server = strchr (volname, '/') + 1; glusterd_get_nodesvc_volfile (server, priv->workdir, path, path_len); diff --git a/xlators/mgmt/glusterd/src/glusterd-op-sm.c b/xlators/mgmt/glusterd/src/glusterd-op-sm.c index 4ad53c126e6..73f4c152460 100644 --- a/xlators/mgmt/glusterd/src/glusterd-op-sm.c +++ b/xlators/mgmt/glusterd/src/glusterd-op-sm.c @@ -2072,6 +2072,11 @@ glusterd_op_set_volume (dict_t *dict) if (!global_opts_set) { gd_update_volume_op_versions (volinfo); + + ret = glusterd_handle_snapd_option (volinfo); + if (ret) + goto out; + ret = glusterd_create_volfiles_and_notify_services (volinfo); if (ret) { gf_log (this->name, GF_LOG_ERROR, @@ -2098,6 +2103,11 @@ glusterd_op_set_volume (dict_t *dict) list_for_each_entry (voliter, &priv->volumes, vol_list) { volinfo = voliter; gd_update_volume_op_versions (volinfo); + + ret = glusterd_handle_snapd_option (volinfo); + if (ret) + goto out; + ret = glusterd_create_volfiles_and_notify_services (volinfo); if (ret) { gf_log (this->name, GF_LOG_ERROR, diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index bd9f7ba39af..6f48767b8a3 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -230,10 +230,10 @@ glusterd_get_uuid (uuid_t *uuid) int glusterd_submit_request_unlocked (struct rpc_clnt *rpc, void *req, - call_frame_t *frame, rpc_clnt_prog_t *prog, - int procnum, struct iobref *iobref, - xlator_t *this, fop_cbk_fn_t cbkfn, - xdrproc_t xdrproc) + call_frame_t *frame, rpc_clnt_prog_t *prog, + int procnum, struct iobref *iobref, + xlator_t *this, fop_cbk_fn_t cbkfn, + xdrproc_t xdrproc) { int ret = -1; struct iobuf *iobuf = NULL; @@ -312,17 +312,17 @@ glusterd_submit_request (struct rpc_clnt *rpc, void *req, xlator_t *this, fop_cbk_fn_t cbkfn, xdrproc_t xdrproc) { glusterd_conf_t *priv = THIS->private; - int ret = -1; + int ret = -1; - synclock_unlock (&priv->big_lock); - { - ret = glusterd_submit_request_unlocked (rpc, req, frame, prog, - procnum, iobref, this, - cbkfn, xdrproc); - } - synclock_lock (&priv->big_lock); + synclock_unlock (&priv->big_lock); + { + ret = glusterd_submit_request_unlocked (rpc, req, frame, prog, + procnum, iobref, this, + cbkfn, xdrproc); + } + synclock_lock (&priv->big_lock); - return ret; + return ret; } @@ -1919,7 +1919,6 @@ glusterd_brick_unlink_socket_file (glusterd_volinfo_t *volinfo, char socketpath[PATH_MAX] = {0}; xlator_t *this = NULL; glusterd_conf_t *priv = NULL; - int ret = 0; GF_ASSERT (volinfo); GF_ASSERT (brickinfo); @@ -1931,15 +1930,8 @@ glusterd_brick_unlink_socket_file (glusterd_volinfo_t *volinfo, GLUSTERD_GET_VOLUME_DIR (path, volinfo, priv); glusterd_set_brick_socket_filepath (volinfo, brickinfo, socketpath, sizeof (socketpath)); - ret = unlink (socketpath); - if (ret && (ENOENT == errno)) { - ret = 0; - } else { - gf_log (this->name, GF_LOG_ERROR, "Failed to remove %s" - " error: %s", socketpath, strerror (errno)); - } - return ret; + return glusterd_unlink_file (socketpath); } int32_t @@ -3124,9 +3116,9 @@ glusterd_compare_friend_volume (dict_t *peer_data, int32_t count, *status = GLUSTERD_VOL_COMP_UPDATE_REQ; goto out; } else if (version < volinfo->version) { - *status = GLUSTERD_VOL_COMP_SCS; - goto out; - } + *status = GLUSTERD_VOL_COMP_SCS; + goto out; + } //Now, versions are same, compare cksums. // @@ -3443,6 +3435,7 @@ glusterd_spawn_daemons (void *opaque) { glusterd_conf_t *conf = THIS->private; gf_boolean_t start_bricks = !conf->restart_done; + int ret = -1; if (start_bricks) { glusterd_restart_bricks (conf); @@ -3450,7 +3443,9 @@ glusterd_spawn_daemons (void *opaque) } glusterd_restart_gsyncds (conf); glusterd_restart_rebalance (conf); - return 0; + ret = glusterd_restart_snapds (conf); + + return ret; } void @@ -5526,7 +5521,7 @@ out: void glusterd_get_nodesvc_dir (char *server, char *workdir, - char *path, size_t len) + char *path, size_t len) { GF_ASSERT (len == PATH_MAX); snprintf (path, len, "%s/%s", workdir, server); @@ -5534,7 +5529,7 @@ glusterd_get_nodesvc_dir (char *server, char *workdir, void glusterd_get_nodesvc_rundir (char *server, char *workdir, - char *path, size_t len) + char *path, size_t len) { char dir[PATH_MAX] = {0}; GF_ASSERT (len == PATH_MAX); @@ -5545,7 +5540,7 @@ glusterd_get_nodesvc_rundir (char *server, char *workdir, void glusterd_get_nodesvc_pidfile (char *server, char *workdir, - char *path, size_t len) + char *path, size_t len) { char dir[PATH_MAX] = {0}; GF_ASSERT (len == PATH_MAX); @@ -5556,7 +5551,7 @@ glusterd_get_nodesvc_pidfile (char *server, char *workdir, void glusterd_get_nodesvc_volfile (char *server, char *workdir, - char *volfile, size_t len) + char *volfile, size_t len) { char dir[PATH_MAX] = {0,}; GF_ASSERT (len == PATH_MAX); @@ -5666,6 +5661,12 @@ out: return rpc; } +inline struct rpc_clnt* +glusterd_snapd_get_rpc (glusterd_volinfo_t *volinfo) +{ + return volinfo->snapd.rpc; +} + struct rpc_clnt* glusterd_nodesvc_get_rpc (char *server) { @@ -5715,7 +5716,8 @@ glusterd_nodesvc_set_rpc (char *server, struct rpc_clnt *rpc) } int32_t -glusterd_nodesvc_connect (char *server, char *socketpath) { +glusterd_nodesvc_connect (char *server, char *socketpath) +{ int ret = 0; dict_t *options = NULL; struct rpc_clnt *rpc = NULL; @@ -5899,9 +5901,25 @@ glusterd_is_nodesvc_running (char *server) } int32_t -glusterd_nodesvc_unlink_socket_file (char *server) +glusterd_unlink_file (char *sockfpath) { int ret = 0; + + ret = unlink (sockfpath); + if (ret) { + if (ENOENT == errno) + ret = 0; + else + gf_log (THIS->name, GF_LOG_ERROR, "Failed to remove %s" + " error: %s", sockfpath, strerror (errno)); + } + + return ret; +} + +int32_t +glusterd_nodesvc_unlink_socket_file (char *server) +{ char sockfpath[PATH_MAX] = {0,}; char rundir[PATH_MAX] = {0,}; glusterd_conf_t *priv = THIS->private; @@ -5912,15 +5930,7 @@ glusterd_nodesvc_unlink_socket_file (char *server) glusterd_nodesvc_set_socket_filepath (rundir, MY_UUID, sockfpath, sizeof (sockfpath)); - ret = unlink (sockfpath); - if (ret && (ENOENT == errno)) { - ret = 0; - } else { - gf_log (THIS->name, GF_LOG_ERROR, "Failed to remove %s" - " error: %s", sockfpath, strerror (errno)); - } - - return ret; + return glusterd_unlink_file (sockfpath); } int32_t @@ -5936,7 +5946,7 @@ glusterd_nodesvc_stop (char *server, int sig) (void)glusterd_nodesvc_disconnect (server); glusterd_get_nodesvc_pidfile (server, priv->workdir, - pidfile, sizeof (pidfile)); + pidfile, sizeof (pidfile)); ret = glusterd_service_stop (server, pidfile, sig, _gf_true); if (ret == 0) { @@ -6218,7 +6228,6 @@ out: return ret; } - int glusterd_check_generate_start_nfs () { @@ -7876,7 +7885,7 @@ glusterd_sm_tr_log_transition_add_to_dict (dict_t *dict, { int ret = -1; char key[512] = {0}; - char timestr[64] = {0,}; + char timestr[64] = {0,}; char *str = NULL; GF_ASSERT (dict); @@ -12890,3 +12899,369 @@ glusterd_enable_default_options (glusterd_volinfo_t *volinfo, char *option) out: return ret; } + +/* Snapd functions */ +int +glusterd_is_snapd_enabled (glusterd_volinfo_t *volinfo) +{ + int ret = 0; + xlator_t *this = THIS; + + ret = dict_get_str_boolean (volinfo->dict, "features.uss", -2); + if (ret == -2) { + gf_log (this->name, GF_LOG_DEBUG, "Key features.uss not " + "present in the volinfo dict"); + ret = 0; + + } else if (ret == -1) { + gf_log (this->name, GF_LOG_ERROR, "Failed to get " + "'features.uss' from %s volume dict", + volinfo->volname); + ret = 0; + } + + return ret; +} + +void +glusterd_get_snapd_rundir (glusterd_volinfo_t *volinfo, + char *path, int path_len) +{ + char workdir [PATH_MAX] = {0,}; + glusterd_conf_t *priv = THIS->private; + + GLUSTERD_GET_VOLUME_DIR (workdir, volinfo, priv); + + snprintf (path, path_len, "%s/run", workdir); +} + +void +glusterd_get_snapd_volfile (glusterd_volinfo_t *volinfo, + char *path, int path_len) +{ + char workdir [PATH_MAX] = {0,}; + glusterd_conf_t *priv = THIS->private; + + GLUSTERD_GET_VOLUME_DIR (workdir, volinfo, priv); + + snprintf (path, path_len, "%s/%s-snapd.vol", workdir, + volinfo->volname); +} + +void +glusterd_get_snapd_pidfile (glusterd_volinfo_t *volinfo, + char *path, int path_len) +{ + char rundir [PATH_MAX] = {0,}; + + glusterd_get_snapd_rundir (volinfo, rundir, sizeof (rundir)); + + snprintf (path, path_len, "%s/%s-snapd.pid", rundir, volinfo->volname); +} + +void +glusterd_set_snapd_socket_filepath (glusterd_volinfo_t *volinfo, + char *path, int path_len) +{ + char sockfilepath[PATH_MAX] = {0,}; + char rundir[PATH_MAX] = {0,}; + + glusterd_get_snapd_rundir (volinfo, rundir, sizeof (rundir)); + snprintf (sockfilepath, sizeof (sockfilepath), "%s/run-%s", + rundir, uuid_utoa (MY_UUID)); + + glusterd_set_socket_filepath (sockfilepath, path, path_len); +} + +gf_boolean_t +glusterd_is_snapd_running (glusterd_volinfo_t *volinfo) +{ + char pidfile [PATH_MAX] = {0,}; + int pid = -1; + glusterd_conf_t *priv = THIS->private; + + glusterd_get_snapd_pidfile (volinfo, pidfile, + sizeof (pidfile)); + + return gf_is_service_running (pidfile, &pid); +} + +int +glusterd_restart_snapds (glusterd_conf_t *priv) +{ + glusterd_volinfo_t *volinfo = NULL; + int ret = 0; + xlator_t *this = THIS; + + list_for_each_entry (volinfo, &priv->volumes, vol_list) { + if (volinfo->status == GLUSTERD_STATUS_STARTED && + glusterd_is_snapd_enabled (volinfo)) { + ret = glusterd_snapd_start (volinfo, _gf_false); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Couldn't start snapd for vol: %s", + volinfo->volname); + goto out; + } + } + } +out: + return ret; +} + +gf_boolean_t +glusterd_is_snapd_online (glusterd_volinfo_t *volinfo) +{ + return volinfo->snapd.online; +} + +void +glusterd_snapd_set_online_status (glusterd_volinfo_t *volinfo, + gf_boolean_t status) +{ + volinfo->snapd.online = status; +} + +inline void +glusterd_snapd_set_rpc (glusterd_volinfo_t *volinfo, struct rpc_clnt *rpc) +{ + volinfo->snapd.rpc = rpc; +} + +int32_t +glusterd_snapd_connect (glusterd_volinfo_t *volinfo, char *socketpath) +{ + int ret = 0; + dict_t *options = NULL; + struct rpc_clnt *rpc = NULL; + glusterd_conf_t *priv = THIS->private; + + rpc = glusterd_snapd_get_rpc (volinfo); + + if (rpc == NULL) { + /* Setting frame-timeout to 10mins (600seconds). + * Unix domain sockets ensures that the connection is reliable. + * The default timeout of 30mins used for unreliable network + * connections is too long for unix domain socket connections. + */ + ret = rpc_transport_unix_options_build (&options, socketpath, + 600); + if (ret) + goto out; + + glusterd_volinfo_ref (volinfo); + + synclock_unlock (&priv->big_lock); + ret = glusterd_rpc_create (&rpc, options, + glusterd_snapd_rpc_notify, + volinfo); + synclock_lock (&priv->big_lock); + if (ret) + goto out; + + (void) glusterd_snapd_set_rpc (volinfo, rpc); + } +out: + return ret; +} + +int32_t +glusterd_snapd_disconnect (glusterd_volinfo_t *volinfo) +{ + struct rpc_clnt *rpc = NULL; + glusterd_conf_t *priv = THIS->private; + + rpc = glusterd_snapd_get_rpc (volinfo); + (void)glusterd_snapd_set_rpc (volinfo, NULL); + + if (rpc) + glusterd_rpc_clnt_unref (priv, rpc); + + return 0; +} + +int32_t +glusterd_snapd_start (glusterd_volinfo_t *volinfo, gf_boolean_t wait) +{ + int32_t ret = -1; + xlator_t *this = NULL; + glusterd_conf_t *priv = NULL; + runner_t runner = {0,}; + char pidfile[PATH_MAX] = {0,}; + char logfile[PATH_MAX] = {0,}; + char volfile[PATH_MAX] = {0,}; + char glusterd_uuid [1024] = {0,}; + char rundir[PATH_MAX] = {0,}; + char sockfpath[PATH_MAX] = {0,}; + char volfileid[256] = {0}; + char valgrind_logfile[PATH_MAX] = {0}; + int snapd_port = 0; + char *volname = volinfo->volname; + char snapd_id [PATH_MAX] = {0,}; + char msg [1024] = {0,}; + + this = THIS; + GF_ASSERT(this); + + if (glusterd_is_snapd_running (volinfo)) { + ret = 0; + goto connect; + } + + priv = this->private; + + glusterd_get_snapd_rundir (volinfo, rundir, sizeof (rundir)); + ret = mkdir (rundir, 0777); + + if ((ret == -1) && (EEXIST != errno)) { + gf_log (this->name, GF_LOG_ERROR, "Unable to create rundir %s", + rundir); + goto out; + } + + glusterd_get_snapd_pidfile (volinfo, pidfile, sizeof (pidfile)); + glusterd_get_snapd_volfile (volinfo, volfile, sizeof (volfile)); + + ret = sys_access (volfile, F_OK); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "snapd Volfile %s is not present", volfile); + goto out; + } + + snprintf (logfile, PATH_MAX, "%s/%s-snapd.log", + DEFAULT_LOG_FILE_DIRECTORY, volname); + + snprintf (volfileid, sizeof (volfileid), "snapd/%s", volname); + glusterd_set_snapd_socket_filepath (volinfo, sockfpath, + sizeof (sockfpath)); + + runinit (&runner); + + if (priv->valgrind) { + snprintf (valgrind_logfile, PATH_MAX, + "%s/valgrind-%s-snapd.log", + DEFAULT_LOG_FILE_DIRECTORY, volname); + + runner_add_args (&runner, "valgrind", "--leak-check=full", + "--trace-children=yes", "--track-origins=yes", + NULL); + runner_argprintf (&runner, "--log-file=%s", valgrind_logfile); + } + + snprintf (snapd_id, sizeof (snapd_id), "snapd-%s", volname); + runner_add_args (&runner, SBIN_DIR"/glusterfsd", + "-s", "localhost", + "--volfile-id", volfileid, + "-p", pidfile, + "-l", logfile, + "--brick-name", snapd_id, + "-S", sockfpath, NULL); + + snapd_port = volinfo->snapd.port; + if (!snapd_port) { + snapd_port = pmap_registry_alloc (THIS); + if (!snapd_port) { + snprintf (msg, sizeof (msg), "Could not allocate port " + "for snapd service for volume %s", volname); + + runner_log (&runner, this->name, GF_LOG_DEBUG, msg); + ret = -1; + goto out; + } + } + + runner_add_arg (&runner, "--brick-port"); + runner_argprintf (&runner, "%d", snapd_port); + runner_add_arg (&runner, "--xlator-option"); + runner_argprintf (&runner, "%s-server.listen-port=%d", + volname, snapd_port); + + snprintf (msg, sizeof (msg), + "Starting the snapd service for volume %s", volname); + runner_log (&runner, this->name, GF_LOG_DEBUG, msg); + + if (!wait) { + ret = runner_run_nowait (&runner); + } else { + synclock_unlock (&priv->big_lock); + { + ret = runner_run (&runner); + } + synclock_lock (&priv->big_lock); + } + +connect: + if (ret == 0) + glusterd_snapd_connect (volinfo, sockfpath); + +out: + return ret; +} + +int +glusterd_snapd_stop (glusterd_volinfo_t *volinfo) +{ + char pidfile [PATH_MAX] = {0,}; + char sockfpath [PATH_MAX] = {0,}; + glusterd_conf_t *priv = THIS->private; + int ret = 0; + + (void)glusterd_snapd_disconnect (volinfo); + + if (!glusterd_is_snapd_running (volinfo)) + goto out; + + glusterd_get_snapd_pidfile (volinfo, pidfile, sizeof (pidfile)); + ret = glusterd_service_stop ("snapd", pidfile, SIGTERM, _gf_true); + + if (ret == 0) { + glusterd_set_snapd_socket_filepath (volinfo, sockfpath, + sizeof (sockfpath)); + (void)glusterd_unlink_file (sockfpath); + } +out: + return ret; +} + +int +glusterd_handle_snapd_option (glusterd_volinfo_t *volinfo) +{ + int ret = 0; + xlator_t *this = THIS; + + if (volinfo->is_snap_volume) + return 0; + + if (glusterd_is_snapd_enabled (volinfo)) { + if (!glusterd_is_volume_started (volinfo)) + goto out; + + ret = glusterd_create_snapd_volfile (volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Couldn't create " + "snapd volfile for volume: %s", + volinfo->volname); + goto out; + } + + ret = glusterd_snapd_start (volinfo, _gf_false); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Couldn't start " + "snapd for volume: %s", volinfo->volname); + goto out; + } + + } else if (glusterd_is_snapd_running (volinfo)) { + ret = glusterd_snapd_stop (volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Couldn't stop snapd for volume: %s", + volinfo->volname); + goto out; + } + } + +out: + return ret; +} diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.h b/xlators/mgmt/glusterd/src/glusterd-utils.h index 91a4c3c2418..4b6e2b0cdbc 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.h +++ b/xlators/mgmt/glusterd/src/glusterd-utils.h @@ -204,7 +204,7 @@ glusterd_is_nodesvc_running (); void glusterd_get_nodesvc_dir (char *server, char *workdir, - char *path, size_t len); + char *path, size_t len); int32_t glusterd_nfs_server_start (); @@ -839,4 +839,56 @@ glusterd_snapshot_restore_cleanup (dict_t *rsp_dict, glusterd_volinfo_t *volinfo, glusterd_snap_t *snap); +int +glusterd_unlink_file (char *sock_file_path); + +/* Snapd functions */ +int +glusterd_handle_snapd_option (glusterd_volinfo_t *volinfo); + +int32_t +glusterd_snapd_disconnect (glusterd_volinfo_t *volinfo); + +void +glusterd_get_snapd_dir (glusterd_volinfo_t *volinfo, + char *path, int path_len); + +void +glusterd_get_snapd_rundir (glusterd_volinfo_t *volinfo, + char *path, int path_len); + +void +glusterd_get_snapd_volfile (glusterd_volinfo_t *volinfo, + char *path, int path_len); + +void +glusterd_get_snapd_pidfile (glusterd_volinfo_t *volinfo, + char *path, int path_len); + +void +glusterd_set_snapd_socket_filepath (glusterd_volinfo_t *volinfo, + char *path, int path_len); + +gf_boolean_t +glusterd_is_snapd_running (glusterd_volinfo_t *volinfo); + +int +glusterd_snapd_stop (glusterd_volinfo_t *volinfo); + +int +glusterd_snapd_start (glusterd_volinfo_t *volinfo, gf_boolean_t wait); + +int +glusterd_is_snapd_enabled (glusterd_volinfo_t *volinfo); + +gf_boolean_t +glusterd_is_snapd_online (glusterd_volinfo_t *volinfo); + +void +glusterd_snapd_set_online_status (glusterd_volinfo_t *volinfo, + gf_boolean_t status); + +int +glusterd_restart_snapds (glusterd_conf_t *priv); +/* End snapd functions */ #endif diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index 165fdd882b1..fa4f88f9a06 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -961,54 +961,54 @@ out: static void volgen_apply_filters (char *orig_volfile) { - DIR *filterdir = NULL; - struct dirent entry = {0,}; - struct dirent *next = NULL; - char *filterpath = NULL; - struct stat statbuf = {0,}; - - filterdir = opendir(FILTERDIR); - if (!filterdir) { - return; - } - - while ((readdir_r(filterdir,&entry,&next) == 0) && next) { - if (!strncmp(entry.d_name,".",sizeof(entry.d_name))) { - continue; - } - if (!strncmp(entry.d_name,"..",sizeof(entry.d_name))) { - continue; - } - /* - * d_type isn't guaranteed to be present/valid on all systems, - * so do an explicit stat instead. - */ - if (gf_asprintf(&filterpath,"%s/%.*s",FILTERDIR, - sizeof(entry.d_name), entry.d_name) == (-1)) { - continue; - } - /* Deliberately use stat instead of lstat to allow symlinks. */ - if (stat(filterpath,&statbuf) == (-1)) { - goto free_fp; - } - if (!S_ISREG(statbuf.st_mode)) { - goto free_fp; - } - /* - * We could check the mode in statbuf directly, or just skip - * this entirely and check for EPERM after exec fails, but this - * is cleaner. - */ - if (access(filterpath,X_OK) != 0) { - goto free_fp; - } - if (runcmd(filterpath,orig_volfile,NULL)) { - gf_log("",GF_LOG_ERROR,"failed to run filter %.*s", - (int)sizeof(entry.d_name), entry.d_name); - } + DIR *filterdir = NULL; + struct dirent entry = {0,}; + struct dirent *next = NULL; + char *filterpath = NULL; + struct stat statbuf = {0,}; + + filterdir = opendir(FILTERDIR); + if (!filterdir) { + return; + } + + while ((readdir_r(filterdir,&entry,&next) == 0) && next) { + if (!strncmp(entry.d_name,".",sizeof(entry.d_name))) { + continue; + } + if (!strncmp(entry.d_name,"..",sizeof(entry.d_name))) { + continue; + } + /* + * d_type isn't guaranteed to be present/valid on all systems, + * so do an explicit stat instead. + */ + if (gf_asprintf(&filterpath,"%s/%.*s",FILTERDIR, + sizeof(entry.d_name), entry.d_name) == (-1)) { + continue; + } + /* Deliberately use stat instead of lstat to allow symlinks. */ + if (stat(filterpath,&statbuf) == (-1)) { + goto free_fp; + } + if (!S_ISREG(statbuf.st_mode)) { + goto free_fp; + } + /* + * We could check the mode in statbuf directly, or just skip + * this entirely and check for EPERM after exec fails, but this + * is cleaner. + */ + if (access(filterpath,X_OK) != 0) { + goto free_fp; + } + if (runcmd(filterpath,orig_volfile,NULL)) { + gf_log("",GF_LOG_ERROR,"failed to run filter %.*s", + (int)sizeof(entry.d_name), entry.d_name); + } free_fp: - GF_FREE(filterpath); - } + GF_FREE(filterpath); + } } static int @@ -1063,7 +1063,7 @@ volgen_write_volfile (volgen_graph_t *graph, char *filename) GF_FREE (ftmp); - volgen_apply_filters(filename); + volgen_apply_filters(filename); return 0; @@ -1656,9 +1656,9 @@ server_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, if (!rbxl) return -1; - ptranst = glusterd_get_trans_type_rb (volinfo->transport_type); - if (NULL == ptranst) - return -1; + ptranst = glusterd_get_trans_type_rb (volinfo->transport_type); + if (NULL == ptranst) + return -1; if (username) { ret = xlator_set_option (rbxl, "username", username); @@ -2203,20 +2203,97 @@ out: } + +static xlator_t * +volgen_graph_build_client (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, + char *hostname, char *subvol, char *xl_id, + char *transt, dict_t *set_dict) +{ + xlator_t *xl = NULL; + int ret = -2; + uint32_t client_type = GF_CLIENT_OTHER; + char *str = NULL; + char *ssl_str = NULL; + gf_boolean_t ssl_bool = _gf_false; + + GF_ASSERT (graph); + GF_ASSERT (subvol); + GF_ASSERT (xl_id); + GF_ASSERT (transt); + + xl = volgen_graph_add_nolink (graph, "protocol/client", + "%s", xl_id); + if (!xl) + goto err; + + ret = xlator_set_option (xl, "ping-timeout", "42"); + if (ret) + goto err; + + if (hostname) { + ret = xlator_set_option (xl, "remote-host", hostname); + if (ret) + goto err; + } + + ret = xlator_set_option (xl, "remote-subvolume", subvol); + if (ret) + goto err; + + ret = xlator_set_option (xl, "transport-type", transt); + if (ret) + goto err; + + ret = dict_get_uint32 (set_dict, "trusted-client", + &client_type); + + if (!ret && client_type == GF_CLIENT_TRUSTED) { + str = NULL; + str = glusterd_auth_get_username (volinfo); + if (str) { + ret = xlator_set_option (xl, "username", + str); + if (ret) + goto err; + } + + str = glusterd_auth_get_password (volinfo); + if (str) { + ret = xlator_set_option (xl, "password", + str); + if (ret) + goto err; + } + } + + if (dict_get_str(set_dict,"client.ssl",&ssl_str) == 0) { + if (gf_string2boolean(ssl_str,&ssl_bool) == 0) { + if (ssl_bool) { + ret = xlator_set_option(xl, + "transport.socket.ssl-enabled", + "true"); + if (ret) { + goto err; + } + } + } + } + + return xl; +err: + return NULL; +} + static int volgen_graph_build_clients (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, dict_t *set_dict, void *param) { int i = 0; int ret = -1; - uint32_t client_type = GF_CLIENT_OTHER; char transt[16] = {0,}; char *volname = NULL; - char *str = NULL; glusterd_brickinfo_t *brick = NULL; xlator_t *xl = NULL; - char *ssl_str = NULL; - gf_boolean_t ssl_bool; volname = volinfo->volname; @@ -2243,59 +2320,14 @@ volgen_graph_build_clients (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, strcpy (transt, "tcp"); i = 0; - ret = -1; list_for_each_entry (brick, &volinfo->bricks, brick_list) { - ret = -1; - xl = volgen_graph_add_nolink (graph, "protocol/client", - "%s", brick->brick_id); - if (!xl) - goto out; - ret = xlator_set_option (xl, "ping-timeout", "42"); - if (ret) - goto out; - ret = xlator_set_option (xl, "remote-host", brick->hostname); - if (ret) - goto out; - ret = xlator_set_option (xl, "remote-subvolume", brick->path); - if (ret) - goto out; - ret = xlator_set_option (xl, "transport-type", transt); - if (ret) + xl = volgen_graph_build_client (graph, volinfo, + brick->hostname, brick->path, + brick->brick_id, + transt, set_dict); + if (!xl) { + ret = -1; goto out; - - ret = dict_get_uint32 (set_dict, "trusted-client", - &client_type); - - if (!ret && client_type == GF_CLIENT_TRUSTED) { - str = NULL; - str = glusterd_auth_get_username (volinfo); - if (str) { - ret = xlator_set_option (xl, "username", - str); - if (ret) - goto out; - } - - str = glusterd_auth_get_password (volinfo); - if (str) { - ret = xlator_set_option (xl, "password", - str); - if (ret) - goto out; - } - } - - if (dict_get_str(set_dict,"client.ssl",&ssl_str) == 0) { - if (gf_string2boolean(ssl_str,&ssl_bool) == 0) { - if (ssl_bool) { - ret = xlator_set_option(xl, - "transport.socket.ssl-enabled", - "true"); - if (ret) { - goto out; - } - } - } } i++; @@ -2360,6 +2392,70 @@ out: return ret; } +/** + * This is the build graph function for user-serviceable snapshots. + * Generates snapview-client + */ +static int +volgen_graph_build_snapview_client (volgen_graph_t *graph, + glusterd_volinfo_t *volinfo, + char *volname, dict_t *set_dict) +{ + int ret = 0; + xlator_t *prev_top = NULL; + xlator_t *prot_clnt = NULL; + xlator_t *svc = NULL; + char transt [16] = {0,}; + char *svc_args[] = {"features/snapview-client", + "%s-snapview-client"}; + char subvol [1024] = {0,}; + char xl_id [1024] = {0,}; + + prev_top = (xlator_t *)(graph->graph.first); + + snprintf (subvol, sizeof (subvol), "snapd-%s", volinfo->volname); + snprintf (xl_id, sizeof (xl_id), "%s-snapd-client", volinfo->volname); + + get_transport_type (volinfo, set_dict, transt, _gf_false); + + prot_clnt = volgen_graph_build_client (graph, volinfo, NULL, subvol, + xl_id, transt, set_dict); + if (!prot_clnt) { + ret = -1; + goto out; + } + + svc = volgen_graph_add_nolink (graph, svc_args[0], svc_args[1], + volname); + if (!svc) { + ret = -1; + goto out; + } + + /** + * Ordering the below two traslators (cur_top & prot_clnt) is important + * as snapview client implementation is built on the policy that + * normal volume path goes to FIRST_CHILD and snap world operations + * goes to SECOND_CHILD + **/ + ret = volgen_xlator_link (graph->graph.first, prev_top); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "failed to link the " + "snapview-client to distribute"); + goto out; + } + + ret = volgen_xlator_link (graph->graph.first, prot_clnt); + if (ret) { + gf_log (THIS->name, GF_LOG_ERROR, "failed to link the " + "snapview-client to snapview-server"); + goto out; + } + +out: + return ret; +} + gf_boolean_t _xl_is_client_decommissioned (xlator_t *xl, glusterd_volinfo_t *volinfo) { @@ -2599,26 +2695,26 @@ out: } static int client_graph_set_perf_options(volgen_graph_t *graph, - glusterd_volinfo_t *volinfo, - dict_t *set_dict) + glusterd_volinfo_t *volinfo, + dict_t *set_dict) { - data_t *tmp_data = NULL; - char *volname = NULL; - - /* - * Logic to make sure NFS doesn't have performance translators by - * default for a volume - */ - volname = volinfo->volname; - tmp_data = dict_get (set_dict, "nfs-volume-file"); - if (!tmp_data) - return volgen_graph_set_options_generic(graph, set_dict, - volinfo, - &perfxl_option_handler); - else - return volgen_graph_set_options_generic(graph, set_dict, - volname, - &nfsperfxl_option_handler); + data_t *tmp_data = NULL; + char *volname = NULL; + + /* + * Logic to make sure NFS doesn't have performance translators by + * default for a volume + */ + volname = volinfo->volname; + tmp_data = dict_get (set_dict, "nfs-volume-file"); + if (!tmp_data) + return volgen_graph_set_options_generic(graph, set_dict, + volinfo, + &perfxl_option_handler); + else + return volgen_graph_set_options_generic(graph, set_dict, + volname, + &nfsperfxl_option_handler); } static int @@ -2815,6 +2911,13 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, if (ret) goto out; + if (!volinfo->is_snap_volume && glusterd_is_snapd_enabled (volinfo)) { + ret = volgen_graph_build_snapview_client + (graph, volinfo, volname, set_dict); + if (ret == -1) + goto out; + } + /* add debug translators depending on the options */ ret = check_and_add_debug_xl (graph, set_dict, volname, "client"); @@ -3534,7 +3637,7 @@ build_quotad_graph (volgen_graph_t *graph, dict_t *mod_dict) dict_t *set_dict = NULL; int ret = 0; xlator_t *quotad_xl = NULL; - char *skey = NULL; + char *skey = NULL; this = THIS; priv = this->private; @@ -4000,13 +4103,110 @@ out: } int -glusterd_create_quotad_volfile () +glusterd_generate_snapd_volfile (volgen_graph_t *graph, + glusterd_volinfo_t *volinfo) +{ + xlator_t *xl = NULL; + char *username = NULL; + char *passwd = NULL; + int ret = 0; + char key [PATH_MAX] = {0, }; + dict_t *set_dict = NULL; + char *loglevel = NULL; + char *xlator = NULL; + + set_dict = dict_copy (volinfo->dict, NULL); + if (!set_dict) + return -1; + + ret = dict_get_str (set_dict, "xlator", &xlator); + if (!ret) { + ret = dict_get_str (set_dict, "loglevel", &loglevel); + if (ret) { + gf_log ("glusterd", GF_LOG_ERROR, "could not get both" + " translator name and loglevel for log level " + "request"); + return -1; + } + } + + xl = volgen_graph_add (graph, "features/snapview-server", + volinfo->volname); + if (!xl) + return -1; + + ret = xlator_set_option (xl, "volname", volinfo->volname); + if (ret) + return -1; + + xl = volgen_graph_add (graph, "performance/io-threads", + volinfo->volname); + if (!xl) + return -1; + + snprintf (key, sizeof (key), "snapd-%s", volinfo->volname); + xl = volgen_graph_add_as (graph, "debug/io-stats", key); + if (!xl) + return -1; + + xl = volgen_graph_add (graph, "protocol/server", volinfo->volname); + if (!xl) + return -1; + + ret = xlator_set_option (xl, "transport-type", "tcp"); + if (ret) + return -1; + + username = glusterd_auth_get_username (volinfo); + passwd = glusterd_auth_get_password (volinfo); + + snprintf (key, sizeof (key), "auth.login.snapd-%s.allow", + volinfo->volname); + ret = xlator_set_option (xl, key, username); + if (ret) + return -1; + + snprintf (key, sizeof (key), "auth.login.%s.password", username); + ret = xlator_set_option (xl, key, passwd); + if (ret) + return -1; + + ret = volgen_graph_set_options_generic + (graph, set_dict, + (xlator && loglevel)? (void *)set_dict: volinfo, + (xlator && loglevel) ? + &server_spec_extended_option_handler: + &server_spec_option_handler); + + return ret; +} + +int +glusterd_create_snapd_volfile (glusterd_volinfo_t *volinfo) +{ + volgen_graph_t graph = {0,}; + int ret = -1; + char filename [PATH_MAX] = {0,}; + + glusterd_get_snapd_volfile (volinfo, filename, PATH_MAX); + + ret = glusterd_generate_snapd_volfile (&graph, volinfo); + if (!ret) + ret = volgen_write_volfile (&graph, filename); + + volgen_graph_free (&graph); + + return ret; +} + +int +glusterd_create_quotad_volfile (void *data) { char filepath[PATH_MAX] = {0,}; glusterd_conf_t *conf = THIS->private; glusterd_get_nodesvc_volfile ("quotad", conf->workdir, - filepath, sizeof (filepath)); + filepath, sizeof (filepath)); return glusterd_create_global_volfile (build_quotad_graph, filepath, NULL); } diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.h b/xlators/mgmt/glusterd/src/glusterd-volgen.h index dab5e1ff03d..f4959f1e6c2 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.h +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.h @@ -125,6 +125,7 @@ void glusterd_get_shd_filepath (char *filename); int glusterd_create_nfs_volfile (); int glusterd_create_shd_volfile (); int glusterd_create_quotad_volfile (); +int glusterd_create_snapd_volfile (glusterd_volinfo_t *volinfo); int glusterd_delete_volfile (glusterd_volinfo_t *volinfo, glusterd_brickinfo_t *brickinfo); diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c index 1eff081516e..9b390321087 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-ops.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-ops.c @@ -1941,6 +1941,10 @@ glusterd_op_start_volume (dict_t *dict, char **op_errstr) if (ret) goto out; + ret = glusterd_handle_snapd_option (volinfo); + if (ret) + goto out; + ret = glusterd_nodesvcs_handle_graph_change (volinfo); out: @@ -2006,10 +2010,15 @@ glusterd_stop_volume (glusterd_volinfo_t *volinfo) runner_end (&runner); } + ret = glusterd_handle_snapd_option (volinfo); + if (ret) + goto out; + ret = glusterd_nodesvcs_handle_graph_change (volinfo); if (ret) { gf_log (this->name, GF_LOG_ERROR, "Failed to notify graph " "change for %s volume", volinfo->volname); + goto out; } diff --git a/xlators/mgmt/glusterd/src/glusterd-volume-set.c b/xlators/mgmt/glusterd/src/glusterd-volume-set.c index ffac2f4ac82..26e86209007 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volume-set.c +++ b/xlators/mgmt/glusterd/src/glusterd-volume-set.c @@ -1095,6 +1095,15 @@ struct volopt_map_entry glusterd_volopt_map[] = { .flags = OPT_FLAG_CLIENT_OPT | OPT_FLAG_XLATOR_OPT }, + { .key = "features.uss", + .voltype = "features/snapview-server", + .op_version = 4, + .value = "uss", + .flags = OPT_FLAG_CLIENT_OPT | OPT_FLAG_XLATOR_OPT, + .description = "Enable/Disable User Servicable Snapshots on the " + "volume." + }, + #ifdef HAVE_LIB_Z /* Compressor-decompressor xlator options * defaults used from xlator/features/compress/src/cdc.h diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 02441c9148b..57a5862a368 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -123,6 +123,12 @@ typedef struct { } nodesrv_t; typedef struct { + struct rpc_clnt *rpc; + int port; + gf_boolean_t online; +} glusterd_snapd_t; + +typedef struct { struct _volfile_ctx *volfile; pthread_mutex_t mutex; struct list_head peers; @@ -372,6 +378,8 @@ struct glusterd_volinfo_ { pthread_mutex_t reflock; int refcnt; gd_quorum_status_t quorum_status; + + glusterd_snapd_t snapd; }; typedef enum gd_snap_status_ { @@ -856,6 +864,10 @@ glusterd_brick_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, void *data); int +glusterd_snapd_rpc_notify (struct rpc_clnt *rpc, void *mydata, + rpc_clnt_event_t event, void *data); + +int glusterd_nodesvc_rpc_notify (struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event, void *data); |