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

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