74b1de
From 267135e74d94d8a1e56a263b37ca4689020b9e53 Mon Sep 17 00:00:00 2001
d1681e
From: Jiffin Tony Thottan <jthottan@redhat.com>
d1681e
Date: Mon, 16 Oct 2017 16:58:28 +0530
74b1de
Subject: [PATCH 055/124] Revert "storhaug HA: first step, remove resource
74b1de
 agents and setup script"
d1681e
d1681e
This reverts commit c822e354e16646adf18bbc5123798663faa543b2.
d1681e
74b1de
Label: DOWNSTREAM ONLY
74b1de
d1681e
Change-Id: Idd50fe1a5be5a3258d560518d810f9ec4c57621a
d1681e
Signed-off-by: Jiffin Tony Thottan <jthottan@redhat.com>
74b1de
Reviewed-on: https://code.engineering.redhat.com/gerrit/167104
74b1de
Reviewed-by: Soumya Koduri <skoduri@redhat.com>
74b1de
Tested-by: RHGS Build Bot <nigelb@redhat.com>
74b1de
Reviewed-by: Sunil Kumar Heggodu Gopala Acharya <sheggodu@redhat.com>
d1681e
---
d1681e
 configure.ac                         |    1 +
d1681e
 extras/ganesha/Makefile.am           |    2 +-
74b1de
 extras/ganesha/ocf/Makefile.am       |   11 +
74b1de
 extras/ganesha/ocf/ganesha_grace     |  221 +++++++
74b1de
 extras/ganesha/ocf/ganesha_mon       |  234 +++++++
74b1de
 extras/ganesha/ocf/ganesha_nfsd      |  167 +++++
d1681e
 extras/ganesha/scripts/Makefile.am   |    6 +-
74b1de
 extras/ganesha/scripts/ganesha-ha.sh | 1125 ++++++++++++++++++++++++++++++++++
74b1de
 glusterfs.spec.in                    |    8 +-
74b1de
 9 files changed, 1771 insertions(+), 4 deletions(-)
d1681e
 create mode 100644 extras/ganesha/ocf/Makefile.am
d1681e
 create mode 100644 extras/ganesha/ocf/ganesha_grace
d1681e
 create mode 100644 extras/ganesha/ocf/ganesha_mon
d1681e
 create mode 100644 extras/ganesha/ocf/ganesha_nfsd
d1681e
 create mode 100644 extras/ganesha/scripts/ganesha-ha.sh
d1681e
d1681e
diff --git a/configure.ac b/configure.ac
74b1de
index 125ae29..baa811a 100644
d1681e
--- a/configure.ac
d1681e
+++ b/configure.ac
74b1de
@@ -199,6 +199,7 @@ AC_CONFIG_FILES([Makefile
d1681e
                 extras/ganesha/Makefile
d1681e
                 extras/ganesha/config/Makefile
d1681e
                 extras/ganesha/scripts/Makefile
d1681e
+                extras/ganesha/ocf/Makefile
d1681e
                 extras/systemd/Makefile
d1681e
                 extras/systemd/glusterd.service
d1681e
                 extras/systemd/glustereventsd.service
d1681e
diff --git a/extras/ganesha/Makefile.am b/extras/ganesha/Makefile.am
d1681e
index 542de68..9eaa401 100644
d1681e
--- a/extras/ganesha/Makefile.am
d1681e
+++ b/extras/ganesha/Makefile.am
d1681e
@@ -1,2 +1,2 @@
d1681e
-SUBDIRS = scripts config
d1681e
+SUBDIRS = scripts config ocf
d1681e
 CLEANFILES =
d1681e
diff --git a/extras/ganesha/ocf/Makefile.am b/extras/ganesha/ocf/Makefile.am
d1681e
new file mode 100644
74b1de
index 0000000..990a609
d1681e
--- /dev/null
d1681e
+++ b/extras/ganesha/ocf/Makefile.am
74b1de
@@ -0,0 +1,11 @@
d1681e
+EXTRA_DIST= ganesha_grace ganesha_mon ganesha_nfsd
d1681e
+
d1681e
+# The root of the OCF resource agent hierarchy
d1681e
+# Per the OCF standard, it's always "lib",
d1681e
+# not "lib64" (even on 64-bit platforms).
d1681e
+ocfdir = $(prefix)/lib/ocf
d1681e
+
d1681e
+# The provider directory
d1681e
+radir = $(ocfdir)/resource.d/heartbeat
d1681e
+
d1681e
+ra_SCRIPTS = ganesha_grace ganesha_mon ganesha_nfsd
d1681e
diff --git a/extras/ganesha/ocf/ganesha_grace b/extras/ganesha/ocf/ganesha_grace
d1681e
new file mode 100644
74b1de
index 0000000..825f716
d1681e
--- /dev/null
d1681e
+++ b/extras/ganesha/ocf/ganesha_grace
74b1de
@@ -0,0 +1,221 @@
d1681e
+#!/bin/bash
d1681e
+#
d1681e
+# Copyright (c) 2014 Anand Subramanian anands@redhat.com
d1681e
+# Copyright (c) 2015 Red Hat Inc.
d1681e
+#                    All Rights Reserved.
d1681e
+#
d1681e
+# This program is free software; you can redistribute it and/or modify
d1681e
+# it under the terms of version 2 of the GNU General Public License as
d1681e
+# published by the Free Software Foundation.
d1681e
+#
d1681e
+# This program is distributed in the hope that it would be useful, but
d1681e
+# WITHOUT ANY WARRANTY; without even the implied warranty of
d1681e
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
d1681e
+#
d1681e
+# Further, this software is distributed without any warranty that it is
d1681e
+# free of the rightful claim of any third person regarding infringement
d1681e
+# or the like.  Any license provided herein, whether implied or
d1681e
+# otherwise, applies only to this software file.  Patent licenses, if
d1681e
+# any, provided herein do not apply to combinations of this program with
d1681e
+# other software, or any other product whatsoever.
d1681e
+#
d1681e
+# You should have received a copy of the GNU General Public License
d1681e
+# along with this program; if not, write the Free Software Foundation,
d1681e
+# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
d1681e
+#
d1681e
+#
d1681e
+
d1681e
+# Initialization:
d1681e
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
d1681e
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
d1681e
+
d1681e
+if [ -n "$OCF_DEBUG_LIBRARY" ]; then
d1681e
+	. $OCF_DEBUG_LIBRARY
d1681e
+else
d1681e
+	: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
d1681e
+	. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
d1681e
+fi
d1681e
+
d1681e
+OCF_RESKEY_grace_active_default="grace-active"
d1681e
+: ${OCF_RESKEY_grace_active=${OCF_RESKEY_grace_active_default}}
d1681e
+
d1681e
+ganesha_meta_data() {
d1681e
+	cat <
d1681e
+
d1681e
+
d1681e
+<resource-agent name="ganesha_grace">
d1681e
+<version>1.0</version>
d1681e
+
d1681e
+<longdesc lang="en">
d1681e
+This Linux-specific resource agent acts as a dummy
d1681e
+resource agent for nfs-ganesha.
d1681e
+</longdesc>
d1681e
+
d1681e
+<shortdesc lang="en">Manages the user-space nfs-ganesha NFS server</shortdesc>
d1681e
+
d1681e
+<parameters>
d1681e
+<parameter name="grace_active">
d1681e
+<longdesc lang="en">NFS-Ganesha grace active attribute</longdesc>
d1681e
+<shortdesc lang="en">NFS-Ganesha grace active attribute</shortdesc>
d1681e
+<content type="string" default="grace-active" />
d1681e
+</parameter>
d1681e
+</parameters>
d1681e
+
d1681e
+<actions>
d1681e
+<action name="start"   timeout="40s" />
d1681e
+<action name="stop"    timeout="40s" />
d1681e
+<action name="status"  timeout="20s" interval="60s" />
d1681e
+<action name="monitor" depth="0" timeout="10s" interval="5s" />
d1681e
+<action name="notify"  timeout="10s" />
d1681e
+<action name="meta-data"  timeout="20s" />
d1681e
+</actions>
d1681e
+</resource-agent>
d1681e
+END
d1681e
+
d1681e
+return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_grace_usage() {
d1681e
+	echo "ganesha.nfsd USAGE"
d1681e
+}
d1681e
+
d1681e
+# Make sure meta-data and usage always succeed
d1681e
+case $__OCF_ACTION in
d1681e
+	meta-data)	ganesha_meta_data
d1681e
+			exit ${OCF_SUCCESS}
d1681e
+			;;
d1681e
+	usage|help)	ganesha_usage
d1681e
+			exit ${OCF_SUCCESS}
d1681e
+			;;
d1681e
+	*)
d1681e
+			;;
d1681e
+esac
d1681e
+
d1681e
+ganesha_grace_start()
d1681e
+{
d1681e
+	local rc=${OCF_ERR_GENERIC}
d1681e
+	local host=$(hostname -s)
d1681e
+
d1681e
+	ocf_log debug "ganesha_grace_start()"
d1681e
+	# give ganesha_mon RA a chance to set the crm_attr first
d1681e
+	# I mislike the sleep, but it's not clear that looping
d1681e
+	# with a small sleep is necessarily better
d1681e
+	# start has a 40sec timeout, so a 5sec sleep here is okay
d1681e
+        sleep 5
d1681e
+	attr=$(crm_attribute --query --node=${host} --name=${OCF_RESKEY_grace_active} 2> /dev/null)
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+		host=$(hostname)
d1681e
+		attr=$(crm_attribute --query --node=${host} --name=${OCF_RESKEY_grace_active} 2> /dev/null )
d1681e
+                if [ $? -ne 0 ]; then
d1681e
+	                ocf_log info "grace start: crm_attribute --query --node=${host} --name=${OCF_RESKEY_grace_active} failed"
d1681e
+                fi
d1681e
+        fi
d1681e
+
d1681e
+	# Three possibilities:
d1681e
+	# 1. There is no attribute at all and attr_updater returns
d1681e
+	#    a zero length string. This happens when
d1681e
+	#    ganesha_mon::monitor hasn't run at least once to set
d1681e
+	#    the attribute. The assumption here is that the system
d1681e
+	#    is coming up. We pretend, for now, that the node is
d1681e
+	#    healthy, to allow the system to continue coming up.
d1681e
+	#    It will cure itself in a few seconds
d1681e
+	# 2. There is an attribute, and it has the value "1"; this
d1681e
+	#    node is healthy.
d1681e
+	# 3. There is an attribute, but it has no value or the value
d1681e
+	#    "0"; this node is not healthy.
d1681e
+
d1681e
+	# case 1
d1681e
+	if [[ -z "${attr}" ]]; then
d1681e
+		return ${OCF_SUCCESS}
d1681e
+	fi
d1681e
+
d1681e
+	# case 2
d1681e
+	if [[ "${attr}" = *"value=1" ]]; then
d1681e
+		return ${OCF_SUCCESS}
d1681e
+	fi
d1681e
+
d1681e
+	# case 3
d1681e
+	return ${OCF_NOT_RUNNING}
d1681e
+}
d1681e
+
d1681e
+ganesha_grace_stop()
d1681e
+{
d1681e
+
d1681e
+	ocf_log debug "ganesha_grace_stop()"
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_grace_notify()
d1681e
+{
d1681e
+        # since this is a clone RA we should only ever see pre-start
d1681e
+        # or post-stop
d1681e
+	mode="${OCF_RESKEY_CRM_meta_notify_type}-${OCF_RESKEY_CRM_meta_notify_operation}"
d1681e
+	case "${mode}" in
d1681e
+	pre-start | post-stop)
d1681e
+		dbus-send --print-reply --system --dest=org.ganesha.nfsd /org/ganesha/nfsd/admin org.ganesha.nfsd.admin.grace string:${OCF_RESKEY_CRM_meta_notify_stop_uname}
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log info "dbus-send --print-reply --system --dest=org.ganesha.nfsd /org/ganesha/nfsd/admin org.ganesha.nfsd.admin.grace string:${OCF_RESKEY_CRM_meta_notify_stop_uname} failed"
d1681e
+		fi
d1681e
+		;;
d1681e
+	esac
d1681e
+
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_grace_monitor()
d1681e
+{
d1681e
+	local host=$(hostname -s)
d1681e
+
d1681e
+	ocf_log debug "monitor"
d1681e
+
d1681e
+	attr=$(crm_attribute --query --node=${host} --name=${OCF_RESKEY_grace_active} 2> /dev/null)
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+		host=$(hostname)
d1681e
+	        attr=$(crm_attribute --query --node=${host} --name=${OCF_RESKEY_grace_active} 2> /dev/null)
d1681e
+                if [ $? -ne 0 ]; then
d1681e
+	                ocf_log info "crm_attribute --query --node=${host} --name=${OCF_RESKEY_grace_active} failed"
d1681e
+                fi
d1681e
+        fi
d1681e
+
d1681e
+	# if there is no attribute (yet), maybe it's because
d1681e
+	# this RA started before ganesha_mon (nfs-mon) has had
d1681e
+	# chance to create it. In which case we'll pretend
d1681e
+	# everything is okay this time around
d1681e
+	if [[ -z "${attr}" ]]; then
d1681e
+		return ${OCF_SUCCESS}
d1681e
+	fi
d1681e
+
d1681e
+	if [[ "${attr}" = *"value=1" ]]; then
d1681e
+		return ${OCF_SUCCESS}
d1681e
+	fi
d1681e
+
d1681e
+	return ${OCF_NOT_RUNNING}
d1681e
+}
d1681e
+
d1681e
+ganesha_grace_validate()
d1681e
+{
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_grace_validate
d1681e
+
d1681e
+# Translate each action into the appropriate function call
d1681e
+case $__OCF_ACTION in
d1681e
+start)          ganesha_grace_start
d1681e
+		;;
d1681e
+stop)           ganesha_grace_stop
d1681e
+		;;
d1681e
+status|monitor) ganesha_grace_monitor
d1681e
+		;;
d1681e
+notify)         ganesha_grace_notify
d1681e
+		;;
d1681e
+*)              ganesha_grace_usage
d1681e
+		exit ${OCF_ERR_UNIMPLEMENTED}
d1681e
+		;;
d1681e
+esac
d1681e
+
d1681e
+rc=$?
d1681e
+
d1681e
+# The resource agent may optionally log a debug message
d1681e
+ocf_log debug "${OCF_RESOURCE_INSTANCE} ${__OCF_ACTION} returned $rc"
d1681e
+exit $rc
d1681e
diff --git a/extras/ganesha/ocf/ganesha_mon b/extras/ganesha/ocf/ganesha_mon
d1681e
new file mode 100644
74b1de
index 0000000..2b4a9d6
d1681e
--- /dev/null
d1681e
+++ b/extras/ganesha/ocf/ganesha_mon
74b1de
@@ -0,0 +1,234 @@
d1681e
+#!/bin/bash
d1681e
+#
d1681e
+# Copyright (c) 2014 Anand Subramanian anands@redhat.com
d1681e
+# Copyright (c) 2015 Red Hat Inc.
d1681e
+#                    All Rights Reserved.
d1681e
+#
d1681e
+# This program is free software; you can redistribute it and/or modify
d1681e
+# it under the terms of version 2 of the GNU General Public License as
d1681e
+# published by the Free Software Foundation.
d1681e
+#
d1681e
+# This program is distributed in the hope that it would be useful, but
d1681e
+# WITHOUT ANY WARRANTY; without even the implied warranty of
d1681e
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
d1681e
+#
d1681e
+# Further, this software is distributed without any warranty that it is
d1681e
+# free of the rightful claim of any third person regarding infringement
d1681e
+# or the like.  Any license provided herein, whether implied or
d1681e
+# otherwise, applies only to this software file.  Patent licenses, if
d1681e
+# any, provided herein do not apply to combinations of this program with
d1681e
+# other software, or any other product whatsoever.
d1681e
+#
d1681e
+# You should have received a copy of the GNU General Public License
d1681e
+# along with this program; if not, write the Free Software Foundation,
d1681e
+# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
d1681e
+#
d1681e
+#
d1681e
+
d1681e
+# Initialization:
d1681e
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
d1681e
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
d1681e
+
d1681e
+if [ -n "${OCF_DEBUG_LIBRARY}" ]; then
d1681e
+	. ${OCF_DEBUG_LIBRARY}
d1681e
+else
d1681e
+	: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
d1681e
+	. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
d1681e
+fi
d1681e
+
d1681e
+# Defaults
d1681e
+OCF_RESKEY_ganesha_active_default="ganesha-active"
d1681e
+OCF_RESKEY_grace_active_default="grace-active"
d1681e
+OCF_RESKEY_grace_delay_default="5"
d1681e
+
d1681e
+: ${OCF_RESKEY_ganesha_active=${OCF_RESKEY_ganesha_active_default}}
d1681e
+: ${OCF_RESKEY_grace_active=${OCF_RESKEY_grace_active_default}}
d1681e
+: ${OCF_RESKEY_grace_delay=${OCF_RESKEY_grace_delay_default}}
d1681e
+
d1681e
+ganesha_meta_data() {
d1681e
+	cat <
d1681e
+
d1681e
+
d1681e
+<resource-agent name="ganesha_mon">
d1681e
+<version>1.0</version>
d1681e
+
d1681e
+<longdesc lang="en">
d1681e
+This Linux-specific resource agent acts as a dummy
d1681e
+resource agent for nfs-ganesha.
d1681e
+</longdesc>
d1681e
+
d1681e
+<shortdesc lang="en">Manages the user-space nfs-ganesha NFS server</shortdesc>
d1681e
+
d1681e
+<parameters>
d1681e
+<parameter name="ganesha_active">
d1681e
+<longdesc lang="en">NFS-Ganesha daemon active attribute</longdesc>
d1681e
+<shortdesc lang="en">NFS-Ganesha daemon active attribute</shortdesc>
d1681e
+<content type="string" default="ganesha-active" />
d1681e
+</parameter>
d1681e
+<parameter name="grace_active">
d1681e
+<longdesc lang="en">NFS-Ganesha grace active attribute</longdesc>
d1681e
+<shortdesc lang="en">NFS-Ganesha grace active attribute</shortdesc>
d1681e
+<content type="string" default="grace-active" />
d1681e
+</parameter>
d1681e
+<parameter name="grace_delay">
d1681e
+<longdesc lang="en">
d1681e
+NFS-Ganesha grace delay.
d1681e
+When changing this, adjust the ganesha_grace RA's monitor interval to match.
d1681e
+</longdesc>
d1681e
+<shortdesc lang="en">NFS-Ganesha grace delay</shortdesc>
d1681e
+<content type="string" default="5" />
d1681e
+</parameter>
d1681e
+</parameters>
d1681e
+
d1681e
+<actions>
d1681e
+<action name="start"   timeout="40s" />
d1681e
+<action name="stop"    timeout="40s" />
d1681e
+<action name="status"  timeout="20s" interval="60s" />
d1681e
+<action name="monitor" depth="0"  timeout="10s" interval="10s" />
d1681e
+<action name="meta-data"  timeout="20s" />
d1681e
+</actions>
d1681e
+</resource-agent>
d1681e
+END
d1681e
+
d1681e
+return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_mon_usage() {
d1681e
+	echo "ganesha.nfsd USAGE"
d1681e
+}
d1681e
+
d1681e
+# Make sure meta-data and usage always succeed
d1681e
+case ${__OCF_ACTION} in
d1681e
+	meta-data)	ganesha_meta_data
d1681e
+			exit ${OCF_SUCCESS}
d1681e
+			;;
d1681e
+	usage|help)	ganesha_usage
d1681e
+			exit ${OCF_SUCCESS}
d1681e
+			;;
d1681e
+	*)
d1681e
+			;;
d1681e
+esac
d1681e
+
d1681e
+ganesha_mon_start()
d1681e
+{
d1681e
+	ocf_log debug "ganesha_mon_start"
d1681e
+	ganesha_mon_monitor
d1681e
+	return $OCF_SUCCESS
d1681e
+}
d1681e
+
d1681e
+ganesha_mon_stop()
d1681e
+{
d1681e
+	ocf_log debug "ganesha_mon_stop"
d1681e
+	return $OCF_SUCCESS
d1681e
+}
d1681e
+
d1681e
+ganesha_mon_monitor()
d1681e
+{
d1681e
+	local host=$(hostname -s)
d1681e
+	local pid_file="/var/run/ganesha.pid"
d1681e
+	local rhel6_pid_file="/var/run/ganesha.nfsd.pid"
d1681e
+	local proc_pid="/proc/"
d1681e
+
d1681e
+	# RHEL6 /etc/init.d/nfs-ganesha adds -p /var/run/ganesha.nfsd.pid
d1681e
+	# RHEL7 systemd does not. Would be nice if all distros used the
d1681e
+	# same pid file.
d1681e
+	if [ -e ${rhel6_pid_file} ]; then
d1681e
+		pid_file=${rhel6_pid_file}
d1681e
+	fi
d1681e
+	if [ -e ${pid_file} ]; then
d1681e
+		proc_pid="${proc_pid}$(cat ${pid_file})"
d1681e
+	fi
d1681e
+
d1681e
+	if [ "x${proc_pid}" != "x/proc/" -a -d ${proc_pid} ]; then
d1681e
+
d1681e
+		attrd_updater -n ${OCF_RESKEY_ganesha_active} -v 1
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log info "warning: attrd_updater -n ${OCF_RESKEY_ganesha_active} -v 1 failed"
d1681e
+		fi
d1681e
+
d1681e
+		# ganesha_grace (nfs-grace) RA follows grace-active attr
d1681e
+		# w/ constraint location
d1681e
+		attrd_updater -n ${OCF_RESKEY_grace_active} -v 1
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log info "warning: attrd_updater -n ${OCF_RESKEY_grace_active} -v 1 failed"
d1681e
+		fi
d1681e
+
d1681e
+		# ganesha_mon (nfs-mon) and ganesha_grace (nfs-grace)
d1681e
+		# track grace-active crm_attr (attr != crm_attr)
d1681e
+		# we can't just use the attr as there's no way to query
d1681e
+		# its value in RHEL6 pacemaker
d1681e
+
d1681e
+		crm_attribute --node=${host} --lifetime=forever --name=${OCF_RESKEY_grace_active} --update=1 2> /dev/null
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			host=$(hostname)
d1681e
+			crm_attribute --node=${host} --lifetime=forever --name=${OCF_RESKEY_grace_active} --update=1 2> /dev/null
d1681e
+			if [ $? -ne 0 ]; then
d1681e
+				ocf_log info "mon monitor warning: crm_attribute --node=${host} --lifetime=forever --name=${OCF_RESKEY_grace_active} --update=1 failed"
d1681e
+			fi
d1681e
+		fi
d1681e
+
d1681e
+		return ${OCF_SUCCESS}
d1681e
+	fi
d1681e
+
d1681e
+	# VIP fail-over is triggered by clearing the
d1681e
+	# ganesha-active node attribute on this node.
d1681e
+	#
d1681e
+	# Meanwhile the ganesha_grace notify() runs when its
d1681e
+	# nfs-grace resource is disabled on a node; which
d1681e
+	# is triggered by clearing the grace-active attribute
d1681e
+	# on this node.
d1681e
+	#
d1681e
+	# We need to allow time for it to run and put
d1681e
+	# the remaining ganesha.nfsds into grace before
d1681e
+	# initiating the VIP fail-over.
d1681e
+
d1681e
+	attrd_updater -D -n ${OCF_RESKEY_grace_active}
d1681e
+	if [ $? -ne 0 ]; then
d1681e
+		ocf_log info "warning: attrd_updater -D -n ${OCF_RESKEY_grace_active} failed"
d1681e
+	fi
d1681e
+
d1681e
+	host=$(hostname -s)
d1681e
+	crm_attribute --node=${host} --name=${OCF_RESKEY_grace_active} --update=0 2> /dev/null
d1681e
+	if [ $? -ne 0 ]; then
d1681e
+		host=$(hostname)
d1681e
+		crm_attribute --node=${host} --name=${OCF_RESKEY_grace_active} --update=0 2> /dev/null
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log info "mon monitor warning: crm_attribute --node=${host} --name=${OCF_RESKEY_grace_active} --update=0 failed"
d1681e
+		fi
d1681e
+	fi
d1681e
+
d1681e
+	sleep ${OCF_RESKEY_grace_delay}
d1681e
+
d1681e
+	attrd_updater -D -n ${OCF_RESKEY_ganesha_active}
d1681e
+	if [ $? -ne 0 ]; then
d1681e
+		ocf_log info "warning: attrd_updater -D -n ${OCF_RESKEY_ganesha_active} failed"
d1681e
+	fi
d1681e
+
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_mon_validate()
d1681e
+{
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_mon_validate
d1681e
+
d1681e
+# Translate each action into the appropriate function call
d1681e
+case ${__OCF_ACTION} in
d1681e
+start)          ganesha_mon_start
d1681e
+		;;
d1681e
+stop)           ganesha_mon_stop
d1681e
+		;;
d1681e
+status|monitor) ganesha_mon_monitor
d1681e
+		;;
d1681e
+*)              ganesha_mon_usage
d1681e
+		exit ${OCF_ERR_UNIMPLEMENTED}
d1681e
+		;;
d1681e
+esac
d1681e
+
d1681e
+rc=$?
d1681e
+
d1681e
+# The resource agent may optionally log a debug message
d1681e
+ocf_log debug "${OCF_RESOURCE_INSTANCE} ${__OCF_ACTION} returned $rc"
d1681e
+exit $rc
d1681e
diff --git a/extras/ganesha/ocf/ganesha_nfsd b/extras/ganesha/ocf/ganesha_nfsd
d1681e
new file mode 100644
74b1de
index 0000000..93fc8be
d1681e
--- /dev/null
d1681e
+++ b/extras/ganesha/ocf/ganesha_nfsd
74b1de
@@ -0,0 +1,167 @@
d1681e
+#!/bin/bash
d1681e
+#
d1681e
+# Copyright (c) 2014 Anand Subramanian anands@redhat.com
d1681e
+# Copyright (c) 2015 Red Hat Inc.
d1681e
+#                    All Rights Reserved.
d1681e
+#
d1681e
+# This program is free software; you can redistribute it and/or modify
d1681e
+# it under the terms of version 2 of the GNU General Public License as
d1681e
+# published by the Free Software Foundation.
d1681e
+#
d1681e
+# This program is distributed in the hope that it would be useful, but
d1681e
+# WITHOUT ANY WARRANTY; without even the implied warranty of
d1681e
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
d1681e
+#
d1681e
+# Further, this software is distributed without any warranty that it is
d1681e
+# free of the rightful claim of any third person regarding infringement
d1681e
+# or the like.  Any license provided herein, whether implied or
d1681e
+# otherwise, applies only to this software file.  Patent licenses, if
d1681e
+# any, provided herein do not apply to combinations of this program with
d1681e
+# other software, or any other product whatsoever.
d1681e
+#
d1681e
+# You should have received a copy of the GNU General Public License
d1681e
+# along with this program; if not, write the Free Software Foundation,
d1681e
+# Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
d1681e
+#
d1681e
+#
d1681e
+
d1681e
+# Initialization:
d1681e
+: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
d1681e
+. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
d1681e
+
d1681e
+if [ -n "${OCF_DEBUG_LIBRARY}" ]; then
d1681e
+	. ${OCF_DEBUG_LIBRARY}
d1681e
+else
d1681e
+	: ${OCF_FUNCTIONS_DIR=${OCF_ROOT}/lib/heartbeat}
d1681e
+	. ${OCF_FUNCTIONS_DIR}/ocf-shellfuncs
d1681e
+fi
d1681e
+
d1681e
+OCF_RESKEY_ha_vol_mnt_default="/var/run/gluster/shared_storage"
d1681e
+: ${OCF_RESKEY_ha_vol_mnt=${OCF_RESKEY_ha_vol_mnt_default}}
d1681e
+
d1681e
+ganesha_meta_data() {
d1681e
+	cat <
d1681e
+
d1681e
+
d1681e
+<resource-agent name="ganesha_nfsd">
d1681e
+<version>1.0</version>
d1681e
+
d1681e
+<longdesc lang="en">
d1681e
+This Linux-specific resource agent acts as a dummy
d1681e
+resource agent for nfs-ganesha.
d1681e
+</longdesc>
d1681e
+
d1681e
+<shortdesc lang="en">Manages the user-space nfs-ganesha NFS server</shortdesc>
d1681e
+
d1681e
+<parameters>
d1681e
+<parameter name="ha_vol_mnt">
d1681e
+<longdesc lang="en">HA State Volume Mount Point</longdesc>
d1681e
+<shortdesc lang="en">HA_State Volume Mount Point</shortdesc>
d1681e
+<content type="string" default="" />
d1681e
+</parameter>
d1681e
+</parameters>
d1681e
+
d1681e
+<actions>
d1681e
+<action name="start"   timeout="5s" />
d1681e
+<action name="stop"    timeout="5s" />
d1681e
+<action name="status" depth="0"  timeout="5s" interval="0" />
d1681e
+<action name="monitor" depth="0"  timeout="5s" interval="0" />
d1681e
+<action name="meta-data"  timeout="20s" />
d1681e
+</actions>
d1681e
+</resource-agent>
d1681e
+END
d1681e
+
d1681e
+return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_nfsd_usage() {
d1681e
+	echo "ganesha.nfsd USAGE"
d1681e
+}
d1681e
+
d1681e
+# Make sure meta-data and usage always succeed
d1681e
+case $__OCF_ACTION in
d1681e
+	meta-data)	ganesha_meta_data
d1681e
+			exit ${OCF_SUCCESS}
d1681e
+			;;
d1681e
+	usage|help)	ganesha_usage
d1681e
+			exit ${OCF_SUCCESS}
d1681e
+			;;
d1681e
+	*)
d1681e
+			;;
d1681e
+esac
d1681e
+
d1681e
+ganesha_nfsd_start()
d1681e
+{
d1681e
+	local long_host=$(hostname)
d1681e
+
d1681e
+	if [[ -d /var/lib/nfs ]]; then
d1681e
+		mv /var/lib/nfs /var/lib/nfs.backup
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log notice "mv /var/lib/nfs /var/lib/nfs.backup failed"
d1681e
+		fi
d1681e
+		ln -s ${OCF_RESKEY_ha_vol_mnt}/nfs-ganesha/${long_host}/nfs /var/lib/nfs
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log notice "ln -s ${OCF_RESKEY_ha_vol_mnt}/nfs-ganesha/${long_host}/nfs /var/lib/nfs failed"
d1681e
+		fi
d1681e
+	fi
d1681e
+
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_nfsd_stop()
d1681e
+{
d1681e
+
d1681e
+	if [ -L /var/lib/nfs -a -d /var/lib/nfs.backup ]; then
d1681e
+		rm -f /var/lib/nfs
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log notice "rm -f /var/lib/nfs failed"
d1681e
+		fi
d1681e
+		mv /var/lib/nfs.backup /var/lib/nfs
d1681e
+		if [ $? -ne 0 ]; then
d1681e
+			ocf_log notice "mv /var/lib/nfs.backup /var/lib/nfs failed"
d1681e
+		fi
d1681e
+	fi
d1681e
+
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_nfsd_monitor()
d1681e
+{
d1681e
+	# pacemaker checks to see if RA is already running before starting it.
d1681e
+	# if we return success, then it's presumed it's already running and
d1681e
+	# doesn't need to be started, i.e. invoke the start action.
d1681e
+	# return something other than success to make pacemaker invoke the
d1681e
+	# start action
d1681e
+	if [[ -L /var/lib/nfs ]]; then
d1681e
+		return ${OCF_SUCCESS}
d1681e
+	fi
d1681e
+	return ${OCF_NOT_RUNNING}
d1681e
+}
d1681e
+
d1681e
+ganesha_nfsd_validate()
d1681e
+{
d1681e
+	return ${OCF_SUCCESS}
d1681e
+}
d1681e
+
d1681e
+ganesha_nfsd_validate
d1681e
+
d1681e
+# ocf_log notice "ganesha_nfsd ${OCF_RESOURCE_INSTANCE} $__OCF_ACTION"
d1681e
+
d1681e
+# Translate each action into the appropriate function call
d1681e
+case $__OCF_ACTION in
d1681e
+start)          ganesha_nfsd_start
d1681e
+		;;
d1681e
+stop)           ganesha_nfsd_stop
d1681e
+		;;
d1681e
+status|monitor) ganesha_nfsd_monitor
d1681e
+		;;
d1681e
+*)              ganesha_nfsd_usage
d1681e
+		exit ${OCF_ERR_UNIMPLEMENTED}
d1681e
+		;;
d1681e
+esac
d1681e
+
d1681e
+rc=$?
d1681e
+
d1681e
+# The resource agent may optionally log a debug message
d1681e
+ocf_log debug "${OCF_RESOURCE_INSTANCE} ${__OCF_ACTION} returned $rc"
d1681e
+exit $rc
d1681e
diff --git a/extras/ganesha/scripts/Makefile.am b/extras/ganesha/scripts/Makefile.am
74b1de
index 00a2c45..7e345fd 100644
d1681e
--- a/extras/ganesha/scripts/Makefile.am
d1681e
+++ b/extras/ganesha/scripts/Makefile.am
d1681e
@@ -1,4 +1,6 @@
d1681e
-EXTRA_DIST= create-export-ganesha.sh generate-epoch.py dbus-send.sh
74b1de
+EXTRA_DIST= create-export-ganesha.sh generate-epoch.py dbus-send.sh \
74b1de
+			ganesha-ha.sh
d1681e
 
d1681e
 scriptsdir = $(libexecdir)/ganesha
74b1de
-scripts_SCRIPTS = create-export-ganesha.sh dbus-send.sh generate-epoch.py
74b1de
+scripts_SCRIPTS = create-export-ganesha.sh dbus-send.sh generate-epoch.py \
74b1de
+				  ganesha-ha.sh
d1681e
diff --git a/extras/ganesha/scripts/ganesha-ha.sh b/extras/ganesha/scripts/ganesha-ha.sh
d1681e
new file mode 100644
74b1de
index 0000000..6b011be
d1681e
--- /dev/null
d1681e
+++ b/extras/ganesha/scripts/ganesha-ha.sh
74b1de
@@ -0,0 +1,1125 @@
d1681e
+#!/bin/bash
d1681e
+
d1681e
+# Copyright 2015-2016 Red Hat Inc.  All Rights Reserved
d1681e
+#
d1681e
+# Pacemaker+Corosync High Availability for NFS-Ganesha
d1681e
+#
d1681e
+# setup, teardown, add, delete, refresh-config, and status
d1681e
+#
d1681e
+# Each participating node in the cluster is assigned a virtual IP (VIP)
d1681e
+# which fails over to another node when its associated ganesha.nfsd dies
d1681e
+# for any reason. After the VIP is moved to another node all the
d1681e
+# ganesha.nfsds are send a signal using DBUS to put them into NFS GRACE.
d1681e
+#
d1681e
+# There are six resource agent types used: ganesha_mon, ganesha_grace,
d1681e
+# ganesha_nfsd, IPaddr, and Dummy. ganesha_mon is used to monitor the
d1681e
+# ganesha.nfsd. ganesha_grace is used to send the DBUS signal to put
d1681e
+# the remaining ganesha.nfsds into grace. ganesha_nfsd is used to start
d1681e
+# and stop the ganesha.nfsd during setup and teardown. IPaddr manages
d1681e
+# the VIP. A Dummy resource named $hostname-trigger_ip-1 is used to
d1681e
+# ensure that the NFS GRACE DBUS signal is sent after the VIP moves to
d1681e
+# the new host.
d1681e
+
d1681e
+HA_NUM_SERVERS=0
d1681e
+HA_SERVERS=""
d1681e
+HA_VOL_NAME="gluster_shared_storage"
d1681e
+HA_VOL_MNT="/var/run/gluster/shared_storage"
d1681e
+HA_CONFDIR=$HA_VOL_MNT"/nfs-ganesha"
d1681e
+SERVICE_MAN="DISTRO_NOT_FOUND"
d1681e
+
d1681e
+RHEL6_PCS_CNAME_OPTION="--name"
d1681e
+SECRET_PEM="/var/lib/glusterd/nfs/secret.pem"
d1681e
+
d1681e
+# UNBLOCK RA uses shared_storage which may become unavailable
d1681e
+# during any of the nodes reboot. Hence increase timeout value.
d1681e
+PORTBLOCK_UNBLOCK_TIMEOUT="60s"
d1681e
+
d1681e
+# Try loading the config from any of the distro
d1681e
+# specific configuration locations
d1681e
+if [ -f /etc/sysconfig/ganesha ]
d1681e
+        then
d1681e
+        . /etc/sysconfig/ganesha
d1681e
+fi
d1681e
+if [ -f /etc/conf.d/ganesha ]
d1681e
+        then
d1681e
+        . /etc/conf.d/ganesha
d1681e
+fi
d1681e
+if [ -f /etc/default/ganesha ]
d1681e
+        then
d1681e
+        . /etc/default/ganesha
d1681e
+fi
d1681e
+
d1681e
+GANESHA_CONF=
d1681e
+
d1681e
+function find_rhel7_conf
d1681e
+{
d1681e
+ while [[ $# > 0 ]]
d1681e
+        do
d1681e
+                key="$1"
d1681e
+                case $key in
d1681e
+                        -f)
d1681e
+                         CONFFILE="$2"
d1681e
+                         break;
d1681e
+                         ;;
d1681e
+                         *)
d1681e
+                         ;;
d1681e
+                 esac
d1681e
+                 shift
d1681e
+         done
d1681e
+}
d1681e
+
d1681e
+if [ -z $CONFFILE ]
d1681e
+        then
d1681e
+        find_rhel7_conf $OPTIONS
d1681e
+
d1681e
+fi
d1681e
+
d1681e
+GANESHA_CONF=${CONFFILE:-/etc/ganesha/ganesha.conf}
d1681e
+
d1681e
+usage() {
d1681e
+
d1681e
+        echo "Usage      : add|delete|refresh-config|status"
d1681e
+        echo "Add-node   : ganesha-ha.sh --add <HA_CONF_DIR> \
d1681e
+<NODE-HOSTNAME>  <NODE-VIP>"
d1681e
+        echo "Delete-node: ganesha-ha.sh --delete <HA_CONF_DIR> \
d1681e
+<NODE-HOSTNAME>"
d1681e
+        echo "Refresh-config : ganesha-ha.sh --refresh-config <HA_CONFDIR> \
d1681e
+<volume>"
d1681e
+        echo "Status : ganesha-ha.sh --status <HA_CONFDIR>"
d1681e
+}
d1681e
+
d1681e
+determine_service_manager () {
d1681e
+
d1681e
+        if [ -e "/usr/bin/systemctl" ];
d1681e
+        then
d1681e
+                SERVICE_MAN="/usr/bin/systemctl"
d1681e
+        elif [ -e "/sbin/invoke-rc.d" ];
d1681e
+        then
d1681e
+                SERVICE_MAN="/sbin/invoke-rc.d"
d1681e
+        elif [ -e "/sbin/service" ];
d1681e
+        then
d1681e
+                SERVICE_MAN="/sbin/service"
d1681e
+        fi
d1681e
+        if [ "$SERVICE_MAN" == "DISTRO_NOT_FOUND" ]
d1681e
+        then
d1681e
+                echo "Service manager not recognized, exiting"
d1681e
+                exit 1
d1681e
+        fi
d1681e
+}
d1681e
+
d1681e
+manage_service ()
d1681e
+{
d1681e
+        local action=${1}
d1681e
+        local new_node=${2}
d1681e
+        local option=
d1681e
+
d1681e
+        if [ "$action" == "start" ]; then
d1681e
+                option="yes"
d1681e
+        else
d1681e
+                option="no"
d1681e
+        fi
d1681e
+        ssh -oPasswordAuthentication=no -oStrictHostKeyChecking=no -i \
d1681e
+${SECRET_PEM} root@${new_node} "/usr/libexec/ganesha/ganesha-ha.sh --setup-ganesha-conf-files $HA_CONFDIR $option"
d1681e
+
d1681e
+        if [ "$SERVICE_MAN" == "/usr/bin/systemctl" ]
d1681e
+        then
d1681e
+                ssh -oPasswordAuthentication=no -oStrictHostKeyChecking=no -i \
d1681e
+${SECRET_PEM} root@${new_node} "$SERVICE_MAN  ${action} nfs-ganesha"
d1681e
+        else
d1681e
+                ssh -oPasswordAuthentication=no -oStrictHostKeyChecking=no -i \
d1681e
+${SECRET_PEM} root@${new_node} "$SERVICE_MAN nfs-ganesha ${action}"
d1681e
+        fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+check_cluster_exists()
d1681e
+{
d1681e
+    local name=${1}
d1681e
+    local cluster_name=""
d1681e
+
d1681e
+    if [ -e /var/run/corosync.pid ]; then
d1681e
+        cluster_name=$(pcs status | grep "Cluster name:" | cut -d ' ' -f 3)
d1681e
+        if [ ${cluster_name} -a ${cluster_name} = ${name} ]; then
d1681e
+            logger "$name already exists, exiting"
d1681e
+            exit 0
d1681e
+        fi
d1681e
+    fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+determine_servers()
d1681e
+{
d1681e
+    local cmd=${1}
d1681e
+    local num_servers=0
d1681e
+    local tmp_ifs=${IFS}
d1681e
+    local ha_servers=""
d1681e
+
d1681e
+    if [ "X${cmd}X" != "XsetupX" -a "X${cmd}X" != "XstatusX" ]; then
d1681e
+        ha_servers=$(pcs status | grep "Online:" | grep -o '\[.*\]' | sed -e 's/\[//' | sed -e 's/\]//')
d1681e
+        IFS=$' '
d1681e
+        for server in ${ha_servers} ; do
d1681e
+            num_servers=$(expr ${num_servers} + 1)
d1681e
+        done
d1681e
+        IFS=${tmp_ifs}
d1681e
+        HA_NUM_SERVERS=${num_servers}
d1681e
+        HA_SERVERS="${ha_servers}"
d1681e
+    else
d1681e
+        IFS=$','
d1681e
+        for server in ${HA_CLUSTER_NODES} ; do
d1681e
+            num_servers=$(expr ${num_servers} + 1)
d1681e
+        done
d1681e
+        IFS=${tmp_ifs}
d1681e
+        HA_NUM_SERVERS=${num_servers}
d1681e
+        HA_SERVERS="${HA_CLUSTER_NODES//,/ }"
d1681e
+    fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+setup_cluster()
d1681e
+{
d1681e
+    local name=${1}
d1681e
+    local num_servers=${2}
d1681e
+    local servers=${3}
d1681e
+    local unclean=""
d1681e
+    local quorum_policy="stop"
d1681e
+
d1681e
+    logger "setting up cluster ${name} with the following ${servers}"
d1681e
+
d1681e
+    pcs cluster auth ${servers}
d1681e
+    # pcs cluster setup --name ${name} ${servers}
d1681e
+    pcs cluster setup ${RHEL6_PCS_CNAME_OPTION} ${name} --transport udpu ${servers}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "pcs cluster setup ${RHEL6_PCS_CNAME_OPTION} ${name} ${servers} failed"
d1681e
+        exit 1;
d1681e
+    fi
d1681e
+    pcs cluster start --all
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "pcs cluster start failed"
d1681e
+        exit 1;
d1681e
+    fi
d1681e
+
d1681e
+    sleep 1
d1681e
+    # wait for the cluster to elect a DC before querying or writing
d1681e
+    # to the CIB. BZ 1334092
d1681e
+    crmadmin --dc_lookup --timeout=5000 > /dev/null 2>&1
d1681e
+    while [ $? -ne 0 ]; do
d1681e
+        crmadmin --dc_lookup --timeout=5000 > /dev/null 2>&1
d1681e
+    done
d1681e
+
d1681e
+    unclean=$(pcs status | grep -u "UNCLEAN")
d1681e
+    while [[ "${unclean}X" = "UNCLEANX" ]]; do
d1681e
+         sleep 1
d1681e
+         unclean=$(pcs status | grep -u "UNCLEAN")
d1681e
+    done
d1681e
+    sleep 1
d1681e
+
d1681e
+    if [ ${num_servers} -lt 3 ]; then
d1681e
+        quorum_policy="ignore"
d1681e
+    fi
d1681e
+    pcs property set no-quorum-policy=${quorum_policy}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs property set no-quorum-policy=${quorum_policy} failed"
d1681e
+    fi
d1681e
+
d1681e
+    pcs property set stonith-enabled=false
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs property set stonith-enabled=false failed"
d1681e
+    fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+setup_finalize_ha()
d1681e
+{
d1681e
+    local cibfile=${1}
d1681e
+    local stopped=""
d1681e
+
d1681e
+    stopped=$(pcs status | grep -u "Stopped")
d1681e
+    while [[ "${stopped}X" = "StoppedX" ]]; do
d1681e
+         sleep 1
d1681e
+         stopped=$(pcs status | grep -u "Stopped")
d1681e
+    done
d1681e
+}
d1681e
+
d1681e
+
d1681e
+refresh_config ()
d1681e
+{
d1681e
+        local short_host=$(hostname -s)
d1681e
+        local VOL=${1}
d1681e
+        local HA_CONFDIR=${2}
d1681e
+        local short_host=$(hostname -s)
d1681e
+
d1681e
+        local export_id=$(grep ^[[:space:]]*Export_Id $HA_CONFDIR/exports/export.$VOL.conf |\
d1681e
+                          awk -F"[=,;]" '{print $2}' | tr -d '[[:space:]]')
d1681e
+
d1681e
+
d1681e
+        if [ -e ${SECRET_PEM} ]; then
d1681e
+        while [[ ${3} ]]; do
d1681e
+            current_host=`echo ${3} | cut -d "." -f 1`
d1681e
+            if [ ${short_host} != ${current_host} ]; then
d1681e
+                output=$(ssh -oPasswordAuthentication=no \
d1681e
+-oStrictHostKeyChecking=no -i ${SECRET_PEM} root@${current_host} \
d1681e
+"dbus-send --print-reply --system --dest=org.ganesha.nfsd \
d1681e
+/org/ganesha/nfsd/ExportMgr org.ganesha.nfsd.exportmgr.UpdateExport \
d1681e
+string:$HA_CONFDIR/exports/export.$VOL.conf \
d1681e
+string:\"EXPORT(Export_Id=$export_id)\" 2>&1")
d1681e
+                ret=$?
d1681e
+                logger <<< "${output}"
d1681e
+                if [ ${ret} -ne 0 ]; then
d1681e
+                        echo "Error: refresh-config failed on ${current_host}."
d1681e
+                        exit 1
d1681e
+                else
d1681e
+                        echo "Refresh-config completed on ${current_host}."
d1681e
+                fi
d1681e
+
d1681e
+          fi
d1681e
+          shift
d1681e
+        done
d1681e
+    else
d1681e
+        echo "Error: refresh-config failed. Passwordless ssh is not enabled."
d1681e
+        exit 1
d1681e
+    fi
d1681e
+
d1681e
+    # Run the same command on the localhost,
d1681e
+        output=$(dbus-send --print-reply --system --dest=org.ganesha.nfsd \
d1681e
+/org/ganesha/nfsd/ExportMgr org.ganesha.nfsd.exportmgr.UpdateExport \
d1681e
+string:$HA_CONFDIR/exports/export.$VOL.conf \
d1681e
+string:"EXPORT(Export_Id=$export_id)" 2>&1)
d1681e
+        ret=$?
d1681e
+        logger <<< "${output}"
d1681e
+        if [ ${ret} -ne 0 ] ; then
d1681e
+                echo "Error: refresh-config failed on localhost."
d1681e
+                exit 1
d1681e
+        else
d1681e
+                echo "Success: refresh-config completed."
d1681e
+        fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+teardown_cluster()
d1681e
+{
d1681e
+    local name=${1}
d1681e
+
d1681e
+    for server in ${HA_SERVERS} ; do
d1681e
+        if [[ ${HA_CLUSTER_NODES} != *${server}* ]]; then
d1681e
+            logger "info: ${server} is not in config, removing"
d1681e
+
d1681e
+            pcs cluster stop ${server} --force
d1681e
+            if [ $? -ne 0 ]; then
d1681e
+                logger "warning: pcs cluster stop ${server} failed"
d1681e
+            fi
d1681e
+
d1681e
+            pcs cluster node remove ${server}
d1681e
+            if [ $? -ne 0 ]; then
d1681e
+                logger "warning: pcs cluster node remove ${server} failed"
d1681e
+            fi
d1681e
+        fi
d1681e
+    done
d1681e
+
d1681e
+    # BZ 1193433 - pcs doesn't reload cluster.conf after modification
d1681e
+    # after teardown completes, a subsequent setup will appear to have
d1681e
+    # 'remembered' the deleted node. You can work around this by
d1681e
+    # issuing another `pcs cluster node remove $node`,
d1681e
+    # `crm_node -f -R $server`, or
d1681e
+    # `cibadmin --delete --xml-text '
d1681e
+    # uname="$server"/>'
d1681e
+
d1681e
+    pcs cluster stop --all
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning pcs cluster stop --all failed"
d1681e
+    fi
d1681e
+
d1681e
+    pcs cluster destroy
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "error pcs cluster destroy failed"
d1681e
+        exit 1
d1681e
+    fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+cleanup_ganesha_config ()
d1681e
+{
d1681e
+    rm -f /etc/corosync/corosync.conf
d1681e
+    rm -rf /etc/cluster/cluster.conf*
d1681e
+    rm -rf /var/lib/pacemaker/cib/*
d1681e
+}
d1681e
+
d1681e
+do_create_virt_ip_constraints()
d1681e
+{
d1681e
+    local cibfile=${1}; shift
d1681e
+    local primary=${1}; shift
d1681e
+    local weight="1000"
d1681e
+
d1681e
+    # first a constraint location rule that says the VIP must be where
d1681e
+    # there's a ganesha.nfsd running
d1681e
+    pcs -f ${cibfile} constraint location ${primary}-group rule score=-INFINITY ganesha-active ne 1
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs constraint location ${primary}-group rule score=-INFINITY ganesha-active ne 1 failed"
d1681e
+    fi
d1681e
+
d1681e
+    # then a set of constraint location prefers to set the prefered order
d1681e
+    # for where a VIP should move
d1681e
+    while [[ ${1} ]]; do
d1681e
+        pcs -f ${cibfile} constraint location ${primary}-group prefers ${1}=${weight}
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning: pcs constraint location ${primary}-group prefers ${1}=${weight} failed"
d1681e
+        fi
d1681e
+        weight=$(expr ${weight} + 1000)
d1681e
+        shift
d1681e
+    done
d1681e
+    # and finally set the highest preference for the VIP to its home node
d1681e
+    # default weight when created is/was 100.
d1681e
+    # on Fedora setting appears to be additive, so to get the desired
d1681e
+    # value we adjust the weight
d1681e
+    # weight=$(expr ${weight} - 100)
d1681e
+    pcs -f ${cibfile} constraint location ${primary}-group prefers ${primary}=${weight}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs constraint location ${primary}-group prefers ${primary}=${weight} failed"
d1681e
+    fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+wrap_create_virt_ip_constraints()
d1681e
+{
d1681e
+    local cibfile=${1}; shift
d1681e
+    local primary=${1}; shift
d1681e
+    local head=""
d1681e
+    local tail=""
d1681e
+
d1681e
+    # build a list of peers, e.g. for a four node cluster, for node1,
d1681e
+    # the result is "node2 node3 node4"; for node2, "node3 node4 node1"
d1681e
+    # and so on.
d1681e
+    while [[ ${1} ]]; do
d1681e
+        if [ "${1}" = "${primary}" ]; then
d1681e
+            shift
d1681e
+            while [[ ${1} ]]; do
d1681e
+                tail=${tail}" "${1}
d1681e
+                shift
d1681e
+            done
d1681e
+        else
d1681e
+            head=${head}" "${1}
d1681e
+        fi
d1681e
+        shift
d1681e
+    done
d1681e
+    do_create_virt_ip_constraints ${cibfile} ${primary} ${tail} ${head}
d1681e
+}
d1681e
+
d1681e
+
d1681e
+create_virt_ip_constraints()
d1681e
+{
d1681e
+    local cibfile=${1}; shift
d1681e
+
d1681e
+    while [[ ${1} ]]; do
d1681e
+        wrap_create_virt_ip_constraints ${cibfile} ${1} ${HA_SERVERS}
d1681e
+        shift
d1681e
+    done
d1681e
+}
d1681e
+
d1681e
+
d1681e
+setup_create_resources()
d1681e
+{
d1681e
+    local cibfile=$(mktemp -u)
d1681e
+
d1681e
+    # fixup /var/lib/nfs
d1681e
+    logger "pcs resource create nfs_setup ocf:heartbeat:ganesha_nfsd ha_vol_mnt=${HA_VOL_MNT} --clone"
d1681e
+    pcs resource create nfs_setup ocf:heartbeat:ganesha_nfsd ha_vol_mnt=${HA_VOL_MNT} --clone
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs resource create nfs_setup ocf:heartbeat:ganesha_nfsd ha_vol_mnt=${HA_VOL_MNT} --clone failed"
d1681e
+    fi
d1681e
+
d1681e
+    pcs resource create nfs-mon ocf:heartbeat:ganesha_mon --clone
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs resource create nfs-mon ocf:heartbeat:ganesha_mon --clone failed"
d1681e
+    fi
d1681e
+
d1681e
+    # see comment in (/usr/lib/ocf/resource.d/heartbeat/ganesha_grace
d1681e
+    # start method. Allow time for ganesha_mon to start and set the
d1681e
+    # ganesha-active crm_attribute
d1681e
+    sleep 5
d1681e
+
d1681e
+    pcs resource create nfs-grace ocf:heartbeat:ganesha_grace --clone meta notify=true
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs resource create nfs-grace ocf:heartbeat:ganesha_grace --clone failed"
d1681e
+    fi
d1681e
+
d1681e
+    pcs constraint location nfs-grace-clone rule score=-INFINITY grace-active ne 1
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs constraint location nfs-grace-clone rule score=-INFINITY grace-active ne 1"
d1681e
+    fi
d1681e
+
d1681e
+    pcs cluster cib ${cibfile}
d1681e
+
d1681e
+    while [[ ${1} ]]; do
d1681e
+
d1681e
+        # this is variable indirection
d1681e
+        # from a nvs like 'VIP_host1=10.7.6.5' or 'VIP_host1="10.7.6.5"'
d1681e
+        # (or VIP_host-1=..., or VIP_host-1.my.domain.name=...)
d1681e
+        # a variable 'clean_name' is created (e.g. w/ value 'VIP_host_1')
d1681e
+        # and a clean nvs (e.g. w/ value 'VIP_host_1="10_7_6_5"')
d1681e
+        # after the `eval ${clean_nvs}` there is a variable VIP_host_1
d1681e
+        # with the value '10_7_6_5', and the following \$$ magic to
d1681e
+        # reference it, i.e. `eval tmp_ipaddr=\$${clean_name}` gives us
d1681e
+        # ${tmp_ipaddr} with 10_7_6_5 and then convert the _s back to .s
d1681e
+        # to give us ipaddr="10.7.6.5". whew!
d1681e
+        name="VIP_${1}"
d1681e
+        clean_name=${name//[-.]/_}
d1681e
+        nvs=$(grep "^${name}=" ${HA_CONFDIR}/ganesha-ha.conf)
d1681e
+        clean_nvs=${nvs//[-.]/_}
d1681e
+        eval ${clean_nvs}
d1681e
+        eval tmp_ipaddr=\$${clean_name}
d1681e
+        ipaddr=${tmp_ipaddr//_/.}
d1681e
+
d1681e
+        pcs -f ${cibfile} resource create ${1}-nfs_block ocf:heartbeat:portblock protocol=tcp \
d1681e
+        portno=2049 action=block ip=${ipaddr} --group ${1}-group
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning pcs resource create ${1}-nfs_block failed"
d1681e
+        fi
d1681e
+        pcs -f ${cibfile} resource create ${1}-cluster_ip-1 ocf:heartbeat:IPaddr ip=${ipaddr} \
d1681e
+        cidr_netmask=32 op monitor interval=15s --group ${1}-group --after ${1}-nfs_block
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning pcs resource create ${1}-cluster_ip-1 ocf:heartbeat:IPaddr ip=${ipaddr} \
d1681e
+            cidr_netmask=32 op monitor interval=15s failed"
d1681e
+        fi
d1681e
+
d1681e
+        pcs -f ${cibfile} constraint order nfs-grace-clone then ${1}-cluster_ip-1
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning: pcs constraint order nfs-grace-clone then ${1}-cluster_ip-1 failed"
d1681e
+        fi
d1681e
+
d1681e
+        pcs -f ${cibfile} resource create ${1}-nfs_unblock ocf:heartbeat:portblock protocol=tcp \
d1681e
+        portno=2049 action=unblock ip=${ipaddr} reset_local_on_unblock_stop=true \
d1681e
+        tickle_dir=${HA_VOL_MNT}/nfs-ganesha/tickle_dir/ --group ${1}-group --after ${1}-cluster_ip-1 \
d1681e
+        op stop timeout=${PORTBLOCK_UNBLOCK_TIMEOUT} op start timeout=${PORTBLOCK_UNBLOCK_TIMEOUT} \
d1681e
+        op monitor interval=10s timeout=${PORTBLOCK_UNBLOCK_TIMEOUT}
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning pcs resource create ${1}-nfs_unblock failed"
d1681e
+        fi
d1681e
+
d1681e
+
d1681e
+        shift
d1681e
+    done
d1681e
+
d1681e
+    create_virt_ip_constraints ${cibfile} ${HA_SERVERS}
d1681e
+
d1681e
+    pcs cluster cib-push ${cibfile}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning pcs cluster cib-push ${cibfile} failed"
d1681e
+    fi
d1681e
+    rm -f ${cibfile}
d1681e
+}
d1681e
+
d1681e
+
d1681e
+teardown_resources()
d1681e
+{
d1681e
+    # local mntpt=$(grep ha-vol-mnt ${HA_CONFIG_FILE} | cut -d = -f 2)
d1681e
+
d1681e
+    # restore /var/lib/nfs
d1681e
+    logger "notice: pcs resource delete nfs_setup-clone"
d1681e
+    pcs resource delete nfs_setup-clone
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs resource delete nfs_setup-clone failed"
d1681e
+    fi
d1681e
+
d1681e
+    # delete -clone resource agents
d1681e
+    # in particular delete the ganesha monitor so we don't try to
d1681e
+    # trigger anything when we shut down ganesha next.
d1681e
+    pcs resource delete nfs-mon-clone
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs resource delete nfs-mon-clone failed"
d1681e
+    fi
d1681e
+
d1681e
+    pcs resource delete nfs-grace-clone
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs resource delete nfs-grace-clone failed"
d1681e
+    fi
d1681e
+
d1681e
+    while [[ ${1} ]]; do
d1681e
+        pcs resource delete ${1}-group
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning: pcs resource delete ${1}-group failed"
d1681e
+        fi
d1681e
+        shift
d1681e
+    done
d1681e
+
d1681e
+}
d1681e
+
d1681e
+
d1681e
+recreate_resources()
d1681e
+{
d1681e
+    local cibfile=${1}; shift
d1681e
+
d1681e
+    while [[ ${1} ]]; do
d1681e
+        # this is variable indirection
d1681e
+        # see the comment on the same a few lines up
d1681e
+        name="VIP_${1}"
d1681e
+        clean_name=${name//[-.]/_}
d1681e
+        nvs=$(grep "^${name}=" ${HA_CONFDIR}/ganesha-ha.conf)
d1681e
+        clean_nvs=${nvs//[-.]/_}
d1681e
+        eval ${clean_nvs}
d1681e
+        eval tmp_ipaddr=\$${clean_name}
d1681e
+        ipaddr=${tmp_ipaddr//_/.}
d1681e
+
d1681e
+        pcs -f ${cibfile} resource create ${1}-nfs_block ocf:heartbeat:portblock protocol=tcp \
d1681e
+        portno=2049 action=block ip=${ipaddr} --group ${1}-group
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning pcs resource create ${1}-nfs_block failed"
d1681e
+        fi
d1681e
+        pcs -f ${cibfile} resource create ${1}-cluster_ip-1 ocf:heartbeat:IPaddr ip=${ipaddr} \
d1681e
+        cidr_netmask=32 op monitor interval=15s --group ${1}-group --after ${1}-nfs_block
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning pcs resource create ${1}-cluster_ip-1 ocf:heartbeat:IPaddr ip=${ipaddr} \
d1681e
+            cidr_netmask=32 op monitor interval=15s failed"
d1681e
+        fi
d1681e
+
d1681e
+        pcs -f ${cibfile} constraint order nfs-grace-clone then ${1}-cluster_ip-1
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning: pcs constraint order nfs-grace-clone then ${1}-cluster_ip-1 failed"
d1681e
+        fi
d1681e
+
d1681e
+        pcs -f ${cibfile} resource create ${1}-nfs_unblock ocf:heartbeat:portblock protocol=tcp \
d1681e
+        portno=2049 action=unblock ip=${ipaddr} reset_local_on_unblock_stop=true \
d1681e
+        tickle_dir=${HA_VOL_MNT}/nfs-ganesha/tickle_dir/ --group ${1}-group --after ${1}-cluster_ip-1 \
d1681e
+        op stop timeout=${PORTBLOCK_UNBLOCK_TIMEOUT} op start timeout=${PORTBLOCK_UNBLOCK_TIMEOUT} \
d1681e
+        op monitor interval=10s timeout=${PORTBLOCK_UNBLOCK_TIMEOUT}
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning pcs resource create ${1}-nfs_unblock failed"
d1681e
+        fi
d1681e
+
d1681e
+        shift
d1681e
+    done
d1681e
+}
d1681e
+
d1681e
+
d1681e
+addnode_recreate_resources()
d1681e
+{
d1681e
+    local cibfile=${1}; shift
d1681e
+    local add_node=${1}; shift
d1681e
+    local add_vip=${1}; shift
d1681e
+
d1681e
+    recreate_resources ${cibfile} ${HA_SERVERS}
d1681e
+
d1681e
+    pcs -f ${cibfile} resource create ${add_node}-nfs_block ocf:heartbeat:portblock \
d1681e
+    protocol=tcp portno=2049 action=block ip=${add_vip} --group ${add_node}-group
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning pcs resource create ${add_node}-nfs_block failed"
d1681e
+    fi
d1681e
+    pcs -f ${cibfile} resource create ${add_node}-cluster_ip-1 ocf:heartbeat:IPaddr \
d1681e
+    ip=${add_vip} cidr_netmask=32 op monitor interval=15s --group ${add_node}-group \
d1681e
+    --after ${add_node}-nfs_block
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning pcs resource create ${add_node}-cluster_ip-1 ocf:heartbeat:IPaddr \
d1681e
+	ip=${add_vip} cidr_netmask=32 op monitor interval=15s failed"
d1681e
+    fi
d1681e
+
d1681e
+    pcs -f ${cibfile} constraint order nfs-grace-clone then ${add_node}-cluster_ip-1
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs constraint order nfs-grace-clone then ${add_node}-cluster_ip-1 failed"
d1681e
+    fi
d1681e
+    pcs -f ${cibfile} resource create ${add_node}-nfs_unblock ocf:heartbeat:portblock \
d1681e
+    protocol=tcp portno=2049 action=unblock ip=${add_vip} reset_local_on_unblock_stop=true \
d1681e
+    tickle_dir=${HA_VOL_MNT}/nfs-ganesha/tickle_dir/ --group ${add_node}-group --after \
d1681e
+    ${add_node}-cluster_ip-1 op stop timeout=${PORTBLOCK_UNBLOCK_TIMEOUT} op start \
d1681e
+    timeout=${PORTBLOCK_UNBLOCK_TIMEOUT} op monitor interval=10s \
d1681e
+    timeout=${PORTBLOCK_UNBLOCK_TIMEOUT}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning pcs resource create ${add_node}-nfs_unblock failed"
d1681e
+    fi
d1681e
+}
d1681e
+
d1681e
+
d1681e
+clear_resources()
d1681e
+{
d1681e
+    local cibfile=${1}; shift
d1681e
+
d1681e
+    while [[ ${1} ]]; do
d1681e
+        pcs -f ${cibfile} resource delete ${1}-group
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning: pcs -f ${cibfile} resource delete ${1}-group"
d1681e
+        fi
d1681e
+
d1681e
+        shift
d1681e
+    done
d1681e
+}
d1681e
+
d1681e
+
d1681e
+addnode_create_resources()
d1681e
+{
d1681e
+    local add_node=${1}; shift
d1681e
+    local add_vip=${1}; shift
d1681e
+    local cibfile=$(mktemp -u)
d1681e
+
d1681e
+    # start HA on the new node
d1681e
+    pcs cluster start ${add_node}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+       logger "warning: pcs cluster start ${add_node} failed"
d1681e
+    fi
d1681e
+
d1681e
+    pcs cluster cib ${cibfile}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs cluster cib ${cibfile} failed"
d1681e
+    fi
d1681e
+
d1681e
+    # delete all the -cluster_ip-1 resources, clearing
d1681e
+    # their constraints, then create them again so we can
d1681e
+    # recompute their constraints
d1681e
+    clear_resources ${cibfile} ${HA_SERVERS}
d1681e
+    addnode_recreate_resources ${cibfile} ${add_node} ${add_vip}
d1681e
+
d1681e
+    HA_SERVERS="${HA_SERVERS} ${add_node}"
d1681e
+    create_virt_ip_constraints ${cibfile} ${HA_SERVERS}
d1681e
+
d1681e
+    pcs cluster cib-push ${cibfile}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs cluster cib-push ${cibfile} failed"
d1681e
+    fi
d1681e
+    rm -f ${cibfile}
d1681e
+}
d1681e
+
d1681e
+
d1681e
+deletenode_delete_resources()
d1681e
+{
d1681e
+    local node=${1}; shift
d1681e
+    local ha_servers=$(echo "${HA_SERVERS}" | sed s/${node}//)
d1681e
+    local cibfile=$(mktemp -u)
d1681e
+
d1681e
+    pcs cluster cib ${cibfile}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs cluster cib ${cibfile} failed"
d1681e
+    fi
d1681e
+
d1681e
+    # delete all the -cluster_ip-1 and -trigger_ip-1 resources,
d1681e
+    # clearing their constraints, then create them again so we can
d1681e
+    # recompute their constraints
d1681e
+    clear_resources ${cibfile} ${HA_SERVERS}
d1681e
+    recreate_resources ${cibfile} ${ha_servers}
d1681e
+    HA_SERVERS=$(echo "${ha_servers}" | sed -e "s/  / /")
d1681e
+
d1681e
+    create_virt_ip_constraints ${cibfile} ${HA_SERVERS}
d1681e
+
d1681e
+    pcs cluster cib-push ${cibfile}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs cluster cib-push ${cibfile} failed"
d1681e
+    fi
d1681e
+    rm -f ${cibfile}
d1681e
+
d1681e
+}
d1681e
+
d1681e
+
d1681e
+deletenode_update_haconfig()
d1681e
+{
d1681e
+    local name="VIP_${1}"
d1681e
+    local clean_name=${name//[-.]/_}
d1681e
+
d1681e
+    ha_servers=$(echo ${HA_SERVERS} | sed -e "s/ /,/")
d1681e
+    sed -i -e "s/^HA_CLUSTER_NODES=.*$/HA_CLUSTER_NODES=\"${ha_servers// /,}\"/" -e "s/^${name}=.*$//" -e "/^$/d" ${HA_CONFDIR}/ganesha-ha.conf
d1681e
+}
d1681e
+
d1681e
+
d1681e
+setup_state_volume()
d1681e
+{
d1681e
+    local mnt=${HA_VOL_MNT}
d1681e
+    local longname=""
d1681e
+    local shortname=""
d1681e
+    local dname=""
d1681e
+    local dirname=""
d1681e
+
d1681e
+    longname=$(hostname)
d1681e
+    dname=${longname#$(hostname -s)}
d1681e
+
d1681e
+    while [[ ${1} ]]; do
d1681e
+
d1681e
+        if [[ ${1} == *${dname} ]]; then
d1681e
+            dirname=${1}
d1681e
+        else
d1681e
+            dirname=${1}${dname}
d1681e
+        fi
d1681e
+
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/tickle_dir ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/tickle_dir
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname} ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}/nfs
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/statd ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/statd
d1681e
+        fi
d1681e
+        if [ ! -e ${mnt}/nfs-ganesha/${dirname}/nfs/state ]; then
d1681e
+            touch ${mnt}/nfs-ganesha/${dirname}/nfs/state
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4recov ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4recov
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4old ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4old
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm
d1681e
+        fi
d1681e
+        if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm.bak ]; then
d1681e
+            mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm.bak
d1681e
+        fi
d1681e
+        if [ ! -e ${mnt}/nfs-ganesha/${dirname}/nfs/statd/state ]; then
d1681e
+            touch ${mnt}/nfs-ganesha/${dirname}/nfs/statd/state
d1681e
+        fi
d1681e
+        for server in ${HA_SERVERS} ; do
d1681e
+            if [ ${server} != ${dirname} ]; then
d1681e
+                ln -s ${mnt}/nfs-ganesha/${server}/nfs/ganesha ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/${server}
d1681e
+                ln -s ${mnt}/nfs-ganesha/${server}/nfs/statd ${mnt}/nfs-ganesha/${dirname}/nfs/statd/${server}
d1681e
+            fi
d1681e
+        done
d1681e
+        shift
d1681e
+    done
d1681e
+
d1681e
+}
d1681e
+
d1681e
+
d1681e
+addnode_state_volume()
d1681e
+{
d1681e
+    local newnode=${1}; shift
d1681e
+    local mnt=${HA_VOL_MNT}
d1681e
+    local longname=""
d1681e
+    local dname=""
d1681e
+    local dirname=""
d1681e
+
d1681e
+    longname=$(hostname)
d1681e
+    dname=${longname#$(hostname -s)}
d1681e
+
d1681e
+    if [[ ${newnode} == *${dname} ]]; then
d1681e
+        dirname=${newnode}
d1681e
+    else
d1681e
+        dirname=${newnode}${dname}
d1681e
+    fi
d1681e
+
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname} ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}
d1681e
+    fi
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}/nfs
d1681e
+    fi
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha
d1681e
+    fi
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/statd ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/statd
d1681e
+    fi
d1681e
+    if [ ! -e ${mnt}/nfs-ganesha/${dirname}/nfs/state ]; then
d1681e
+        touch ${mnt}/nfs-ganesha/${dirname}/nfs/state
d1681e
+    fi
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4recov ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4recov
d1681e
+    fi
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4old ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/v4old
d1681e
+    fi
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm
d1681e
+    fi
d1681e
+    if [ ! -d ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm.bak ]; then
d1681e
+        mkdir ${mnt}/nfs-ganesha/${dirname}/nfs/statd/sm.bak
d1681e
+    fi
d1681e
+    if [ ! -e ${mnt}/nfs-ganesha/${dirname}/nfs/statd/state ]; then
d1681e
+        touch ${mnt}/nfs-ganesha/${dirname}/nfs/statd/state
d1681e
+    fi
d1681e
+
d1681e
+    for server in ${HA_SERVERS} ; do
d1681e
+
d1681e
+        if [[ ${server} != ${dirname} ]]; then
d1681e
+            ln -s ${mnt}/nfs-ganesha/${server}/nfs/ganesha ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha/${server}
d1681e
+            ln -s ${mnt}/nfs-ganesha/${server}/nfs/statd ${mnt}/nfs-ganesha/${dirname}/nfs/statd/${server}
d1681e
+
d1681e
+            ln -s ${mnt}/nfs-ganesha/${dirname}/nfs/ganesha ${mnt}/nfs-ganesha/${server}/nfs/ganesha/${dirname}
d1681e
+            ln -s ${mnt}/nfs-ganesha/${dirname}/nfs/statd ${mnt}/nfs-ganesha/${server}/nfs/statd/${dirname}
d1681e
+        fi
d1681e
+    done
d1681e
+
d1681e
+}
d1681e
+
d1681e
+
d1681e
+delnode_state_volume()
d1681e
+{
d1681e
+    local delnode=${1}; shift
d1681e
+    local mnt=${HA_VOL_MNT}
d1681e
+    local longname=""
d1681e
+    local dname=""
d1681e
+    local dirname=""
d1681e
+
d1681e
+    longname=$(hostname)
d1681e
+    dname=${longname#$(hostname -s)}
d1681e
+
d1681e
+    if [[ ${delnode} == *${dname} ]]; then
d1681e
+        dirname=${delnode}
d1681e
+    else
d1681e
+        dirname=${delnode}${dname}
d1681e
+    fi
d1681e
+
d1681e
+    rm -rf ${mnt}/nfs-ganesha/${dirname}
d1681e
+
d1681e
+    for server in ${HA_SERVERS} ; do
d1681e
+        if [[ "${server}" != "${dirname}" ]]; then
d1681e
+            rm -f ${mnt}/nfs-ganesha/${server}/nfs/ganesha/${dirname}
d1681e
+            rm -f ${mnt}/nfs-ganesha/${server}/nfs/statd/${dirname}
d1681e
+        fi
d1681e
+    done
d1681e
+}
d1681e
+
d1681e
+
d1681e
+status()
d1681e
+{
d1681e
+    local scratch=$(mktemp)
d1681e
+    local regex_str="^${1}-cluster_ip-1"
d1681e
+    local healthy=0
d1681e
+    local index=1
d1681e
+    local nodes
d1681e
+
d1681e
+    # change tabs to spaces, strip leading spaces
d1681e
+    pcs status | sed -e "s/\t/ /g" -e "s/^[ ]*//" > ${scratch}
d1681e
+
d1681e
+    nodes[0]=${1}; shift
d1681e
+
d1681e
+    # make a regex of the configured nodes
d1681e
+    # and initalize the nodes array for later
d1681e
+    while [[ ${1} ]]; do
d1681e
+
d1681e
+        regex_str="${regex_str}|^${1}-cluster_ip-1"
d1681e
+        nodes[${index}]=${1}
d1681e
+        ((index++))
d1681e
+        shift
d1681e
+    done
d1681e
+
d1681e
+    # print the nodes that are expected to be online
d1681e
+    grep -E "^Online:" ${scratch}
d1681e
+
d1681e
+    echo
d1681e
+
d1681e
+    # print the VIPs and which node they are on
d1681e
+    grep -E "${regex_str}" < ${scratch} | cut -d ' ' -f 1,4
d1681e
+
d1681e
+    echo
d1681e
+
d1681e
+    # check if the VIP and port block/unblock RAs are on the expected nodes
d1681e
+    for n in ${nodes[*]}; do
d1681e
+
d1681e
+        grep -E -x "${n}-nfs_block \(ocf::heartbeat:portblock\): Started ${n}" > /dev/null 2>&1 ${scratch}
d1681e
+        result=$?
d1681e
+        ((healthy+=${result}))
d1681e
+        grep -E -x "${n}-cluster_ip-1 \(ocf::heartbeat:IPaddr\): Started ${n}" > /dev/null 2>&1 ${scratch}
d1681e
+        result=$?
d1681e
+        ((healthy+=${result}))
d1681e
+        grep -E -x "${n}-nfs_unblock \(ocf::heartbeat:portblock\): Started ${n}" > /dev/null 2>&1 ${scratch}
d1681e
+        result=$?
d1681e
+        ((healthy+=${result}))
d1681e
+    done
d1681e
+
d1681e
+    grep -E "\):\ Stopped|FAILED" > /dev/null 2>&1 ${scratch}
d1681e
+    result=$?
d1681e
+
d1681e
+    if [ ${result} -eq 0 ]; then
d1681e
+        echo "Cluster HA Status: BAD"
d1681e
+    elif [ ${healthy} -eq 0 ]; then
d1681e
+        echo "Cluster HA Status: HEALTHY"
d1681e
+    else
d1681e
+        echo "Cluster HA Status: FAILOVER"
d1681e
+    fi
d1681e
+
d1681e
+    rm -f ${scratch}
d1681e
+}
d1681e
+
d1681e
+create_ganesha_conf_file()
d1681e
+{
d1681e
+        if [ $1 == "yes" ];
d1681e
+        then
d1681e
+                if [  -e $GANESHA_CONF ];
d1681e
+                then
d1681e
+                        rm -rf $GANESHA_CONF
d1681e
+                fi
d1681e
+        # The symlink /etc/ganesha/ganesha.conf need to be
d1681e
+        # created using ganesha conf file mentioned in the
d1681e
+        # shared storage. Every node will only have this
d1681e
+        # link and actual file will stored in shared storage,
d1681e
+        # so that ganesha conf editing of ganesha conf will
d1681e
+        # be easy as well as it become more consistent.
d1681e
+
d1681e
+                ln -s $HA_CONFDIR/ganesha.conf $GANESHA_CONF
d1681e
+        else
d1681e
+        # Restoring previous file
d1681e
+                rm -rf $GANESHA_CONF
d1681e
+                cp $HA_CONFDIR/ganesha.conf $GANESHA_CONF
d1681e
+                sed -r -i -e '/^%include[[:space:]]+".+\.conf"$/d' $GANESHA_CONF
d1681e
+        fi
d1681e
+}
d1681e
+
d1681e
+set_quorum_policy()
d1681e
+{
d1681e
+    local quorum_policy="stop"
d1681e
+    local num_servers=${1}
d1681e
+
d1681e
+    if [ ${num_servers} -lt 3 ]; then
d1681e
+        quorum_policy="ignore"
d1681e
+    fi
d1681e
+    pcs property set no-quorum-policy=${quorum_policy}
d1681e
+    if [ $? -ne 0 ]; then
d1681e
+        logger "warning: pcs property set no-quorum-policy=${quorum_policy} failed"
d1681e
+    fi
d1681e
+}
d1681e
+
d1681e
+main()
d1681e
+{
d1681e
+
d1681e
+    local cmd=${1}; shift
d1681e
+    if [[ ${cmd} == *help ]]; then
d1681e
+        usage
d1681e
+        exit 0
d1681e
+    fi
d1681e
+    HA_CONFDIR=${1%/}; shift
d1681e
+    local ha_conf=${HA_CONFDIR}/ganesha-ha.conf
d1681e
+    local node=""
d1681e
+    local vip=""
d1681e
+
d1681e
+    # ignore any comment lines
d1681e
+    cfgline=$(grep  ^HA_NAME= ${ha_conf})
d1681e
+    eval $(echo ${cfgline} | grep -F HA_NAME=)
d1681e
+    cfgline=$(grep  ^HA_CLUSTER_NODES= ${ha_conf})
d1681e
+    eval $(echo ${cfgline} | grep -F HA_CLUSTER_NODES=)
d1681e
+
d1681e
+    case "${cmd}" in
d1681e
+
d1681e
+    setup | --setup)
d1681e
+        logger "setting up ${HA_NAME}"
d1681e
+
d1681e
+        check_cluster_exists ${HA_NAME}
d1681e
+
d1681e
+        determine_servers "setup"
d1681e
+
d1681e
+        if [ "X${HA_NUM_SERVERS}X" != "X1X" ]; then
d1681e
+
d1681e
+            setup_cluster ${HA_NAME} ${HA_NUM_SERVERS} "${HA_SERVERS}"
d1681e
+
d1681e
+            setup_create_resources ${HA_SERVERS}
d1681e
+
d1681e
+            setup_finalize_ha
d1681e
+
d1681e
+            setup_state_volume ${HA_SERVERS}
d1681e
+
d1681e
+        else
d1681e
+
d1681e
+            logger "insufficient servers for HA, aborting"
d1681e
+        fi
d1681e
+        ;;
d1681e
+
d1681e
+    teardown | --teardown)
d1681e
+        logger "tearing down ${HA_NAME}"
d1681e
+
d1681e
+        determine_servers "teardown"
d1681e
+
d1681e
+        teardown_resources ${HA_SERVERS}
d1681e
+
d1681e
+        teardown_cluster ${HA_NAME}
d1681e
+
d1681e
+        cleanup_ganesha_config ${HA_CONFDIR}
d1681e
+        ;;
d1681e
+
d1681e
+    cleanup | --cleanup)
d1681e
+        cleanup_ganesha_config ${HA_CONFDIR}
d1681e
+        ;;
d1681e
+
d1681e
+    add | --add)
d1681e
+        node=${1}; shift
d1681e
+        vip=${1}; shift
d1681e
+
d1681e
+        logger "adding ${node} with ${vip} to ${HA_NAME}"
d1681e
+
d1681e
+        determine_service_manager
d1681e
+
d1681e
+        manage_service "start" ${node}
d1681e
+
d1681e
+        determine_servers "add"
d1681e
+
d1681e
+        pcs cluster node add ${node}
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning: pcs cluster node add ${node} failed"
d1681e
+        fi
d1681e
+
d1681e
+        addnode_create_resources ${node} ${vip}
d1681e
+        # Subsequent add-node recreates resources for all the nodes
d1681e
+        # that already exist in the cluster. The nodes are picked up
d1681e
+        # from the entries in the ganesha-ha.conf file. Adding the
d1681e
+        # newly added node to the file so that the resources specfic
d1681e
+        # to this node is correctly recreated in the future.
d1681e
+        clean_node=${node//[-.]/_}
d1681e
+        echo "VIP_${node}=\"${vip}\"" >> ${HA_CONFDIR}/ganesha-ha.conf
d1681e
+
d1681e
+        NEW_NODES="$HA_CLUSTER_NODES,${node}"
d1681e
+
d1681e
+        sed -i s/HA_CLUSTER_NODES.*/"HA_CLUSTER_NODES=\"$NEW_NODES\""/ \
d1681e
+$HA_CONFDIR/ganesha-ha.conf
d1681e
+
d1681e
+        addnode_state_volume ${node}
d1681e
+
d1681e
+        # addnode_create_resources() already appended ${node} to
d1681e
+        # HA_SERVERS, so only need to increment HA_NUM_SERVERS
d1681e
+        # and set quorum policy
d1681e
+        HA_NUM_SERVERS=$(expr ${HA_NUM_SERVERS} + 1)
d1681e
+        set_quorum_policy ${HA_NUM_SERVERS}
d1681e
+        ;;
d1681e
+
d1681e
+    delete | --delete)
d1681e
+        node=${1}; shift
d1681e
+
d1681e
+        logger "deleting ${node} from ${HA_NAME}"
d1681e
+
d1681e
+        determine_servers "delete"
d1681e
+
d1681e
+        deletenode_delete_resources ${node}
d1681e
+
d1681e
+        pcs cluster node remove ${node}
d1681e
+        if [ $? -ne 0 ]; then
d1681e
+            logger "warning: pcs cluster node remove ${node} failed"
d1681e
+        fi
d1681e
+
d1681e
+        deletenode_update_haconfig ${node}
d1681e
+
d1681e
+        delnode_state_volume ${node}
d1681e
+
d1681e
+        determine_service_manager
d1681e
+
d1681e
+        manage_service "stop" ${node}
d1681e
+
d1681e
+        HA_NUM_SERVERS=$(expr ${HA_NUM_SERVERS} - 1)
d1681e
+        set_quorum_policy ${HA_NUM_SERVERS}
d1681e
+        ;;
d1681e
+
d1681e
+    status | --status)
d1681e
+        determine_servers "status"
d1681e
+
d1681e
+        status ${HA_SERVERS}
d1681e
+        ;;
d1681e
+
d1681e
+    refresh-config | --refresh-config)
d1681e
+        VOL=${1}
d1681e
+
d1681e
+        determine_servers "refresh-config"
d1681e
+
d1681e
+        refresh_config ${VOL} ${HA_CONFDIR} ${HA_SERVERS}
d1681e
+        ;;
d1681e
+
d1681e
+    setup-ganesha-conf-files | --setup-ganesha-conf-files)
d1681e
+
d1681e
+        create_ganesha_conf_file ${1}
d1681e
+        ;;
d1681e
+
d1681e
+    *)
d1681e
+        # setup and teardown are not intended to be used by a
d1681e
+        # casual user
d1681e
+        usage
d1681e
+        logger "Usage: ganesha-ha.sh add|delete|status"
d1681e
+        ;;
d1681e
+
d1681e
+    esac
d1681e
+}
d1681e
+
d1681e
+main $*
d1681e
diff --git a/glusterfs.spec.in b/glusterfs.spec.in
74b1de
index dd7438c..d748ebc 100644
d1681e
--- a/glusterfs.spec.in
d1681e
+++ b/glusterfs.spec.in
74b1de
@@ -460,7 +460,8 @@ Summary:          NFS-Ganesha configuration
d1681e
 Group:            Applications/File
d1681e
 
d1681e
 Requires:         %{name}-server%{?_isa} = %{version}-%{release}
d1681e
-Requires:         nfs-ganesha-gluster, pcs, dbus
d1681e
+Requires:         nfs-ganesha-gluster >= 2.4.1
d1681e
+Requires:         pcs, dbus
d1681e
 %if ( 0%{?rhel} && 0%{?rhel} == 6 )
d1681e
 Requires:         cman, pacemaker, corosync
d1681e
 %endif
74b1de
@@ -1138,6 +1139,7 @@ exit 0
74b1de
 #exclude ganesha related files
74b1de
 %exclude %{_sysconfdir}/ganesha/*
74b1de
 %exclude %{_libexecdir}/ganesha/*
74b1de
+%exclude %{_prefix}/lib/ocf/resource.d/heartbeat/*
74b1de
 %endif
74b1de
 
74b1de
 %files api
74b1de
@@ -1306,6 +1308,7 @@ exit 0
d1681e
 %files ganesha
d1681e
 %{_sysconfdir}/ganesha/*
d1681e
 %{_libexecdir}/ganesha/*
d1681e
+%{_prefix}/lib/ocf/resource.d/heartbeat/*
d1681e
 %endif
d1681e
 
74b1de
 %if ( 0%{!?_without_ocf:1} )
74b1de
@@ -1904,6 +1907,9 @@ fi
74b1de
 %endif
74b1de
 
74b1de
 %changelog
74b1de
+* Sat Apr 6 2019 Jiffin Tony Thottan <jthottan@redhat.com>
74b1de
+- Adding ganesha ha resources back in gluster repository
74b1de
+
74b1de
 * Fri Apr 5 2019 Jiffin Tony Thottan <jthottan@redhat.com>
74b1de
 - Adding ganesha bits back in gluster repository
74b1de
 
d1681e
-- 
d1681e
1.8.3.1
d1681e