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

# This file contains the code to verify the connection to an Eternus Storage.
#
# @param : IP Address - Eternus Storage IP Address
#
# @return : In case of Success, returns 0. In case of Failure, returns 1.
#
# Sample command: perl eternusStorageVerifier.pl <IP Address>

#!/usr/bin/perl -w

# It is used for strict compilation.
use strict;

# It is used to get base file name from the complete file name.
use File::Basename;

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

# It is used to idicate the path where common module is placed.
use lib "/usr/local/megha/lib/eternus";

# It is required for using the function of common module.
use commonModule;

# ----------------------------------------------------------------------------------------------------------------------------------------------------
# Error codes corresponding to eternusGetConfData.sh. Always keep it in sync with error codes in eternusGetConfData.sh.
# ----------------------------------------------------------------------------------------------------------------------------------------------------
my $ERROR_SUCCESS                        = 0;
my $ERROR_MICC_INVALID_CRED              = 1;
my $ERROR_MICC_DEVICE_ALREADY_REGISTERED = 2;
my $ERROR_SSH_INVALID_CRED               = 3;
my $ERROR_SSH_CONNECTION_FAILED          = 4;
my $ERROR_MICC_CONNECTION_FAILED         = 5;

# ----------------------------------------------------------------------------------------------------------------------------------------------------
# GLOBAL Variables
# ----------------------------------------------------------------------------------------------------------------------------------------------------

# This variable is used to store the complete name of file where data from Eternus Storage through SSH method will be dumped.
my $sshDumpFile = "";

# This variable is used to store the complete name of file where data from Eternus Storage through MICC method will be dumped.
my $miccDumpFile = "";

# This variable is used to store the complete name of file where error output from Eternus Storage will be dumped.
my $errorDumpFile = "";

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

# This variable is used to store the Eternus Storage User-Id which is used to get the Storage Configuration data.
my $eternusConfUserId = "";

# This variable is used to store the Eternus Storage Password corresponding to $eternusConfUserId.
my $eternusConfPassword = "";

# This variable is used to store the Eternus Storage User-Id which is used to get the Storage Performance data.
my $eternusPerfUserId = "";

# This variable is used to store the Eternus Storage Password corresponding to $eternusPerfUserId.
my $eternusPerfPassword = "";

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

# 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 Eternus MICC utility which is used to collect the Eternus Configuration data.
my $miccUtil = "/opt/FJSVstxs/bin/stxsconfiguration";

# This variable is used to store the Performace data collection interval. It is set to 60 seconds.
my $perfDataCollectionInterval = 60;

# This variable is used to store the complete name of file where output of "Control" command will be dumped.
my $controlCmdOutputFile = "";

# This variable is used to store the status of Eternus Configuration credential verification.
my $confCredentialVerified = 0;

# This variable is used to store the status of Eternus Performance credential verification.
my $perfCredentialVerified = 0;

# This variable is used to store the location of Eternus runtime files.
my $eternusRunTimeLocation = "";

# This variable is used to store the complete path of MARS app.properties file.
my $appPropertiesFilePath = "";

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

# This variable is used to store the Storage model type.
my $storageModel = "";

# This variable is used to check whether we are using SSH method or MICC method for verifying Configuration credentials.
my $sshEnabled = 1;

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

# 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 the base folder path on the MARS probe.
my $baseFolder = "";

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

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

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

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

EXIT:

# If verification is successful then dump the Storage model in a temporary file so that caller of this script can read the information and update
# Probe specific properties file with the model information. If verification fail then dump the respective error message in the temporary file.
$status = dumpVerificationInfo();
if (0 != $status)
{
    logMsg("Error: Call to dumpVerificationInfo() failed.");
}

# De-init the environment.
deInit();

exit $status;

# ----------------------------------------------------------------------------------------------------------------------------------------------------
# Sub-routines
# ----------------------------------------------------------------------------------------------------------------------------------------------------

# This function is used to verify Eternus Configuration credentials.
#
# @affected global variables :
#   $confCredentialVerified
#
# @return :
#   0 if Success
#   1 if Error
sub verifyConfCredential
{
    # This variable is used to store the return value of function calls.
    my $retVal = 0;

    # Connect to the Eternus Storage and fetch some configuration data.
    $retVal = getConfData();
    if (0 != $retVal)
    {
        logMsg("Error: Call to getConfData() failed.");
        return 1;
    }

    # Verify the Eternus configuration data.
    $retVal = verifyConfData();
    if (0 != $retVal)
    {
        logMsg("Error: Call to verifyConfData() failed.");
        return 1;
    }

    $confCredentialVerified = 1;

    return 0;
}

# This function is used to verify Eternus Performance credentials.
#
# @affected global variables :
#   $perfCredentialVerified
#
# @return :
#   0 if Success
#   1 if Error
sub verifyPerfCredential
{
    # This variable is used to store the return value of function calls.
    my $retVal = 0;

    # This variable is used to store the current status of Performance monitoring.
    my $perfMonitorStatus = 0;

    # Get current Performance monitoring status.
    $retVal = checkPerfMonitorStatus($perfMonitorStatus);
    if (0 != $retVal)
    {
        logMsg("Error: Call to checkPerfMonitorStatus() failed.");
        return 1;
    }

    # If Performance monitoring is OFF.
    if (0 == $perfMonitorStatus)
    {
        # Switch ON the Performance monitoring.
        $retVal = switchOnPerfMonitoring();
        if (0 != $retVal)
        {
            logMsg("Error: Call to switchOnPerfMonitoring() failed.");
            return 1;
        }

        # If Performance monitoring is ON now then it means that Performance credentials are correct.
        $perfCredentialVerified = 1;

        # Switch OFF the Performance monitoring to revert-back to the original Performance monitoring state.
        $retVal = switchOffPerfMonitoring();
        if (0 != $retVal)
        {
            logMsg("Error: Call to switchOffPerfMonitoring() failed.");

            # Though there is some error while switching OFF the Performance monitoring, our task of verifing Performance credential is already done.
            # So return will success.
            return 0;
        }
    }
    # If Performance monitoring is ON.
    elsif (1 == $perfMonitorStatus)
    {
        # Switch OFF the Performance monitoring.
        $retVal = switchOffPerfMonitoring();
        if (0 != $retVal)
        {
            logMsg("Error: Call to switchOffPerfMonitoring() failed.");
            $errorMsg = "Error:MARS Probe appliance could not stop the performance monitoring tool. Turn off the performance monitoring tool and try adding the probe again";
            return 1;
        }

        # If Performance monitoring is OFF now then it means that Performance credentials are correct.
        $perfCredentialVerified = 1;

        # Switch ON the Performance monitoring to revert-back to the original Performance monitoring state.
        $retVal = switchOnPerfMonitoring();
        if (0 != $retVal)
        {
            logMsg("Error: Call to switchOnPerfMonitoring() failed.");

            # Though there is some error while switching ON the Performance monitoring, our task of verifing Performance credential is already done.
            # So return will success.
            return 0;
        }
    }
    else
    {
        logMsg("Error: Invalid Performance monitor status returned from getPerfMonitorStatus(). Status = [$perfMonitorStatus].");
        return 1;
    }

    return 0;
}

# This function is used to initialize the environment to run the Perl script correctly.
#
# @affected global variables :
#   $eternusIpAddress
#   $appPropertiesFilePath
#   $verificationOutputFile
#
# @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 (6 != ($#ARGV + 1))
    {
        logMsg("Error: Number of arguments to eternusStorageVerifier.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]");

    # Get the Eternus Conf User name from command line argument.
    $eternusConfUserId = $ARGV[2];
    logMsg("Info: Input Conf User = [$eternusConfUserId]");

    # Get the Eternus Conf password from command line argument.
    $eternusConfPassword = $ARGV[3];
    logMsg("Info: Input Conf Password = [$eternusConfPassword]");

    # Get the Eternus Perf User name from command line argument.
    $eternusPerfUserId = $ARGV[4];
    logMsg("Info: Input Perf User = [$eternusPerfUserId]");

    # Get the Eternus Perf password from command line argument.
    $eternusPerfPassword = $ARGV[5];
    logMsg("Info: Input Perf Password = [$eternusPerfPassword]");

    # 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 the Eternus Storage data through SSH method will be dumped.
    $sshDumpFile = $probeFolder."/eternusVerificationSsh.dump";
    logMsg("Info: SSH Verification dump file: [$sshDumpFile].");

    # Set the file name where the Eternus Storage data through MICC method will be dumped.
    $miccDumpFile = $probeFolder."/eternusVerificationMicc.dump";
    logMsg("Info: MICC Verification dump file: [$miccDumpFile].");

    # Set the file name where the Eternus error message will be dumped.
    $errorDumpFile = $probeFolder."/eternusErrorVerification.dump";
    logMsg("Info: Eternus Error Verification dump file: [$errorDumpFile].");

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

    # Set the file name where the output of "Control" command will be dumped.
    $controlCmdOutputFile = $probeFolder."/eternusControlCmd.dump";

    # Set the complete path of MARS app.properties file.
    $appPropertiesFilePath = $baseFolder."/conf/app.properties";
    logMsg("Info: app.properties file path: [$appPropertiesFilePath].");

    # Read the content of app.properties file.
    $retVal = readAppPropertyFile($appPropertiesFilePath, $eternusIpAddress, $eternusRunTimeLocation);
    if (0 != $retVal)
    {
        logMsg("Error: Call to readAppPropertyFile() failed.");
        $retVal = 1;

        goto EXIT;
    }

EXIT:

    return $retVal;
}

# This function is used to check the owner and group of folders associated with Micc utility. Both should be set of "megha" user.
#
# @affected global variables :
#   None
#
# @return :
#   0 if owner and group of folders associated with Micc utility is megha.
#   1 if owner and group of any of the folders associated with Micc utility is not megha.
sub checkMiccOwner
{
    # 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 Micc utility.
    my $cmd = "";

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

    # Check the owner of /opt/FJSVstxs folder.
    $cmd = "ls -l /opt | grep FJSVstxs| 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/FJSVstxs\" folder is not \"megha\". Current owner: [$cmdOutput].");
        $errorMsg = "Error:Owner of \"/opt/FJSVstxs\" folder is not \"megha\". Current owner: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

    # Check the owner of /var/opt/FJSVstxs folder.
    $cmd = "ls -l /var/opt | grep FJSVstxs | 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/FJSVstxs\" folder is not \"megha\". Current owner: [$cmdOutput].");
        $errorMsg = "Error:Owner of \"/var/opt/FJSVstxs\" folder is not \"megha\". Current owner: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

    # Check the group of /opt/FJSVstxs folder.
    $cmd = "ls -l /opt | grep FJSVstxs | 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/FJSVstxs\" folder is not \"megha\". Current group: [$cmdOutput].");
        $errorMsg = "Error:Group of \"/opt/FJSVstxs\" folder is not \"megha\". Current group: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

    # Check the group of /var/opt/FJSVstxs folder.
    $cmd = "ls -l /var/opt | grep FJSVstxs | 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/FJSVstxs\" folder is not \"megha\". Current group: [$cmdOutput].");
        $errorMsg = "Error:Group of \"/var/opt/FJSVstxs\" folder is not \"megha\". Current group: [$cmdOutput].";
        $retVal = 1;

        goto EXIT;
    }

EXIT:

    return $retVal;
}

# This function is used to run a shell script which connects to the Eternus Storage and dump some configuration data in a file.
#
# @affected global variables :
#   None
#
# @return :
#   0 if Success
#   1 if Error
sub getConfData
{
    # This variable is used to store the exit status of "system" command.
    my $exitCode = 0;

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

    # This variable is used to store the command to get the Eternus conf data.
    my $cmd = "";

    # Construct the command to get the Eternus Conf data. First check whether the SSH is enabled on Storage.
    $cmd = $eternusRunTimeLocation."/eternusGetConfData.sh System $eternusIpAddress $eternusConfUserId $eternusConfPassword > $sshDumpFile 2>&1";
    logMsg("Info: Trying to get Configuration information using SSH method. Running command: [$cmd].");

    $exitCode = executeSystemCmd($cmd);
    if ($ERROR_SUCCESS == $exitCode)
    {
        # If SSH is enabled on Storage then return with Success.
        logMsg("Info: Succeded in getting EternusConfData through SSH.");
    }
    # If SSH connection to Storage failed with "Invalid credential" error then exit with error.
    elsif ($ERROR_SSH_INVALID_CRED == $exitCode)
    {
        logMsg("Error: SSH connection to Storage failed. Error: Invalid credentials.");
        $errorMsg = "Error:SSH connection to Storage failed. Error: Invalid credentials.";
        $exitStatus = $exitCode;

        goto EXIT;
    }
    # If SSH connection to Storage failed with "Connection failed" error then try to use MICC method for Storage connection.
    elsif ($ERROR_SSH_CONNECTION_FAILED == $exitCode)
    {
        logMsg("Warning: SSH connection to Storage failed. Error: Connection failed. Now trying to use MICC method for Storage connection.");

        # Set sshEnabled to false as we are now collecting data through Micc.
        $sshEnabled = 0;

        # Check the existence of Eternus MICC utility.
        unless (-e $miccUtil)
        {
            logMsg("Error: Eternus MICC utility is not present: [$miccUtil].");
            $errorMsg = "Error:Eternus MICC utility is not present: [$miccUtil].";
            $exitStatus = 1;

            goto EXIT;
        }

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

            goto EXIT;
        }

        # First check whether Storage is registered with MICC or not. If not Registered then register it.
        $cmd = "$miccUtil DevSts -i $eternusIpAddress -v > $miccDumpFile 2> $errorDumpFile";
        logMsg("Info: Trying to get Configuration data using MICC utility. Running command: [$cmd].");

        $exitCode = executeSystemCmd($cmd);
        if (0 != $exitCode)
        {
            # Open the eternusErrorVerication.dump to check for any error messages.
            open(CONFERROR_DUMP, $errorDumpFile) or die logMsg("Error: Not able to open the file: [$errorDumpFile].");

            my $errorFileContent = join("", <CONFERROR_DUMP>);
            # If not able to communicate with the Storage device then return with error.
            if (grep(/Failed to communicate with the device/, $errorFileContent))
            {
                logMsg("Error: MICC command failed. Error: Failed to communicate with the device.");
                $errorMsg = "Error:MICC command failed. Error: Failed to communicate with the device.";
                $exitStatus = $exitCode;

                goto EXIT;
            }
            # If Storage is not registerd with MICC then try to register Storage with MICC.
            elsif (grep(/The specified device has not been registered/, $errorFileContent))
            {
                logMsg("Warning: The Storage device is not registered with MICC.");

                # Register the Storage with Micc utility.
                $cmd = $eternusRunTimeLocation."/eternusGetConfData.sh MiccRegistration $miccUtil $eternusIpAddress $eternusConfUserId $eternusConfPassword > $errorDumpFile 2>&1";
                logMsg("Info: Trying to register Storage with MICC utility. Running command: [$cmd].");

                $exitCode = executeSystemCmd($cmd);
                if ($ERROR_SUCCESS == $exitCode)
                {
                    logMsg("Info: Storage registration is successful with MICC.");
                }
                # If Storage registration failed with "Invalid credential" error then return with error.
                elsif ($ERROR_MICC_INVALID_CRED == $exitCode)
                {
                    logMsg("Error: Storage registration with MICC failed. Error: Invalid credentials.");
                    $errorMsg = "Error:Storage registration with MICC failed. Error: Invalid credentials.";
                    $exitStatus = $ERROR_MICC_INVALID_CRED;

                    goto EXIT;
                }
                # If Storage registration failed with "Connection failed" error then return with error.
                elsif ($ERROR_MICC_CONNECTION_FAILED == $exitCode)
                {
                    logMsg("Error: Storage registration with MICC failed. Error: Connection failed.");
                    $errorMsg = "Error:Storage registration with MICC failed. Error: Connection failed.";
                    $exitStatus = $ERROR_MICC_CONNECTION_FAILED;

                    goto EXIT;
                }
                else
                {
                    logMsg("Error: Storage registration with MICC failed. Error code: [$exitCode].");
                    $exitStatus = $exitCode;

                    goto EXIT;
                }
            }
            # Found some unknown error while getting the data through MICC. Please open eternusErrorVerification.dump file to understand the error.
            else
            {
                logMsg("Error: Data collection from MICC failed with some unknown error. Please open eternusErrorVerification.dump file to understand the error.");
                $errorMsg = "Error:Data collection from MICC failed with some unknown error. Please open eternusErrorVerification.dump file to understand the error.";
                $exitStatus = $exitCode;

                goto EXIT;
            }

            # Now Storage is registered with MICC. Try to get Configuration data using MICC utility.
            $cmd = "$miccUtil DevSts -i $eternusIpAddress -v > $miccDumpFile 2> $errorDumpFile";
            logMsg("Info: Trying to get Configuration data using MICC utility. Running command: [$cmd].");

            # Run the command to get the Eternus Conf data.
            $exitCode = executeSystemCmd($cmd);

            # If the command doesn't succeed then return with error.
            if (0 != $exitCode)
            {
                logMsg("Error: Configuration data collection from MICC failed. Please open eternusVerificationMicc.dump file to understand the error.");
                $errorMsg = "Error:Configuration data collection from MICC failed. Please open eternusVerificationMicc.dump file to understand the error.";
                $exitStatus = 1;

                goto EXIT;
            }
            else
            {
                # If Storage is MICC compatible then return with Success.
                logMsg("Info: Succeded in getting Eternus Configuration data through MICC.");
                goto EXIT;
            }
        }

        logMsg("Info: Succeded in getting Eternus Configuration data through MICC.");
    }

EXIT:

    close(CONFERROR_DUMP);
    close(CONF_DUMP);

    return $exitStatus;
}

# This function is used to verify the data retrieved from the Eternus Storage.
#
# @affected global variables :
#   None
#
# @return :
#   0 if Storage connection is successful.
#   1 if Storage connection failed.
sub verifyConfData
{
    # This variable is used to store the return value of the function.
    my $retVal = 0;

    # It is used to check whether we found correct information in the Verification dump file.
    my $found = 0;

    if ($sshEnabled == 1)
    {
        logMsg("Info: Opening Eternus Storage verification dump file. File = [$sshDumpFile].");

        open(CONF_DUMP, $sshDumpFile) or die logMsg("Error: Not able to open the file: [$sshDumpFile].");
    }
    else
    {
        logMsg("Info: Opening Eternus Storage verification dump file. File = [$miccDumpFile].");

        open(CONF_DUMP, $miccDumpFile) or die logMsg("Error: Not able to open the file: [$miccDumpFile].");
    }

    # Loop through the content of Verification dump file.
    while (<CONF_DUMP>)
    {
        # Remove the new line character.
        chomp;

        logMsg("Info: Eternus Storage connection data = [$_].");
        
        # If the data collection is through ssh then look for the following pattern. 
        if ($sshEnabled == 1)
        {
            # Look for "Summary Status" string in the file. If we found that then it means that we can connect to Eternus Storage.
            if (/^(\s*)Model Name(\s*)\[(\w+)\](\s*)$/)
            {
                $storageModel = "StorageModel:".$3;

                logMsg("Info: Eternus Storage mode using SSH method. Model = [$storageModel].");
                $found = 1;

                last;
            }
        }
        # If the data collection is through Micc then look for the following pattern. 
        if (/^(\s*)\|(\s*)Model Name(\s*)\|(\s*)(\w*)(\s*)\|/)
        {
            $storageModel = "StorageModel:".$5;
            logMsg("Info: Found Eternus Storage model using Micc method. Model = [$storageModel].");
            $found = 1;
    
            last;
        }
    }

    if (0 == $found)
    {
        $retVal = 1;
    }

    close(CONF_DUMP);

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

    my $switchedOnPerfMonitoring = 0;

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

                $_[0] = 0;
            }
            elsif ("ON" eq $4)
            {
                logMsg("Info: Performance Monitoring is ON.");

                $_[0] = 1;
            }
            else
            {
                logMsg("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].");
            $retVal = 1;

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

    close($RESULT_HANDLE);

    return $retVal;
}

# This function is used to switch ON the Performance Monitoring. Once the Performance monitoring is in ON state, we can start collecting Performance
# data.
#
# @affected global variables :
#   None
#
# @return :
#   0 if Success
#   1 if Error
sub switchOnPerfMonitoring
{
    # This variable is used to store the return value of the function.
    my $retVal = 0;

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

    # This variable is used to store the current Performance monitoring status.
    my $currentMonitorStatus = 0;

    # This variable is used to store the command which is used to switch ON the performance monitoring.
    my $controlCmd = "";

    # This variable is used to store the exit status of "system" command.
    my $cmdExitCode = 0;

    logMsg("Info: Executing Shell script to switch ON the Performance Monitoring.");

    # Construct the command to switch-on the Eternus Perf data generation.
    $controlCmd = $eternusRunTimeLocation."/eternusGetConfData.sh PerfControlOn $perfUtility $eternusIpAddress $eternusPerfUserId $eternusPerfPassword $perfDataCollectionInterval > $controlCmdOutputFile";
    logMsg("Info: Control command: [$controlCmd].");

    # Run the command to switch-on the Eternus Perf data generation..sh
    $cmdExitCode = system($controlCmd);
    if (0 != $cmdExitCode)
    {
        logMsg("Error: Failed to execute: [eternusGetConfData.sh].");
        $retVal = 1;

        goto EXIT;
    }

    # Check the status of "Control" command.
    open($RESULT_HANDLE, '<', $controlCmdOutputFile);

    # If there is no error in the execution of "Control" command then $controlCmdOutputFile file will be empty. If we found some message in
    # $controlCmdOutputFile file then this means that "Control" command failed.
    while (<$RESULT_HANDLE>)
    {
        # Remove the new line character.
        chomp;

        if (/^(.+)[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. Error: [$_].");
            $retVal = 1;

            goto EXIT;
        }
    }

    # Also verify the status of "Control" command by checking the status of "Control" command.
    $status = checkPerfMonitorStatus($currentMonitorStatus);
    if (0 != $status)
    {
        logMsg("Error: Call to checkPerfMonitorStatus() failed.");
        $retVal = 1;

        goto EXIT;
    }

    # If Performance monitoring is OFF then it is an error.
    if (0 == $currentMonitorStatus)
    {
        logMsg("Error: Performance monitoring is still in OFF state.");
        $retVal = 1;

        goto EXIT;
    }

    # It takes some time to enable obtaining the Performance information so we are sleeping for some time. If we don't sleep then we will get
    # following error: "ERROR The specified device is not obtaining performance information. [IP address=<IP Address>]".
    logMsg("Info: Sleeping for 20 seconds.");
    sleep(20);

EXIT:

    close($RESULT_HANDLE);

    return $retVal;
}

# This function is used to switch OFF the Performance Monitoring. Once the Performance monitoring is in OFF state, Performance data collection will
# be stopped.
#
# @affected global variables :
#   None
#
# @return :
#   0 if Success
#   1 if Error
sub switchOffPerfMonitoring
{
    # This variable is used to store the return value of the function.
    my $retVal = 0;

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

    # This variable is used to store the current Performance monitoring status.
    my $currentMonitorStatus = 0;

    # This variable is used to store the command which is used to switch OFF the performance monitoring.
    my $controlCmd = "";

    # This variable is used to store the exit status of "system" command.
    my $cmdExitCode = 0;

    logMsg("Info: Executing Shell script to switch OFF the Performance Monitoring.");

    # Make the command to switch-off the Eternus Perf data generation.
    $controlCmd = $eternusRunTimeLocation."/eternusGetConfData.sh PerfControlOff $perfUtility $eternusIpAddress $eternusPerfUserId $eternusPerfPassword > $controlCmdOutputFile";
    logMsg("Info: Control command: [$controlCmd].");

    # Run the command to switch-off the Eternus Perf data generation.
    $cmdExitCode = system($controlCmd);
    if (0 != $cmdExitCode)
    {
        logMsg("Error: Failed to execute: [eternusGetConfData.sh].");
        $retVal = 1;

        goto EXIT;
    }

    # Check the status of "Control" command.
    open($RESULT_HANDLE, '<', $controlCmdOutputFile);

    # If there is no error in the execution of "Control" command then $controlCmdOutputFile file will be empty. If we found some message in
    # $controlCmdOutputFile file then this means that "Control" command failed.
    while (<$RESULT_HANDLE>)
    {
        # Remove the new line character.
        chomp;

        if (/^(.+)[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. Error: [$_].");
            $retVal = 1;

            goto EXIT;
        }
    }

    # Also verify the status of "Control" command by checking the status of "Control" command.
    $status = checkPerfMonitorStatus($currentMonitorStatus);
    if (0 != $status)
    {
        logMsg("Error: Call to checkPerfMonitorStatus() failed.");
        $retVal = 1;

        goto EXIT;
    }

    # If Performance monitoring is ON then it is an error.
    if (1 == $currentMonitorStatus)
    {
        logMsg("Error: Performance monitoring is still in ON state.");
        $retVal = 1;

        goto EXIT;
    }

EXIT:

    close($RESULT_HANDLE);

    return $retVal;
}

# This function is used to create a file at: db/probe/Eternus-<IP>/eternusVerificationInfo.txt
# It puts Eternus Storage model name 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 dumpVerificationInfo
{
    # 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, '>'.$verificationOutputFile)
    {
        # Die with error message if we can't open it.
        logMsg("Error: Unable to create: [$verificationOutputFile].");

        $retVal = 1;
        goto EXIT;
    }

    if("" eq $errorMsg)
    {
        # Write Storage model name in this file.
        print FILE $storageModel; 
    }
    else
    {
        # Write error message in this file.
        print FILE $errorMsg;
    }

    # 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."] [Verifier] ".$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);
}
# ----------------------------------------------------------------------------------------------------------------------------------------------------
