lmn-client/tools/emitter
Andreas B. Mundt 202ca25466 Improve emitter logic: Only run upgrade tasks if full run not needed.
If a machine's timestamp is older than the date of the last
git commit, do a full ansible run.  If the time stamp is older
than the trigger time (given as argument to 'emitter') but
younger than the latest git commit, run only the upgrade tasks.

A single outdated machine triggers the full run for all
machines in the list.
2024-02-02 19:25:30 +01:00

96 lines
3 KiB
Bash
Executable file

#!/usr/bin/bash
#
# Run ansible on all hosts older than the latest git commit.
# Use argument "$(date)" to update all machines independent
# of the last ansible run.
#
set -eu
## maximal age of file in minutes:
age="15"
pbook="lmn-client"
logdir="/tmp/collector"
debug=false
## date of latest git commit in ansible repository:
git_date="$(date --iso-8601=seconds --date="$(git log --date=iso-strict | \
head -3 | sed -nE "s/^Date:\s+(.+)$/\1/p")")"
echo "Latest commit in git at: $git_date."
if [[ $# = 0 ]] ; then
timestamp="$git_date"
else
timestamp="$(date --iso-8601=seconds --date="$1")"
fi
echo "Time stamp at: $timestamp."
#dir="$(mktemp -d)"
dir="/tmp/emitter"
mkdir -vp "$dir"
touch "$dir/${timestamp//T*/}"
hlist=""
n=0
running=0
ansible_arg=""
find_outdated(){
hlist=""
n=0
running=0
ansible_arg="--tags=upgrade"
while IFS= read -r -d '' file ; do
running=$(( running + 1 ))
$debug && echo -n "Processing host '$file' with IP address "
d="$(sed -nE "s/^2\s+(\S.+)$/\1/p" "$file")"
if [[ -z "$d" ]] || \
[[ $(date --date="$d" +%s) -lt $(date --date="$timestamp" +%s) ]] ; then
r='([0-9]{1,3}\.){3}[0-9]{1,3}'
ipa="$(sed -nE "s/^3\s+default via.+ src ($r) metric.+/\1/p" "$file")"
if [[ -z "$ipa" ]] ; then
# FIXME: Outdated report format, try fallback:
ipa="$(sed -nE "s|^.+default via.+ src ($r) metric.+|\1|p" "$file" | head -1)"
fi
$debug && echo "'$ipa'."
if ! grep -q "$ipa" "$dir/${timestamp//T*/}" ; then
echo "$ipa" >> "$dir/${timestamp//T*/}"
hlist="$hlist,$ipa"
n=$(( n + 1 ))
if [[ $(date --date="$d" +%s) -lt $(date --date="$git_date" +%s) ]] ; then
## ansible run needed at least on one machine, run it on all:
echo "Triggering full ansible run!"
ansible_arg=""
fi
else
$debug && echo "Host already processed before."
fi
fi
done < <(find "$logdir" -maxdepth 1 -type f -mmin -$age -print0)
hlist="${hlist#,}"
echo -n "Running hosts: $running, to be upgraded: $n. "
}
run_ansible(){
local hsts="$1"
if [[ -n "$hsts" ]] ; then
if ! echo | eval ANSIBLE_RETRY_FILES_ENABLED=1 ANSIBLE_RETRY_FILES_SAVE_PATH="$dir" \
ansible-playbook --vault-password-file ~/.vaultpwd \
-bi inventory.yml "$pbook.yml" "$ansible_arg" -l "$hsts" ; then
while IFS= read -r ipa ; do
sed -i "/$ipa/d" "$dir/${timestamp//T*/}"
echo "IP address '$ipa' removed from '$dir/${timestamp//T*/}'."
done < "$dir/$pbook.retry"
fi
fi
}
#################
while true ; do
date --rfc-3339=seconds
find_outdated
run_ansible "$hlist"
t=$(( 600/(n*n+1) ))
echo -n "Sleeping for $t seconds now ... "
sleep $t
done