#!/usr/bin/env python3

import sys
import traceback
import os
import logging
import json
import time
import shutil
import re
import sys
import socket
from netaddr import IPNetwork, IPAddress

sbxType = ["isbc", "ssbc","msbc","tsbc","mrfp","slb"]
ipType = [1,2,3]
keys = ["installType", "systemName", "ceName", "peerCeName", "mgtIpType", "mgtIp", "mgtPrefix", "mgtGw", "haIp",
        "haPrefix", "peerMgtIpType", "peerMgtIp", "peerMgtPrefix", "peerMgtGw", "peerHaIp", "ntpIp", "timezone",
        "sbctype", "tipc", "mgtIpV6", "peerMgtGwV6", "peerMgtIpV6", "peerMgtPrefixV6", "mgtGwV6", "mgtPrefixV6",
        "rgIp", "haMode", "role", "enableCoreEMA", "enableTS", "enableREST", 'peerMgt1IpType', 'peerMgt1Ip',
        'peerMgt1Gw', 'mgt1PrefixV6', 'peerMgt1GwV6', 'mgt1Ip', 'mgt1Prefix', 'mgt1GwV6', 'peerMgt1IpV6',
        'mgt1Gw', 'peerMgt1Prefix', 'mgt1IpV6', 'peerMgt1PrefixV6',
        'mgt1IpType', 'isMgt1Conf', 'personality', 'productType', "sshKeyReq",
        "adminSshKey", "linuxadminSshKey" ]
emsKeys = ["emsName", "emsPass", "downloadEmsConfig", "emsIp1", "emsIp2","EmsPrivateNodeParameters"]
oamKeys = ["oamIp1", "oamIp2"]
extraConfigKeys = ["haFaultDetectionMode"]

def validateGW(ip, net, logger="None"):
    if IPAddress(ip) in IPNetwork(net):
        return True
    if logger is not "None":
        logger.error("GW IP is not in the same network.")
    return False

def validateName(name, maxLen, logger, tstr="None"):

    if not re.match("^[A-Za-z]{1}[-A-Za-z0-9.]*[A-Za-z0-9]{1}$", name) or len(name) > maxLen:
        if tstr is not None:
            logger.error('Invalid ' + tstr + ': ' + name)
            logger.error('Name must match regular expression: ^[A-Za-z]{1}[-A-Za-z0-9.]*[A-Za-z0-9]{1}$ and max length ' + str(maxLen))
        return False
    return True

def validatePassword(passwdStr, maxLen, logger, tstr="None"):

    if not re.match("^[A-Za-z]{1}[-A-Za-z0-9.!@#$%^&*()]*[A-Za-z0-9]{1}$", passwdStr) or len(passwdStr) > maxLen:
        if tstr is not None:
            logger.error('Password is invalid because it does not match regular expression: ^[A-Za-z]{1}[-A-Za-z0-9.!@#$%^&*()]*[A-Za-z0-9]{1}$ and max length ' + str(maxLen))
        return False
    return True

def validateId(name, maxLen, logger, tstr="None"):

    if not re.match("^[A-Za-z0-9]{1}[-A-Za-z0-9-]*[A-Za-z0-9]{1}$", name) or len(name) > maxLen or len(name) < 2:
        if tstr is not None:
            logger.error('Invalid ' + tstr + ': ' + name)
            logger.error('Name must match regular expression: [A-Za-z0-9]{1}[-A-Za-z0-9-]*[A-Za-z0-9]{1}$ and min length 2 max length ' + str(maxLen))
        return False
    return True

def validateIPv4(address, addressType, logger="None"):
    """
    :param address:
    :param addressType:
    :param logger:
    :return:
    """

    # If prefix information is there in the IP, remove it and validate only the IP address
    if address.find('/') >= 0:
        isValidPrefix = validatePrefix(address, "V4")
        if isValidPrefix:
            address = address.split('/')[0]
        else:
            if logger is not None:
                logger.error("Invalid IPV4 Prefix found with IP address. Value: " + str(address))
            return False
    try :
        socket.inet_pton(socket.AF_INET, address)
    except socket.error:  # not a valid address
        if logger is not None:
            logger.error('ValidateIPv4 error for addressType : ' + addressType + ' , Invalid.  Address : ' + str(address))
        print('ValidateIPv4 error for addressType : ' + addressType + ' , Invalid.  Address : ' + str(address))
        return False
    except Exception as e:
        if logger is not None:
            logger.error('ValidateIPv4 error:' + str(e) + ' Address : ' + str(address))
        print('ValidateIPv4 error:' + str(e) + ' Address : ' + str(address))

        return False
    return True

def validateIPv6(address, addressType, logger="None"):
    """

    :param address:
    :param addressType:
    :param logger:
    :return:
    """

    # If prefix information is there in the IP, remove it and validate only the IP address
    if address.find('/') >= 0:
        isValidPrefix = validatePrefix(address, "V6")
        if isValidPrefix:
            address = address.split('/')[0]
        else:
            if logger is not None:
                logger.error("Invalid IPV6 Prefix found with IP address. Value: " + str(address))
            return False
    #logger.info("validateIPv6 : address :" + str(address))

    try:
        socket.inet_pton(socket.AF_INET6, address)
    except socket.error:  # not a valid address
        if logger is not None:
            logger.error('ValidateIPv6 error for addressType : ' + addressType + ' , Invalid. Address : ' + str(address))
        return False
    except Exception as e:
        if logger is not None:
            logger.error('ValidateIPv6 error:' + str(e)+ ' Address : ' + str(address))
        return False

    return True

def getIpVersion(address):
    """
    Input Param : IP address.
    Output Param: IP address version.
                  Returns 0 if IP address is invalid.
                  Returns 4/6 if IP address is V4/V6 respectively.
    """

    ipVersion = 0

    try:
        socket.inet_pton(socket.AF_INET, address)
        ipVersion = 4
    except:
        pass

    try:
        socket.inet_pton(socket.AF_INET6, address)
        ipVersion = 6
    except:
        pass

    return ipVersion

def validatePrefix(address, type):
    """
    Input Params :
    1. address : Can be address or prefix value.
    2. IP version : V4 or V6
    """

    # Check if the prefix information is present in the IP field.
    if address.find('/') >= 0:
        prefix = address.split('/')[1]
    else:
        # Will consider the scenario where prefix is passed directly
        prefix = address

    if prefix.isdigit():
        if type == "V4":
            if int(prefix) >= 0 and int(prefix) <=32:
                return True
        if type == "V6":
            if int(prefix) >= 0 and int(prefix) <=128:
                return True
    #logger.error('validatePrefix: Error for prefix Invalid. Value: ' + str(address))
    return False

def validateIP(address, tstr, logger="None"):
    ver = getIpVersion(address)
    if tstr == "ha" and ver != 4:
        return False
    elif tstr == "mgtv4" and ver != 4:
        return False
    elif tstr == "mgtv6" and ver !=6:
        return False
    if ver == 4:
        return validateIPv4(address,"V4", logger)
    elif ver == 6:
        return validateIPv6(address,"V6", logger)
    else:
        return False

def validateSbcType(sbcType):
    sbcType = sbcType.lower()
    if sbcType in sbxType:
        return True
    return False

def validateAllIps(data,emsData,oamData, logger):
    ret = True
    if emsData :
        if str(emsData["emsIp1"]) == str(emsData["emsIp2"]):
            logger.error("EMS IP1 and EMS IP2 cannot be same.")
            ret = False
    if oamData :
        if str(oamData["oamIp1"]) == str(oamData["oamIp2"]):
            logger.error("OAM IP1 and OAM IP2 cannot be same.")
            ret = False
    if emsData and oamData:
        if str(emsData["emsIp1"]) == str(oamData["oamIp1"]):
            logger.error("EMS IP1 and OAM IP1 cannot be same.")
            ret = False
        if str(emsData["emsIp1"]) == str(oamData["oamIp2"]):
            logger.error("EMS IP1 and OAM IP2 cannot be same.")
            ret = False
        if str(emsData["emsIp2"]) == str(oamData["oamIp1"]):
            logger.error("EMS IP2 and OAM IP1 cannot be same.")
            ret = False
        if str(emsData["emsIp2"]) == str(oamData["oamIp2"]):
            logger.error("EMS IP2 and OAM IP2 cannot be same.")
            ret = False
    if data["mgtIpType"] == 1 or data["mgtIpType"] == 3:
        if data["haMode"] == "Nto1":
            if str(data["mgtIp"]) == str(data["rgIp"]):
                logger.error("The Active mgtIP and rgIP cannot be same.")
                ret = False
            if str(data["mgtGw"]) == str(data["rgIp"]):
                logger.error("The Active mgtGw and rgIP cannot be same.")
                ret = False
            if emsData :
                if str(emsData["emsIp1"]) == str(data["rgIp"]):
                    logger.error("EMS IP1 and rgIp cannot be same.")
                    ret = False
                if str(emsData["emsIp2"]) == str(data["rgIp"]):
                    logger.error("EMS IP2 and rgIp cannot be same.")
                    ret = False
            if oamData :
                if str(oamData["oamIp1"]) == str(data["rgIp"]):
                    logger.error("OAM IP1 and rgIp cannot be same.")
                    ret = False
                if str(oamData["oamIp2"]) == str(data["rgIp"]):
                    logger.error("OAM IP2 and rgIp cannot be same.")
                    ret = False
        if emsData and ( str(emsData["emsIp1"]) == str(data["mgtIp"])):
            logger.error("The Active mgtIP and emsIP1 cannot be same.")
            ret = False
        if emsData and ( str(emsData["emsIp1"]) == str(data["mgtGw"])):
            logger.error("The Active mgtGw and emsIP1 cannot be same.")
            ret = False
        if emsData and ( str(emsData["emsIp1"]) == str(data["haIp"])):
            logger.error("The Active HA IP and emsIP1 cannot be same.")
            ret = False
        if emsData and ( str(emsData["emsIp2"]) == str(data["mgtIp"])):
            logger.error("The Active mgtIP and emsIP2 cannot be same.")
            ret = False
        if emsData and ( str(emsData["emsIp2"]) == str(data["mgtGw"])):
            logger.error("The Active mgtGw and emsIP2 cannot be same.")
            ret = False
        if emsData and ( str(emsData["emsIp2"]) == str(data["haIp"])):
            logger.error("The Active HA IP and emsIP2 cannot be same.")
            ret = False
        if oamData and ( str(oamData["oamIp1"]) == str(data["mgtIp"])):
            logger.error("The Active mgtIP and oamIP1 cannot be same.")
            ret = False
        if oamData and ( str(oamData["oamIp1"]) == str(data["mgtGw"])):
            logger.error("The Active mgtGw and oamIP1 cannot be same.")
            ret = False
        if oamData and ( str(oamData["oamIp1"]) == str(data["haIp"])):
            logger.error("The Active HA IP and oamIP1 cannot be same.")
            ret = False
        if oamData and ( str(oamData["oamIp2"]) == str(data["mgtIp"])):
            logger.error("The Active mgtIP and oamIP2 cannot be same.")
            ret = False
        if oamData and ( str(oamData["oamIp2"]) == str(data["mgtGw"])):
            logger.error("The Active mgtGw and oamIP2 cannot be same.")
            ret = False
        if oamData and ( str(oamData["oamIp2"]) == str(data["haIp"])):
            logger.error("The Active HA IP and oamIP2 cannot be same.")
            ret = False
        if str(data["mgtIp"]) == str(data["mgtGw"]):
            logger.error("The Active mgtIP and mgtGw cannot be same.")
            ret = False
        if (str(data["mgtIp"]) == str(data["haIp"])):
            logger.error("The Active mgtIP and HA IP cannot be same.")
            ret = False
        if (str(data["mgtGw"]) == str(data["haIp"])):
            logger.error("The Active mgtGw and HA IP cannot be same.")
            ret = False
    if data["mgtIpType"] == 2 or data["mgtIpType"] == 3:
        if str(data["mgtIpV6"]) == str(data["mgtGwV6"]):
            logger.error("The Active mgtIPV6 and mgtGwV6 cannot be same.")
            ret = False
    if data["isMgt1Conf"] == 1:
        if data["mgt1IpType"] == 1 or data["mgt1IpType"] == 3:
            if data["haMode"] == "Nto1":
                if str(data["mgt1Ip"]) == str(data["rgIp"]):
                    logger.error("The Active mgt1IP and rgIP cannot be same.")
                    ret = False
                if str(data["mgt1Gw"]) == str(data["rgIp"]):
                    logger.error("The Active mgt1Gw and rgIP cannot be same.")
                    ret = False
            if emsData and ( str(emsData["emsIp1"]) == str(data["mgt1Ip"])):
                logger.error("The Active mgt1IP and emsIP1 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp1"]) == str(data["mgt1Gw"])):
                logger.error("The Active mgt1Gw and emsIP1 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp2"]) == str(data["mgt1Ip"])):
                logger.error("The Active mgt1IP and emsIP2 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp2"]) == str(data["mgt1Gw"])):
                logger.error("The Active mgt1Gw and emsIP2 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp1"]) == str(data["mgt1Ip"])):
                logger.error("The Active mgt1IP and oamIP1 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp1"]) == str(data["mgt1Gw"])):
                logger.error("The Active mgt1Gw and oamIP1 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp2"]) == str(data["mgt1Ip"])):
                logger.error("The Active mgt1IP and oamIP2 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp2"]) == str(data["mgt1Gw"])):
                logger.error("The Active mgt1Gw and oamIP2 cannot be same.")
                ret = False
            if str(data["mgt1Ip"]) == str(data["mgt1Gw"]):
                logger.error("The Active mgt1IP and mgt1Gw cannot be same.")
                ret = False
            if (str(data["mgt1Ip"]) == str(data["haIp"])):
                logger.error("The Active mgt1IP and HA IP cannot be same.")
                ret = False
            if (str(data["mgt1Gw"]) == str(data["haIp"])):
                logger.error("The Active mgt1Gw and HA IP cannot be same.")
                ret = False
        if (data["mgtIpType"] == 1 or data["mgtIpType"] == 3) and (data["mgt1IpType"] == 1 or data["mgt1IpType"] == 3):
            if str(data["mgt1Ip"]) == str(data["mgtGw"]):
                logger.error("The Active mgt1IP and mgtGw cannot be same.")
                ret = False
            if str(data["mgtIp"]) == str(data["mgt1Ip"]):
                logger.error("The Actve mgtIP and mgt1IP cannot be same.")
                ret = False
            if str(data["mgtIp"]) == str(data["mgt1Gw"]):
                logger.error("The Active mgtIP and mgt1Gw cannot be same.")
                ret = False
        if data["mgt1IpType"] == 2 or data["mgt1IpType"] == 3:
            if str(data["mgt1IpV6"]) == str(data["mgt1GwV6"]):
                logger.error("The Active mgt1IPV6 and mgt1GwV6 cannot be same.")
                ret = False
        if (data["mgtIpType"] == 2 or data["mgtIpType"] == 3) and (data["mgt1IpType"] == 2 or data["mgt1IpType"] == 3):
            if str(data["mgtIpV6"]) == str(data["mgt1IpV6"]):
                logger.error("The Active mgtIPV6 and mgt1IPV6 cannot be same.")
                ret = False
            if str(data["mgt1IpV6"]) == str(data["mgtGwV6"]):
                logger.error("The Active mgt1IPV6 and mgtGwV6 cannot be same.")
                ret = False

    if int(data["installType"]) == 2:
        if str(data["ceName"]) == str(data["peerCeName"]):
            logger.error("The Ce Name and Peer Ce Name cannot be same.")
            ret = False
        if str(data["haIp"]) == str(data["peerHaIp"]):
            logger.error("The HA IP of active and standby cannot be same.")
            ret = False
        if (data["mgtIpType"] == 1 or data["mgtIpType"] == 3) and (data["peerMgtIpType"] == 1 or data["peerMgtIpType"] == 3):
            if str(data["mgtIp"]) == str(data["peerMgtIp"]):
                logger.error("The Mgt IP of active and standby cannot be same.")
                ret = False
            if str(data["mgtIp"]) == str(data["peerMgtGw"]):
                logger.error("The Active mgtIP and Standby MgtGw cannot be same.")
                ret = False
            if str(data["peerMgtIp"]) == str(data["mgtGw"]):
                logger.error("The Standby mgtIP and Active mgtGw cannot be same.")
                ret = False
        if data["mgtIpType"] == 1 or data["mgtIpType"] == 3:
            if (str(data["mgtIp"]) == str(data["peerHaIp"])):
                logger.error("The Active mgtIP and Standby HA IP cannot be same.")
                ret = False
            if (str(data["mgtGw"]) == str(data["peerHaIp"])):
                logger.error("The Active mgtGw and Standby HA IP cannot be same.")
                ret = False
        if data["peerMgtIpType"] == 1 or data["peerMgtIpType"] == 3:
            if emsData and ( str(emsData["emsIp1"]) == str(data["peerMgtIp"])):
                logger.error("The Standby mgtIP and emsIP1 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp1"]) == str(data["peerMgtGw"])):
                logger.error("The Standby mgtGw and emsIP1 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp1"]) == str(data["peerHaIp"])):
                logger.error("The Standby HA IP and emsIP1 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp2"]) == str(data["peerMgtIp"])):
                logger.error("The Standby mgtIP and emsIP2 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp2"]) == str(data["peerMgtGw"])):
                logger.error("The Standby mgtGw and emsIP2 cannot be same.")
                ret = False
            if emsData and ( str(emsData["emsIp2"]) == str(data["peerHaIp"])):
                logger.error("The Standby HA IP and emsIP2 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp1"]) == str(data["peerMgtIp"])):
                logger.error("The Standby mgtIP and oamIP1 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp1"]) == str(data["peerMgtGw"])):
                logger.error("The Standby mgtGw and oamIP1 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp1"]) == str(data["peerHaIp"])):
                logger.error("The Standby HA IP and oamIP1 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp2"]) == str(data["peerMgtIp"])):
                logger.error("The Standby mgtIP and oamIP2 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp2"]) == str(data["peerMgtGw"])):
                logger.error("The Standby mgtGw and oamIP2 cannot be same.")
                ret = False
            if oamData and ( str(oamData["oamIp2"]) == str(data["peerHaIp"])):
                logger.error("The Standby HA IP and oamIP2 cannot be same.")
                ret = False
            if str(data["peerMgtIp"]) == str(data["peerMgtGw"]):
                logger.error("The Standby mgtIP and mgtGw cannot be same.")
                ret = False
            if (str(data["peerMgtGw"]) == str(data["peerHaIp"])):
                logger.error("The Standby mgtGw and HA IP cannot be same.")
                ret = False
            if (str(data["peerMgtGw"]) == str(data["haIp"])):
                logger.error("The Standby mgtGw and HA IP cannot be same.")
                ret = False
            if (str(data["peerMgtIp"]) == str(data["haIp"])):
                logger.error("The Standby mgtIP and HA IP cannot be same.")
                ret = False
            if (str(data["peerMgtIp"]) == str(data["peerHaIp"])):
                logger.error("The Standby mgtIP and HA IP cannot be same.")
                ret = False
        if (data["mgtIpType"] == 2 or data["mgtIpType"] == 3) and (data["peerMgtIpType"] == 2 or data["peerMgtIpType"] == 3):
            if str(data["mgtIpV6"]) == str(data["peerMgtIpV6"]):
                logger.error("The Mgt IPV6 of active and standby cannot be same.")
                ret = False
            if str(data["mgtIpV6"]) == str(data["peerMgtGwV6"]):
                logger.error("The Active mgtIPV6 and Standby MgtGwV6 cannot be same.")
                ret = False
            if str(data["peerMgtIpV6"]) == str(data["mgtGwV6"]):
                logger.error("The Standby mgtIPV6 and Active mgtGwV6 cannot be same.")
                ret = False
        if data["peerMgtIpType"] == 2 or data["peerMgtIpType"] == 3:
            if str(data["peerMgtIpV6"]) == str(data["peerMgtGwV6"]):
                logger.error("The Standby mgtIPV6 and mgtGwV6 cannot be same.")
                ret = False
        if data["isMgt1Conf"] == 1:
            if (data["mgt1IpType"] == 1 or data["mgt1IpType"] == 3) and (data["peerMgt1IpType"] == 1 or data["peerMgt1IpType"] == 3):
                if str(data["mgt1Ip"]) == str(data["peerMgt1Ip"]):
                    logger.error("The Mgt1 IP of active and standby cannot be same.")
                    ret = False
                if str(data["mgt1Ip"]) == str(data["peerMgt1Gw"]):
                    logger.error("The Active mgt1IP and Standby Mgt1Gw cannot be same.")
                    ret = False
                if str(data["peerMgt1Ip"]) == str(data["mgt1Gw"]):
                    logger.error("The Standby mgt1IP and Active mgt1Gw cannot be same.")
                    ret = False
            if data["mgt1IpType"] == 1 or data["mgt1IpType"] == 3:
                if (str(data["mgt1Ip"]) == str(data["peerHaIp"])):
                    logger.error("The Active mgt1IP and Standby HA IP cannot be same.")
                    ret = False
                if (str(data["mgt1Gw"]) == str(data["peerHaIp"])):
                    logger.error("The Active mgt1Gw and Standby HA IP cannot be same.")
                    ret = False
            if data["peerMgt1IpType"] == 1 or data["peerMgt1IpType"] == 3:
                if emsData and ( str(emsData["emsIp1"]) == str(data["peerMgt1Ip"])):
                    logger.error("The Standby mgt1IP and emsIP1 cannot be same.")
                    ret = False
                if emsData and ( str(emsData["emsIp1"]) == str(data["peerMgt1Gw"])):
                    logger.error("The Standby mgt1Gw and emsIP1 cannot be same.")
                    ret = False
                if emsData and ( str(emsData["emsIp2"]) == str(data["peerMgt1Ip"])):
                    logger.error("The Standby mgt1IP and emsIP2 cannot be same.")
                    ret = False
                if emsData and ( str(emsData["emsIp2"]) == str(data["peerMgt1Gw"])):
                    logger.error("The Standby mgt1Gw and emsIP2 cannot be same.")
                    ret = False
                if oamData and ( str(oamData["oamIp1"]) == str(data["peerMgt1Ip"])):
                    logger.error("The Standby mgt1IP and oamIP1 cannot be same.")
                    ret = False
                if oamData and ( str(oamData["oamIp1"]) == str(data["peerMgt1Gw"])):
                    logger.error("The Standby mgt1Gw and oamIP1 cannot be same.")
                    ret = False
                if oamData and ( str(oamData["oamIp2"]) == str(data["peerMgt1Ip"])):
                    logger.error("The Standby mgt1IP and oamIP2 cannot be same.")
                    ret = False
                if oamData and ( str(oamData["oamIp2"]) == str(data["peerMgt1Gw"])):
                    logger.error("The Standby mgt1Gw and oamIP2 cannot be same.")
                    ret = False
                if str(data["peerMgt1Ip"]) == str(data["peerMgt1Gw"]):
                    logger.error("The Standby mgt1IP and mgt1Gw cannot be same.")
                    ret = False
                if (str(data["peerMgt1Ip"]) == str(data["haIp"])):
                    logger.error("The Standby mgt1IP and HA IP cannot be same.")
                    ret = False
                if (str(data["peerMgt1Ip"]) == str(data["peerHaIp"])):
                    logger.error("The Standby mgt1IP and HA IP cannot be same.")
                    ret = False
                if (str(data["peerMgt1Gw"]) == str(data["haIp"])):
                    logger.error("The Standby mgt1Gw and HA IP cannot be same.")
                    ret = False
                if (str(data["peerMgt1Gw"]) == str(data["peerHaIp"])):
                    logger.error("The Standby mgt1Gw and HA IP cannot be same.")
                    ret = False
            if (data["mgt1IpType"] == 2 or data["mgt1IpType"] == 3) and (data["peerMgt1IpType"] == 2 or data["peerMgt1IpType"] == 3):
                if str(data["mgt1IpV6"]) == str(data["peerMgt1IpV6"]):
                    logger.error("The Mgt1 IPV6 of active and standby cannot be same.")
                    ret = False
                if str(data["mgt1IpV6"]) == str(data["peerMgt1GwV6"]):
                    logger.error("The Active mgt1IPV6 and Standby Mgt1GwV6 cannot be same.")
                    ret = False
                if str(data["peerMgt1IpV6"]) == str(data["mgt1GwV6"]):
                    logger.error("The Standby mgt1IPV6 and Active mgt1GwV6 cannot be same.")
                    ret = False
            if data["peerMgt1IpType"] == 2 or data["peerMgt1IpType"] == 3:
                if str(data["peerMgt1IpV6"]) == str(data["peerMgt1GwV6"]):
                    logger.error("The Standby mgt1IPV6 and mgt1GwV6 cannot be same.")
                    ret = False
    else:
        logger.info("Non HA setup..")
    return ret

def validateKeysinJSON(data, logger):
    ret = True
    tempkey = list(keys)
    extrakey = []
    for key, value in data.items():
        if key in keys:
            tempkey.remove(key)
        if key not in keys:
            extrakey.append(str(key))
            ret = False
    if ret == False:
        logger.error("JSON input File is missing mandatory keys....")
        logger.error("Missing Keys are %r" % tempkey)
        logger.error("Unwanted Keys are %r" % extrakey)
    return ret

def validateKeyeinJSON(data, logger):
    ret = True
    tempkey = list(emsKeys)
    extrakey = []
    for key, value in data.items():
        if key in emsKeys:
            tempkey.remove(key)
        if key not in emsKeys:
            extrakey.append(str(key))
            ret = False
    if ret == False:
        logger.error("JSON input File is missing mandatory keys....")
        logger.error("Missing Keys are %r" % tempkey)
        logger.error("Unwanted Keys are %r" % extrakey)
    return ret

def validateKeyoinJSON(data, logger):
    ret = True
    tempkey = list(oamKeys)
    extrakey = []
    for key, value in data.items():
        if key in oamKeys:
            tempkey.remove(key)
        if key not in oamKeys:
            extrakey.append(str(key))
            ret = False
    if ret == False:
        logger.error("JSON input File is missing mandatory keys....")
        logger.error("Missing Keys are %r" % tempkey)
        logger.error("Unwanted Keys are %r" % extrakey)
    return ret

def validateKeyexinJSON(data, logger):
    ret = True
    tempkey = list(extraConfigKeys)
    extrakey = []
    for key, value in data.items():
        if key in extraConfigKeys:
            tempkey.remove(key)
        if key not in extraConfigKeys:
            extrakey.append(str(key))
            ret = False
    if ret == False:
        logger.error("JSON input File is missing mandatory keys....")
        logger.error("Missing Keys are %r" % tempkey)
        logger.error("Unwanted Keys are %r" % extrakey)
    return ret

def validateMandatoryValue(data, logger):
    ret = True
    for key, value in data.items():
        if value is None or value == "" :
            if int(data["installType"]) == 1 and ("peer" in key):
                continue
            elif int(data["installType"]) == 1 and ("ha" in key):
                continue
            elif int(data["mgtIpType"]) == 1 and ("mgtIpV6" in key or "mgtPrefixV6" in key or "mgtGwV6" in key):
                continue
            elif int(data["mgtIpType"]) == 2 and ("mgtIp" in key or "mgtPrefix" in key or "mgtGw" in key):
                continue
            elif int(data["peerMgtIpType"]) == 1 and ("peerMgtIpV6" in key or "peerMgtPrefixV6" in key or "peerMgtGwV6" in key):
                continue
            elif int(data["peerMgtIpType"]) == 2 and ("peerMgtIp" in key or "peerMgtPrefix" in key or "peerMgtGwV6" in key):
                continue
            elif int(data["isMgt1Conf"]) == 2 and ("mgt1IpType" in key or "mgt1Ip" in key or "mgt1Prefix" in key or "mgt1Gw" in key or "mgt1IpV6" in key or "mgt1PrefixV6" in key or "mgt1GwV6" in key or "peerMgtIpType" in key or "peerMgtIp" in key or "peerMgtPrefix" in key or "peerMgtGw" in key or "peerMgt1IpV6" in key or "peerMgt1PrefixV6" in key or "peerMgt1GwV6" in key or "peerMgt1IpType" in key or "peerMgt1Ip" in key or "peerMgt1Prefix" in key or "peerMgt1Gw" in key):
                continue
            elif (int(data["isMgt1Conf"]) == 1 and int(data["mgt1IpType"]) == 2) and ("mgt1Ip" in key or "mgt1Prefix" in key or "mgt1Gw" in key):
                continue
            elif (int(data["isMgt1Conf"]) == 1 and int(data["mgt1IpType"]) == 1) and ("mgt1IpV6" in key or "mgt1PrefixV6" in key or "mgt1GwV6" in key):
                continue
            elif (int(data["isMgt1Conf"]) == 1 and int(data["peerMgtIpType"]) == 2) and ("peerMgtIp" in key or "peerMgtPrefix" in key or "peerMgtGw" in key):
                continue
            elif (int(data["isMgt1Conf"]) == 1 and int(data["peerMgtIpType"]) == 1) and ("peerMgt1IpV6" in key or "peerMgt1PrefixV6" in key or "peerMgt1GwV6" in key):
                continue
            elif int(data["sshKeyReq"]) == 2 and ("adminSshKey" in key or "linuxadminSshKey" in key):
                    continue
            else:
                ret = False
                logger.error("Value is missing for %s" % key)

    return ret

def validateOamConfig(data, logger):
    ret = True
    if not validateKeyoinJSON(data, logger):
        return False
    if data["oamIp1"] == "":
        print("OAM configuration is not set")
        return False;
    if not validateIP(data["oamIp1"], "ha", logger):
        ret = False
    if not data["oamIp2"] == "" and not validateIP(data["oamIp1"], "ha", logger):
        ret = False
    if ret == False:
        sys.exit(1)
    else:
        return True

def validateEmsConfig(data, logger):
    ret = True
    if not validateKeyeinJSON(data, logger):
        return False
    if data["emsName"] == "":
        print("EMS configuration is not set")
        return False
    data["clusterId"]=data["EmsPrivateNodeParameters"]["clusterId"]
    if not validateName(data["emsName"], 26, logger,"emsName"):
        ret = False
    if not validatePassword(data["emsPass"], 26, logger,"emsPass"):
        ret = False
    if not (data["downloadEmsConfig"] == "True" or data["downloadEmsConfig"] == "False"):
        ret = False
    if not validateIP(data["emsIp1"], "ha", logger):
        ret = False
    if not data["emsIp2"] == "" and not validateIP(data["emsIp1"], "ha", logger):
        ret = False
    if not validateId(data["clusterId"],63, logger, "clusterId"):
        ret = False
    if ret == False:
        sys.exit(1)
    else:
        return True

def validateExtraConfig(data, logger):
    ret = True
    if not validateKeyexinJSON(data, logger):
        return False
    return ret

def validateConfig(data, emsData, oamData, logger):
    ret = True
    if not validateKeysinJSON(data, logger):
        return False
    if not validateMandatoryValue(data, logger):
        return False
    if int(data["installType"]) != 1 and int(data["installType"]) != 2:
        ret = False
        logger.error("Invalid Install Type[1 - StandAlone, 2- HA] : %s. " % data["installType"])
    if not validateName(data["systemName"], 26, logger,"systemName"):
        ret = False
    if not validateName(data["ceName"], 63, logger, "ceName"):
        ret = False

    if int(data["mgtIpType"]) not in ipType:
        ret = False
        logger.error('mgtIpType is invalid ' + data["mgtIpType"])
    if int(data["mgtIpType"]) == 1 or int(data["mgtIpType"]) == 3:
        if not validatePrefix(data["mgtPrefix"], "V4"):
            logger.error('Invalid mgtPrefix value in conf ' + data["mgtPrefix"])
            ret = False
        if not validateIP(data["mgtIp"], "mgt", logger):
            ret = False
        if not (validateIP(data["mgtGw"],"mgt",logger) and validateGW(data["mgtGw"], data['mgtIp'] + '/' + data['mgtPrefix'], logger)):
            ret = False
    elif int(data["mgtIpType"]) == 2 or int(data["mgtIpType"]) == 3:
        if not validatePrefix(data["mgtPrefixV6"], "V6"):
            logger.error('Invalid mgtPrefixV6 value in conf ' + data["mgtPrefixV6"])
            ret = False
        if not validateIP(data["mgtIpV6"], "mgt", logger):
            ret = False
        if not (validateIP(data["mgtGwV6"],"mgt",logger) and validateGW(data["mgtGwV6"], data['mgtIp'] + '/' + data['mgtPrefix'], logger)):
            ret = False
    if not validateIP(data["haIp"],"ha",logger):
        ret = False
    if not validatePrefix(data["haPrefix"], "V4"):
        logger.error('Invalid haPrefix value in conf ' + data["haPrefix"])
        ret = False
    if data["installType"] == 2:
        if not validateName(data["peerCeName"], 63, logger, "peerCeName"):
            ret = False


        if int(data["peerMgtIpType"]) not in ipType:
            ret = False
            logger.error('peerMgtIpType is invalid ' + data["peerMgtIpType"])
        if int(data["peerMgtIpType"]) == 1 or int(data["peerMgtIpType"]) == 3:
            if not validatePrefix(data["peerMgtPrefix"], "V4"):
                logger.error('Invalid peerMgtPrefix value in conf ' + data["mgtPrefix"])
                ret = False
            if not validateIP(data["peerMgtIp"], "mgt", logger):
                ret = False
            if not (validateIP(data["peerMgtGw"],"mgt",logger) and validateGW(data["peerMgtGw"], data['peerMgtIp'] + '/' + data['peerMgtPrefix'], logger)):
                ret = False
        elif int(data["peerMgtIpType"]) == 2 or int(data["peerMgtIpType"]) == 3:
            if not validatePrefix(data["peerMgtPrefixV6"], "V6"):
                logger.error('Invalid peerMgtPrefix value in conf ' + data["mgtPrefix"])
                ret = False
            if not validateIP(data["peerMgtIpV6"], "mgt", logger):
                ret = False
            if not (validateIP(data["peerMgtGwV6"],"mgt",logger) and validateGW(data["peerMgtGwV6"], data['peerMgtIpV6'] + '/' + data['peerMgtPrefixV6'], logger)):
                ret = False
        if not (validateIP(data["peerHaIp"],"ha",logger) and validateGW(data["peerHaIp"], data['haIp'] + '/' + data['haPrefix'])):
            logger.error('Peer HA IP is not in same subnet as the active.')
            ret = False
        if not validateIP(data["ntpIp"], "ntp", logger):
            ret = False
        if not validateSbcType(data["sbctype"]):
            ret = False
            logger.error('SBC Type is invalid. Please use %r' % sbxType)
        if not (int(data["tipc"]) > 1025 and int(data["tipc"]) < 4095):
            logger.error("Invalid tipc id " + data["tipc"])
            ret = False
        if not (int(data["timezone"]) > 0 and int(data["timezone"]) < 596):
            logger.error("Invalid timezone id " + data["timezone"] + ". Value should be between 1-595.")
            ret = False
    if not validateAllIps(data,emsData,oamData,logger):
        logger.error("HA Validation failed..")
        ret = False

    return ret

def validateGPUFlag(gpuFlag, logger):
    """
    Validate GPU flag information
    """
    allowedValues = ["true", "false"]
    if type(gpuFlag) != str:
        logger.error("GPU flag must be a string value. Allowed value : %s" %(allowedValues))
        logger.error("type : %s" %(type(gpuFlag)))
        return False
    if gpuFlag.lower() not in allowedValues:    
        logger.error("GPU flag : Invalid Value : %s" %(gpuFlag))
        return False
    return True


def validateCallMixData(callmix, gpuFlag, logger):
    """
    Validate callmix data.
    """
    if gpuFlag == "false":
        logger.info("CPU Profile. Not validating the callmix")
        return True
    else:
        if not callmix:
            logger.error("GPU Flag is enabled. Please provide a valid callmix.")
            return False
        else:
            g711Percentage = 0
            gpuCodecPercentage = 0
            cpuOnlyCodecPercentage = 0
            totalPercentage = 0
            gpuCodecs = ['G729', 'G722', 'EVRCB', 'AMRWB', 'EVRC', 'AMR']
            cpuCodecs = ['G723', 'G726', 'G7221', 'ILBC', 'OPUS', 'SILK_8', 'SILK_16', 'EVS', 'T38', 'G7112G711']
            g711Codec = ['G711']
            supportedCodecs = gpuCodecs + cpuCodecs + g711Codec
            for allowedCodec in supportedCodecs:
                codecPercentage = callmix.get(allowedCodec, 0)
                if codecPercentage > 0:
                    totalPercentage += codecPercentage
                    if allowedCodec in gpuCodecs:
                        gpuCodecPercentage += codecPercentage
                    if allowedCodec in cpuCodecs:
                        cpuOnlyCodecPercentage += codecPercentage
                    if allowedCodec in g711Codec:
                        g711Percentage += codecPercentage
            if totalPercentage != 100:
                logger.error("Sum of codec Percentage does not add to 100%. Please provide a valid callmix.")
                return False

            if (g711Percentage > cpuOnlyCodecPercentage + gpuCodecPercentage):
                logger.error("G711% cannot be greater than non-G711%. Please provide a valid callmix.")
                return False

            if gpuCodecPercentage == 0:
                logger.error("Sum of GPU codec percentage cannot be 0 in a GPU profile. Please provide a valid callmix.")
                return False

        return True


def validateTonePercentage(tonePercentage, gpuFlag, sbcConfData, logger):
    """
    Validate Tone Percentage.
    """
    if gpuFlag == "false":
        logger.info("CPU Profile. Not validating the tone percentge.")
        return True
    elif ((sbcConfData["sbctype"] != "isbc") and (tonePercentage != 0)):
        logger.error("Tone percentage can only be provided in the ISBC mode")
        return False
    else:
        if type(tonePercentage) != int:
            logger.error("Invalid Value for tone percentage. Please enter an integer value 0<=x<=100")
            return False
        if tonePercentage > 100 or tonePercentage < 0:
            logger.error("Invalid Value for tone percentage. Please enter an integer value 0<=x<=100")
            return False
    return True

def validateTsbcConfig(tsbcData, sbcConfData, logger):
    """
    Validates TSBC configuration information
    TSBC configuration contains 3 main parts : 
    
    1. GPU flag.
    2. Callmix dictionary.
    3. Tone Percentage information.
    
    """
    tsbcConfig = tsbcData.get("TranscodeConfig", {})
    if not tsbcConfig:
        logger.error("TranscodeConfig cannot be null. Please enter a valid TSBC configuration.")
        return False

    gpuFlag = tsbcConfig.get("gpu", "false")
    if type(gpuFlag) is "<class 'bytes'>":
        gpuFlag = gpuFlag.decode('utf8')
    if not validateGPUFlag(gpuFlag, logger):
        logger.error("Invalid value provided for GPU flag in transcode config")
        return False

    callmixData = tsbcConfig.get("callmix", {})
    if not validateCallMixData(callmixData, gpuFlag, logger):
        logger.error("Invalid value/s provided in callmix in transcode config")
        return False

    tonePercentage = tsbcConfig.get("tone", 0)
    if not validateTonePercentage(tonePercentage, gpuFlag, sbcConfData, logger):
        logger.error("Invalid value provided for LRBT Percentage in transcode config")
        return False

    logger.info("The TSBC configuration provided is a valid data. Proceeding further.")
    return True
