#----------------------------------------------------------------------------
#  ALTRAN_PROLOG_BEGIN_TAG
#  This is an automatically generated prolog.
#
#  Copyright (C) Altran ACT S.A.S. 2018,2019,2020,2021.  All rights reserved.
#
#  ALTRAN_PROLOG_END_TAG
#
# %Z%  %ci%  %fn%, %R%, %t%, %G% %U%
#----------------------------------------------------------------------------
# Import Python Modules
#----------------------------------------------------------------------------
import os
import sys
import inspect
from datetime import datetime
try:
    # For Python 3.0 and later versions
    from subprocess import getstatusoutput
except:
    # Fall back to Python 2 version
    from commands import getstatusoutput

#----------------------------------------------------------------------------
# Global Definitions
#----------------------------------------------------------------------------
DSP_MSG = "/usr/bin/dspmsg -s"
HA_UTILS = "/usr/es/sbin/cluster/utilities"
UTILS_LOG = "clutils.log"
CAT_FILE = "scripts.cat"

#----------------------------------------------------------------------------
# Functions
#    displayMsg
#----------------------------------------------------------------------------

def log_message(logfile, msg):
    """
    Function    : log_message
    Description : log message to log file with file name and line number. 
    Arguments   : Logfile and message.
    """
    filename=""
    # stack utility of inspect Python module returns the list of frame records
    # for the caller's stack. First entry in the returned list represents the
    # caller. Fetch the caller details for the function.
    frame = inspect.stack()[1]

    # Fetch the file name of the caller function from the stack frame
    filename = inspect.getfile(frame[0])
    file_info="[" + filename + "]" + "[" + str(inspect.currentframe().f_back.f_lineno) + "]"   
    date_info=datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
    msg_info=date_info + file_info + ": " + msg
    with open(logfile,'a') as log_file:
        log_file.write(msg_info + '\n')

def getFilePath(fileName):
    """
    Function    : getFilePath
    Description : This function fetches the log file path configured on the
                  node from HACMPlogs odm.
    Arguments   : 
                  fileName - Required; Log file name
    Return      : Log file path configured on the node. In case of failure, this
                  function returns default path of logfile as /var/hacmp/log.
    """
    # Fetch the log file directory configured on the node from HACMPlogs odm.
    cmd = "%s/clodmget -q name='%s' -f value -n HACMPlogs"%(HA_UTILS,fileName)
    status,logDir = getstatusoutput(cmd)
    if (logDir == ""):
        cmd = "%s/clodmget -q name='%s' -f defaultdir -n HACMPlogs"%(HA_UTILS,fileName)
        status,logDir = getstatusoutput(cmd)
        if (logDir == ""):
            logDir = "/var/hacmp/log"
    logDir = logDir.strip('\n')
    logFile = "%s/%s"%(logDir,fileName)
    return logFile

def displayMsg(*args):
    """
    Function    : displayMsg
    Description : This function displays converted message to the user and logs the
                  message to the specified log file based on input argument.
    Arguments   : 
                  args[0] - Required; Log file name to which message is intended
                            to log. In case logging is not required an empty
                            string should be passed as first argument.
                  args[1] - Required; Set number of the message in catalog
                  args[2] - Required; Name of the message catalog
                  args[3] - Required; Message number in catalog
                  args[4] - Required; Default message to display
                  args[5:]- Optional; any arguments that the message may need 
    Return      : 0, On success
                  1, On Failure
    """

    utilsLog = getFilePath("clutils.log")
    # Validate if set number, catalog file, message number and default
    # message arguments are passed
    argLen = len(args)
    if argLen >= 5:
        logFile = args[0]
        setNum = args[1]
        catFile = args[2]
        msgNum = args[3]
        defaulMsg = args[4]
    else:
        msg = "echo 'displayMsg: Invalid Arguments!'>>%s"%(utilsLog)
        status,output=getstatusoutput(msg)
        return 1

    # Fetch full path of the log file configured on the node.
    if logFile != "":
        logFile = getFilePath(logFile)

    dspCmd="%s %s %s %s '%s'"%(DSP_MSG,setNum,catFile,msgNum,defaulMsg)

    # Capture arguments to message, if any.
    msgArgs = ""
    for arg in args[5:]:
        msgArgs = "%s %s"%(msgArgs,arg)
    if msgArgs != "":
        dspCmd = "%s %s"%(dspCmd,msgArgs)
    # Execute 'dspmsg' utility
    status,output=getstatusoutput(dspCmd)
    if status == 0:
        print(output)
        # Log the message to log file
        if logFile != "":
            msg = "echo '%s' >>%s"%(output,logFile)
            status,output=getstatusoutput(msg)
    else:
        msg = "echo 'Command %s, failed with reason:%s' >>%s"%(dspCmd,output,utilsLog)
        res,output=getstatusoutput(msg)
    return status

def displayMsg2(*args):
    """
    Function    : displayMsg
    Description : This function displays converted message to the stderr and logs the
                  message to the specified log file based on input argument.
    Arguments   : 
                  args[0] - Required; Log file name to which message is intended 
                            to log. In case logging is not required an empty
                            string should be passed as first argument.
                  args[1] - Required; Set number of the message in catalog
                  args[2] - Required; Name of the message catalog
                  args[3] - Required; Message number in catalog
                  args[4] - Required; Default message to display
                  args[5:]- Optional; any arguments that the message may need 
    Return      : 0, On success
                  1, On Failure
    """

    utilsLog = getFilePath("clutils.log")
    # Validate if set number, catalog file, message number and default
    # message arguments are passed
    argLen = len(args)
    if (argLen >= 5):
        logFile = args[0]
        setNum = args[1]
        catFile = args[2]
        msgNum = args[3]
        defaulMsg = args[4]
    else:
        msg = "echo 'displayMsg: Invalid Arguments!'>>%s"%(utilsLog)
        status,output=getstatusoutput(msg)
        return 1

    # Fetch full path of the log file configured on the node.
    if (logFile != ""):
        logFile = getFilePath(logFile)

    dspCmd="%s %s %s %s '%s'"%(DSP_MSG,setNum,catFile,msgNum,defaulMsg)

    # Capture arguments to message, if any.
    msgArgs = ""
    for arg in args[5:]:
        msgArgs = "%s %s"%(msgArgs,arg)
    if (msgArgs != ""):
        dspCmd = "%s %s"%(dspCmd,msgArgs)
    # Execute 'dspmsg' utility
    status,output=getstatusoutput(dspCmd)
    if (status == 0):
        sys.stderr.write(output)
        # Log the message to log file
        if (logFile != ""):
            msg = "echo '%s' >>%s"%(output,logFile)
            status,output=getstatusoutput(msg)
    else:
        msg = "echo 'Command %s, failed with reason: %s' >>%s"%(dspCmd,output,utilsLog)
        res,output=getstatusoutput(msg)
    return status

def executeCommand(node, command):
    """
    Function    : executeCommand
    Description : This function executes the command on the node
    Arguments   : node, command
    Return      : status - return code of the command
                  output - output of the command
    """
    
    # Fetching paths using cl_get_path all, this is set as PATH while executing command
    status,PATH=getstatusoutput(HA_UTILS+"/cl_get_path all 2>/dev/null")
    
    # Appending path to command
    command="PATH="+ PATH + " " + command
    
    if node:
        # Fetching local node name
        status,localNode=getstatusoutput("PATH=%s get_local_nodename 2>/dev/null" % PATH)
        
        if node != localNode:
            # Check whether node is reachable or not
            cmd="PATH=%s cl_rsh %s date 2>/dev/null"%(PATH,node)
            status,output=getstatusoutput(cmd)
            if status:
                defMsg = "Error: Failed to communicate with node %1$s in a cluster\n"
                displayMsg(UTILS_LOG,44,CAT_FILE,3,defMsg,node)
                return (status,None)
            else:
                # command is executed using rsh only if node is not localnode
                command=HA_UTILS+"/cl_rsh "+ node + " "+command
    
    status,output = getstatusoutput(command)
    return (status,output)
  
def log_stderr(msg):

    """
    Function    : log_stderr
    Description : This function logs the message to stderr
    Arguments   : msg - message to print
    Return      : None
    """
    # This will work for both python versions 2.7 and 3.0
    sys.stderr.write("%s" %msg)

def check_config_file(path):
    """
    Function    : check_config_file
    Description : This function will be used to check whether the
                  given file is exist and it has data.
    Arguments   : Filename with fullpath
    Return      : 0 - File is not present
                  1 - File exists
    """
    # Check if file exists and it has data.
    if os.path.isfile(path) and os.path.getsize(path) > 0:
        #If file exists, checks the read/write permissions
        return 1
    else:
        return 0

def rotateFile(filename):
    """
    Function    : rotateFile
    Description : This function will be move the file data in to
                  new files.
    Arguments   : Filename with fullpath
    Return      : 0 - successfully rotated
                  1 - failed to rotate file data
    """
    filenames=filename+"*"
    # retrieving the list of existing files associated to file which is passed as argument. 
    command="ls -lrt "+filenames+" | awk -F\" \" '{print $NF}'"
    status,output=executeCommand("",command)
    if output:
        filesList=output.split('\n')
        # retrieving the number of files associated to provided filename. 
        command="ls -lrt "+filenames+" | wc -l"
        status,output=executeCommand("",command)
        if output:
            # Removing leading and trailing spaces
            count=output.strip()
            for file in filesList:
                # Rotating files count should not be exceed 8 
                if ( int(count)<8 ):
                    newfile=filename+"."+str(count)
                    command="mv "+file+" "+newfile
                    status,output=executeCommand("",command)
                    if status != 0:
                        return 1
                count=(int(count)-1)
                if (int(count)<0):
                    break
            command="touch "+filename
            status,output=executeCommand("",command)
            if status != 0:
                return 1
    return 0
