#!/bin/sh
#
# Copyright (C) 2026 Nethesis S.r.l.
# SPDX-License-Identifier: GPL-2.0-only
#
# Acquire a global serialization lock for keepalived state-transition events
# (NOTIFY_MASTER, NOTIFY_BACKUP, NOTIFY_FAULT, NOTIFY_STOP) to prevent
# concurrent hotplug chains from racing when keepalived transitions happen in
# quick succession.
#
# The lock is released by 999-unlock at the end of the hotplug chain.
# Because hotplug-call sources each script in a subshell, a flag file is used
# to communicate whether the lock was actually acquired to 999-unlock.
#
# On timeout (60 s) the event proceeds with a warning rather than being dropped,
# to avoid leaving the system in an inconsistent state.

case "$ACTION" in
	NOTIFY_MASTER|NOTIFY_BACKUP|NOTIFY_FAULT|NOTIFY_STOP) ;;
	*) return 0 2>/dev/null || exit 0 ;;
esac

LOCKFILE="/var/lock/keepalived-hotplug.lock"
ACQUIRED_FLAG="/var/lock/keepalived-hotplug-acquired"
TIMEOUT=$(uci -q get keepalived.globals.ns_lock_timeout)
elapsed=0

if [ -z "$TIMEOUT" ] || [ "$TIMEOUT" -le 0 ]; then
	# Locking disabled by configuration
	return 0 2>/dev/null || exit 0
fi

while [ "$elapsed" -lt "$TIMEOUT" ]; do
	if lock -n "$LOCKFILE" > /dev/null 2>&1; then
		touch "$ACQUIRED_FLAG"
		return 0 2>/dev/null || exit 0
	fi
	sleep 1
	elapsed=$((elapsed + 1))
done

logger -t ns-ha "WARNING: lock timeout after ${TIMEOUT}s waiting for previous $ACTION event to complete, proceeding anyway"
