Blame SOURCES/bz2014415-nfsserver-add-nfs_server_scope-parameter.patch

e87a70
From 764dacb6195f8940f13b9c322b1bc8189c5619fc Mon Sep 17 00:00:00 2001
e87a70
From: Lars Ellenberg <lars.ellenberg@linbit.com>
e87a70
Date: Mon, 6 Sep 2021 12:13:42 +0200
e87a70
Subject: [PATCH 1/6] Fix NFSv4 lock failover: set NFS Server Scope
e87a70
e87a70
Problem: https://github.com/ClusterLabs/resource-agents/issues/1644
e87a70
RFC8881, 8.4.2.1 State Reclaim:
e87a70
e87a70
| If the server scope is different, the client should not attempt to
e87a70
| reclaim locks. In this situation, no lock reclaim is possible.
e87a70
| Any attempt to re-obtain the locks with non-reclaim operations is
e87a70
| problematic since there is no guarantee that the existing
e87a70
| filehandles will be recognized by the new server, or that if
e87a70
| recognized, they denote the same objects. It is best to treat the
e87a70
| locks as having been revoked by the reconfiguration event.
e87a70
e87a70
That's why for lock reclaim to even be attempted, we have to define and set
e87a70
the same server scope for NFSD on all cluster nodes in the NFS failover
e87a70
cluster. And in linux, that is done by setting the uts nodename for the
e87a70
command that starts the nfsd kernel threads.
e87a70
e87a70
For "init scripts", just set it directly using unshare --uts.
e87a70
For systemd units, add NFS_SERVER_SCOPE to some environment files
e87a70
and inject the "unshare --uts" into the ExecStart command lines
e87a70
using override drop-in files.
e87a70
---
e87a70
 heartbeat/nfsserver | 120 +++++++++++++++++++++++++++++++++++++++++++-
e87a70
 1 file changed, 119 insertions(+), 1 deletion(-)
e87a70
e87a70
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
e87a70
index 96b19abe36..0888378645 100755
e87a70
--- a/heartbeat/nfsserver
e87a70
+++ b/heartbeat/nfsserver
e87a70
@@ -5,6 +5,18 @@
e87a70
 # by hxinwei@gmail.com
e87a70
 # License: GNU General Public License v2 (GPLv2) and later
e87a70
 
e87a70
+
e87a70
+# I don't know for certain whether all services actuall _need_ this,
e87a70
+# I know that at least nfs-server needs it.
e87a70
+# The rgmanager resource agent in rgmanager/src/resources/nfsserver.sh.in
e87a70
+# did the unshare for gssd and idmapd as well, even though it seems unclear why.
e87a70
+# Let's start with just the nfs-server, and add others if/when we have clear
e87a70
+# indication they need it.
e87a70
+#NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-idmapd.service nfs-mountd.service nfs-server.service nfsdcld.service rpc-gssd.service rpc-statd.service rpcbind.service"
e87a70
+NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-server.service"
e87a70
+SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE=/run/sysconfig/nfs-server-scope
e87a70
+SYSTEMD_UNSHARE_UTS_DROPIN=51-resource-agents-unshare-uts.conf
e87a70
+
e87a70
 if [ -n "$OCF_DEBUG_LIBRARY" ]; then
e87a70
     . $OCF_DEBUG_LIBRARY
e87a70
 else
e87a70
@@ -99,6 +111,31 @@ Specifies the length of sm-notify retry time (minutes).
e87a70
 <content type="integer" default="" />
e87a70
 </parameter>
e87a70
 
e87a70
+<parameter name="nfs_server_scope" unique="0" required="0">
e87a70
+<longdesc lang="en">
e87a70
+RFC8881, 8.4.2.1 State Reclaim:
e87a70
+
e87a70
+If the server scope is different, the client should not attempt to
e87a70
+reclaim locks. In this situation, no lock reclaim is possible.
e87a70
+Any attempt to re-obtain the locks with non-reclaim operations is
e87a70
+problematic since there is no guarantee that the existing
e87a70
+filehandles will be recognized by the new server, or that if
e87a70
+recognized, they denote the same objects. It is best to treat the
e87a70
+locks as having been revoked by the reconfiguration event.
e87a70
+
e87a70
+For lock reclaim to even be attempted, we have to define and set the same
e87a70
+server scope for NFSD on all cluster nodes in the NFS failover cluster.
e87a70
+
e87a70
+This agent won't "guess" a suitable server scope name for you, you need to
e87a70
+explicitly specify this. But without it, NFSv4 lock reclaim after failover
e87a70
+won't work properly.  Suggested value: the failover "service IP".
e87a70
+</longdesc>
e87a70
+<shortdesc lang="en">
e87a70
+RFC8881 NFS server scope for (lock) state reclaim after failover.
e87a70
+</shortdesc>
e87a70
+<content type="string"/>
e87a70
+</parameter>
e87a70
+
e87a70
 <parameter name="nfs_ip" unique="0" required="0">
e87a70
 <longdesc lang="en">
e87a70
 Comma separated list of floating IP addresses used to access the nfs service
e87a70
@@ -269,7 +306,11 @@ nfs_exec()
e87a70
 	set_exec_mode
e87a70
 
e87a70
 	case $EXEC_MODE in 
e87a70
-		1) ${OCF_RESKEY_nfs_init_script} $cmd;;
e87a70
+		1) if [ -z "$OCF_RESKEY_nfs_server_scope" ] ; then
e87a70
+			${OCF_RESKEY_nfs_init_script} $cmd
e87a70
+		   else
e87a70
+			unshare -u /bin/sh -c "hostname ${OCF_RESKEY_nfs_server_scope}; exec ${OCF_RESKEY_nfs_init_script} $cmd"
e87a70
+		   fi ;;
e87a70
 		2) if ! echo $svc | grep -q "\."; then
e87a70
 			svc="${svc}.service"
e87a70
 		   fi
e87a70
@@ -623,6 +664,74 @@ notify_locks()
e87a70
 	fi
e87a70
 }
e87a70
 
e87a70
+# Problem: https://github.com/ClusterLabs/resource-agents/issues/1644
e87a70
+# RFC8881, 8.4.2.1 State Reclaim:
e87a70
+#
e87a70
+# | If the server scope is different, the client should not attempt to
e87a70
+# | reclaim locks. In this situation, no lock reclaim is possible.
e87a70
+# | Any attempt to re-obtain the locks with non-reclaim operations is
e87a70
+# | problematic since there is no guarantee that the existing
e87a70
+# | filehandles will be recognized by the new server, or that if
e87a70
+# | recognized, they denote the same objects. It is best to treat the
e87a70
+# | locks as having been revoked by the reconfiguration event.
e87a70
+#
e87a70
+# That's why for lock reclaim to even be attempted, we have to define and set
e87a70
+# the same server scope for NFSD on all cluster nodes in the NFS failover
e87a70
+# cluster. And in linux, that is done by setting the uts nodename for the
e87a70
+# command that starts the nfsd kernel threads.
e87a70
+#
e87a70
+inject_unshare_uts_name_into_systemd_units ()
e87a70
+{
e87a70
+	local END_TAG="# END OF DROP-IN FOR NFS SERVER SCOPE"
e87a70
+	local services
e87a70
+	services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE | cut -d ' ' -f1)
e87a70
+
e87a70
+	local svc dir dropin edited_exec_start do_reload=false
e87a70
+	for svc in $services ; do
e87a70
+		dir=/run/systemd/system/$svc.d
e87a70
+		dropin=$dir/$SYSTEMD_UNSHARE_UTS_DROPIN
e87a70
+		grep -sqF "$END_TAG" "$dropin" && continue
e87a70
+
e87a70
+		test -d "$dir" || mkdir -p "$dir"
e87a70
+		test -e "$dropin" && rm -f "$dropin"
e87a70
+
e87a70
+		edited_exec_start=$(systemctl cat $svc | sed -ne "s#^ExecStart=\\(.*\\)#ExecStart=/usr/bin/unshare --uts /bin/sh -ec 'hostname \${NFS_SERVER_SCOPE}; exec \"\$@\"' -- \\1#p")
e87a70
+		cat > "$dropin" <<___
e87a70
+[Service]
e87a70
+EnvironmentFile=$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE
e87a70
+# reset list of exec start, then re-populate with unshared uts namespace
e87a70
+ExecStart=
e87a70
+$edited_exec_start
e87a70
+$END_TAG
e87a70
+___
e87a70
+		do_reload=true
e87a70
+		ocf_log debug "injected unshare --uts into $dropin"
e87a70
+	done
e87a70
+
e87a70
+	mkdir -p "${SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE%/*}"
e87a70
+	echo "NFS_SERVER_SCOPE=$OCF_RESKEY_nfs_server_scope" > "$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE"
e87a70
+
e87a70
+	$do_reload && systemctl daemon-reload
e87a70
+}
e87a70
+
e87a70
+remove_unshare_uts_dropins ()
e87a70
+{
e87a70
+	local services
e87a70
+	services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE)
e87a70
+
e87a70
+	local svc dir dropin do_reload=false
e87a70
+	for svc in $services ; do
e87a70
+		dir=/run/systemd/system/$svc.d
e87a70
+		dropin=$dir/$SYSTEMD_UNSHARE_UTS_DROPIN
e87a70
+		test -e "$dropin" || continue
e87a70
+		rm -f "$dropin"
e87a70
+		do_reload=true
e87a70
+		ocf_log debug "removed unshare --uts from $svc"
e87a70
+	done
e87a70
+	rm -f "${SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE}"
e87a70
+	$do_reload && systemctl daemon-reload
e87a70
+}
e87a70
+
e87a70
 nfsserver_start ()
e87a70
 {
e87a70
 	local rc;
e87a70
@@ -636,6 +745,13 @@ nfsserver_start ()
e87a70
 	is_redhat_based && set_env_args
e87a70
 	bind_tree
e87a70
 	prepare_directory
e87a70
+	case $EXEC_MODE in [23])
e87a70
+		if [ -z "$OCF_RESKEY_nfs_server_scope" ] ; then
e87a70
+			remove_unshare_uts_dropins
e87a70
+		else
e87a70
+			inject_unshare_uts_name_into_systemd_units
e87a70
+		fi ;;
e87a70
+	esac
e87a70
 
e87a70
 	if ! `mount | grep -q " on $OCF_RESKEY_rpcpipefs_dir "`; then
e87a70
 		mount -t rpc_pipefs sunrpc $OCF_RESKEY_rpcpipefs_dir
e87a70
@@ -854,6 +970,8 @@ nfsserver_stop ()
e87a70
 		ocf_log info "NFS server stopped"
e87a70
 	fi
e87a70
 
e87a70
+	case $EXEC_MODE in [23]) remove_unshare_uts_dropins;; esac
e87a70
+
e87a70
 	return $rc
e87a70
 }
e87a70
 
e87a70
e87a70
From 515697b53c1614d05d39491c9af83e8d8b844b17 Mon Sep 17 00:00:00 2001
e87a70
From: Lars Ellenberg <lars.ellenberg@linbit.com>
e87a70
Date: Fri, 8 Oct 2021 12:01:41 +0200
e87a70
Subject: [PATCH 2/6] Fix NFSv4 lock failover: set NFS Server Scope, regardless
e87a70
 of EXEC_MODE
e87a70
e87a70
Debian (and other systems) may provide "init scripts",
e87a70
which will only redirect back to systemd.
e87a70
e87a70
If we just unshare --uts the init script invocation,
e87a70
the uts namespace is useless in that case.
e87a70
e87a70
If systemd is running, mangle the nfs-server.service unit,
e87a70
independent of the "EXEC_MODE".
e87a70
---
e87a70
 heartbeat/nfsserver | 18 ++++++++++++++----
e87a70
 1 file changed, 14 insertions(+), 4 deletions(-)
e87a70
e87a70
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
e87a70
index 0888378645..054aabbaf6 100755
e87a70
--- a/heartbeat/nfsserver
e87a70
+++ b/heartbeat/nfsserver
e87a70
@@ -745,13 +745,20 @@ nfsserver_start ()
e87a70
 	is_redhat_based && set_env_args
e87a70
 	bind_tree
e87a70
 	prepare_directory
e87a70
-	case $EXEC_MODE in [23])
e87a70
+
e87a70
+	# Debian (and other systems) may provide "init scripts",
e87a70
+	# which will only redirect back to systemd.
e87a70
+	# If we just unshare --uts the init script invocation,
e87a70
+	# the uts namespace is useless in that case.
e87a70
+	# If systemd is running, mangle the nfs-server.service unit,
e87a70
+	# independent of the "EXEC_MODE" we detected.
e87a70
+	if $systemd_is_running ; then
e87a70
 		if [ -z "$OCF_RESKEY_nfs_server_scope" ] ; then
e87a70
 			remove_unshare_uts_dropins
e87a70
 		else
e87a70
 			inject_unshare_uts_name_into_systemd_units
e87a70
-		fi ;;
e87a70
-	esac
e87a70
+		fi
e87a70
+	fi
e87a70
 
e87a70
 	if ! `mount | grep -q " on $OCF_RESKEY_rpcpipefs_dir "`; then
e87a70
 		mount -t rpc_pipefs sunrpc $OCF_RESKEY_rpcpipefs_dir
e87a70
@@ -970,7 +977,9 @@ nfsserver_stop ()
e87a70
 		ocf_log info "NFS server stopped"
e87a70
 	fi
e87a70
 
e87a70
-	case $EXEC_MODE in [23]) remove_unshare_uts_dropins;; esac
e87a70
+	if $systemd_is_running; then
e87a70
+		remove_unshare_uts_dropins
e87a70
+	fi
e87a70
 
e87a70
 	return $rc
e87a70
 }
e87a70
@@ -1008,6 +1017,7 @@ nfsserver_validate ()
e87a70
 }
e87a70
 
e87a70
 nfsserver_validate
e87a70
+systemd_is_running && systemd_is_running=true || systemd_is_running=false
e87a70
 
e87a70
 case $__OCF_ACTION in
e87a70
 	start)      nfsserver_start
e87a70
e87a70
From e83c20d88f404f9f9d829c654883d60eb6cc9ff3 Mon Sep 17 00:00:00 2001
e87a70
From: Lars Ellenberg <lars.ellenberg@linbit.com>
e87a70
Date: Fri, 8 Oct 2021 17:06:18 +0200
e87a70
Subject: [PATCH 3/6] Fix NFSv4 lock failover: add missing "|cut -f1" in
e87a70
 remove_unshare_uts_dropins
e87a70
e87a70
---
e87a70
 heartbeat/nfsserver | 2 +-
e87a70
 1 file changed, 1 insertion(+), 1 deletion(-)
e87a70
e87a70
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
e87a70
index 054aabbaf6..d3db89a537 100755
e87a70
--- a/heartbeat/nfsserver
e87a70
+++ b/heartbeat/nfsserver
e87a70
@@ -717,7 +717,7 @@ ___
e87a70
 remove_unshare_uts_dropins ()
e87a70
 {
e87a70
 	local services
e87a70
-	services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE)
e87a70
+	services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE | cut -d ' ' -f1)
e87a70
 
e87a70
 	local svc dir dropin do_reload=false
e87a70
 	for svc in $services ; do
e87a70
e87a70
From b5b0e4a0b60d285af576b2d8ecfbe95e5a177a87 Mon Sep 17 00:00:00 2001
e87a70
From: Lars Ellenberg <lars.ellenberg@linbit.com>
e87a70
Date: Fri, 8 Oct 2021 17:07:13 +0200
e87a70
Subject: [PATCH 4/6] Fix NFSv4 lock failover: get rid of "world-inaccessible"
e87a70
 warning
e87a70
e87a70
by temporarily changing the umask before generating the dropins
e87a70
---
e87a70
 heartbeat/nfsserver | 3 +++
e87a70
 1 file changed, 3 insertions(+)
e87a70
e87a70
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
e87a70
index d3db89a537..447e0302b2 100755
e87a70
--- a/heartbeat/nfsserver
e87a70
+++ b/heartbeat/nfsserver
e87a70
@@ -687,6 +687,8 @@ inject_unshare_uts_name_into_systemd_units ()
e87a70
 	services=$(systemctl list-unit-files --no-legend $NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE | cut -d ' ' -f1)
e87a70
 
e87a70
 	local svc dir dropin edited_exec_start do_reload=false
e87a70
+	local old_umask=$(umask)
e87a70
+	umask 0022
e87a70
 	for svc in $services ; do
e87a70
 		dir=/run/systemd/system/$svc.d
e87a70
 		dropin=$dir/$SYSTEMD_UNSHARE_UTS_DROPIN
e87a70
@@ -710,6 +712,7 @@ ___
e87a70
 
e87a70
 	mkdir -p "${SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE%/*}"
e87a70
 	echo "NFS_SERVER_SCOPE=$OCF_RESKEY_nfs_server_scope" > "$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE"
e87a70
+	umask $old_umask
e87a70
 
e87a70
 	$do_reload && systemctl daemon-reload
e87a70
 }
e87a70
e87a70
From 3c6c91ce5a00eeef9cd766389d73a0b42580a1e6 Mon Sep 17 00:00:00 2001
e87a70
From: Lars Ellenberg <lars.ellenberg@linbit.com>
e87a70
Date: Fri, 8 Oct 2021 17:08:09 +0200
e87a70
Subject: [PATCH 5/6] Fix NFSv4 lock failover: deal with "special executable
e87a70
 prefix" chars in ExecStart
e87a70
e87a70
---
e87a70
 heartbeat/nfsserver | 2 +-
e87a70
 1 file changed, 1 insertion(+), 1 deletion(-)
e87a70
e87a70
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
e87a70
index 447e0302b2..5326bd2c6e 100755
e87a70
--- a/heartbeat/nfsserver
e87a70
+++ b/heartbeat/nfsserver
e87a70
@@ -697,7 +697,7 @@ inject_unshare_uts_name_into_systemd_units ()
e87a70
 		test -d "$dir" || mkdir -p "$dir"
e87a70
 		test -e "$dropin" && rm -f "$dropin"
e87a70
 
e87a70
-		edited_exec_start=$(systemctl cat $svc | sed -ne "s#^ExecStart=\\(.*\\)#ExecStart=/usr/bin/unshare --uts /bin/sh -ec 'hostname \${NFS_SERVER_SCOPE}; exec \"\$@\"' -- \\1#p")
e87a70
+		edited_exec_start=$(systemctl cat $svc | sed -ne "s#^ExecStart=\\([-+:!@]*\\)\\(.*\\)#ExecStart=\\1/usr/bin/unshare --uts /bin/sh -c 'hostname \${NFS_SERVER_SCOPE}; exec \"\$@\"' -- \\2#p")
e87a70
 		cat > "$dropin" <<___
e87a70
 [Service]
e87a70
 EnvironmentFile=$SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE
e87a70
e87a70
From 512fbaf61e6d24a1236ef50e323ea17a62485c36 Mon Sep 17 00:00:00 2001
e87a70
From: Lars Ellenberg <lars.ellenberg@linbit.com>
e87a70
Date: Fri, 8 Oct 2021 17:08:59 +0200
e87a70
Subject: [PATCH 6/6] Fix NFSv4 lock failover: add rpc-statd-notify to the
e87a70
 comment list of potentially interesting services
e87a70
e87a70
---
e87a70
 heartbeat/nfsserver | 2 +-
e87a70
 1 file changed, 1 insertion(+), 1 deletion(-)
e87a70
e87a70
diff --git a/heartbeat/nfsserver b/heartbeat/nfsserver
e87a70
index 5326bd2c6e..240dd1a76c 100755
e87a70
--- a/heartbeat/nfsserver
e87a70
+++ b/heartbeat/nfsserver
e87a70
@@ -12,7 +12,7 @@
e87a70
 # did the unshare for gssd and idmapd as well, even though it seems unclear why.
e87a70
 # Let's start with just the nfs-server, and add others if/when we have clear
e87a70
 # indication they need it.
e87a70
-#NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-idmapd.service nfs-mountd.service nfs-server.service nfsdcld.service rpc-gssd.service rpc-statd.service rpcbind.service"
e87a70
+#NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-idmapd.service nfs-mountd.service nfs-server.service nfsdcld.service rpc-gssd.service rpc-statd.service rpc-statd-notify.service rpcbind.service"
e87a70
 NFSD_RELATED_SYSTEMD_SERVICE_FOR_UNSHARE_UTS_NAMESPACE="nfs-server.service"
e87a70
 SYSTEMD_ENVIRONMENT_FILE_NFS_SERVER_SCOPE=/run/sysconfig/nfs-server-scope
e87a70
 SYSTEMD_UNSHARE_UTS_DROPIN=51-resource-agents-unshare-uts.conf