packages/net/keepalived/files/lib/functions/keepalived/hotplug.sh
Jaymin Patel 33398a38aa keepalived: high-availability files and data sync
add new package keepalived-sync to synchronize files and data
between master and backup node. The master node uses SSH over rsync
to send and the backup node will use inotifywatch to watch received files.

The master node can track rsync.sh script to send configuration file on
a backup node based on the vrrp_script configuration of the same script.

The backup node will have a keepalived-inotify service, which would watch
for newly received files and it would call hotplug event. Each service
can keep its respective script under the keepalived hotplug directory and
executes commands to stop, start service or update any config in real-time.

Whenever a switchover will happen, the backup node would have the latest
config and data files from the master node.

Hotplug events can be used to apply config when files are received.

Signed-off-by: Jaymin Patel <jem.patel@gmail.com>
2022-10-13 16:57:02 +05:30

257 lines
4 KiB
Bash

#!/bin/sh
# shellcheck disable=SC2039
# shellcheck source=/dev/null
. /lib/functions/keepalived/common.sh
set_var() {
export "$1=$2"
}
get_var() {
eval echo "\"\${${1}}\""
}
get_var_flag() {
local value
value=$(get_var "$1")
value=${value:-0}
[ "$value" = "0" ] && return 1
return 0
}
_service() {
[ -z "$SERVICE_NAME" ] && return
local rc="/etc/init.d/$SERVICE_NAME"
[ ! -x "$rc" ] && return
case $1 in
start) $rc running || $rc start ;;
stop) $rc running && $rc stop ;;
reload)
if $rc running; then
$rc reload
else
$rc start
fi
;;
restart)
if $rc running; then
$rc restart
else
$rc start
fi
;;
esac
}
_start_service() {
_service start
}
_stop_service() {
_service stop
}
_restart_service() {
_service restart
}
_reload_service() {
_service reload
}
set_service_name() {
set_var SERVICE_NAME "$1"
}
add_sync_file() {
append SYNC_FILES_LIST "$1"
}
is_sync_file() {
list_contains SYNC_FILES_LIST "$1"
}
set_update_target() {
set_var UPDATE_TARGET "${1:-1}"
}
get_update_target() {
get_var UPDATE_TARGET
}
unset_update_target() {
set_var UPDATE_TARGET
}
is_update_target() {
get_var_flag UPDATE_TARGET
}
set_master_cb() {
set_var MASTER_CB "$1"
}
get_master_cb() {
get_var MASTER_CB
}
set_backup_cb() {
set_var BACKUP_CB "$1"
}
get_backup_cb() {
get_var BACKUP_CB
}
set_fault_cb() {
set_var FAULT_CB "$1"
}
get_fault_cb() {
get_var FAULT_CB
}
set_sync_cb() {
set_var SYNC_CB "$1"
}
get_sync_cb() {
get_var SYNC_CB
}
set_reload_if_master() {
set_var NOTIFY_MASTER_RELOAD 1
}
master_and_reload() {
get_var_flag NOTIFY_MASTER_RELOAD
}
set_restart_if_master() {
set_var NOTIFY_MASTER_RESTART 1
}
master_and_restart() {
get_var_flag NOTIFY_MASTER_RESTART
}
set_reload_if_backup() {
set_var NOTIFY_BACKUP_RELOAD 1
}
backup_and_reload() {
get_var_flag NOTIFY_BACKUP_RELOAD
}
set_stop_if_backup() {
set_var NOTIFY_BACKUP_STOP 1
}
backup_and_stop() {
get_var_flag NOTIFY_BACKUP_STOP 1
}
set_reload_if_sync() {
set_var NOTIFY_SYNC_RELOAD "${1:-1}"
}
get_reload_if_sync() {
get_var NOTIFY_SYNC_RELOAD
}
sync_and_reload() {
get_var_flag NOTIFY_SYNC_RELOAD
}
set_restart_if_sync() {
set_var NOTIFY_SYNC_RESTART 1
}
sync_and_restart() {
get_var_flag NOTIFY_SYNC_RESTART
}
_notify_master() {
if master_and_reload; then
log_debug "reload service $SERVICE_NAME"
_reload_service
elif master_and_restart; then
log_debug "restart service $SERVICE_NAME"
_restart_service
fi
}
_notify_backup() {
if backup_and_stop; then
log_debug "stop service $SERVICE_NAME"
_stop_service
elif backup_and_reload; then
log_debug "restart service $SERVICE_NAME"
_restart_service
fi
}
_notify_fault() {
return 0
}
_notify_sync() {
[ -z "$RSYNC_SOURCE" ] && return
[ -z "$RSYNC_TARGET" ] && return
if ! is_update_target; then
log_notice "skip $RSYNC_TARGET. Update target not set. To set use \"set_update_target 1\""
return
fi
is_sync_file "$RSYNC_TARGET" || return
if ! cp -a "$RSYNC_SOURCE" "$RSYNC_TARGET"; then
log_err "can not copy $RSYNC_SOURCE => $RSYNC_TARGET"
return
fi
log_debug "updated $RSYNC_SOURCE to $RSYNC_TARGET"
if sync_and_reload; then
log_debug "reload service $SERVICE_NAME"
_reload_service
elif sync_and_restart; then
log_debug "restart service $SERVICE_NAME"
_restart_service
fi
}
call_cb() {
[ $# -eq 0 ] && return
if __function__ "$1"; then
log_debug "calling function \"$1\""
"$1"
else
log_err "function \"$1\" not defined"
fi
}
keepalived_hotplug() {
[ -z "$(get_master_cb)" ] && set_master_cb _notify_master
[ -z "$(get_backup_cb)" ] && set_backup_cb _notify_backup
[ -z "$(get_fault_cb)" ] && set_fault_cb _notify_fault
[ -z "$(get_sync_cb)" ] && set_sync_cb _notify_sync
[ -z "$(get_update_target)" ] && set_update_target "$@"
[ -z "$(get_reload_if_sync)" ] && set_reload_if_sync "$@"
case $ACTION in
NOTIFY_MASTER) call_cb "$(get_master_cb)" ;;
NOTIFY_BACKUP) call_cb "$(get_backup_cb)" ;;
NOTIFY_FAULT) call_cb "$(get_fault_cb)" ;;
NOTIFY_SYNC) call_cb "$(get_sync_cb)" ;;
esac
}