From 33398a38aacc02c89c277f5106c079b9c61b97a2 Mon Sep 17 00:00:00 2001 From: Jaymin Patel Date: Fri, 9 Sep 2022 19:10:49 +0530 Subject: 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 --- .../files/lib/functions/keepalived/common.sh | 47 ++++ .../files/lib/functions/keepalived/hotplug.sh | 257 +++++++++++++++++++++ 2 files changed, 304 insertions(+) create mode 100644 net/keepalived/files/lib/functions/keepalived/common.sh create mode 100644 net/keepalived/files/lib/functions/keepalived/hotplug.sh (limited to 'net/keepalived/files/lib') diff --git a/net/keepalived/files/lib/functions/keepalived/common.sh b/net/keepalived/files/lib/functions/keepalived/common.sh new file mode 100644 index 000000000..bca57a214 --- /dev/null +++ b/net/keepalived/files/lib/functions/keepalived/common.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# shellcheck disable=SC2039 + +__FILE__="$(basename "$0")" + +KEEPALIVED_USER=keepalived +KEEPALIVED_DEBUG=0 + +__function__() { + type "$1" > /dev/null 2>&1 +} + +log() { + local facility=$1 + shift + logger -t "${__FILE__}[$$]" -p "$facility" "$*" +} + +log_info() { + log info "$*" +} + +log_debug() { + [ "$KEEPALIVED_DEBUG" = "0" ] && return + log debug "$*" +} + +log_notice() { + log notice "$*" +} + +log_warn() { + log warn "$*" +} + +log_err() { + log err "$*" +} + +get_rsync_user() { + echo "$KEEPALIVED_USER" +} + +get_rsync_user_home() { + awk -F: "/^$KEEPALIVED_USER/{print \$6}" /etc/passwd +} diff --git a/net/keepalived/files/lib/functions/keepalived/hotplug.sh b/net/keepalived/files/lib/functions/keepalived/hotplug.sh new file mode 100644 index 000000000..8691872c6 --- /dev/null +++ b/net/keepalived/files/lib/functions/keepalived/hotplug.sh @@ -0,0 +1,257 @@ +#!/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 +} -- cgit v1.2.3