#!/usr/bin/perl 

#ModulePurpose: put link, linkset info, and hardware monitoring the link in a .csv format
#ModuleName: map_links_to_hardware 

# First have to make ETR links are in correct linkset/link/interface/monitoring syntax
# perl -ne 'chomp ; if (/^\[linkset/){print "\n $_"}; \
#  if (/^\[link\]/){print "$_"}; \
#  if (/^\[monitoring\]/){print "$_"}; ' etr.bad_slcs \
#  |sort -u  | grep -E "\[link\]\[link\]"

# lookfor:
# (no monitoring or interface)
# [linkset][link]
#  [linkset][link][monitoring]
#  [linkset][link][monitoring][link]
#  [linkset][link][monitoring][link][monitoring]

# (two links next to each other)
#[linkset][link][monitoring][link][monitoring][link][monitoring][link][monitoring][link][monitoring] \
#[link][monitoring][link][monitoring][link][link][monitoring][link][monitoring][link][monitoring] \

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();

  $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 {
# parse ETR file 

     print "map links to hardware\n";

      my $local_problems = "$TmpDir/hw_problems";
      my $local_details  = "$TmpDir/hw_details";
      my $local_junk1    = "$TmpDir/junk1";    # temp file for problems
      my $local_junk2    = "$TmpDir/junk2";    # temp file for details
      my $local_junk3    = "$TmpDir/junk3";    # temp file for link/interface/monitoring info

    # 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 $local_details for write: $!\n";

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

    # 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 {
         open (IN, "<$etrfile") or croak "Can't open etr $etrfile for read: $!\n";
         open (JUNK3, ">>$local_junk3") or croak "Can't open junk3 $local_junk3 for write: $!\n";
         while (<IN>) { 
              my @etrdata=();
              chomp;
              next if /^\#/; 

              if (/^\[link\]$/ ... /p7ctf /) {
                   if (/\[link\]/ ... /\\$/) {  #just link info
                      push @etrdata,$_;
                   }
#                   if (/NETELE/ .. /^\s+/) {  #chanA info
#                      push @etrdata,$_;
#                   }
                   if (/^\[interface\]$/ ... /^\s+/) { 
                      push @etrdata,$_;
                   }
                       
#                  if (/^V35CU:/ .. /^\s+/) {  #great, a one off if link type is:Q703:V35
#                                              # V35CU:J6736A 5 \
#                                              #   BOTH 31 3 0 12 1 0 
#                      push @etrdata,$_;
#                   }
                   if (/monitoring/ .. /BOTH/) {  #just monitoring 
                      push @etrdata,$_;
                   }
              }
              
              foreach my $line (@etrdata){ 
                 $line =~ s/(\s+|\\)/ /g; 
                 if ($line =~ /^\[link\]$/) {  #new link
                     print JUNK3 "\n$line ";
                 }else {
                     print JUNK3 "$line ";   #join lines
                 }
             }
        } #end while (<IN>)
     }
     close(IN);       #etr
     close(JUNK3);    # all link/interface/monitoring info
     close(PROBLEMS); # only info captured is stale etr file

    # junk3 now contains required elements from each section
      # lable  [link_protocol] (link_num) "personality"  "name"       "alt_name" "mon sys" [active_flag]
      # [link] Q703:NxDS0        9         LowSpeed    mpc3<09>lsmpc3   ""         acceSS7   ENABLED

      #  [interface_type] (site) [chan] (cardcage/PP) (i/f slot/HSIC_num  type param1]...[type_paramN]}
      #  NETELEM:J6739A     1    CHANA   4                  8              SSG 440 6156 1 "" 1 0 ""
      #  V35CU:J6736A       5    BOTH    31                 3              0 12 1 0


      # "application" [chan] (cardcage) (slot/PP num)
      #  p7ctf         BOTH      4           5


      open (JUNK3, "<$local_junk3") or croak "Can't open junk3 $local_junk3 for read: $!\n";

      while (my $line = <JUNK3>) {    #each line has all link/interface/monitoring info
             my $link_protocol = "";
             my $link_number   = "";
             my $personality   = "";
             my $name          = "";
             my $alt_name      = "";
             my $interface_type = "";
             my $site          = "";
             my $link_numb     = "";
             my $cardcage      = "";
             my $bpp           = "";

          chomp $line;
          next if ($line =~ /^$/);

          my @arr =  split(/\s+/,$line);
          my $elements = @arr ;
          if ($arr[1] =~ /NxDS0/)  {
             $link_protocol  = $arr[1];
             $link_number    = $arr[2];
             $personality    = $arr[3];
             $name           = $arr[4];
             $alt_name       = $arr[5];
             $interface_type = $arr[9];
             $site           = $arr[10];
             $link_numb      = $arr[15];  
             $cardcage       = $arr[25];  
             $bpp            = $arr[26];  
          }   
          if ($arr[1] =~ /IP:ETHERNET/)  {
             $link_protocol  = $arr[1];
             $link_number    = $arr[2];
             $personality    = $arr[3];
             $name           = $arr[4];
             $alt_name       = $arr[5];
             $interface_type = $arr[9];
             $site           = $arr[10];
             $link_numb      = "NA";  
             $cardcage       = $arr[25];  
             $bpp            = $arr[26];  
          }   
          if ($arr[1] =~ /Q703:V35/)  {
             $link_protocol  = $arr[1];
             $link_number    = $arr[2];
             $personality    = $arr[3];
             $name           = $arr[4];
             $alt_name       = $arr[5];
             $interface_type = $arr[9];
             $site           = $arr[10];
             $link_numb      = "NA";  
             $cardcage       = $arr[21];  
             $bpp            = $arr[22];  
          }   
             
 print DETAILS "$link_protocol,$link_number,$personality,$name,$alt_name,$link_numb,$site,$cardcage,$bpp\n";
      }
      close(DETAILS);

    my $badcount = line_count($local_problems);

    # open local 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--- $badcount issues creating link_mapping.csv\n";
    my $local_header = "link_protocol,link_number,personality,name,alt_name,link_number,site,CC,BPP,\n";

    if ( $badcount > 0 ){  # at least one problem
         #format and header
         print JUNK1 $header;
         qx[cat $local_problems >> $local_junk1];
         close(JUNK1);
    
          #format and header
          print JUNK2 $header;    #only problem will be stale etr, and no details will exist
          close(JUNK2);
    } else {
          #format and header
          print JUNK2 $local_header;
         qx[sort $local_details >> $local_junk2];
         close(JUNK2);
    }
   copy($local_junk1,$local_problems) or die "junk1 cannot be copied";
   copy($local_junk2,$local_details) or die "junk2 cannot be copied";

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

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

