#!@BASH@
# -*- mode: sh; sh-basic-offset: 3; indent-tabs-mode: nil; -*-
# vim: set filetype=sh sw=3 sts=3 expandtab autoindent:
#
#
# Ninjareport - generate a single simple report for a lot of hosts
#
# requires logtail
#
# Copyright (C) 2007 - riseup.net -- property is theft.

# TODO:
#
#  . check for logs that are never updating and warn
#  . change constantly updating logs (maildir) to be more friendly
#  . documentation
#  . maybe make config option that lists all hosts that should report-in, and if
#    one doesn't then warn
#  . restrict rsync somehow?
#  . abstract path for logtail
#  . on the report master, the reportdirectory should be set where the reports will be going, note this

mail=1
display=0

process() {

# look in the logfile for any lines like the following:
# Jan 20 01:02:46 Info: FINISHED: 2 actions run. 0 fatal. 0 error. 0 warning.
#
# note: some backups never finish, such as the maildir one, need to handle these
# perhaps by looking for FAILED messages?
# note2: what about logs that aren't being updated? this is a failure case and
# should be looked for
# note3: there are also these entries:
# Jan 20 14:00:01 Fatal: No backup actions configured in '/etc/backup.d', run ninjahelper!

# The following has to be done without invoking a subshell (see BashFAQ #24)
logupdates=`maketemp ninjadata`

/usr/sbin/logtail -f $host > $logupdates
grep FINISHED $logupdates |
(
   fatal=0
   warning=0
   error=0

   while read line
   do
      line_array=($line)
      fatal=$(($fatal + ${line_array[8]}))
      error=$(($error + ${line_array[10]}))
      warning=$(($warning + ${line_array[12]}))
   done
   if (( $fatal || $warning || $error )); then
      echo "`basename $host .log`: $fatal fatals found, $error errors found, $warning warnings found" >> $statusfile
      echo "" >> $reportappend
      echo "`basename $host .log` log entries since last ninjareport" >> $reportappend
      echo "---------" >> $reportappend
      cat $logupdates >> $reportappend
      rm $logupdates
   fi
)

}

generatereport() {

reportfile=`maketemp ninjareport`

# Generate a report, only if there are failures
if [ -s $statusfile ]; then
   echo "         backupninja mission failures - `date`" >> $reportfile
   echo "       --------------------------------------------------------------" >> $reportfile
   echo "" >> $reportfile
   cat $statusfile | column -t >> $reportfile
   echo "" >> $reportfile
   echo "         log entries from failed reports" >> $reportfile
   echo "       -----------------------------------" >> $reportfile
   cat $reportappend >> $reportfile
fi

}

usage() {
   cat << EOF
This script generates a backupninja status report for all configured
systems. It requires that each status report is placed in a spot where
ninjareport can read it, reports are mailed to the reportemail
configured in @CFGDIR@/backupninja.conf.

The following options are available:
-h, --help             This usage message
-f, --conffile FILE    Use FILE for the configuration instead
                       of @CFGDIR@/backupninja.conf
-m, --mail <email>     Mail the report to this address
-o, --out              Don't mail the report, just display it

EOF
}

#####################################################
## MAIN

conffile="@CFGDIR@/backupninja.conf"

## process command line options

while [ $# -ge 1 ]; do
   case $1 in
      -h|--help)
         usage
         exit 0
         ;;
      -f|--conffile)
         if [ -f $2 ]; then
            conffile=$2
         else
            echo "-f|--conffile option must be followed by an existing filename"
            fatal "-f|--conffile option must be followed by an existing filename"
            usage
         fi
         # we shift here to avoid processing the file path
         shift
         ;;
      -m|--mail)
         reportemail=$2
         shift
         ;;
      -o|--out)
         mail=0
         display=1
         ;;
      *)
         echo "Unknown option $1"
         usage
         exit
         ;;
   esac
   shift
done

## Load and confirm basic configuration values

# bootstrap
if [ ! -r "$conffile" ]; then
   echo "Configuration file $conffile not found."
   fatal "Configuration file $conffile not found."
fi

# find $libdirectory
libdirectory=`grep '^libdirectory' $conffile | awk '{print $3}'`
if [ -z "$libdirectory" ]; then
   if [ -d "@libdir@" ]; then
      libdirectory="@libdir@"
   else
      echo "Could not find entry 'libdirectory' in $conffile."
      exit 1
   fi
else
   if [ ! -d "$libdirectory" ]; then
      echo "Lib directory $libdirectory not found."
      exit 1
   fi
fi

# include shared functions
. $libdirectory/tools

setfile $conffile

getconf reportdirectory
getconf reportemail

## Process each configuration file

hosts=`find $reportdirectory -follow -mindepth 1 -maxdepth 1 -type f ! -name '*.offset' | sort -n`

if [ -z "$hosts" ]; then
   echo "Fatal: No backupninja reports found in '$reportdirectory'!"
   mail=0
fi

statusfile=`maketemp ninjastatus`
reportappend=`maketemp ninjaappend`

for host in $hosts; do
   [ -f "$host" ] || continue
   # Check somehow that the file is a valid report file
   process $host
done

generatereport

## mail the report to the report address or display it

if [ -s $reportfile ]; then
   if [ $mail == 1 ]; then
      mail -s "backupninja mission failure report" $reportemail < $reportfile
   fi
fi

if [ $display == 1 ]; then
   cat $reportfile
fi