Commit d61ae7bc authored by Jean-Claude BAU's avatar Jean-Claude BAU

New feature: System clock monitor

The system clock monitor measures the offset between the local time and
the NTP time. If this offset exceed a given threshold an alarm will be
raised .
parent dfd464d3
......@@ -881,6 +881,75 @@ config SNMP_SWCORESTATUS_DISABLE
# Error if frame rate of any RX priority exceed given value.
#
menu "System clock monitor"
config SNMP_SYSTEM_CLOCK_MONITOR_ENABLED
depends on NTP_SERVER != ""
bool "Enable system clock monitor"
default y
help
When set, the local system time is compared to the time
returned by the NTP server (CONFIG_NTP_SERVER). If the difference
of time exceed a given threshold (CONFIG_SNMP_SYSTEM_CLOCK_DRIFT_THOLD)
then an error will be notified to SNMP.
config SNMP_SYSTEM_CLOCK_DRIFT_THOLD
depends on SNMP_SYSTEM_CLOCK_MONITOR_ENABLED
int "Threshold level for local system clock drift (seconds)"
range 1 65535
default 3
help
Threshold level for the local system clock drift compared to
a NTP server. The value is expressed in seconds.
When the threshold exceed, warning is notified by SNMP.
choice SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_UNIT
prompt "Unit of check interval value"
depends on SNMP_SYSTEM_CLOCK_MONITOR_ENABLED
default SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_MINUTES
help
Defines the unit used for the check interval value.
config SNMP_SYSTEM_CLOCK_UNIT_MINUTES
bool "Minutes"
config SNMP_SYSTEM_CLOCK_UNIT_HOURS
bool "Hours"
config SNMP_SYSTEM_CLOCK_UNIT_DAYS
bool "Days "
endchoice
config SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_MINUTES
depends on SNMP_SYSTEM_CLOCK_MONITOR_ENABLED && SNMP_SYSTEM_CLOCK_UNIT_MINUTES
int "Interval to verify system clock (Minutes)"
range 1 59
default 10
help
Sets the time interval between checks of the system clock.
This interval is expressed in minutes.
config SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_HOURS
depends on SNMP_SYSTEM_CLOCK_MONITOR_ENABLED && SNMP_SYSTEM_CLOCK_UNIT_HOURS
int "Interval to verify system clock (Hours)"
range 1 23
default 1
help
Sets the time interval between checks of the system clock.
This interval is expressed in hours.
config SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_DAYS
depends on SNMP_SYSTEM_CLOCK_MONITOR_ENABLED && SNMP_SYSTEM_CLOCK_UNIT_DAYS
int "Interval to verify system clock (Days)"
range 1 31
default 1
help
Sets the time interval between checks of the system clock.
This interval is expressed in days
endmenu
endmenu
menu "External clk2 clock signal configuration"
......
Subproject commit 01cd0a15d291bc74322141d90c1d0527027884f5
Subproject commit 13e4a0cfda3f368cb63edf5834fdd145a2f8a2d4
#!/bin/bash
# This script measure the drift between the local system clock and
# a NTP server
tmpdir="/tmp"
cronFile="/etc/cron.d/root"
tmpCronFile="$tmpdir/root.cron"
prefix="system_clock_monitor"
debugLogFile="$tmpdir/$prefix.log"
script="/etc/init.d/system_clock_monitor"
systemClockMonitoringStatus="$tmpdir/${prefix}_status"
systemClockMonitoringDrift="$tmpdir/${prefix}_drift"
dotConfig="/wr/etc/dot-config"
fileNtpServerConfig="/etc/wr_date.conf"
ntpTool="/usr/sbin/ntpd"
suspendKillDaemon=0
pidKillDaemon=0
verbose=0
#
# Print message if verbose is set
#
debug () {
if [[ $verbose == 1 ]]; then
echo $1 >&1| tee -a $debugLogFile
eval echo $1 $LOGPIPE
fi
}
#
# remove from cron file any entry related to system clock monitor
#
cleanCronConfig ()
{
local entryPresent=0
set -f
: > $tmpCronFile
while IFS= read -r line; do
if [[ "$line" =~ $script ]] ; then
entryPresent=1
else
echo "$line" >> $tmpCronFile
fi
done < "$cronFile"
if (( entryPresent == 1 )) ; then
debug "$cronFile has been cleaned up"
mv $cronFile $cronFile.old
mv $tmpCronFile $cronFile
else
debug "$cronFile does not need to be cleaned up "
rm -f $tmpCronFile
fi
set +f
}
#
# Add system clock monitor entry in crontab
#
setCronConfig ()
{
local __entry=$1
debug "Add new entry in cron file $cronFile"
debug "New entry added \"$__entry\""
echo "$entry" >> $cronFile
}
#
# Compare the offset to the threshold value
#
compareToThreshold ()
{
local __resultvar=$1
local __c_offset=$2
local __c_threshold=$3
if (( $__c_offset >= __c_threshold )) ; then
x=$(expr $__c_offset - $__c_threshold)
debug "System clock drift is exceedind the threshold by ${x} sec"
eval $__resultvar="1"
else
debug "System clock drift is not exceeding the threshold"
eval $__resultvar="0"
fi
}
#
# Decode NTPD deamon output to get the offset in ms
#
decodeOffsetMs ()
{
local __resultvar=$1
local __str=$2
local __offset=$(echo $__str | sed -n 's/.* offset:[+-]\?\([0-9]*\).*/\1/p')
if [[ -z "$__offset" ]] ; then
# Empty string
debug "Invalid Offset !!!"
debug "NTP msg=\"$__str\""
eval $__resultvar="-1"
else
offset=$(expr $__offset + 0)
debug "NTP offset=$__offset ms"
eval $__resultvar="'$__offset'"
fi
}
#
# Kill the NTPD daemon in background after few seconds
#
killNTPD ()
{
local delay=$1 # Delay in seconds
if (( $pidKillDaemon != 0 )) ; then
debug "Daemon actif !!!"
kill -9 $pidKillDaemon &>/dev/null
pidKillDaemon=0
fi
(
sleep $delay
p=$(pidof $ntpTool)
if [[ -n "$p" ]] ; then
kill -9 $p &>/dev/null
fi
pidKillDaemon=0
) &
pidKillDaemon=$!
}
#
# Read the NTP server to get the offset between NTP and local system time
#
read_ntp_server()
{
local __result=$1
local ltThreshold=$2
local server=$3
local retries=2
local offset=-1
debug "NTP server=$server"
for i in `seq $retries` ; do # Manual retries
killNTPD 10
ntpRes=$($ntpTool -n -w -q -d -p $server 2>&1)
if [ -n "$ntpRes" ] ; then
decodeOffsetMs offset "$ntpRes"
if (( $offset >= 0 )) ; then
compareToThreshold alarmState $offset $ltThreshold
if (( $alarmState == 1 )) ; then
# Exceeded Threshold
echo "exceeded_threshold" > $systemClockMonitoringStatus
else
echo "no_error" > $systemClockMonitoringStatus
fi
echo $offset > $systemClockMonitoringDrift
eval $__result="0"
return
fi
eval echo "Retry $i/$N : Cannot extract offset from NTP message." $LOGPIPE
else
eval echo "Retry $i/$N : NTP query failed, unable to contact server ($server)." $LOGPIPE
fi
done
eval echo "ERROR: could not reach NTP server '$S' after $N retries" $LOGPIPE
eval $__result="1"
}
#
# Apply dot-config configuration
#
if [ -f $dotConfig ]; then
# source dot-config
. $dotConfig
else
echo "$0 unable to source dot-config ($dotConfig)!"
fi
WRS_LOG=$CONFIG_WRS_LOG_OTHER
# if empty turn it to /dev/null
if [ -z $WRS_LOG ]; then
WRS_LOG="/dev/null";
fi
# if a pathname, use it
if echo "$WRS_LOG" | grep / > /dev/null; then
eval LOGPIPE=\" \> $WRS_LOG 2\>\&1 \";
else
# not a pathname: use verbatim
eval LOGPIPE=\" 2\>\&1 \| logger -t $prefix -p $WRS_LOG\"
fi
debug "Script started with options \"$@\""
# Read options
if [ "$#" -eq 1 ] && [ "$1" == "-s" ] ; then
debug "Setup configuration"
cleanCronConfig
if [ "$CONFIG_SNMP_SYSTEM_CLOCK_MONITOR_ENABLED" = "y" ] ; then
set -f # Disable globbing
NEWLINE=$'\n'
# System clock monitor enabled. Setup cron file
if [ "$CONFIG_SNMP_SYSTEM_CLOCK_UNIT_MINUTES" = "y" ] ; then
intervalValue=$CONFIG_SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_MINUTES
debug "Time interval: ${intervalValue} minutes"
entry="# System clock monitor: Execute the script \"${script}\" every ${intervalValue} minute(s)${NEWLINE}"
entry+="*/${intervalValue} * * * * ${script}";
setCronConfig "$entry"
else
if [ "$CONFIG_SNMP_SYSTEM_CLOCK_UNIT_HOURS" = "y" ] ; then
intervalValue=$CONFIG_SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_HOURS
debug "Time interval: ${intervalValue} hours"
entry="# System clock monitor: Execute the script \"${script}\" every ${intervalValue} hour(s)${NEWLINE}"
entry+="* */${intervalValue} * * * ${script}"
setCronConfig "$entry"
else
if [ "$CONFIG_SNMP_SYSTEM_CLOCK_UNIT_DAYS" = "y" ]; then
intervalValue=$CONFIG_SNMP_SYSTEM_CLOCK_CHECK_INTERVAL_DAYS
debug "Time interval: ${intervalValue} days"
entry="# System clock monitor: Execute the script \"${script}\" every ${intervalValue} day(s)${NEWLINE}"
entry+="* * */${intervalValue} * * ${script}"
setCronConfig "$entry"
else
eval echo "Invalid unit for system clock check interval." $LOGPIPE
echo "config_error" > $systemClockMonitoringStatus
echo "0" > $systemClockMonitoringDrift
exit 1
fi
fi
fi
set +f # Re-enable globbing
eval echo "cron file \"root\" configured" $LOGPIPE
else
# System clock monitor disabled. Make a clean up
rm -f $systemClockMonitoringStatus
rm -f $systemClockMonitoringDrift
fi
exit 0
fi
if [ "$CONFIG_SNMP_SYSTEM_CLOCK_MONITOR_ENABLED" = "y" ] ; then
threshold=$CONFIG_SNMP_SYSTEM_CLOCK_DRIFT_THOLD
ntpServer=""
# Get the NTP server
if [ -f $fileNtpServerConfig ]; then
# pick the first server, if any
ntpServer=$(grep 'ntpserver' $fileNtpServerConfig | sed 's/ntpserver//' | head -n 1)
fi
if [ -z "$threshold" ] ; then
eval echo "System clock drift threshold not set." $LOGPIPE
echo "config_error" > $systemClockMonitoringStatus
echo "0" > $systemClockMonitoringDrift
exit 1
fi
if [ -z "$ntpServer" ]; then
eval echo "Empty NTP server name" $LOGPIPE
echo "config_error" > $systemClockMonitoringStatus
echo "0" > $systemClockMonitoringDrift
exit 1
fi
read_ntp_server result $threshold $ntpServer
if (( result != 0 )) ; then
echo "ntp_error" > $systemClockMonitoringStatus
echo "0" > $systemClockMonitoringDrift
exit 1
fi
fi
exit 0
......@@ -154,3 +154,7 @@ else
# no valid PTP option keep ppsi.conf with old postfix
echo "No valid PTP option in dot-config!" | tee $log_output >& 2
fi
# System clock monitor: program the cron tab
/etc/init.d/system_clock_monitor -s
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment