#!/usr/bin/perl  

#ModulePurpose: Audit links in ETR 
#ModuleName: validate_ETR_links 

# Requires link data saved as text file in format of:


# Files are saved in archives dir

use lib '/h/bmetzger/s/p/hc/';
use HC qw(:ALL);  #functions available to all modules 

use English;
use Carp;
use Cwd;
use DBI;
use Net::Ping;
use File::Basename;
use File::Path;
use File::Glob;
use File::Copy;

###############3###
# define location of, and open files
##################

   my ($TmpDir,$sitelist,$global_problems,$global_details,$global_summary,$ArchiveDir) = InitVars();

   my $local_problems = "$TmpDir/ETRaudit_problems";    # temp place for all localjunk1 
   my $local_details  = "$TmpDir/ETRaudit_details";     # temp place for all localjunk2;

   unlink("$local_problems") || print $!;
   unlink("$local_details") || print $!;

  $ENV{'PATH'} = '/usr/bin:/usr/local/bin:/usr/sbin/:/usr/ucb:/etc/:/opt/platform7/lbin/:.';
  &initvars();

### checks
 ($header, $local_problems, $local_details)= &check(); 
#  summarize($header, $local_problems, $local_details);

###################33
sub initvars {

   ($sys_day,$sys_mon,$sys_year) = (localtime)[3,4,5];
   $sys_mon += 1;  #jan is 0
   $sys_year += 1900;
   $today = sprintf "%02d.%02d.%d",$sys_mon,$sys_day,$sys_year;  # zero fill date

   $ENV{'PATH'} = '/usr/bin:/usr/local/bin:/usr/sbin/:/usr/ucb:/etc/:.';
} #initvars

####################
sub line_count {
# perform a  wc -l

  my $file = shift;
    open my $fh, "<", $file or die "could not open $file:$!";
    my $lines = 0;
    $lines++ while <$fh>;
    return $lines;
    close ($fh);
} #line_count

#########
sub check {
# Using ETR generated by daily backups, and switch.linkinfo.txt files provided,
#  a) verify links are configured into a7

     print "audit ETR linkinfo \n";

    # open local output files
    open PROBLEMS, ">>$local_problems" or croak "Can't open file $local_problems for write: $!\n";
    open DETAILS, ">>$local_details" or croak "Can't open file $local_details for write: $!\n";

     $etrfile = "/h/bmetzger/s/tmp/all/wm.etr";

     my $local_junk1    = "$TmpDir/junk1";    # temp file for problems
     my $local_junk2    = "$TmpDir/junk2";    # temp file for details

    # if ETR file is missing, or created > one days ago.....
    if ( (! -e $etrfile) || (-C $etrfile > 1) ) {
         printf   "$etrfile missing or old\n";
         printf PROBLEMS  "$etrfile missing or old\n";
    }else {

       #sprint switches:  akr314 atl306   chc301 ftw302   nas307 nyc305  ril304 stk303
       my @sprintlist = (akr_hsl);
#       my @sprintlist = (306, 314, 301, 302, 305, 307, 303, 304);
#       my @sprintlist = reverse(@sprintlist);
#       @sprintlist = sort(@sprintlist);
    
       foreach $DBfile (@sprintlist){
             print "  working on DB $DBfile...\n";

             #reset for each switch
             my $delta = 0;               # number of times linksets are seen in etr
             my @linksets = ();           # array of unique, sorted linksets by site 
             my $total_etrlinks = 0;      # number of times linksets are seen in etr
             my $total_switchlinks = 0;   # number of times linksets are seen in etr
             my $numunique_linksets = 0;  #number of linksets / switch
#stopped
                 # to avoid the need for specific filenames,
                 # the filename just has to have the switch number somewhere
             $DB = qx[ls $TmpDir/db.$DBfile 2> /dev/null ];  
             if (! $DB) {
                  print PROBLEMS "  No database file for $DBfile\n";
                  print  "  No database file for $DBfile\n";
                  next;
             }

             #parse DBfile, and create unique, sorted list of linksets 
               my (@linksets) = &create_linkset_list($DBfile);

             #count number of linkset entries in ETR and switchlist 
             #  pre-req: need list of linksets from create_listset_list

             # using switch data, look for matching info in ETR
             #  pre-req: need list of linksets from create_listset_list
#             my ($totalExtraSLCs_found_in_ETR, $totalSLCs_missing_from_ETR) = &lookfor_linkset_slc(\@linksets, $switchfile, $etrfile); 

             # see what data in ETR can be removed
#                &check_etr($switchfile, $etrfile); 

#            foreach (@linksets) { 
#                 print "$_\n";
#            }
       }
    }

    #gotta close, so lines can be counted
    close(DETAILS);
    close(PROBLEMS);

    my $badcount = line_count($local_problems);
 

#print "extra:$totalExtraSLCs_found_in_ETR  "; 
#print "missing:$totalSLCs_missing_from_ETR\n"; 

    # Format output files
    open JUNK1, ">>$local_junk1" or croak "Can't open file local_junk1 for write: $!\n";
    open JUNK2, ">>$local_junk2" or croak "Can't open file local_junk2 for write: $!\n";

#    my $header = "\n--- compare links in SwitchData and ETR \n";
#    my $localheader = "
# $slc_missing_from_ETR ACT link SLCs missing in ETR
# $extra_slc_in_ETR links in ETR not found in SwitchData\n";

     #format and header
     print JUNK1 $header;
     print JUNK1 $localheader;
    
     qx[grep -E "but not in ETR"        $local_problems >> $local_junk1];
     qx[grep -E "but not in switchdata" $local_problems >> $local_junk1];
    
         #format and header
         print JUNK2 $header;
         print JUNK1 $localheader;
         qx[cat $local_details >> $local_junk2];

   copy($local_junk1,$local_problems) or die "junk1 cannot be copied";
   copy($local_junk2,$local_details) or die "junk2 cannot be copied";

   close (JUNK1);
   close (JUNK2);

#   unlink("$local_junk1") || print $!;
#   unlink("$local_junk2") || print $!;

  return($header, $local_problems, $local_details);
} #check

sub create_linkset_list {
# parse switchlist, and create unique, sorted list of linksets 

   print "              create_linkset_list\n";

   my $switchfile = shift;       #read in reference to file
   my @linksets = ();

    # open   files
    open INFILE, "<$switchfile" or croak "Can't open switchfile for read $!\n";
    open PROBLEMS, ">>$local_problems" or croak "Can't open file $local_problems for write: $!\n";

    # produce unique, sorted, list of linksets for switch
    while (my $line = <INFILE>){
         chomp $line;
         next if ($line =~ /^\D/);   # eliminate headers and text
         if ( ($line =~ /^[0-9]*/) && ($line =~ /ACT/)) {
             my @arr = split(/\s+/,$line);
             push(@linksets, $arr[4]);
         } 
    }
    undef %saw;
    @linksets = sort(@linksets);
    @linksets = grep(!$saw{$_}++, @linksets);

#    foreach (@linksets) { 
#         print "$_\n";
#    }

  close INFILE;
  close PROBLEMS;
  return(@linksets);
} #create_linkset_list


sub lookfor_linkset_slc {
# using switch data, look for matching info in ETR

   my $ref_linksets = shift;
   my $switchfile   = shift;
   my $etrfile      = shift;

   print "              count_linkset_lines\n";

   # for each linkset, see if linkset<slc> exists in ETR
   foreach $linksetname (@$ref_linksets) {
#     print "\n";

      open SWITCH, "<$switchfile" or croak "Can't open switchfile for read $!\n";
      open ETR, "<$etrfile" or croak "Can't open etrfile for read $!\n";
      open PROBLEMS, ">>$local_problems" or croak "Can't open file $local_problems for write: $!\n";
      open DETAILS, ">>$local_details" or croak "Can't open file $local_details for write: $!\n";

      my @switchSLCs = ();   # reset for each linkset
      my @etrSLCs = ();   

      # create array of all SLCs found
      while (my $line = <SWITCH>){
          chomp $line;
          $line =~ s/(\<|\>)//g;      #remove arrows around slc
          if ($line =~ /$linksetname/) {   
               my @arr = split(/\s+/,$line);
               my $switchSLC  = $arr[2];  #01, 02 ....
               if ($switchSLC =~ /^0\d/) {       #remove leading 0.  But don't change nuber 10
                  $switchSLC =~ s/0//;   #0, 1, 2 ....
               }
               push(@switchSLCs, $switchSLC);
          }
          #sort and unique SLCs
          undef %saw;
          @switchSLCs = sort(@switchSLCs);
          @switchSLCs = grep(!$saw{$_}++, @switchSLCs);
#print "switch:$linksetname @switchSLCs ";
          # Now have array of sorted SLCs for current linkset
      }
#print "  post switchSLCs:   @switchSLCs";

      while (my $etrline = <ETR>){
          chomp $etrline;
         if ( ($etrline =~ /$linksetname/) && $etrline =~ /\\/) {  #only want lines w/linkset info
#print "etr: $etrline\n";
              #Q703:NxDS0 0 LowSpeed ATL306 WAS230/00 ATL LS6055/0 006 acceSS7 ENABLED \
              my @etrarr = split(/\s+/,$etrline);
              my $etrSLC = $etrarr[1];
              push(@etrSLCs, $etrSLC);
         } 
          #sort and unique SLCs
          undef %saw;
          @etrSLCs = sort(@etrSLCs);
          @etrSLCs = grep(!$saw{$_}++, @etrSLCs);
          # Now have array of sorted SLCs for current linkset
      } #finished one pass thru etrfile for each linkset
#print "  post etrSLCs:   @etrSLCs";

      # from Perl Cookbook
      # Want to find elements in @A that aren't in @B. 
      # Build a hash of the keys of @B to use as a lookup table. 
      # Then check each element in @A to see if it is in @B.

#foreach (@etrSLCs) {
#   print "$_\n";
#}
#print "  post switchSLCs:   @switchSLCs";
#print "  post etrSLCs:   @etrSLCs";
      @A = @switchSLCs;
      @B = @etrSLCs;
      %seen = ();         # lookup table to test membership of B
      @aonly = ();        # answer

      # build lookup table
      foreach $item (@B) { $seen{$item} = 1 }

      # find only elements in @A and not in @B
      foreach $item (@A) {
           unless ($seen{$item}) {
           # it's not in %seen, so add to @aonly
           push(@aonly, $item);
         }
     }
      my $asize = @A; 
      my $bsize = @B; 
      my $missing = @aonly;
      $totalSLCs_missing_from_ETR = $totalSLCs_missing_from_ETR + $missing;
         }
print "missing_insub:$totalSLCs_missing_from_ETR\n";
     if ( $missing > 0) {
             print PROBLEMS "$linksetname:  $missing SLCs found in switch data, but not in ETR: @aonly ";
             print PROBLEMS "\n";
             print  "$linksetname:  $missing SLCs found in switch data, but not in ETR: @aonly ";
             print  "\n";
      }
#-------------------------------------------------------------
#print "$linksetname: ";
#print "  switch:   @switchSLCs";
#print "  etr:   @etrSLCs";
      @A = @etrSLCs;
      @B = @switchSLCs;
      %seen = ();         # lookup table to test membership of B
      @aonly = ();        # answer

      # find only elements in @A and not in @B
      foreach $item (@B) {
           unless ($seen{$item}) {
           # it's not in %seen, so add to @aonly
           push(@aonly, $item);
     }
      my ($asize, $bsize, $missing) = 0;
      my $asize = @A; 
      my $bsize = @B; 
      my $missing = @aonly;

      $totalExtraSLCs_found_in_ETR = $totalExtraSLCs_found_in_ETR + $missing;
print "extra_insub:$totalExtraSLCs_found_in_ETR\n";

      if ( $missing > 0) {
             print PROBLEMS "$linksetname:  $missing SLCs found in ETR, but not in switchdata: @aonly ";
             print PROBLEMS "\n";
             print  "$linksetname:  $missing SLCs found in ETR, but not in switchdata: @aonly ";
             print  "\n";
     } 
      close (ETR);
      close (SWITCH);
      close (DETAILS);
      close (PROBLEMS);

      return ($totalExtraSLCs_found_in_ETR, $totalSLCs_missing_from_ETR);
   }  #finished processing all linksets 
} #end of function

