Veritas-bu

[Veritas-bu] Report functionality in NetBackup

2001-07-02 11:23:20
Subject: [Veritas-bu] Report functionality in NetBackup
From: RYAN_ANDERSON AT udlp DOT com (RYAN ANDERSON)
Date: Mon, 2 Jul 2001 10:23:20 -0500
This is a multi-part message in MIME format.
--------------646A8C28D04B25B9986CDBB0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

support.cphvt-s AT sas DOT dk wrote:
> 
> Hi
> 
> We are running NB ver 3.4 on a HP-UX 11.00.
> 
> We are missing some Reporting functionality in NetBackup.
> 
> We would like to know how much data we are backing up (on a full scheldule)
> - on our UNIX clients which are running Standard-Filebackup, Oracle, SAP
> - on our NT clients   which are running Standard-Filebackup, Oracle,
> Exchange
> 
> Furthermore we would also like to know how much data we are backing up of
> particular file types e.g. *.avi, *.jpeg...
> 
> Is there anybody out there who has already developed scripts which can do
> these things - or similar.
> 
> Or generally tips on statistics reporting tools/scripts.
> 
> Thanks in advance.
> 
> Regards Martyn
> _______________________________________________
> Veritas-bu maillist  -  Veritas-bu AT mailman.eng.auburn DOT edu
> http://mailman.eng.auburn.edu/mailman/listinfo/veritas-bu

Try this Perl script written by Rob Worman (distributed with his
permission). It gives a lot of what you are looking for.


RCA
--
Ryan C. Anderson       | United Defense L.P.
ryan_anderson AT udlp DOT com | pager 952.235.9936
--------------646A8C28D04B25B9986CDBB0
Content-Type: application/x-perl;
 name="backup_report.pl"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="backup_report.pl"

#!/usr/local/bin/perl
#
# $Id: backup_report.pl,v 1.1 1999/03/01 19:16:37 cswormr Exp $
#
# $Log: backup_report.pl,v $
# Revision 1.1  1999/03/01 19:16:37  cswormr
# Initial revision
#
#
# This script generates a formatted report of backup activity
# including client/class/start time/gigabytes/end time/elapsed time
#
############################
$usage_msg = "usage: backup_report.pl -mail<user1,user2,user3> [-help|-h] 
[-nofulls] [-noincrementals] [-weekend] [-start<DD/MM/YY>] [-end<DD/MM/YY>]\n\n
-help, -h           :   produces this message

-mail<user1,user2,user3>  :  who receives the report email

-nofulls        :   report only incremental (and obackup) backup jobs
-noincrementals :   report only full backup jobs

-weekend        :   report the previous 2 days of backups (instead
                    of the default 1 day)

-start<DD/MM/YY> :   desired start date for your report
-end<DD/MM/YY>   :   desired end date for your report

 
If no date arguments are provided, the script will
report on backups that occurred from 7am yesterday 
to 7am today.  Otherwise, BOTH start and end must 
be provided.\n\n";
############################

############
# Grab any flags or switches that
# may have been passed from the
# command line
############
while ($_ = $ARGV[0], /^-/) {
    shift;
    last if /^--$/;
    if (/^-help/ || /^-h$/) { die "$usage_msg" }
    
    if (/^-nofulls/) { $omit_fulls = 1 }
    if (/^-noincrementals/) { $omit_incs = 1 }

    if (/^-start(.*)/) { $start_date = $1 }
    if (/^-end(.*)/) { $end_date = $1 }

    if (/^-mail(.*)/) { $mail_to = $1 }

    if (/^-weekend/) { $weekend = 1 }
}

if ($mail_to eq "") {die "$usage_msg"}

############
# In case there were no "start" or "end"
# flags provided, set end_date to today
# and start_date to yesterday, UNLESS
# the $weekend flag is set, in which
# case start_date is set to TWO days ago
############
if ($start_date eq "" || $end_date eq "") {    

    $end_day = (localtime) [3];
    $end_mon = (localtime) [4] + 1;
    $end_yr = (localtime) [5];

    if ($weekend) {
        ($a,$b,$c,$start_day,$start_mon,$start_yr,$d,$e,$f) = 
localtime(time-172800);
    }
    else {
        ($a,$b,$c,$start_day,$start_mon,$start_yr,$d,$e,$f) = 
localtime(time-86400);
    }

    $start_yr = ($start_yr + 1900) % 100;
    $start_yr =~ s/^([0-9])$/0$1/;              # left pad with 0
    $end_yr = ($end_yr + 1900) % 100;
    $end_yr =~ s/^([0-9])$/0$1/;                # left pad with 0

    $start_date = $start_mon+1 . "/" . $start_day . "/" . $start_yr;
    $end_date = $end_mon . "/" . $end_day . "/" . $end_yr;
}

$report_cmd = "/usr/openv/netbackup/bin/admincmd/bpimagelist";
$error_cmd = "/usr/openv/netbackup/bin/admincmd/bperror";
$error_codes = "/usr/openv/scripts/error_codes";
use Sys::Hostname;
$server = hostname();
$mail = "/bin/mailx";
$imagefile = "/tmp/imagelist.tmp";
$errorfile = "/tmp/errorlist.tmp";
$report_file = "report.txt";

#######################
#run the NetBackup reports to grab the raw data
#######################
system("$report_cmd -A -d $start_date 7:00 -e $end_date 7:00 > $imagefile \n");
system("$error_cmd -l -d $start_date 7:00 -e $end_date 7:00 > $errorfile \n");

#######################
#parse the list of backup status
#messages and build a list of all
#the failures
#######################
open(ERRORS,"$errorfile") || warn "Could not open $errorfile:$!";
$failed_found = 0;

LINE: while (<ERRORS>) {
     chop;
     next LINE if (!/EXIT STATUS/);

     ($error_stamp, $a, $b, $c, $d, $e, $f, $g, $h, $i, $j, $error_client, $k, 
$error_class, $l, $error_schedule, $m, $n, $exit_status, $therest) = split / 
+/, $_, 20;

     next LINE if ($exit_status < 2);
     # need to do this for NetApps, since they are backed up over NFS,
     # the client name wouldn't be correct otherwise
     if ($error_class =~ /tyr_/) { $error_client = "tyr"; }
     elsif ($error_class =~ /heimdall_/) { $error_client = "heimdall"; }

     # construct the following tmp array:
     #      0= start_time (MM/DD/YY HH:MM:SS)
     #      1= client (machine name, e.g. merlin)
     #      2= class name (class name, e.g. merlin_data)
     #      3= schedule (Full, Incremental, etc)
     #      4= exit status (some number >1)
     #
     # @tmp is then put in a hash called "failed_hash", with
     # back_id as the key, where back_id always
     # looks like "hostname_timestamp"

     $failed_found = 1;
     $error_back_id = $error_client . "_" . $error_stamp;
     $error_start_time = &stamp2time($error_stamp);

     $error_tmp[0] = $error_start_time;
     $error_tmp[1] = $error_client;
     $error_tmp[2] = $error_class;
     $error_tmp[3] = $error_schedule;
     $error_tmp[4] = $exit_status;

     $failed_hash{$error_back_id} = [ @error_tmp ];

}
close ERRORS;


#######################
#parse the list of successful backups
#and build our hash of successes.
#######################
open(IMAGES,"$imagefile") || warn "Could not open $imagefile:$!";

$last_full = $last_incremental = "";
$first_full = $first_incremental = 9999999999;
$total_full_gb = $total_inc_gb = 0;

LINE2:  while (<IMAGES>) {
    chop;
    if (/^Backup ID: /) { $back_id = &get_val($_);  }
    if (/^Client: /) { $client = &get_val($_);  }
    elsif (/^Class:/) { $class = &get_val($_); }
    elsif (/^Sched Label:/) { $type = &get_val($_); }
    elsif (/^Kilobytes:/) { $kb = &get_val($_); }
    elsif (/^Backup Time:/) { $start_time = &get_val($_);}
    elsif (/^Elapsed Time:/) { $elapsed = &get_val($_); }
    elsif (/^$/) {
        
      # this will prevent an initial CR in the report from
      # generating a bogus entry.
      next LINE2 if $back_id eq "";

      # the local backup of the backup master server should
      # be ignored.  (hopefully, these classes names won't
      # change......)
      next LINE2 if $class eq "master_local";

      # this is where we ignore fulls or incrementals, based on the command 
line switches
      next LINE2 if $omit_fulls && $type =~ /Full/;
      next LINE2 if $omit_incs && ($type =~ /Incremental/ || $class =~ 
/nitti_online_Oracle/);

      # need to do this for NetApps, since they are backed up over NFS, 
      # the client name wouldn't be correct otherwise
      if ($class =~ /tyr_/) { $client = "tyr"; }
      elsif ($class =~ /heimdall_/) { $client = "heimdall"; }

      # construct the following tmp array:
      #      0= start_time (MM/DD/YY HH:MM:SS)
      #      1= client (machine name, e.g. merlin)
      #      2= class name (class name, e.g. merlin_data)
      #      3= schedule (Full, Incremental, etc)
      #      4= gb (gigabytes backed up)
      #      5= end_time (MM/DD/YY HH:MM:SS)
      #      6= elapsed (HH:MM:SS)
      #
      # @tmp is then put in a hash called "jobs_hash", with
      # back_id as the key, where back_id always
      # looks like "hostname_timestamp"

      $gb = $kb/1024/1024;
      ($junk,$start_stamp) = split /_/, $back_id, 2; 

      $end_stamp = &sumtime($start_stamp,$elapsed);
      $end_time = &stamp2time($end_stamp);

      # if this is being run on athena, we need to look at
      # the oracle/obackup jobs, too.  We will treat these
      # like incrementals, while renaming the type "Oracle"
      # to replace "user_directed"
      # 
      if ($class =~ /nitti_online_Oracle/) { 
         $total_inc_gb = $total_inc_gb + $gb;
         $type = "Oracle";
        
         # check to see if this is the earliest job in the output
        if ($start_stamp < $first_incremental) {
           $first_incremental = $start_stamp;
        }
         # check to see if this is the latest job in the output
        if ($end_stamp > $last_incremental) {
           $last_incremental = $end_stamp;
        }
      }

      if ($type =~ /Full/) { 
         $total_full_gb = $total_full_gb + $gb;
         # check to see if this is the earliest job in the output
        if ($start_stamp < $first_full) {
           $first_full = $start_stamp;
        }
         # check to see if this is the latest job in the output
        if ($end_stamp > $last_full) {
           $last_full = $end_stamp;
        }
      }

     elsif ($type =~ /Incremental/) {
         $total_inc_gb = $total_inc_gb + $gb;
         $type = "Incr.";
         # check to see if this is the earliest job in the output
        if ($start_stamp < $first_incremental) {
           $first_incremental = $start_stamp;
        }
 
         # check to see if this is the latest job in the output
        if ($end_stamp > $last_incremental) {
           $last_incremental = $end_stamp;
        }
      }

       
      $tmp[0] = $start_time;
      $tmp[1] = $client;
      $tmp[2] = $class;
      $tmp[3] = $type;
      $tmp[4] = $gb;
      $tmp[5] = $end_time;
      $tmp[6] = $elapsed;
 
      $jobs_hash{$back_id} = [ @tmp ];
 
      $client=$class=$type=$kb=$end=$elapsed="";
    } #elsif "^$"
} #while
close IMAGES;

#
# printing of the report header
# begins here, we use the first_
# and last_ variables in the
# header, but we need to convert
# them from epoch time to human
# readable dates
#
$first_full_time = &stamp2time($first_full);
$last_full_time = &stamp2time($last_full);
$first_incremental_time = &stamp2time($first_incremental);
$last_incremental_time = &stamp2time($last_incremental);

open(REPORT,">$report_file");
 
print REPORT "               Backup Report - $server ($start_date - $end_date) 
\n\n";


############
# the other place where those command
# line switches have an effect.
# If "-nofulls" or "-noincrementals"
# was specified at the command line,
# then there won't be a summary line
# printed.
############

if (!$omit_fulls && $last_full) {
    print REPORT "                   Summary - Fulls:\n\n";
    print REPORT "Started              Finished             Total GB Backed 
Up\n#################    #################    ################\n";
    print REPORT "$first_full_time    $last_full_time    $total_full_gb\n\n";
}

if (!$omit_incs && $last_incremental) {
    print REPORT "                   Summary - Incrementals:\n\n";
    print REPORT "Started              Finished             Total GB Backed 
Up\n#################    #################    ################\n";
    print REPORT "$first_incremental_time    $last_incremental_time    
$total_inc_gb\n\n";
}

############
# dump out the failed backups
############
use FileHandle;
REPORT->format_name("ERRORS");
REPORT->format_top_name("ERRORS_TOP");

if ($failed_found) {
   foreach $job ( sort keys %failed_hash ) {
 
     $error_client= $failed_hash{$job}[1];
     $error_class= $failed_hash{$job}[2];
     $error_type= $failed_hash{$job}[3];
     $exit_status= $failed_hash{$job}[4];
     $error_start_time= $failed_hash{$job}[0];

     $errors_to_print{$exit_status} = 1;
 
     write REPORT;
   } #foreach
}
else {
   $error_client= "No Problems";
   $error_class = "";
   $error_type = "";
   $exit_status = "";
   $error_start_time = "";

   write REPORT;
} 

format_lines_left REPORT 0;

REPORT->format_name("ERROR_TEXT");
REPORT->format_top_name("ERROR_TEXT_TOP");
slurp_error_text();
foreach $error (sort {$a <=> $b} keys %errors_to_print) {
   write REPORT;
}

format_lines_left REPORT 0;

############
# dump out the successful backups
############
REPORT->format_name("REPORT");
REPORT->format_top_name("REPORT_TOP");

foreach $job ( sort keys %jobs_hash ) {
 
     $client= $jobs_hash{$job}[1];
     $class= $jobs_hash{$job}[2];
     $type= $jobs_hash{$job}[3];
     $start= $jobs_hash{$job}[0];
     $end= $jobs_hash{$job}[5];
     $gbytes= $jobs_hash{$job}[4];
     $elapsed= $jobs_hash{$job}[6];

$start_time = substr($start, 9, 8);
$end_time = substr($end, 9, 8);
 
     write REPORT;
} #foreach

close REPORT;

#system("/usr/bin/cat $error_codes >> $report_file");
system("$mail -s \"Backup Report - $server\" $mail_to < $report_file");

############
#  end of the actual program
############


###########
# Reports and subroutines below
########### 

format ERRORS_TOP = 
               The following backups had problems:
    (three entries for a client probably means that client failed completely)

Client       Class               Type    Start Time         Exit Status
=======================================================================
.


format ERRORS = 
@<<<<<<<<<<  @<<<<<<<<<<<<<<<<<  @<<<<<  @<<<<<<<<<<<<<<<<      @<<<
$error_client,$error_class,$error_type,$error_start_time,$exit_status
.


format ERROR_TEXT_TOP =

Error Codes
=======================================================================
.


format ERROR_TEXT =
@<<< 
@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
$error, $error_text{$error}
.


format REPORT_TOP = 

               The following backups were successful:

                                         Start     End
Client       Class               Type    Time      Time      Elapsed    GBytes
==============================================================================
.


format REPORT = 
@<<<<<<<<<<  @<<<<<<<<<<<<<<<<<  @<<<<<  @<<<<<<<  @<<<<<<<  @<<<<<<<<  @<<<<
$client,     $class,             $type,  $start_time,$end_time,$elapsed,  
$gbytes
.

########
# this subroutine is given a line of text
# (in this case, a line of bpimagelist output)
# and returns everything (minus leading whitespace)
# after the colon.  e.g.
#
#    "Client:     ewok"
# 
# would return as just "ewok"
########
sub get_val {
   my ($str) = @_;
   $str =~ s/^.*?://;
   $str =~ s/   *//g;
   return $str;
}

#########
# this subroutine is given an epoch-style
# date (10 digits, seconds since 1970) and
# returns the equivalent date as "MM/DD/YY HH:MM:SS"
# e.g. if it is passed "0918799217", it will return
# "02/12/99 00:00:17"
#########

sub stamp2time {

my ($stamp) = @_;

($tmp_sec,$tmp_min,$tmp_hour,$tmp_day,$tmp_month,$tmp_year,$a,$b,$c) = 
localtime($stamp);
$tmp_month = $tmp_month + 1;
$tmp_year = ($tmp_year + 1900) % 100;

#don't really need to do this, but it makes for a
#prettier report.  (turns 2/3/99 23:6:9 into 02/03/99 23:06:09)
#
foreach $item ($tmp_sec,$tmp_min,$tmp_hour,$tmp_day,$tmp_month,$tmp_year) {
$item =~ s/^([0-9])$/0$1/;
}

$time = $tmp_month . "/" . $tmp_day . "/" . $tmp_year . " " . $tmp_hour . ":" . 
$tmp_min . ":" . $tmp_sec;
 
return $time;
}

#########
# this subroutine is given a human-readable
# date (MM/DD/YY HH:MM:SS) and returns the
# equivalent epoch-style date (10 digits, 
# seconds since 1970) 
# e.g. if it is passed  "02/12/99 00:00:17",
# it will return "0918799217"
#########
sub time2stamp {

my ($time) = @_;

use Time::Local;
($tmp_date,$tmp_time) = split / /, $time, 2;
($tmp_month,$tmp_day,$tmp_year) = split /\//, $tmp_date, 3;
($tmp_hour,$tmp_min,$tmp_sec) = split /:/,$tmp_time, 3;

$stamp = timelocal($tmp_sec,$tmp_min,$tmp_hour,$tmp_day,$tmp_month-1,$tmp_year);
 
return $stamp;
}

##########
# this subroutine is given two
# parameters - an epoch start time
# and an elapsed time in the form
# of HH:MM:SS.  The returned value
# is an epoch time that represents
# start + elapsed
##########
sub sumtime {

my ($s_stamp) = @_[0];
my ($e_hours,$e_min,$e_sec) = split /:/,@_[1], 3;

$e_seconds = $e_sec + 60*$e_min + 3600*$e_hours;
$sum = $s_stamp + $e_seconds;

return $sum;
}

#
# Slurp error text into an array for use later:
sub slurp_error_text {
    undef %error_text;
    open(E, $error_codes);
    while (<E>) {
        if (/^[0-9]/) {
            chomp;
            ($num, $text) = split(/\s+/, $_, 2);
            $error_text{$num} = $text;
        }
    }
    close(E);
}

--------------646A8C28D04B25B9986CDBB0--


<Prev in Thread] Current Thread [Next in Thread>