#!/usr/bin/perl  

#ModulePurpose: Audit links in ETR 
#ModuleName: validate_ETR_links 
# On hold. Their bieker webpage still has issues with SLCs 0/1.

# Requires STP link data saved as text file
# 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 unique_array {
# Find elements that are in one array but not another.
# find only elements in @A and not in @B
#assume @A and @B are already loaded

   $refA = shift;
   $refB = shift;
   ($asize, $bsize, $missing) = 0;

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

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

   # find only elements in @A and not in @B
   foreach $item (@$refA) {
       unless ($seen{$item}) {
           # it's not in %seen, so add to @aonly
           push(@aonly, $item);
#print "aonly:$item\n";
       }
   }
       $asize = @$refA; 
       $bsize = @$refB; 
       $missing = scalar @aonly;

  return ($asize, $bsize, $missing, @aonly);

} #unique_array
#########
sub check {
# Using ETR generated by daily backups, and switch.linkinfo.txt files provided,
#  a) verify switch links are configured into a7
#  b) find invalid links configured in 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";
#     $etrfile = "$TmpDir/junk.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 = (514, 302);
#       my @sprintlist = (306, 314, 301, 302, 305, 307, 303, 304);
#       my @sprintlist = reverse(@sprintlist);
#       @sprintlist = sort(@sprintlist);
    
       foreach $switch (@sprintlist){
             print "  working on switch $switch...\n";

             #reset for each switch
             my @linksets = ();           # array of unique, sorted linksets by site 

                 # to avoid the need for specific filenames,
                 # the filename just has to have the switch number somewhere
#configurable
             $switchfile = qx[ls $TmpDir/../files/*$switch* 2> /dev/null ];  
             if (! $switchfile) {
                  print PROBLEMS "  No text file for $switch\n";
#                  print "  No text file for $switch\n";
                  next;
             }

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

             #count number of linkset entries in ETR and switchlist 
             #  pre-req: need list of linksets from create_listset_list
               &count_linkset_lines(\@linksets, $switchfile, $etrfile); 
               my ($total_switchlinks, $total_etrlinks) = &count_linkset_lines(\@linksets, $switchfile, $etrfile); 
               my $delta = $total_etrlinks - $total_switchlinks; 

             # using switch data, look for matching info in ETR
             #  pre-req: need list of linksets from create_listset_list
             ($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);

   # Just in case they exist 
   unlink("$local_junk1") || print $!;
   unlink("$local_junk2") || print $!;

    # 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";

     #format and header
     print JUNK1 $header;
    
     qx[grep -E " No text file for "                               $local_problems >> $local_junk1];
        print JUNK1 "\n";
     qx[grep -E "links in ETR not found in SwitchData"             $local_problems >> $local_junk1];
        print JUNK1 "\n";
     qx[grep -E "SLCs found in SwitchData, but missing from ETR. " $local_problems >> $local_junk1];
        print JUNK1 "\n";
     qx[grep -E "SLCs found in ETR, but not in SwitchData: "       $local_problems >> $local_junk1]; 
    
     #format and header
     print JUNK2 $header;
     qx[grep -E "UniqueLinksets:"                                  $local_details  >> $local_junk2];
     qx[grep -E "links in ETR not found in SwitchData"             $local_details  >> $local_junk2];
     qx[grep -E "SLCs found in SwitchData, but missing from ETR. " $local_details  >> $local_junk2];
     qx[grep -E "SLCs found in ETR, but not in SwitchData: "       $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 count_linkset_lines {
# count number of linkset entries in ETR and switchlist 

   print "              count_linkset_lines\n";

   my $ref_linksets = shift;
   my $switchfile = shift;
   my $etrfile    = shift;
   
   my ($total_switchlinks, $total_etrlinks) = 0;  #total for site

   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";

   foreach my $linksetname(@{$ref_linksets}) {
      open SWITCH, "<$switchfile" or croak "Can't open switchfile for read $!\n";
      open ETR, "<$etrfile" or croak "Can't open etrfile for read $!\n";

      my ($switch_linkscount,$etr_linkscount) = 0;   #count per linkset 
      my $numunique_linksets = scalar @{$ref_linksets};

      while (my $line = <SWITCH>){
         if ( ($line =~ /$linksetname/) && ($line =~ /ACT/) ){
                 $switch_linkscount++ ;
         } 
      }
      while (<ETR>)    {$etr_linkscount++    if /$linksetname/ }; 

#      if ( $switch_linkscount != $etr_linkscount) {
#           printf "%8s  switch:%3d  etr:%3d  \n", $linksetname, $switch_linkscount, $etr_linkscount;
#      }

      $total_switchlinks = $total_switchlinks + $switch_linkscount;
      $total_etrlinks    = $total_etrlinks    + $etr_linkscount;

      close (SWITCH);
      close (ETR);
    }  #end of processing each linkset

    my $delta = $total_etrlinks - $total_switchlinks; 
   printf DETAILS "switch:$switch  UniqueLinksets:%-4d  EtrLinks(configured):%-6d   SwitchLinks(RefData):%-6d  Configured-RefData_Delta:%-6d\n",$numunique_linksets, $total_etrlinks, $total_switchlinks, $delta;

  close (PROBLEMS);
  close (DETAILS);
  return ($total_switchlinks, $total_etrlinks);
} #count_linkset_lines

sub lookfor_linkset_slc {
# using switch data, look for matching info in ETR
  # &lookfor_linkset_slc(\@linksets, $switchfile, $etrfile); 

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

   my ($totalExtraSLCs_found_in_ETR, $totalSLCs_missing_from_ETR) = 0;

   print "              lookfor_linkset_slc\n";

   # for each linkset, see if linkset<slc> exists in ETR
   foreach $linksetname (@{$ref_linksets}) {

      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 = grep(!$saw{$_}++, @switchSLCs);
          @switchSLCs = sort(@switchSLCs);
#print "switch:$linksetname @switchSLCs ";
#print "\n";
          # Now have array of sorted SLCs for current linkset
      }

      while (my $etrline = <ETR>){
          chomp $etrline;
         if ( ($etrline =~ /$linksetname/) && $etrline =~ /\\/) {  #only want lines w/linkset info
#print "etr: $etrline\n";
              #703:NxDS0 15 iDEN_LowSpeed FTW302<15>WSLDMI05D00 FTW-LS9999/15-1900 acceSS7 ENABLED \

              my @etrarr = split(/\s+/,$etrline);
              my $etrSLC = $etrarr[1];
              if ( $etrSLC =~ /\d+/) {
                  push(@etrSLCs, $etrSLC);
              }
         } 
          #sort and unique SLCs
          undef %saw;
          @etrSLCs = grep(!$saw{$_}++, @etrSLCs);
          @etrSLCs = sort(@etrSLCs);
          # Now have array of sorted SLCs for current linkset
      } #finished one pass thru etrfile for each linkset

    # for each linkset, find which SLCs are found in switch but missing from ETR
     my($asize, $bsize, $missing, @aonly) = &unique_array(\@switchSLCs,\@etrSLCs);
     $totalSLCs_missing_from_ETR = $totalSLCs_missing_from_ETR + $missing;

#print "switchCount:$asize  etrCount:$bsize  missing:$asize - $bsize  missing2:$missing   sum:$sum  $totalSLCs_missing_from_ETR\n";
     if ($missing > 0) {
             print PROBLEMS "$linksetname:  $missing SLCs found in SwitchData, but missing from ETR:  @aonly";
             print PROBLEMS  "\n";
             print DETAILS  "$linksetname:  $missing SLCs found in SwitchData, but missing from ETR. ";
             print DETAILS "\n";
      }
#-------------------------------------------------------------
    # for each linkset, find which SLCs are found in ETR and not switch
     my($asize, $bsize, $missing, @aonly) = &unique_array(\@etrSLCs,\@switchSLCs);
     $totalExtraSLCs_found_in_ETR = $totalExtraSLCs_found_in_ETR + $missing;

#print "etrCount: $asize  switchCount:$bsize  missing:$asize - $bsize  missing2:$missing   sum:$sum  $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 DETAILS  "$linksetname:  $missing SLCs found in ETR, but not in SwitchData\n";
     } 
      close (ETR);
      close (SWITCH);
      close (DETAILS);
      close (PROBLEMS);

      next;
      return ($totalExtraSLCs_found_in_ETR, $totalSLCs_missing_from_ETR);
   } #process each linksetname
} # lookfor_linkset_slc 

sub check_etr {
# see what data in ETR can be removed

   print "              check_etr\n";
   my $switchfile   = shift;
   my $etrfile      = shift;

   my ($site, $switch, $etrsite, $etrlink) = "";
   my (@arr, @switchData, @etrarr, @etrData) = ();
   my ($switchlink, $switchlinkset) = "";

   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";

      while (my $line = <SWITCH>){
          chomp $line;

#print "before  @switchData";  
          if ($. == 1) {     # get site from header 
               # Site: FTW302 - Status: ALL
               @arr = split(/\s+/,$line);
               $switch  = $arr[1];   #  AKR314 
               $site    = $arr[1];   #  AKR314 
               $site  =~ s/[0-9]//g; #  AKR 
          }   
          if ( ($line =~ /^\d+\b/) && ($line =~ /ACT/) ) {
               @arr = split(/\s+/,$line);
               $switchlink    = $arr[0];   # 2414
               $switchlinkset = $arr[4];   # LS4152
#print "linkset: $switchlinkset  \n";
               push (@switchData, "$switchlink");
          } 
     }
      close (SWITCH);
 
      #sort and unique link numbers 
      undef %saw;
      @switchData = grep(!$saw{$_}++, @switchData);
      @switchData = sort {$a <=> $b} @switchData;
    
      #prefix link number w/ site 
      foreach my $xx(@switchData){  
          $xx = "$site-$xx";   #AKR-1094
      }


      # now get numbers from ETR file
      while (my $line = <ETR>){
          chomp $line;

          if ( ($line =~ /$switch/)&& ($line =~ /ENABLED/) && ($line !~ /ILM/) ) {
               @arr  = split(/\s+/,$line);
               if ($arr[3] =~ /\b^$switch(-|<)\b/) {
                     $etrdata = $arr[4];   
                     @etrarr  = split(/-/,$arr[4]);
                     $etrsite = $etrarr[0];  #  AKR 
                     $etrlink = $etrarr[2];  #  2176 
                 
                     if($etrlink =~ /[0-9]+/){
#print "$etrlink\n";
                          push (@etrData, $etrlink);
                     }
               }
          } 
      }
      close (ETR);

      #sort and unique link numbers 
      undef %saw;
      @etrData = grep(!$saw{$_}++, @etrData);
      @etrData = sort {$a <=> $b} @etrData;
    
      #prefix link number w/ site 
      foreach my $item(@etrData){  
          $item = "$etrsite-$item";   #AKR-1094
      }

    # find what's in ETR only
    my($asize, $bsize, $missing, @aonly) = &unique_array(\@etrData,\@switchData);

 print "etrcount:$asize   switchcount:$bsize   missing:$missing  \n";
     if ( $missing != 0) {
             print PROBLEMS "$switch: $missing links in ETR not found in SwitchData:    @aonly\n";
             print  "$switch: $missing links in ETR not found in SwitchData:    @aonly\n";
             print DETAILS  "$switch: $missing links in ETR not found in SwitchData.\n";
      }
      print "\n";
    close (DETAILS);
    close (PROBLEMS);

} # check_etr 
