From 368dfd695928e8fc40988b8f2de86c3b469172d2 Mon Sep 17 00:00:00 2001 From: Meghana Madhusudhan Date: Wed, 18 Mar 2015 11:33:50 +0530 Subject: NFS-Ganesha: Volume set option for managing NFS-Ganesha exports. A dummy translator has been introduced as a place holder for functions related to managing NFS-Ganesha exports. A volume set option is introduced to manage volume level exports. gluster vol set ganesha.enable ON/OFF 1. gluster volume set ganesha.enable ON It creates the export config file with a unique export ID. Sends a DBus signal to export this volume dynamically. 2. gluster vol set ganesha.enable OFF Unexports the specific volume. Deletes the specfic config file related to the volume. This change also removes the handling of the older keys "nfs-ganesha.enable" and "nfs-ganesha.host" Change-Id: I8d4a0b542326a6a0c8e4711600b106274d666587 BUG: 1188184 Signed-off-by: Meghana Madhusudhan Reviewed-on: http://review.gluster.org/9585 Tested-by: Gluster Build System Reviewed-by: Niels de Vos --- xlators/mgmt/glusterd/src/Makefile.am | 5 +- xlators/mgmt/glusterd/src/glusterd-ganesha.c | 365 +++++++++++++++++++++++++++ xlators/mgmt/glusterd/src/glusterd-volgen.c | 48 ++-- xlators/mgmt/glusterd/src/glusterd.h | 2 +- 4 files changed, 390 insertions(+), 30 deletions(-) create mode 100644 xlators/mgmt/glusterd/src/glusterd-ganesha.c (limited to 'xlators/mgmt') diff --git a/xlators/mgmt/glusterd/src/Makefile.am b/xlators/mgmt/glusterd/src/Makefile.am index a3217c35574..f95fc02d4fd 100644 --- a/xlators/mgmt/glusterd/src/Makefile.am +++ b/xlators/mgmt/glusterd/src/Makefile.am @@ -5,7 +5,7 @@ glusterd_la_LDFLAGS = -module -avoid-version glusterd_la_SOURCES = glusterd.c glusterd-handler.c glusterd-sm.c \ glusterd-op-sm.c glusterd-utils.c glusterd-rpc-ops.c \ glusterd-store.c glusterd-handshake.c glusterd-pmap.c \ - glusterd-volgen.c glusterd-rebalance.c glusterd-quota.c \ + glusterd-volgen.c glusterd-rebalance.c glusterd-ganesha.c glusterd-quota.c \ glusterd-geo-rep.c glusterd-replace-brick.c glusterd-log-ops.c \ glusterd-volume-ops.c glusterd-brick-ops.c glusterd-mountbroker.c \ glusterd-syncop.c glusterd-hooks.c glusterd-volume-set.c \ @@ -44,8 +44,11 @@ AM_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \ -I$(CONTRIBDIR)/userspace-rcu \ -DSBIN_DIR=\"$(sbindir)\" -DDATADIR=\"$(localstatedir)\" \ -DGSYNCD_PREFIX=\"$(libexecdir)/glusterfs\" \ + -DCONFDIR=\"$(sysconfdir)/ganesha\" \ + -DGANESHA_PREFIX=\"$(libexecdir)/ganesha\" \ -DSYNCDAEMON_COMPILE=$(SYNCDAEMON_COMPILE) $(XML_CPPFLAGS) + AM_CFLAGS = -Wall $(GF_CFLAGS) $(URCU_CFLAGS) $(URCU_CDS_CFLAGS) AM_LDFLAGS = -L$(xlatordir) $(URCU_LIBS) $(URCU_CDS_LIBS) diff --git a/xlators/mgmt/glusterd/src/glusterd-ganesha.c b/xlators/mgmt/glusterd/src/glusterd-ganesha.c new file mode 100644 index 00000000000..267e4b995cd --- /dev/null +++ b/xlators/mgmt/glusterd/src/glusterd-ganesha.c @@ -0,0 +1,365 @@ +/* + Copyright (c) 2015 Red Hat, Inc. + This file is part of GlusterFS. + + This file is licensed to you under your choice of the GNU Lesser + General Public License, version 3 or any later version (LGPLv3 or + later), or the GNU General Public License, version 2 (GPLv2), in all + cases as published by the Free Software Foundation. +*/ + + + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "common-utils.h" +#include "glusterd.h" +#include "glusterd-op-sm.h" +#include "glusterd-store.h" +#include "glusterd-utils.h" +#include "glusterd-nfs-svc.h" +#define MAXBUF 1024 +#define DELIM "=\"" + +/* Following 2 functions parses GANESHA_HA_CONF + * The sample file looks like below, + * HA_NAME="ganesha-ha-360" + * HA_VOL_NAME="ha-state" + * HA_VOL_MNT="/mount-point" + * HA_VOL_SERVER="server1" + * HA_CLUSTER_NODES="server1,server2" + * VIP_rhs_1="10.x.x.x" + * VIP_rhs_2="10.x.x.x." */ + +gf_boolean_t +is_ganesha_host (void) +{ + char *host_from_file = NULL; + FILE *fp; + char line[MAXBUF]; + gf_boolean_t ret = _gf_false; + int i = 1; + xlator_t *this = NULL; + + this = THIS; + + fp = fopen (GANESHA_HA_CONF, "r"); + + if (fp == NULL) { + gf_log (this->name, GF_LOG_INFO, "couldn't open the file %s", + GANESHA_HA_CONF); + return _gf_false; + } + + while (fgets (line, sizeof(line), fp) != NULL) { + /* Read GANESHA_HA_CONFIG till we find the HA VOL server */ + host_from_file = strstr ((char *)line, "HA_VOL_SERVER"); + if (host_from_file != NULL) { + host_from_file = strstr (host_from_file, DELIM); + host_from_file = host_from_file + strlen(DELIM); + i = strlen(host_from_file); + host_from_file[i - 2] = '\0'; + break; + } + } + + ret = gf_is_local_addr (host_from_file); + if (ret) { + gf_log (this->name, GF_LOG_INFO, "ganesha host found " + "Hostname is %s", host_from_file); + } + + fclose (fp); + return ret; +} + +/* Check if the localhost is listed as one of nfs-ganesha nodes */ +gf_boolean_t +check_host_list (void) +{ + + char *host_from_file = NULL; + glusterd_conf_t *priv = NULL; + char *hostname = NULL; + FILE *fp; + char line[MAXBUF]; + int ret = _gf_false; + int i = 1; + xlator_t *this = NULL; + + this = THIS; + priv = THIS->private; + GF_ASSERT (priv); + + fp = fopen (GANESHA_HA_CONF, "r"); + + if (fp == NULL) { + gf_log (this->name, GF_LOG_INFO, "couldn't open the file %s", + GANESHA_HA_CONF); + return 0; + } + + while (fgets (line, sizeof(line), fp) != NULL) { + /* Read GANESHA_HA_CONFIG till we find the list of HA_CLUSTER_NODES */ + hostname = strstr ((char *)line, "HA_CLUSTER_NODES"); + if (hostname != NULL) { + hostname = strstr (hostname, DELIM); + hostname = hostname + strlen(DELIM); + i = strlen (hostname); + hostname[i - 2] = '\0'; + break; + } + } + + /* Hostname is a comma separated list now */ + hostname = strtok (hostname, ","); + while (hostname != NULL) { + ret = gf_is_local_addr (hostname); + if (ret) { + gf_log (this->name, GF_LOG_INFO, "ganesha host found " + "Hostname is %s", hostname); + break; + } + hostname = strtok (NULL, ","); + } + + fclose (fp); + return ret; + +} + +int +create_export_config (char *volname, char **op_errstr) +{ + runner_t runner = {0,}; + int ret = -1; + + GF_ASSERT(volname); + runinit (&runner); + runner_add_args (&runner, "sh", + GANESHA_PREFIX"/create-export-ganesha.sh", + CONFDIR, volname, NULL); + ret = runner_run(&runner); + + if (ret) + gf_asprintf (op_errstr, "Failed to create" + " NFS-Ganesha export config file."); + + return ret; +} + +int +ganesha_manage_export (dict_t *dict, char *value, char **op_errstr) +{ + runner_t runner = {0,}; + int ret = -1; + char str[1024]; + glusterd_volinfo_t *volinfo = NULL; + char *volname = NULL; + xlator_t *this = NULL; + int i = 1; + + runinit (&runner); + this = THIS; + + GF_ASSERT (value); + GF_ASSERT (dict); + + ret = dict_get_str (dict, "volname", &volname); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + "Unable to get volume name"); + goto out; + } + + ret = glusterd_volinfo_find (volname, &volinfo); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, + FMTSTR_CHECK_VOL_EXISTS, volname); + goto out; + } + + /* Create the export file only when ganesha.enable "on" is executed */ + if (strcmp (value, "on") == 0) { + ret = create_export_config (volname, op_errstr); + if (ret) { + gf_log (this->name, GF_LOG_ERROR, "Failed to create" + "export file for NFS-Ganesha\n"); + goto out; + } + } + + if (check_host_list()) { + runner_add_args (&runner, "sh", GANESHA_PREFIX"/dbus-send.sh", + CONFDIR, value, volname, NULL); + ret = runner_run (&runner); + if (ret) + gf_asprintf(op_errstr, "Dynamic export" + " addition/deletion failed." + "Please see log file for details"); + } +out: + return ret; +} + +int +tear_down_cluster(void) +{ + int ret = 0; + runner_t runner = {0,}; + + if (is_ganesha_host()) { + runinit (&runner); + runner_add_args (&runner, "sh", CONFDIR, + GANESHA_PREFIX"/ganesha-ha.sh", "teardown", + CONFDIR, NULL); + ret = runner_run(&runner); + } + return ret; +} + + +int +setup_cluster(void) +{ + int ret = 0; + runner_t runner = {0,}; + + if (is_ganesha_host()) { + runinit (&runner); + runner_add_args (&runner, "sh", GANESHA_PREFIX"/ganesha-ha.sh", + "setup", CONFDIR, NULL); + ret = runner_run (&runner); + } + return ret; +} + + +int +stop_ganesha (char **op_errstr) +{ + runner_t runner = {0,}; + int ret = 1; + + ret = tear_down_cluster(); + if (ret == -1) { + gf_asprintf (op_errstr, "Cleanup of NFS-Ganesha" + "HA config failed."); + goto out; + } + + if (check_host_list ()) { + runinit (&runner); + runner_add_args (&runner, "service nfs-ganesha", "stop", NULL); + ret = runner_run (&runner); + } +out: + return ret; +} + +int +start_ganesha (char **op_errstr) +{ + + runner_t runner = {0,}; + int ret = -1; + char key[1024] = {0,}; + char *hostname = NULL; + dict_t *vol_opts = NULL; + glusterd_volinfo_t *volinfo = NULL; + int count = 0; + char *volname = NULL; + glusterd_conf_t *priv = NULL; + + priv = THIS->private; + GF_ASSERT (priv); + + cds_list_for_each_entry (volinfo, &priv->volumes, vol_list) { + vol_opts = volinfo->dict; + /* Gluster-nfs has to be disabled across the trusted pool */ + /* before attempting to start nfs-ganesha */ + ret = dict_set_str (vol_opts, "nfs.disable", "on"); + if (ret) + goto out; + } + + ret = priv->nfs_svc.stop (&(priv->nfs_svc), SIGKILL); + if (ret) { + ret = -1; + gf_asprintf (op_errstr, "Gluster-NFS service could" + "not be stopped, exiting."); + goto out; + } + + if (check_host_list()) { + runinit(&runner); + runner_add_args (&runner, "service", + "nfs-ganesha", "start", NULL); + + ret = runner_run (&runner); + if (ret) { + gf_asprintf (op_errstr, "NFS-Ganesha failed to start." + "Please see log file for details"); + goto out; + } + + ret = setup_cluster(); + if (ret == -1) { + gf_asprintf (op_errstr, "Failed to set up HA " + "config for NFS-Ganesha." + "Please check the log file for details"); + goto out; + } + } + +out: + return ret; +} + +int +glusterd_handle_ganesha_op (dict_t *dict, char **op_errstr, + char *key, char *value) +{ + + int32_t ret = -1; + char *volname = NULL; + xlator_t *this = NULL; + static int export_id = 1; + glusterd_volinfo_t *volinfo = NULL; + char *option = NULL; + + GF_ASSERT (dict); + GF_ASSERT (op_errstr); + GF_ASSERT (key); + GF_ASSERT (value); + + /* TODO: enable only if global option is set */ + /* BUG ID : 1200265 */ + + if (strcmp (key, "ganesha.enable") == 0) { + ret = ganesha_manage_export(dict, value, op_errstr); + if (ret < 0) + goto out; + } + + if (strcmp (key, "features.ganesha") == 0) { + if (strcmp (value, "enable") == 0) { + ret = start_ganesha(op_errstr); + if (ret < 0) + goto out; + } + + else if (strcmp (value, "disable") == 0) { + ret = stop_ganesha (op_errstr); + if (ret < 0) + goto out; + } + } + +out: + return ret; +} + diff --git a/xlators/mgmt/glusterd/src/glusterd-volgen.c b/xlators/mgmt/glusterd/src/glusterd-volgen.c index f20490423f6..c140e680261 100644 --- a/xlators/mgmt/glusterd/src/glusterd-volgen.c +++ b/xlators/mgmt/glusterd/src/glusterd-volgen.c @@ -3318,6 +3318,25 @@ client_graph_builder (volgen_graph_t *graph, glusterd_volinfo_t *volinfo, } } + ret = dict_get_str_boolean (set_dict, "ganesha.enable", _gf_false); + + if (ret == -1) { + gf_log (this->name, GF_LOG_WARNING, "setting ganesha.enable" + "option failed."); + goto out; + } + + if (ret) { + xl = volgen_graph_add (graph, "features/ganesha", volname); + + if (!xl) { + gf_log (this->name, GF_LOG_ERROR, "failed to add" + "add features/ganesha to graph"); + ret = -1; + goto out; + } + } + /* add debug translators depending on the options */ ret = check_and_add_debug_xl (graph, set_dict, volname, "client"); @@ -3535,35 +3554,8 @@ nfs_option_handler (volgen_graph_t *graph, return -1; } - if (! strcmp (vme->option, "!nfs-ganesha.enable")) { - ret = gf_asprintf (&aa, "nfs-ganesha.%s.enable", - volinfo->volname); - - if (ret != -1) { - ret = xlator_set_option (xl, aa, vme->value); - GF_FREE (aa); - } - - if (ret) - return -1; - } - - if (! strcmp (vme->option, "!nfs-ganesha.host")) { - ret = gf_asprintf (&aa, "nfs-ganesha.%s.host", - volinfo->volname); - - if (ret != -1) { - ret = xlator_set_option (xl, aa, vme->value); - GF_FREE (aa); - } - - if (ret) - return -1; - } - - - if ( (strcmp (vme->voltype, "nfs/server") == 0) && + if ((strcmp (vme->voltype, "nfs/server") == 0) && (vme->option && vme->option[0]!='!') ) { ret = xlator_set_option (xl, vme->option, vme->value); if (ret) diff --git a/xlators/mgmt/glusterd/src/glusterd.h b/xlators/mgmt/glusterd/src/glusterd.h index 98019f81d4c..7aeed450932 100644 --- a/xlators/mgmt/glusterd/src/glusterd.h +++ b/xlators/mgmt/glusterd/src/glusterd.h @@ -52,7 +52,7 @@ #define GLUSTERD_CREATE_HOOK_SCRIPT "/hooks/1/gsync-create/post/" \ "S56glusterd-geo-rep-create-post.sh" - +#define GANESHA_HA_CONF CONFDIR "/ganesha-ha.conf" #define GLUSTERD_SNAPS_MAX_HARD_LIMIT 256 #define GLUSTERD_SNAPS_DEF_SOFT_LIMIT_PERCENT 90 #define GLUSTERD_SNAPS_MAX_SOFT_LIMIT_PERCENT 100 -- cgit