diff --git a/modules/ha/cluster-config.nix b/modules/ha/cluster-config.nix index 76ad56b..0c7003b 100644 --- a/modules/ha/cluster-config.nix +++ b/modules/ha/cluster-config.nix @@ -21,7 +21,26 @@ # STONITH device during the testing phase. Switch to resource-and-stonith # once the fence_pve_ssh STONITH resource is active (see # scripts/ha/cluster-enable-stonith.sh). -{ lib, vars, ... }: +# +# PATH wrapper: when the DRBD kernel module invokes the fence-peer handler +# via the UMH (User Mode Helper) mechanism it provides a minimal PATH that +# omits /run/current-system/sw/bin. crm-fence-peer.sh calls cibadmin, +# crm_mon etc.; if those aren't found a pipeline in the script breaks with +# SIGPIPE. A process killed by signal has WEXITSTATUS() == 0, so the kernel +# sees exit code 0 and logs "fence-peer helper broken, returned 0", looping +# forever. The writeShellScript wrappers below prepend the NixOS sw path +# before exec-ing the real handler, giving it a working Pacemaker toolchain. +{ lib, pkgs, vars, ... }: +let + fencePeerWrapper = pkgs.writeShellScript "drbd-fence-peer" '' + export PATH="/run/current-system/sw/bin:/run/current-system/sw/sbin:$PATH" + exec /run/current-system/sw/lib/drbd/crm-fence-peer.sh "$@" + ''; + unfencePeerWrapper = pkgs.writeShellScript "drbd-unfence-peer" '' + export PATH="/run/current-system/sw/bin:/run/current-system/sw/sbin:$PATH" + exec /run/current-system/sw/lib/drbd/crm-unfence-peer.sh "$@" + ''; +in { # Root SSH access — same key set as nixos user so all admin keys can reach root. users.users.root.openssh.authorizedKeys.keys = [ @@ -62,8 +81,8 @@ fencing resource-only; } handlers { - fence-peer "/run/current-system/sw/lib/drbd/crm-fence-peer.sh"; - unfence-peer "/run/current-system/sw/lib/drbd/crm-unfence-peer.sh"; + fence-peer "${fencePeerWrapper}"; + unfence-peer "${unfencePeerWrapper}"; } }