#!/usr/bin/perl
#
# SAPHanaSR-monitor
# (c) 2014 SUSE Linux Products GmbH, Nuremberg, Germany
# (c) 2015-2016 SUSE Linux GmbH, Nuremberg, Germany
# Author: Fabian Herschel <fabian.herschel@suse.com>
# License: GPL v2+
my $Version="0.23.2019.09.04.1";
#
##################################################################
use POSIX;
use strict;
use Sys::Syslog;
use Sys::Hostname;
use File::Path;
use Getopt::Long;
use lib '/usr/lib/SAPHanaSR';
use SAPHanaSRTools;

###################################
## this part is not for scale out and currently NOT zero-config

my $ClusterNodes=2;
my $ClusterPrimaries=1;
my $ClusterSecondaries=1;
#my %Name;
my %Host;
my $host = hostname();
my $sortBy="";

my $varlib='/var/lib/SAPHanaTD';
my $testfile='SAPHanaTD.status';
my $testcount=0;
my $first_test=1;
my $sid="";
my @sids=();
my $ino="";
my $Format="txt";
my $Continuous="no";
my $HtmlPage="/srv/www/hawk/public/SAPHanaSR/index.html";
my $Intervall=10;
my $cibFile="";
my $help=0;
my $ident = "SAPHanaSR-mon";
my $logopt = "pid";
my $facility = "LOCAL0";
my $priority = "info";
my %Colors;
#$Colors{"green"}="#7AC142";
#$Colors{"yellow"}="#fde944";
#$Colors{"red"}="#BB0000";
#$Colors{"grey"}="#B9B9B9";
$Colors{"green"}="#00c081";
$Colors{"yellow"}="#ffef8d";
$Colors{"red"}="#ed6924";
$Colors{"grey"}="#afa9ac";

sub init()
{
	my $result = GetOptions ("sid=s" => \@sids,
	                      "format=s" => \$Format,
	                      "cont=s" => \$Continuous,
                          "out=s" => \$HtmlPage,
	                      "cib=s" => \$cibFile,
                          "intervall=s" => \$Intervall,
                          "nodes=s" => \$ClusterNodes,
                          "help" => \$help,
	);
    if ( $help )  {
        printf "SAPHanaSR-monitor {[--sid=<sid[:instNr]>]} [--format=(txt|html)] [--cont=(yes|no)] [--out=<file>] [--intervall=<time>] [--nodes=<nodeNr>] [--help]\n";
        exit 0;
    }
    if ( $cibFile ) {
       set_cibFile($cibFile);
    }
    return 0;
}

#
################ BEGIN CUT - MOVE THAT TO AN PERL-LIBRARY LATER
#

sub  print_page
{
  my %P = @_;
  my $format=$P{format}; my  $sid=$P{sid}; my  $sid_color=$P{sidColor};
  my  $hana1stat=$P{hanaStatusA}; my  $node1=$P{nodeListA};
  my  $hana2stat=$P{hanaStatusB}; my  $node2=$P{nodeListB};
  my  $syncstat=$P{syncColor}; my  $syncdir=$P{syncDirection};
  my  $crm_out=$P{crmOut}; my  $crm_col=$P{crmColor}; my  $crm_errors=$P{crmErrors}; my  $crm_cfg=$P{crmConfig};
  my  $attr_out=$P{attrOut}; my  $attr_col=$P{attrColor}; my  $attr_errors=$P{attrErrors};
  my  $score_out=$P{scoreOut}; my  $score_col=$P{scoreColor}; my  $score_errors=$P{scoreErrors};
  my  $log_out=$P{logOut}; my  $log_col=$P{logColor}; my  $log_errors=$P{logErrors};
  my  $ftd_out=$P{ftdOut}; my  $ftd_col=$P{ftdColor}; my  $ftd_errors=$P{ftdErrors};
  my  $check_lpa_col=$P{lpaColor}; my  $check_lpa_msg=$P{lpaMessage};
  my  $cibtime=$P{cibTime} ;




  # in the page layout $score_col is ignored right now
  # TODO: Check id we add more and more parameters to the print_page or if we will use an hash as parameter or
  #       id we (recover) more values here inside of the function like for the lpa values:
    my $lpa_node1=get_lpa_by_host($sid, $node1);
    my $lpa_node2=get_lpa_by_host($sid, $node2);

  my $mydate=`date`; # TODO: do it with perl ;-)
  chomp($crm_errors);
  chomp($attr_errors);
  chomp($log_errors);
  my $nextUrl=".";
  my $nextNr; my $prevNr; my $prevUrl;
  if ( $format eq "html2" ) {
     my $Nr=0;
     my $FirstPart="";
     my $LastPart="";
     if ( $HtmlPage =~ /(.*\.)([0-9]+)(\.html)/ ) {
         $FirstPart = $1;
         $Nr = $2;
         $LastPart  = $3;
         #
         # remove path from url
         #
         $FirstPart =~ s/\/.*\/([^\/]*)$/.\/$1/ ;
         $nextNr = $Nr + 1;
         $prevNr = $Nr - 1;
         if ( $prevNr < 0 ) { $prevNr = 0; }
         $nextUrl="$FirstPart" . "$nextNr" . "$LastPart";
         $prevUrl="$FirstPart" . "$prevNr" . "$LastPart";
     }
  }
  if ($format eq "txt") {
      my $syncArrow="??";
      my $SID=uc($sid);
      if ( $syncdir eq "right" ) { $syncArrow = "=>"; }
      if ( $syncdir eq "left" ) { $syncArrow = "<="; }
      my $myPage = <<EOF;
OVERALL:   $SID: $sid_color                   $mydate
SR:        $syncstat $node1 $syncArrow $node2

Cluster:   $crm_col ($crm_errors)
HANA1:     $node1 ${hana1stat}
HANA2:     $node2 ${hana2stat}

SAPHanaSR: $attr_col ($attr_errors)
LPA:       $check_lpa_col ($check_lpa_msg)
LPA:       $node1 $lpa_node1
LPA:       $node2 $lpa_node2

Syslog:    $log_col ($log_errors)
EOF
    printf( "%s\n", $myPage);
  } elsif (($format eq "html")||($format eq "html2")) {
  my $myPage = <<EOF;
<!DOCTYPE html>
<html lang="en">
<head>
<title>SAPHanaSR status</title>
<meta http-equiv="refresh" content="10; url=$nextUrl" />
<meta charset="utf-8"/>
</head>
<body class="" style="background-color:#dcddde;">
<table cellpadding=5>
  <!-- ################## AREA SID-STATUS ################# -->
  <tr><td valign="top" bgcolor="$Colors{$sid_color}"><h2>$sid</h2></td>
      <td valign="top"><b>SAPHanaSR-monitor $cibtime</b>

      <table cellpadding=1>
          <tr><td valign="top"><a href="../1"><img width="75%" height="75%" src="icons/server_${hana1stat}.svg"/></a></td>
              <td><img width="75%" height="75%" src="icons/arrow_${syncdir}_${syncstat}.svg"/></td>
              <td valign="top"><a href="../2"><img width="75%" height="75%" src="icons/server_${hana2stat}.svg"/></a></td>
          </tr>
          <tr><td valign="top" align="center"><b>$node1</b></td>
              <td valign="top" align="center"><b>$sid</b></td>
              <td valign="top" align="center"><b>$node2</b></td>
          </tr>
          <tr>
      <td></td><td><a href="$prevUrl"> <img width="30" height="30" src="icons/back.svg"/></a>
      <a href="$nextUrl"> <img width="30" height="30" src="icons/fwd.svg"/></a></td>
          </tr>

      </table>
      </td>
      <td valign="top" align="right"><a href="https://www.suse.com/de-de/products/sles-for-sap/resource-library/sap-best-practices.html"><img width="45%" height="45%" src="icons/suse-logo.svg"/></a></td>
  </tr>
  <!-- ################## AREA ATTR ################# -->
  <tr><td valign="top" bgcolor="$Colors{$attr_col}" rowspan="2"><h2>Attr</h2></td>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$attr_out</pre></td>
  </tr>
  <tr><td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$attr_errors</pre></td>
  </tr>
  <!-- ################## AREA CRM #################
  <tr><td valign="top" bgcolor="$Colors{$crm_col}" rowspan="2"><h2>Crm</h2></td>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$crm_out</pre></td>
  </tr>
  <tr>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$crm_errors</pre></td>
  </tr>
  -->
  <!-- ################## AREA CFG #################
  <tr><td valign="top" bgcolor="$Colors{$crm_col}" rowspan="2"><h2>Cfg</h2></td>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$crm_cfg</pre></td>
  </tr>
  <tr>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$crm_errors</pre></td>
  </tr>
  -->
  <!-- ################## AREA LOG ##################
  <tr><td valign="top" bgcolor="$Colors{$log_col}" rowspan="2"><h2>Log</h2></td>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$log_out</pre></td>
  </tr>
  <tr>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$log_errors</pre></td>
  </tr>
  -->
  <!-- ################## AREA TD ##################
  <tr><td valign="top" bgcolor="#B9B9B9"><h2>TD</h2></td>
      <td valign="top" bgcolor="#B9B9B9" colspan="2"><pre>$ftd_out</pre></td>
  </tr>
  -->
</table>
</body>
</html>
EOF
open HTML, ">$HtmlPage.new";
print HTML $myPage;
close HTML;
system ("mv $HtmlPage.new $HtmlPage");
  } # end html
}




openlog $ident, $logopt, $facility;

#( $sid, $ino ) = get_sid_and_InstNr();

mysyslog $priority, "%s", "Monitor startup";

sub processMonitor($) {
    my $sid = shift();
    my $message;
    my $phost;
    my $shost;
    my $laststate="";
    #
    my %Global;
    my %GName;
    my %HName;
    my %Site;
    my %SName;
    my %Resource;
    my %RName;
    %Host=();
    %Host=(); %HName=(); %Global=(); %GName=(); %Site=(); %SName=();
    set_HName(\%HName);
    # set_Host(\%Host);
    # get_hana_attributes($sid, \%Host, \%HName, \%Global, \%GName, \%Site,   \%SName);
    get_hana_attributes($sid, \%Host, \%HName, \%Global, \%GName, \%Site,   \%SName, \%Resource, \%RName);
    # get_hana_attributes($sid);
# we do not need the crm_mon status in the monitor any more
    my $crm_out="";
    my $crm_cfg="";
#    if ( $cibFile ne "" ) {
#       $crm_out=`/usr/sbin/crm_mon -r1 -D --xml-file $cibFile`;
#       system("mkdir -p ~/.cib");
#       system("cp $cibFile ~/.cib/shadow.srMon");
#       $crm_cfg=`/usr/sbin/crm --cib srMon configure show`;
#    }
#    my $crm_out="Should be visible!!";
    my $attr_out=sprintf("%s%s%s%s\n", host_attr2string(\%Global, \%GName, "global", "", "tables"),
       host_attr2string(\%Site, \%SName, "sites", "", "tables"),
       host_attr2string(\%Resource, \%RName, "resources", "", "tables"),
       host_attr2string(\%Host, \%HName, "global", "", "tables"),
      );
 #   my $score_out=`crm_simulate -Ls | grep -i promo`;
    my $cibtime = $GName{"cib-time"}->{"global"};
 printf ("=========== %s ================\n", $cibtime );
    my $score_out="";
    my $log_out="";
    my $ftd_out="";
    if ( $cibFile eq "" ) {
        $log_out=`grep 'SAPHana.*INFO: RA' /var/log/messages | tail -20`; # TODO: Do we need to optimize the runtime of this command?
        $ftd_out=`grep 'fhTD' /var/log/messages | tail -10`;
    }
    my $ftd_col="grey";
    my $crm_col="green";
    my $attr_col="green";
    my $score_col="green";
    my $log_col="green";
    my $complete_col="green";

    #
    #  for the grafic output
    #
    my @node_list;
    @node_list = ( sort ( get_node_list() ));


    my $sync_col="green";
    my ( $first_node_name, $second_node_name ) = @node_list;
    my %hanaStatus;
    #unset %hanaStatus;

    my $thenode;
    foreach $thenode ( @node_list ) {
        $hanaStatus{$thenode}="grey";
        if ( check_node_status($sid, "34" , $thenode) ) { $hanaStatus{$thenode}="green"; }
        if ( check_node_status($sid, "2" , $thenode) ) { $hanaStatus{$thenode}="yellow"; }
        if ( check_node_status($sid, "1" , $thenode) ) { $hanaStatus{$thenode}="red"; }
    }
    if ( get_hana_sync_state($sid) ne "SOK" ) { $sync_col="red"; }
    my $sync_direction="none";
    if ( check_node_mode( $sid, "P" , $node_list[0]) && check_node_mode( $sid, "S" , $node_list[1]) ) {
    	$sync_direction="right";
    } elsif ( check_node_mode( $sid, "S" , $node_list[0]) && check_node_mode( $sid, "P" , $node_list[1]) ) {
	    $sync_direction="left";
    } else  {
        $sync_direction="none";
        $sync_col="grey";
    }

    #printf "first node: %s \n", $first_node_name;
    #printf "second node: %s \n", $second_node_name;
    my $first_node_col="green";
    my $second_node_col="green";

    #
    # crm checks
    #
    my $crm_errors="";
    if ( get_nodes_online() != $ClusterNodes ) { $crm_col="yellow"; $crm_errors .= " C#n\n";}

    # attr checks
    my $attr_errors="";
    if ( get_number_primary($sid, "1234") != 1 ) { $attr_col="yellow"; $attr_errors .= " A#p"; }
    if ( get_number_primary($sid, "234") != 1 ) { $attr_col="yellow"; $attr_errors .= " A-P"; }
    if ( get_number_secondary($sid, "1234") != 1 ) { $attr_col="yellow"; $attr_errors .= " A-s";}
    if ( get_number_secondary($sid, "234") != 1 ) { $attr_col="yellow"; $attr_errors .= " A-S";}
    if ( get_number_primary($sid, "234") > 1 ) { $attr_col="red"; $attr_errors .= " A-PP";}
    if ( get_hana_sync_state($sid) ne "SOK" ) { $attr_col="yellow"; $attr_errors .= " A-SFAIL"; }

    #printf "\n";

    #printf "%-16s %-16s %-16s\n", $hanaStatus{$node_list[0]}, "$sync_direction : $sync_col", $hanaStatus{$node_list[1]};
    #printf "%-16s %-16s %-16s\n", $node_list[0], $sid, $node_list[1];

    #printf "\n";
    # log checks
    my $log_errors="";
    my $check_lpa_status_col;
    my $check_lpa_msg;

    ( $check_lpa_status_col, $check_lpa_msg)=check_lpa_status($sid, $node_list[0], $node_list[1]);

    if ( ( $attr_col eq "yellow" ) || ( $crm_col eq "yellow" ) ||
         ( $log_col eq "yellow" ) || ( $attr_col eq "yellow" ) ||
         ( $score_col eq "yellow" ) || ( $check_lpa_status_col eq "yellow") )
       { $complete_col="yellow"; }
    if ( ( $attr_col eq "red" ) || ( $crm_col eq "red" ) ||
         ( $log_col eq "red" ) || ( $attr_col eq "red" ) ||
         ( $score_col eq "red" ) || ( $check_lpa_status_col eq "red"))
       { $complete_col="red"; }
# printf ("== 2 ========= %s ================\n", $cibtime );
    print_page(  format => $Format,
                  sid    => $sid,
                  sidColor => $complete_col,
                  hanaStatusA => $hanaStatus{$node_list[0]},
                  nodeListA  => $node_list[0],
                  hanaStatusB => $hanaStatus{$node_list[1]},
                  nodeListB  => $node_list[1],
                  syncColor  => $sync_col,
                  syncDirection => $sync_direction,
                  crmOut => $crm_out,
                  crmColor => $crm_col,
                  crmErrors => $crm_errors,
                  crmConfig => $crm_cfg,
                  attrOut => $attr_out,
                  attrColor => $attr_col,
                  attrErrors => $attr_errors,
                  scoreOut => $score_out,
                  scoreColor => $attr_col,
                  scoreErrors => $attr_errors,
                  logOut => $log_out,
                  logColor => $log_col,
                  logErrors => $log_errors,
                  ftdOut => $ftd_out,
                  ftdColor => $ftd_col,
                  ftdErrors => "",
                  lpaColor => $check_lpa_status_col,
                  lpaMessage => $check_lpa_msg,
                  cibTime => $cibtime,
              );
    #
    $phost=get_host_primary($sid, "1234");
    $shost=get_host_secondary($sid, "1234");
    my ($checkOK, $failures ) = check_all_ok($sid, $ClusterNodes);
    if ( $checkOK == 0 ) {
        $message="All checks passed - primary=$phost secondary=$shost";
        mysyslog $priority, "%s", $message;
    } else {
        if ( $checkOK == 1 ) {
		$message="$checkOK check failed ($failures) - primary=$phost secondary=$shost";
        } else {
		$message="$checkOK checks failed ($failures) - primary=$phost secondary=$shost";
        }
        mysyslog $priority, "%s", $message;
    }
}

init();
if ( 0 == @sids ) {
    my $sid_ino_list;
    ( $sid_ino_list ) = get_sid_and_InstNr();
    @sids = split(",", $sid_ino_list);
}
foreach $sid ( @sids ) {
    ( $sid, $ino ) = split(":", $sid);
    processMonitor($sid);
}
while ( $Continuous eq "yes" ) {
    sleep $Intervall;
    foreach $sid ( @sids ) {
        ( $sid, $ino ) = split(":", $sid);
        processMonitor($sid);
    }
}

closelog;
#
