# Copyright 2008-2013 Cumulus Systems Incorporated.
# All Rights Reserved.

# This file contains the code to check the status of PMCC monitor.
#
# @param : IP Address - Eternus Storage IP Address
# @param : Site Name - MARS Site name
#
# @return : In case of Success, returns 0. In case of Failure, returns 1.
#
# Sample command: perl eternusCheckPmccStatus.pl <IP Address> <MARS Site name>

#!/usr/bin/perl -w

# It is used for strict compilation.
use strict;

# These are used to get the current date and time.
use Time::HiRes qw(gettimeofday);
use POSIX "strftime";

# This is used to create folder recursively.
use File::Path qw(mkpath);

# This variable is used to store the Eternus Storage IP Address.
my $eternusIpAddress = "";

# This variable is used to store the MARS Site name.
my $marsSiteName = "";

# This variable is used to store the return status of function calls.
my $status = 0;

# This variable is used to store the complete name of Eternus utility which is used to collect the Eternus Performance data.
my $perfUtility = "/opt/FJSVstxp/bin/stxpmonitor";

# This variable is used to store the complete name of log file.
my $logFile = "";

# This variable is used to store the file handle of log file.
my $LOG_HANDLE;

# This variable is used to store error message which will be displayed in UI.
my $message = "";

# This variable is used to store the base folder path on the MARS probe.
my $baseFolder = "";

# This variable is used to store the complete name of file which contain the output of this script.
my $pmccStatusFile = "";

# ----------------------------------------------------------------------------------------------------------------------------------------------------
# Main function
# ----------------------------------------------------------------------------------------------------------------------------------------------------

# Initialize the environment.
$status = init();
if (0 != $status)
{
    logMsg("Error: Call to init() failed.");
    goto EXIT;
}

# Verify Eternus PMCC status.
$status = checkPerfMonitorStatus();
if (0 != $status)
{
    logMsg("Error: Call to checkPerfMonitorStatus() failed.");
    goto EXIT;
}

EXIT:

# If the script excecuted successfully then dump the Status of PMCC monitor in a temporary file . If the script fail then dump the
# respective error message in the temporary file.
$status = dumpStatusInfo();
if (0 != $status)
{
    logMsg("Error: Call to dumpStatusInfo() failed.");
}

# De-init the environment.
deInit();

exit $status;

# This function is used to initialize the environment to run the Perl script correctly.
#
# @affected global variables :
#   $eternusIpAddress
#   $marsSiteName
#   $pmccStatusFile
#
# @return :
#   0 if Success
#   1 if Error
sub init
{
    # This variable is used to store the return value of function calls.
    my $retVal = 0;

    # This variable is used to store the complete path of probe specific folder in db/probe folder.
    my $probeFolder = "";

    # Set MARS base folder.
    $baseFolder = "/usr/local/megha";

    # If number of command line arguments are not correct then quit.
    if (2 != ($#ARGV + 1))
    {
        logMsg("Error: Number of arguments to eternusCheckPmccStatus.pl are not correct. Input arguments = ".($#ARGV + 1));
        $retVal = 1;

        goto EXIT;
    }

    # Get the Eternus Storage IP Addrss from command line argument.
    $eternusIpAddress = $ARGV[0];
    logMsg("Info: Input IP Address = [$eternusIpAddress]");

    # Get the MARS Site name from command line argument.
    $marsSiteName = $ARGV[1];
    logMsg("Info: Input Site name = [$marsSiteName]");

    # Set MARS probe folder path.
    $probeFolder = $baseFolder."/db/probe/".$marsSiteName."/Eternus_".$eternusIpAddress;
    logMsg("Info: Creating folder: [$probeFolder].");

    # Create the Eternus Probe folder in the db/probe folder.
    unless (defined eval {mkpath($probeFolder)})
    {
        logMsg("Error: Not able to create folder: [$probeFolder].");
        $retVal = 1;

        goto EXIT;
    }

    # Set the file name where output of this script will be stored.
    $pmccStatusFile = $probeFolder."/eternusPmccStatus.txt";
    logMsg("Info: PMCC Status file: [$pmccStatusFile].");

    # Check the existence of Eternus Performance collection utility.
    unless (-e $perfUtility)
    {
        logMsg("Error: Eternus Performance utility is not present: [$perfUtility].");
        $message = "Error:Eternus Performance utility is not present: [$perfUtility].";
        $retVal = 1;

        goto EXIT;
    }

    # Check the owner and group of PMCC utility.
    $retVal = checkPmccOwner();
    if (0 != $retVal)
    {
        logMsg("Error: Call to checkPmccOwner() failed.");
        $retVal = 1;

        goto EXIT;
    }

EXIT:

    return $retVal;
}

# This function is used to check the owner and group of folders associated with PMCC utility. Both should be set of "megha" user.
#
# @affected global variables :
#   None
#
# @return :
#   0 if Storage connection is successful.
#   1 if Storage connection failed.
sub checkPmccOwner
{
    # This variable is used to store the return value of function calls.
    my $retVal = 0;

    # This variable is used to store the command to check the group/owner information of PMCC utility.
    my $cmd = "";

    # This variable is used to store the output of $cmd command.
    my $cmdOutput = "";

    # Check the owner of /opt/FJSVstxp folder.
    $cmd = "ls -l /opt | grep FJSVstxp | awk '{print \$3}'";
    logMsg("Info: Running command = [$cmd].");

    # Run the command.
    $cmdOutput = `$cmd`;

    # Remove new line character.
    chomp $cmdOutput;

    if ("megha" ne $cmdOutput)
    {
        logMsg("Error: Owner of \"/opt/FJSVstxp\" folder is not \"megha\". Current owner: [$cmdOutput].");
        $message = "Error:Owner of \"/opt/FJSVstxp\" folder is not \"megha\". Current owner: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

    # Check the owner of /var/opt/FJSVstxp folder.
    $cmd = "ls -l /var/opt | grep FJSVstxp | awk '{print \$3}'";
    logMsg("Info: Running command = [$cmd].");

    # Run the command.
    $cmdOutput = `$cmd`;

    # Remove new line character.
    chomp $cmdOutput;

    if ("megha" ne $cmdOutput)
    {
        logMsg("Error: Owner of \"/var/opt/FJSVstxp\" folder is not \"megha\". Current owner: [$cmdOutput].");
        $message = "Error:Owner of \"/var/opt/FJSVstxp\" folder is not \"megha\". Current owner: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

    # Check the group of /opt/FJSVstxp folder.
    $cmd = "ls -l /opt | grep FJSVstxp | awk '{print \$4}'";
    logMsg("Info: Running command = [$cmd].");

    # Run the command.
    $cmdOutput = `$cmd`;

    # Remove new line character.
    chomp $cmdOutput;

    if ("megha" ne $cmdOutput)
    {
        logMsg("Error: Group of \"/opt/FJSVstxp\" folder is not \"megha\". Current group: [$cmdOutput].");
        $message = "Error:Group of \"/opt/FJSVstxp\" folder is not \"megha\". Current group: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

    # Check the group of /var/opt/FJSVstxp folder.
    $cmd = "ls -l /var/opt | grep FJSVstxp | awk '{print \$4}'";
    logMsg("Info: Running command = [$cmd].");

    # Run the command.
    $cmdOutput = `$cmd`;

    # Remove new line character.
    chomp $cmdOutput;

    if ("megha" ne $cmdOutput)
    {
        logMsg("Error: Group of \"/var/opt/FJSVstxp\" folder is not \"megha\". Current group: [$cmdOutput].");
        $message = "Error:Group of \"/var/opt/FJSVstxp\" folder is not \"megha\". Current group: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

EXIT:

    return $retVal;
}

# This function is used to check the status of Performance Monitoring. Performance monitoring should be in "ON" state to start collecting Performance
# data.
#
# @param :
#   $_[0] - [Out] Return the current status of Perf monitoring. 1 if monitoring is ON. 0 if monitoring is OFF.
#
# @return :
#   0 if Success
#   1 if Error
sub checkPerfMonitorStatus
{
    # This variable is used to store the return value of the function.
    my $retVal = 0;

    # This variable is used to store the "Control" command.
    my $controlCmd = "";

    # This variable is used to store the output of "Control" command.
    my $cmdOutput = "";

    # This variable is used as the temporary file handle to traverse the output of "Control" command.
    my $RESULT_HANDLE;

    # Construct the "Control" command.
    $controlCmd = "$perfUtility Control -i $eternusIpAddress";
    logMsg("Info: \"Control\" command = [$controlCmd].");

    # Run "Control" command.
    $cmdOutput = `$controlCmd`;

    # Redirect the output of "Control" to a temporary file
    open($RESULT_HANDLE, '<', \$cmdOutput);

    # Traverse the output of "Control" command using the temporary file handle.
    while (defined (my $resultLine = <$RESULT_HANDLE>))
    {
        # Remove the new line character.
        chomp($resultLine);

        if ($resultLine =~ /^(\s*)Monitor Status(\s*):(\s*)(\w+)(\s*)$/)
        {
            if ("OFF" eq $4)
            {
                logMsg("Info: Performance Monitoring is OFF.");
                $message = "Status:OFF";
                $retVal = 0;
            }
            elsif ("ON" eq $4)
            {
                logMsg("Info: Performance Monitoring is ON.");
                $message = "Status:ON";
                $retVal = 0;
            }
            else
            {
                logMsg("Error: Invalid monitoring status found. Status = [$4].");
                $message = "Error: Invalid monitoring status found. Status = [$4].";
                $retVal = 1;
            }

            last;
        }
        elsif ($resultLine =~ /^(.+)[E|e][r|R][r|R][o|O][r|R](.+)$/)
        {
            # If some error found in the execution of "Control" command then exit with error.
            logMsg("Error: \"Control\" command failed. Msg: [$resultLine].");
            $message = "Error: \"Control\" command failed. Msg: [$resultLine].";
            $retVal = 1;

            last;
        }
        else
        {
            logMsg("Info: [$resultLine].");
        }
    }

    close($RESULT_HANDLE);

    return $retVal;
}

# This function is used to create a file at: db/probe/Eternus-<IP>/eternusPmccStatus.txt
# It puts the PMCC Monitor status in this file. Caller of this script is responsible for deleting this file.
#
# @affected global variables :
#   None
#
# @return :
#   0 if Success
#   1 if Error
sub dumpStatusInfo
{
    # This variable is used to store the return value of the function.
    my $retVal = 0;
    
    # Use the open() function to create the file.
    unless(open FILE, '>'.$pmccStatusFile)
    {
        # Die with error message if we can't open it.
        logMsg("Error: Unable to create: [$pmccStatusFile].");

        $retVal = 1;
        goto EXIT;
    }
 
    # Write message in this file.
    print FILE $message;

    # Close the file.
    close(FILE);

EXIT:

    return $retVal;
}

# This function is used to run a command through system() call. system() call somehow returns error code differently by shifting the exit code to 8
# bits left side. So this function also shifted back the exit code to 8 bits right side and return it.
#
# @affected global variables :
#   None
#
# @return :
#   Exit code shifted to 8 bits right.
sub executeSystemCmd
{
    my $tempExitCode = system($_[0]);

    my $exitCode = $tempExitCode >> 8;

    return $exitCode;
}

# This function is used to log a message in the log file. It logs the message in the following format:
# [YYYY-MM-DD HH:MM:ss,SSS]  [Eternus-<IP Address>] [Verifier] <Log message>
#
# @param :
#   $_[0] - Log message.
#
# @affected global variables :
#   None
#
# @return :
#   Nothing
sub logMsg
{
    # This variable is used to store the complete path of probe specific folder in db/probe folder.
    my $eternusLogFolder = "";

    # Set Eternus log folder path.
    $eternusLogFolder = $baseFolder."/logs/eternusProbe";

    # If log folder does not exist then create it.
    if (!(-e $eternusLogFolder))
    {
        # TODO: Check the return value of mkpath.
        mkpath($eternusLogFolder);
    }

    # Get the current date and time.
    my ($seconds, $microseconds) = gettimeofday;
    my $currentTime = strftime("%Y-%m-%d %H:%M:%S", localtime($seconds));

    # Get the date from the given date and time .
    my($date, $time) = split(' ', $currentTime, 2);

    # Set the name of log file.
    $logFile = $eternusLogFolder."/eternusProbe.".$date.".log";

    # Open the log file.
    open($LOG_HANDLE, ">>", $logFile) or die "Not able to open the file: [$logFile].";

    # Read input parameters.
    my $logMsg = $_[0];

    # For getting time in a given format.
    $currentTime = "[".$currentTime.",".$microseconds."]";

    # Construct the final log message.
    my $finalMsg = $currentTime." [Eternus-".$eternusIpAddress."] [PMCCStatus] ".$logMsg."\n";

    # Dump the final log message in log file.
    print $LOG_HANDLE $finalMsg;
}

# This function is used to de-initialize the environment.
#
# @affected global variables :
#   $CONF_HANDLE
#
# @return :
#   None
sub deInit
{
    close($LOG_HANDLE);
}
# ----------------------------------------------------------------------------------------------------------------------------------------------------
