Skip to content

Commit

Permalink
Add zonetable external load mechanism; make remote pyalive check conf…
Browse files Browse the repository at this point in the history
…igurable; add license headers; bug fixes (#76)

* auto dns/port selection based on zone

* add zone map

* Update README.md

* make use of zonetable persistent across all functions

* make logging more consistent

* cleanup

* cleanup

* made ImAlive more robust

* add EU zones

* improve zonetable to auto-extract zone names; add EU zones

* Update README.md

* add FALLBACK_IMALIVE_SERVICE

* Update zonetable

* implement zonetable auto updates

* Update imalive

* Update zonetable-update

* Update zonetable-update

* Update zonetable

* change to test zonetable downloads

* Create imalive-original

* Update Dockerfile

* Update imalive

* Update zonetable-update

* Update zonetable

* Update zonetable-update

* Update zonetable

* Update imalive

* Update imalive

* Update imalive

* Update imalive

* Update zonetable

* Update zonetable-update

* Update zonetable-update

* Update zonetable

* Update imalive

* Update zonetable

* Update zonetable-update

* Update zonetable

* Update 50-radarvirtuel

* Update 55-mlat-client

* Update imalive

* Update mlat-client

* Update radarvirtuel

* Update zonetable-update

* Update healthcheck.sh

* remove file
  • Loading branch information
kx1t authored Aug 7, 2024
1 parent 566a0c2 commit e2783e7
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 66 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ RUN --mount=type=bind,from=downloader,source=/,target=/downloader/ \
# Needed to run the mlat_client:
KEPT_PACKAGES+=(python3-minimal) && \
KEPT_PACKAGES+=(python3-pkg-resources) && \
# Needed for the new ImAlive:
KEPT_PACKAGES+=(tcpdump) && \
#
# Install all these packages:
apt-get update -q -y && \
Expand Down
Empty file.
Empty file.
Empty file.
2 changes: 2 additions & 0 deletions rootfs/etc/s6-overlay/s6-rc.d/zonetable-update/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
exec /etc/s6-overlay/scripts/zonetable-update
1 change: 1 addition & 0 deletions rootfs/etc/s6-overlay/s6-rc.d/zonetable-update/type
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
longrun
16 changes: 16 additions & 0 deletions rootfs/etc/s6-overlay/scripts/50-radarvirtuel
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
#!/command/with-contenv bash
# shellcheck shell=bash disable=SC1091,SC2015,SC2145,SC2154

#---------------------------------------------------------------------------------------------
# Copyright (C) 2023-2024, Ramon F. Kolb (kx1t) and contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------------------------

source /scripts/common
"${s6wrap[@]}" echo "Initializing RadarVirtuel..."

Expand Down
16 changes: 16 additions & 0 deletions rootfs/etc/s6-overlay/scripts/55-mlat-client
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
#!/command/with-contenv bash
# shellcheck shell=bash disable=SC1091,SC2015,SC2145,SC2154

#---------------------------------------------------------------------------------------------
# Copyright (C) 2023-2024, Ramon F. Kolb (kx1t) and contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------------------------

source /scripts/common

"${s6wrap[@]}" echo "Initializing mlat-client..."
Expand Down
146 changes: 81 additions & 65 deletions rootfs/etc/s6-overlay/scripts/imalive
Original file line number Diff line number Diff line change
@@ -1,20 +1,42 @@
#!/command/with-contenv bash
# shellcheck shell=bash disable=SC1091,SC2015,SC2145,SC2154

#---------------------------------------------------------------------------------------------
# Copyright (C) 2023-2024, Ramon F. Kolb (kx1t) and contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------------------------

source /scripts/common

KEEPALIVE_ALIVE=600 # keepalive timer in seconds if previous run was fine
KEEPALIVE_DEAD=60 # keepalive timer in seconds if previous run failed
# dont make this shorter than 60 secs to allow services to be properly restarted after a failure
CONNECTION_TIMEOUT=10 # timeout when checking ability to connect using netcat
while [[ -f /run/zonetable.lock ]]; do sleep 1; done
touch /run/zonetable.lock
source /home/zonetable
rm -f /run/zonetable.lock

KEEPALIVE_ALIVE="${KEEPALIVE_ALIVE:-600}" # keepalive timer in seconds if previous run was fine
KEEPALIVE_DEAD="${KEEPALIVE_DEAD:-60}" # keepalive timer in seconds if previous run failed
# dont make this shorter than 60 secs to allow services to be properly restarted after a failure
CONNECTION_TIMEOUT="{CONNECTION_TIMEOUT:-10}" # timeout when checking ability to connect using netcat
ALIVE=true
mkdir -p /run/imalive
touch /run/imalive/errors
"${s6wrap[@]}" echo "Started as an s6 service"

RV_SERVER="${RV_SERVER:-mg22.adsbnetwork.com:50050}"
FALLBACK_IMALIVE_SERVICE="${FALLBACK_IMALIVE_SERVICE:-http://mg22.adsbnetwork.com/rtools/pyalive.php}"
[[ "${RV_SERVER%%:*}" == "mg2.adsbnetwork.com" ]] && RV_SERVER="mg22.adsbnetwork.com:${RV_SERVER##*:}" || true
source /home/zonetable

if [[ -n "$zone_id" ]]; then
RV_SERVER="${zone_dns}:${zone_port}"
fi
Expand All @@ -40,91 +62,85 @@ do
"${s6wrap[@]}" echo "Running ImAlive..."
fi

# Get the latest zonetable values:
while [[ -f /run/zonetable.lock ]]; do sleep 1; done
touch /run/zonetable.lock
source /home/zonetable
rm -f /run/zonetable.lock
if [[ -n "$zone_id" ]]; then
RV_SERVER="${zone_dns}:${zone_port}"
fi

ALIVE=true
# kx1t: retrieve station name from $FEEDER_KEY docker env variable
st=${FEEDER_KEY%%:*}
timestamp=$(date "+%s")
#echo " $st Current Time : $ts"
#
# 07-AUG-2024 -- added the following code because at the moment, MG21 is providing a "ko" unduely due to server side MongoDB issues
# once fixed, we can revert to the original line
# ORIGINAL:
# if ! STATUS="$(curl -sSL "${RV_SERVER%%:*}"/rtools/pyalive.php?stid="${st,,}" 2>&1)"; then
# NEW: (revert this 1 line once MG21 is fixed)
if ! STATUS="$(curl -sSL "${RV_SERVER%%:*}"/rtools/pyalive.php?stid="${st,,}" 2>&1)" || [[ "${STATUS%%-*}" == "ko" ]]; then
if STATUS="$(curl -sSL http://mg22.adsbnetwork.com/rtools/pyalive.php?stid="${st,,}" 2>&1)"; then
"${s6wrap[@]}" echo "ImAlive status on ${RV_SERVER%%:*} wasn't available, fell back to mg22.adsbnetwork.com"
else
STATUS=""
fi
fi
# STATUS now contains either "ok-12345678" or "ko-12345678"
# If STATUS is empty then there was a connection error
# where ok/ko means OK or not OK and 12345678 is the secs since epoch
# STATUS can also contain the error page if the server returns an error

status="${STATUS%%-*}"
remote_timestamp="${STATUS##*-}"

# check the ImAlive server:
if grep -o "404 Not Found" <<< "$STATUS" >/dev/null 2>&1; then
"${s6wrap[@]}" echo "ImAlive Server returned 404-Not Found. Restarting ANFeeder \"just in case\"..."
killall /home/py/ANfeeder >/dev/null 2>&1

if ! chk_disabled "${FALLBACK_IMALIVE_SERVICE}"; then
if ! STATUS="$(curl -sSL "${RV_SERVER%%:*}"/rtools/pyalive.php?stid="${st,,}" 2>&1)"; then
if STATUS="$(curl -sSL "${FALLBACK_IMALIVE_SERVICE}"?stid="${st,,}" 2>&1)"; then
"${s6wrap[@]}" echo "ImAlive status on ${RV_SERVER%%:*} wasn't available, fell back to mg22.adsbnetwork.com"
else
STATUS=""
fi
fi
# STATUS now contains either "ok-12345678" or "ko-12345678"
# If STATUS is empty then there was a connection error
# where ok/ko means OK or not OK and 12345678 is the secs since epoch
# STATUS can also contain the error page if the server returns an error

status="${STATUS%%-*}"
remote_timestamp="${STATUS##*-}"

# check the ImAlive server:
if grep -o "404 Not Found" <<< "$STATUS" >/dev/null 2>&1; then
"${s6wrap[@]}" echo "ImAlive Server returned 404-Not Found. Restarting ANFeeder \"just in case\"..."
ALIVE="404 failure for ${RV_SERVER%%:*}/rtools/pyalive.php?stid=$st"
elif [[ -z "$STATUS" ]]; then
elif [[ -z "$STATUS" ]]; then
"${s6wrap[@]}" echo "ImAlive Server cannot be reached: network failure. Restarting ANFeeder \"just in case\"..."
killall /home/py/ANfeeder >/dev/null 2>&1
ALIVE="no network failure"
elif [[ $timestamp -lt $(( remote_timestamp - 10 )) ]]; then
elif [[ $timestamp -lt $(( remote_timestamp - 10 )) ]]; then
# kx1t: using killall to restart the service instead of the RestartANfeeder.sh script
"${s6wrap[@]}" echo "ImAlive Server: time stamp discrepancy: local $(date -d @"$timestamp") / remote $(date -d @"$remote_timestamp"); restarting ANfeeder"
# kx1t: added warning that Docker image cannot resync NTP
"${s6wrap[@]}" echo "Warning - Please make sure your host machine uses an accurate external time source!"
killall /home/py/ANfeeder >/dev/null 2>&1
ALIVE="time discrepancy failure"
elif [[ "$status" == "ko" ]]; then
elif [[ "$status" == "ko" ]]; then
# kx1t: using s6 to restart the service
"${s6wrap[@]}" echo "ImAlive Server says that no data is received: Restarting ANfeeder"
killall /home/py/ANfeeder >/dev/null 2>&1
ALIVE="no data received by server failure"
elif [[ "$status" == "ok" ]]; then
elif [[ "$status" == "ok" ]]; then
chk_enabled "${VERBOSE}" && "${s6wrap[@]}" echo "ImAlive Server: connection is fine!"
else
"${s6wrap[@]}" echo "ImAlife error: $STATUS. Restarting ANfeeder"
killall /home/py/ANfeeder >/dev/null 2>&1
else
"${s6wrap[@]}" echo "ImAlive error: $STATUS. Restarting ANfeeder"
ALIVE="$STATUS"
fi
else
"${s6wrap[@]}" echo "Server Check-in is disabled - skipped querying ${RV_SERVER%%:*}"
fi

# check the SOURCE_HOST connection
# if ! check_tcp4_connection_established ANY ANY $(get_ipv4 ${SOURCE_HOST%%:*}) ${SOURCE_HOST##*:} >/dev/null 2>&1
# if [[ $(timeout --preserve-status $CONNECTION_TIMEOUT netcat -z -v "${SOURCE_HOST%%:*}" "${SOURCE_HOST##*:}" 2>/dev/null ; echo $?) != "0" ]]
if [[ "$(grep captured <<< "$(timeout --preserve-status 3 tcpdump -p src "${SOURCE_HOST%%:*}" and port "${SOURCE_HOST##*:}" 2>/dev/stdout 1>/dev/null)" | awk '{print $1}')" == "0" ]]
then
"${s6wrap[@]}" echo "Your data source at $SOURCE_HOST appears to be down. Restarting ANfeeder."
killall /home/py/ANfeeder >/dev/null 2>&1
if [[ "$(grep captured <<< "$(timeout --preserve-status 3 tcpdump -p src "${SOURCE_HOST%%:*}" and port "${SOURCE_HOST##*:}" 2>/dev/stdout 1>/dev/null)" | awk '{print $1}')" == "0" ]]; then
"${s6wrap[@]}" echo "Your data source at $SOURCE_HOST appears to be down. Restarting ANfeeder"
ALIVE="cannot establish connection to SOURCE HOST $SOURCE_HOST"
else
chk_enabled "${VERBOSE}" && "${s6wrap[@]}" echo "$SOURCE_HOST can be reached! "
if chk_enabled "${VERBOSE}"; then "${s6wrap[@]}" echo "$SOURCE_HOST is sending data to the container"; fi
fi

# check if the RV_SERVER can be reached
# Note - in the future we have to revisit this. `netcat -u` relies on ICMP Not Available messages from a UDP port to be
# returned in case of failure, and often these messages are not sent or are filtered on the way back.
# See https://serverfault.com/a/416269 for explanation
#
# In reality, false passes of this check aren't too important as we already pinged the ImAlive server to see that they think the connection is OK
#
# if ! check_udp4_connection_established ANY ANY $(get_ipv4 ${RV_SERVER%%:*}) ${RV_SERVER##*:} >/dev/null 2>&1
if [[ $(timeout --preserve-status $CONNECTION_TIMEOUT netcat -u -z -v "${RV_SERVER%%:*}" "${RV_SERVER##*:}" 2>/dev/null ; echo $?) != "0" ]]
then
"${s6wrap[@]}" echo "The RadarVirtuel server at $RV_SERVER appears to be down. Restarting ANfeeder."
killall /home/py/ANfeeder >/dev/null 2>&1
ALIVE="$RV_SERVER down failure"
# check if we see UDP data on the RV_SERVER port in 3 seconds, if that fails, try again for 30 secs
# this is so the check will pass in 3 secs during times of high traffic, but we'll check for a longer period of time during low traffic
if (( $(grep captured <<< "$(timeout --preserve-status 3 tcpdump -p udp port "${RV_SERVER##*:}" 2>/dev/stdout 1>/dev/null)" | awk '{print $1}') > 0 )) \
|| (( $(grep captured <<< "$(timeout --preserve-status 30 tcpdump -p udp port "${RV_SERVER##*:}" 2>/dev/stdout 1>/dev/null)" | awk '{print $1}') > 0 )); then
if chk_enabled "${VERBOSE}"; then "${s6wrap[@]}" echo "The container is sending data to $RV_SERVER"; fi
else
if chk_enabled "${VERBOSE}"; then
"${s6wrap[@]}" echo "$RV_SERVER can be reached!"
fi
"${s6wrap[@]}" echo "The container is not sending any data to the RadarVirtuel server at $RV_SERVER. Restarting ANfeeder"
ALIVE="$RV_SERVER down failure"
fi

[[ "$ALIVE" != "true" ]] && echo "$(date +%s) - $ALIVE" >> /run/imalive/errors || echo "" > /run/imalive/errors
if [[ "$ALIVE" != "true" ]]; then
killall /home/py/ANfeeder >/dev/null 2>&1 || true
echo "$(date +%s) - $ALIVE" >> /run/imalive/errors
else
echo "" > /run/imalive/errors
fi
done
16 changes: 16 additions & 0 deletions rootfs/etc/s6-overlay/scripts/mlat-client
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
#!/command/with-contenv bash
# shellcheck shell=bash disable=SC1091,SC2015,SC2145,SC2154

#---------------------------------------------------------------------------------------------
# Copyright (C) 2023-2024, Ramon F. Kolb (kx1t) and contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------------------------

source /scripts/common

"${s6wrap[@]}" echo "Started as an s6 service"
Expand Down
16 changes: 16 additions & 0 deletions rootfs/etc/s6-overlay/scripts/radarvirtuel
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
#!/command/with-contenv bash
# shellcheck shell=bash disable=SC1091,SC2015,SC2145,SC2154

#---------------------------------------------------------------------------------------------
# Copyright (C) 2023-2024, Ramon F. Kolb (kx1t) and contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------------------------

source /scripts/common

START_DELAY=5s
Expand Down
43 changes: 43 additions & 0 deletions rootfs/etc/s6-overlay/scripts/zonetable-update
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/command/with-contenv bash
# shellcheck shell=bash disable=SC1091,SC2015,SC2145,SC2154

#---------------------------------------------------------------------------------------------
# Copyright (C) 2023-2024, Ramon F. Kolb (kx1t) and contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------------------------

source /scripts/common
ZONETABLE_CHECK_INT="${ZONETABLE_CHECK_INT:-7200}" # check every 2 hours
ZONETABLE_URL="${ZONETABLE_URL:-https://raw.githubusercontent.com/sdr-enthusiasts/docker-radarvirtuel/main/rootfs/home/zonetable}"

"${s6wrap[@]}" echo "[INFO] checking if zonetable needs to get updated"

if curl -sSL "${ZONETABLE_URL}" -o /tmp/zonetable >/dev/null 2>&1; then
if [[ -n "$(comm --nocheck-order -3 /home/zonetable /tmp/zonetable 2>/dev/null)" ]]; then
"${s6wrap[@]}" echo "[INFO] zonetable has changed, installing new version"
while [[ -f /run/zonetable.lock ]]; do sleep 1; done
touch /run/zonetable.lock
mv -f /tmp/zonetable /home/zonetable
chmod +x /home/zonetable
rm -f /run/zonetable.lock
else
"${s6wrap[@]}" echo "[INFO] zonetable has not changed since last check"
rm -f /tmp/zonetable
fi
else
"${s6wrap[@]}" echo "[WARNING] couldn't reach the remote server with the latest zonetable - we will keep on using the current table"
fi

"${s6wrap[@]}" echo "[INFO] next zonetable update check will be at $(date -d "+$ZONETABLE_CHECK_INT seconds" | xargs)"
sleep $ZONETABLE_CHECK_INT
16 changes: 16 additions & 0 deletions rootfs/home/healthcheck/healthcheck.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
#!/command/with-contenv bash
#shellcheck shell=bash

#---------------------------------------------------------------------------------------------
# Copyright (C) 2023-2024, Ramon F. Kolb (kx1t) and contributors
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program.
# If not, see <https://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------------------------

# Import healthchecks-framework
# shellcheck disable=SC1091
source /opt/healthchecks-framework/healthchecks.sh
Expand Down
Loading

0 comments on commit e2783e7

Please sign in to comment.