From 05ecc2418251a63d029e4e3ad988e22176be8ada Mon Sep 17 00:00:00 2001 From: Heuzef Date: Fri, 8 Nov 2019 16:44:05 +0100 Subject: [PATCH] Init project. --- Check.pm | 186 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 20 ++++++- update.sh | 8 +++ 3 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 Check.pm create mode 100644 update.sh diff --git a/Check.pm b/Check.pm new file mode 100644 index 0000000..45e7a8f --- /dev/null +++ b/Check.pm @@ -0,0 +1,186 @@ +#============================================================= -*-perl-*- +# +# BackupPC::CGI::Check package +# +# DESCRIPTION +# +# This module implements the Check action for the CGI interface. +# +# AUTHOR +# Heuze Florent +# +#======================================================================== +# +# Released November 2019 - firewall-services.com +# +#======================================================================== + +package BackupPC::CGI::Check; + +use strict; +use lib "/usr/share/BackupPC/lib"; +use BackupPC::Lib; +use BackupPC::CGI::Lib qw(:all); +use Statistics::Descriptive; + +sub action +{ + # Init + my($str, $strGood, $header); + GetStatusInfo("hosts info"); + my $Privileged = CheckPermission(); + my $bpc = BackupPC::Lib->new(); + + # Start loop + foreach my $host ( GetUserHosts(1) ) { + my($incrAge, $reasonHilite, $frequency, $idBackup, $lastAge, $lastAgeColor, $tempState, $tempReason, $lastXferErrors, $lastXferErrorsColor, $ifErrors, $sizeConsistency, $sizeConsistencyColor); + my($shortErr); + my @Backups = $bpc->BackupInfoRead($host); + + $bpc->ConfigRead($host); + %Conf = $bpc->Conf(); + + next if ( $Conf{XferMethod} eq "archive" ); + next if ( !$Privileged && !CheckPermission($host) ); + + # Get frequency for this host + if ( $Conf{IncrPeriod} < $Conf{FullPeriod} ) { + $frequency = $Conf{IncrPeriod}; + } else { + $frequency = $Conf{FullPeriod}; + } + + # ID + my $idBackup = $Backups[@Backups-1]->{num} if ( @Backups ); + + # Age + my $lastBackup = ( $Backups[-1]->{type} =~ m/^full|incr$/ ) ? -1 : -2; + $lastAge = sprintf("%.1f", (time - $Backups[$lastBackup]->{startTime}) / (24 * 3600)); + + # Color for age + if ( $lastAge < $frequency ) { + $lastAgeColor = "MediumSeaGreen"; + } else { + $lastAgeColor = "Tomato"; + } + + # Color and link for errors + $lastXferErrors = $Backups[@Backups-1]->{xferErrs} if ( @Backups ); + if ( $lastXferErrors == 0 ) { + $lastXferErrorsColor = "MediumSeaGreen"; + $ifErrors = ""; + } else { + $lastXferErrorsColor = "Tomato"; + my $browseErrors = "?action=view&type=XferErr&num=$idBackup&host=$host"; + $ifErrors = "| Read me !"; + } + + # Colors statuts + $reasonHilite = $Conf{CgiStatusHilightColor}{$Status{$host}{reason}} || $Conf{CgiStatusHilightColor}{$Status{$host}{state}}; + $reasonHilite = " bgcolor=\"$reasonHilite\"" if ( $reasonHilite ne "" ); + + # Check Size Consistency + my $new_size = 0; + my $new_size_avg = 0; + my $new_size_q1 = 0; + my $new_size_q3 = 0; + my $sizes = new Statistics::Descriptive::Full; + + foreach my $backup ( @Backups ) { + my $idBackup = $Backups[@Backups-1]->{num} if ( @Backups ); + # Skip partial or active backups + next if ( $backup->{type} !~ m/^full|incr$/ ); + # Push all the sizes in our data set to compute avg sizes + # Exclude backup N°0 as it'll always have much more new data than normal backups + $sizes->add_data($backup->{sizeNew}) unless ( $backup->{num} == 0 ); + + # Ignore the last backup if it's not full or incr (which means it's either partial or active) + my $i = ( $Backups[-1]->{type} =~ m/^full|incr$/ ) ? -1 : -2; + $new_size = $Backups[$i]->{sizeNew}; + $new_size_avg = int $sizes->mean; + $new_size_q1 = eval { int $sizes->quantile(1) } || 0; + $new_size_q3 = eval { int $sizes->quantile(3) } || 0; + } + + # Using a mathematical formula to calculate the consistency of the average size, for new files, on all backups + my $toobig = 0; + my $toosmall = 0; + my $sizeConsistencyColor = "Tomato"; + my $sizeConsistency = "ANOMALOUS"; + + # TOO BIG ? If the size is 6 times higher than usual : + if ( $new_size > ($new_size_q3 + ($new_size_q3 - $new_size_q1) ) * 1.5 and $new_size > $new_size_avg * 6 ) { + $toobig = 1; + } + + # TOO SMALL ? If the size is 3 times lower than usual : + if ( $new_size < ($new_size_q1 - ($new_size_q3 - $new_size_q1) ) * 1.5 and $new_size < $new_size_avg / 3 ) { + $toosmall = 1; + } + + # Get result + if ( not $idBackup > 4) { + $sizeConsistencyColor = "Gray"; + $sizeConsistency = "Not enough backups"; + } + elsif ( not $toobig and not $toosmall and not $idBackup < 4) { + $sizeConsistencyColor = "MediumSeaGreen"; + $sizeConsistency = "Normal"; + } + + # Get URL for explore file + my $browseFile = "?action=browse&host=$host"; + + # Show summary + $str .= < + $host ($idBackup) + $lastAge (Freq: $frequency) + $lastXferErrors $ifErrors + $sizeConsistency + +EOF + + } + # End loop + + # Time set + my $now = timeStamp2(time); + my $DUmaxTime = timeStamp2($Info{DUDailyMaxTime}); + my $DUInodemaxTime = timeStamp2($Info{DUInodeDailyMaxTime}); + + # Show header + $header = <This check was generated at \$now.

+ +

File system pool size usage (\$DUmaxTime) :

+
+
\$Info{DUDailyMax}%
+
+ +

File system inode size usage (\$DUInodemaxTime) :

+
+
\$Info{DUInodeDailyMax}%
+
+ + \${h2("Backups summary")} + + + + + + + + + \$str +
Host (Explore files)Last backup in daysErrorsSize Consistency
+EOF + + # Show page + my $content = eval ("qq{$header}"); + Header("BackupPC: Check", $content); + Trailer(); +} + +1; diff --git a/README.md b/README.md index 6d585a0..74c7c9e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,21 @@ # BackupPC-Check -VĂ©rification des sauvegardes BackupPC \ No newline at end of file +Verifying BackupPC Backups + +# Install + +## Install dependencies + +``yum -y perl-Statistics-Descriptive`` + +## Install Backup-Check + +``cd /root ; git clone ssh://gitea@gitea.fws.fr:3222/fws/BackupPC-Check.git ; sh /root/BackupPC-Check/update.sh`` + +## Add menu link + +Edit config -> CGI -> CgiNavBarLinks and add name "Check" with link "?action=check". + +# Update + +``sh /root/BackupPC-Check/update.sh`` diff --git a/update.sh b/update.sh new file mode 100644 index 0000000..33d874e --- /dev/null +++ b/update.sh @@ -0,0 +1,8 @@ +echo "" +echo "Updating ..." +echo "" +git pull +sleep 1 +\cp -v Check.pm /usr/share/BackupPC/lib/BackupPC/CGI/Check.pm +echo "" +echo "OK"