#!/usr/bin/python
import sys
import os
try:
    from vmguestlib import VMGuestLib, VMGuestLibException
    from multiprocessing import cpu_count
    import xml.etree.ElementTree as ET
    import subprocess
    from socket import gethostname
    from syslog import openlog, syslog, LOG_ERR
    from optparse import OptionParser
except ImportError as e:
    if sys.stdout.isatty():
        print "Could not import all needed modules: %s\n" % str(e)
        print "Letting check pass."
    sys.exit(0)

CHECKS_PASSED=0
CHECKS_FAILED=3

# RMX Alarms
NO_ALARM = 0;
MINOR_ALARM = 1;
MAJOR_ALARM = 2;

# Deployment constants
DEP_SINGLE_NODE_SRV=0
DEP_LOCAL_SEP_SRV=10
DEP_LOCAL_SEP_SRV_SG=11
DEP_SURV_SG=20
DEP_STANDALONE_SG=21
DEP_REDU_SG=30
DEP_APE=40
DEP_DSCXLV2_SIMPLEX=50
DEP_DSCXLV2_DUPLEX=60
DEP_DSCXLV2_DUPLEX_SG=61
DEP_DSCXLV2_LOCAL_SEP_DUPLEX=62
DEP_ECOAP=70
DEP_SURVIVABLE_ECOAP=71
DEP_DSCXLV2_DUPLEX_REPLACEMENT=99
DEP_UNDEFINED=100

# Required number of CPU cores for each VM deployment
CPUCoreRequirement = {
    "Quorum" : 2,
    "QuorumWithSoftGate" : 4,
    "SeparatedDuplex" : 4,
    "SimplexWithSoftGate" : 4,
    "Simplex" : 4,
    "SurvivableUnit" : 4,
    "SurvivableSoftGateStandard" : 4,
    "SoftGateStandard" : 4,
}

# Required reserved CPU frequency for each VM deployment
# NOTE: Fixed only for Quorum.
# The other deployments should follow the formula: CPU_Cores x CPU_Frequency
CPUReservedRequirement = {
    "Quorum" : 500,
}

CPUReservedRequirement_preV8 = {
    "Quorum" : 500,
    "QuorumWithSoftGate" : 4000,
    "SeparatedDuplex" : 8000,
    "SimplexWithSoftGate" : 8000,
    "Simplex" : 8000,
    "SurvivableUnit" : 8000,
    "SurvivableSoftGateStandard" : 8000,
}

# Required memory allocation for each VM deployment
MemoryRequirement = {
    "Quorum" : 2048,
    "QuorumWithSoftGate" : 4096,
    "SeparatedDuplex" : 4096,
    "SimplexWithSoftGate" : 8192,
    "Simplex" : 4096,
    "SurvivableUnit" : 4096,
    "SurvivableSoftGateStandard" : 8192,
    "SoftGateStandard" : 4096,
}

# Required memory reservation for each VM deployment
ReservedMemoryRequirement = {
    "Quorum" : 1024,
    "QuorumWithSoftGate" : 4096,
    "SeparatedDuplex" : 4096,
    "SimplexWithSoftGate" : 8192,
    "Simplex" : 4096,
    "SurvivableUnit" : 4096,
    "SurvivableSoftGateStandard" : 8192,
    "SoftGateStandard" : 4096,
}

# Print in colors for clearer display of results
def print_color(text, color):
    is_tty = sys.stdout.isatty()
    if is_tty:
        sys.stdout.write(color)
    sys.stdout.write(text)
    if is_tty:
        sys.stdout.write(print_color.RESET)
    sys.stdout.write("\n")

print_color.RED   = "\033[1;31m"
print_color.GREEN = "\033[0;32m"
print_color.RESET = "\033[0;0m"

def print_red(text):
    print_color(text, print_color.RED)

def print_green(text):
    print_color(text, print_color.GREEN)

def cmd(command):
    try:
        process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
        stdout, stderr = process.communicate()
        return process.returncode, stdout
    except Exception as e:
        print "Error: Failed to execute command: %s" % command
        print "Exception: %s" % str(e)
        return 127, ""

def send_hista(alarm, event, subevent, message):
    hostname = gethostname()
    is_host = cmd('/opt/webservice/scripts/is_running_with_a_central_CC_on_same_node.sh')[0] == 1
    identifier = ""
    if is_host:
        identifier = 'Host: '
    else:
        ltu = cmd('/opt/soco/native/os/linux/get_LTU.sh')[1].strip()
        slot = cmd('/opt/soco/native/os/linux/get_Slot.sh')[1].strip()
        if ltu:
            identifier = "LTU %s: " % ltu
        if slot:
            identifier += "Slot %s: " % slot

    message = "%s %s %s" % (identifier, hostname, message)

    if is_host:
        # Use direct HISTA message interface - via Atlantic LAN telnet interface.
        exit_code, output = cmd("/opt/dscxl/hcm-test/histamessage.py --alarm %s --event %s --subevent %s '%s'" % (alarm, event, subevent, message))
    else:
        # Use Inventory HISTA message interface - HISTA sent to Primary Node of Central Host.
        exit_code, output = cmd("/opt/inventory/inventory-client.sh notification HISTA_MESSAGE --alarm %s --event %s --subevent %s '%s'" % (alarm, event, subevent, message))

    if output.find('HISTA message successfully sent') != -1:
        return True

    return False

def report_error(errorMessage, report=False, quiet=False, dont_report_hista=False):
    if not quiet:
        if sys.stdout.isatty():
            print_red("\nError: %s" % errorMessage)
        else:
            print "Error: %s" % errorMessage

    if not report:
        return True

    # Report to syslog
    syslog(LOG_ERR, "Error: %s" % errorMessage)

    if dont_report_hista:
        return True
    # Report HISTA message via Inventory callback to Central Host RMX
    # event=0x2b and subevent=0x37 should result in MAINTENANCE message.
    return send_hista(NO_ALARM, 0x2b, 0x37, errorMessage)

def get_haipsetup_entry(name):
    if os.path.isfile('/var/opt/ha/conf/haipsetup.xml'):
        try:
            tree = ET.parse('/var/opt/ha/conf/haipsetup.xml')
            root = tree.getroot()
            for entry in root.findall("entry"):
                if entry.attrib['key'] == name:
                    return entry.text
        except ET.ParseError as e:
            print "Could not parse haipsetup.xml: %s" % str(e)
            return None
    else:
        return None

def deployment_name():
    """ Detect Platform deployment from system. Only returns VM relevant deployments. """
    code = get_haipsetup_entry("system.multiNodeSystem")
    if code is None:
        return "Undefined"
    code = int(code)
    if code == DEP_LOCAL_SEP_SRV or code == DEP_DSCXLV2_LOCAL_SEP_DUPLEX:
          ret = cmd("/opt/webservice/scripts/is_quorum")[0]
          if ret == 1:
              ret = cmd("/opt/webservice/scripts/has_softgate")[0]
              if ret == 1:
                  return "QuorumWithSoftGate"
              else:
                  return "Quorum"
          return "SeparatedDuplex"
    elif code == DEP_SINGLE_NODE_SRV or code == DEP_DSCXLV2_SIMPLEX:
          ret = cmd("/opt/webservice/scripts/has_softgate")[0]
          if ret == 1:
              return "SimplexWithSoftGate"
          return "Simplex"
    elif code == DEP_SURV_SG:
          ret = cmd("/opt/webservice/scripts/has_softgate")[0]
          if ret == 0:
              return "SurvivableUnit"
          return "SurvivableSoftGateStandard"
    elif code == DEP_STANDALONE_SG:
          return "SoftGateStandard"
    else:
          return "Irrelevant"

def deployment_name_fi_deployment(fi_deployment):
    deployment_mapping = {
        "simplex"             : "Simplex",
        "simplex_with_sg"     : "SimplexWithSoftGate",
        "quorum"              : "Quorum",
        "quorum_with_sg"      : "QuorumWithSoftGate",
        "separated_duplex"    : "SeparatedDuplex",
        "survivable"          : "SurvivableUnit",
        "survivable_softgate" : "SurvivableSoftGateStandard",
        "standalone_softgate" : "SoftGateStandard",
    }
    if fi_deployment in deployment_mapping:
        return deployment_mapping[fi_deployment]

    return "Irrelevant"

def platform_version():
    # This detects the version inside OS4k installer
    if os.path.isdir('/livecd/'):
        for File in reversed(sorted(os.listdir('/livecd/'))):
            if File.startswith('ver_'):
                return File[4:]

    # This is the interface for getting OS4k version on already installed system.
    return cmd("getydata -v")[1]

def platform_major_release():
    return platform_version().split('.')[0].split('_')[0].upper()

def GetTotalMemory():
    """ Returns the sum of virtual memory modules assigned to VM. """
    return int(cmd("dmidecode -t 17 | grep 'Size.*MB' | awk '{s+=$2} END {print s}'")[1])

def GetCPUCores():
    return cpu_count()

def VMGuestInstance():
    if VMGuestInstance.instance is None or VMGuestInstance.always_update:
        VMGuestInstance.instance = VMGuestLib()
        VMGuestInstance.instance.UpdateInfo()
    return VMGuestInstance.instance

VMGuestInstance.instance = None
VMGuestInstance.always_update = False

def AlwaysUpdateVMGuestInfo(value=True):
    VMGuestInstance.always_update = value

def GetReservedCPU():
    return VMGuestInstance().GetCpuReservationMHz()

def GetCPUShares():
    return VMGuestInstance().GetCpuShares()

def GetMemShares():
    return VMGuestInstance().GetMemShares()

def GetReservedMem():
    return VMGuestInstance().GetMemReservationMB()

def GetPhysicalCPUSpeed():
    return VMGuestInstance().GetHostProcessorSpeed()

def validate_CPUCores(Deployment, PlatformRelease, CPUCores, report=False, quiet=False):
    if Deployment in CPUCoreRequirement:
        if Deployment in ["SoftGateStandard", "QuorumWithSoftGate"]:
            # Special case: SoftGate or QuorumWithSoftGate in V7 had more complicated requirements
            # based on the SG number of channels and codec used.
            if CPUCores == 2:
                if not quiet:
                    if PlatformReleaseMajor >= 8:
                        print "\nWarning: Only 2 vCPU cores detected."
                    print "Recommended maximum setting for SoftGate type (SOCOTYPE): SG50"
                return True

            if CPUCores in [2, 4, 8] or CPUCores >= 8:
                if PlatformReleaseMajor < 8 and not quiet:
                    if CPUCores == 4:
                        print "Recommended maximum setting of SoftGate type (SOCOTYPE):\n SG1000 (with G.711 codec)\nor\n SG50   (with G.729 codec)"
                return True

            report_error("VM has fewer CPU cores than required.\n"
                        " Has: %s cores  Required: %s cores" % (CPUCores, "2, 4 or 8"), report, quiet)
            if not quiet:
                print ""
                print "# Hint: Here's a table of the V7 requirements for SG and Quorum w/ SG:"
                print "# +-------------------------+-----------------------+"
                print "# | OpenScape 4000          |         Codecs        |"
                print "# | V7 R2 SG CPU requirement|   G.711   |   G.729   |"
                print "# +-------------------------+-----------+-----------+"
                print "# |          |         SG50 |  2 cores  |  4 cores  |"
                print "# |          |        SG500 |  4 cores  |  8 cores  |"
                print "# |          |       SG1000 |  4 cores  |  8 cores  |"
                print "# | SOCOTYPE |  Quorum+SG50 |  2 cores  |  4 cores  |"
                print "# |(Channels)| Quorum+SG500 |  4 cores  |  8 cores  |"
                print "# |          |Quorum+SG1000 |  4 cores  |  8 cores  |"
                print "# +----------+--------------+-----------+-----------+"

            return False
        elif CPUCores < CPUCoreRequirement[Deployment]:
            report_error("VM has fewer CPU cores than required.\n"
                        " Has: %s cores  Required: %s" % (CPUCores, CPUCoreRequirement[Deployment]), report, quiet)
            return False
    return True

def validate_ReservedCPU(Deployment, PlatformRelease, ReservedCPU, PhysicalCPUFreq, CPUCores, CalledAutomatically, report=False, quiet=False):
    # Deployments with fixed CPU reservation requirement:
    if PlatformReleaseMajor < 8:
        # The requirements for V7R2 for CPU reservations were static.
        # SG requirements were based on the SG settings (channels and codec).
        # The Frequency Reservation requirement however followed the rule: Reserved = CPUCores x 2000 Mhz
        if Deployment in ["SoftGateStandard", "QuorumWithSoftGate"]:
            RequiredCPUReserved = CPUCores * 2000
            if ReservedCPU < RequiredCPUReserved:
                report_error("VM reserved CPU frequency lower than required.\n"
                            " Has: %s MHz Required: %s Mhz" % (ReservedCPU, RequiredCPUReserved), report, quiet)
                return False
            return True
        if Deployment in CPUReservedRequirement_preV8:
            if ReservedCPU < CPUReservedRequirement_preV8[Deployment]:
                report_error("VM reserved CPU frequency lower than required.\n"
                            " Has: %s MHz Required: %s Mhz" % (ReservedCPU, CPUReservedRequirement_preV8[Deployment]), report, quiet)
                return False
        return True
    else:
        if Deployment in CPUReservedRequirement:
            if ReservedCPU < CPUReservedRequirement[Deployment]:
                report_error("VM reserved CPU frequency lower than required.\n"
                            " Has: %s MHz Required: %s Mhz" % (ReservedCPU, CPUReservedRequirement[Deployment]), report, quiet)
                return False
            return True

    # V8 and later deployments: Check that Reserved CPU is following the formula: CPU_Cores x Physical_CPU_Frequency
    # Let check pass with 1% tolerance - to allow cases, when reservation in ESXi can't be set to exact Frequency of CPU.
    if ReservedCPU < (PhysicalCPUFreq * CPUCores * 0.99):
        # OSFOURK-7797 - adjust reporting to HISTA - only report to HISTA if ReservedCPU is under the V7 threshold (2000Mhz per core).
        v7_requirement_met = not (ReservedCPU < (CPUCores * 2000 * 0.99))
        if CalledAutomatically and v7_requirement_met:
            # Let check pass, but report error to syslog.
            syslog(LOG_ERR, "Error: VM reserved CPU frequency lower than required.\n"
                            " Has: %s MHz Required: %s MHz" % (ReservedCPU, PhysicalCPUFreq * CPUCores))
            return True
        report_error("VM reserved CPU frequency lower than required.\n"
                     " Has: %s MHz Required: %s MHz" % (ReservedCPU, PhysicalCPUFreq * CPUCores), report, quiet, dont_report_hista=v7_requirement_met)
        if not quiet:
            print "Hint: Recommended CPU reservation is the maximum setting possible for the number of vCPU."
            print "      ReservedCPU = Number_of_vCPU_Cores * Physical_CPU_Speed"
        return False
    return True

def validate_CPUShares(CPUCores, CPUShares, report=False, quiet=False):
    if CPUShares/CPUCores < 2000:
        report_error("VM CPU Shares are lower than required.\n"
                     ' Has: %s Required: %s ("High" setting)' % (CPUShares, CPUCores * 2000), report, quiet)
        return False
    return True

def validate_Memory(Deployment, PlatformRelease, TotalMemory, CPUCores, report=False, quiet=False):
    # V7 Standalone SGs and Quorum SGs
    if PlatformReleaseMajor < 8:
        if Deployment in ["SoftGateStandard", "QuorumWithSoftGate"]:
            MemoryRequiredSG = CPUCores * 1024
            if TotalMemory < MemoryRequiredSG:
                report_error("VM Memory allocation is lower than required.\n"
                            " Has: %s MB Required: %s MB" % (TotalMemory, MemoryRequiredSG), report, quiet)
                if not quiet:
                    print ""
                    print "# Hint: Here's a table of the V7 requirements for SG and Quorum w/ SG:"
                    print "# +-------------------------+-----------------------+"
                    print "# | OpenScape 4000          |         Codecs        |"
                    print "# | V7 R2 SG Mem requirement|   G.711   |   G.729   |"
                    print "# +-------------------------+-----------+-----------+"
                    print "# |          |         SG50 |    2 GB   |    4 GB   |"
                    print "# |          |        SG500 |    4 GB   |    8 GB   |"
                    print "# |          |       SG1000 |    4 GB   |    8 GB   |"
                    print "# | SOCOTYPE |  Quorum+SG50 |    2 GB   |    4 GB   |"
                    print "# |(Channels)| Quorum+SG500 |    4 GB   |    8 GB   |"
                    print "# |          |Quorum+SG1000 |    4 GB   |    8 GB   |"
                    print "# +----------+--------------+-----------+-----------+"
                return False
            return True
        if Deployment in MemoryRequirement:
            if TotalMemory < MemoryRequirement[Deployment]:
                report_error("VM Memory allocation is lower than required.\n"
                            " Has: %s MB Required: %s MB" % (TotalMemory, MemoryRequirement[Deployment]), report, quiet)
                return False
        return True

    # V8 and later

    # Special case: Might be a Standalone SG upgraded from V7R2 SG50 - only had 2GB requirement.
    if Deployment in ["SoftGateStandard", "QuorumWithSoftGate"] and CPUCores == 2:
        SG50_MemoryRequirement = 2048
        if TotalMemory < SG50_MemoryRequirement:
            report_error("VM Memory allocation is lower than required.\n"
                        " Has: %s MB Required: %s MB" % (TotalMemory, SG50_MemoryRequirement), report, quiet)
            return False
        return True

    if Deployment in MemoryRequirement:
        if TotalMemory < MemoryRequirement[Deployment]:
            report_error("VM Memory allocation is lower than required.\n"
                        " Has: %s MB Required: %s MB" % (TotalMemory, MemoryRequirement[Deployment]), report, quiet)
            return False
    return True

def validate_MemoryReservation(Deployment, PlatformRelease, ReservedMem, CPUCores, report=False, quiet=False):
    if PlatformReleaseMajor < 8:
        if Deployment in ["SoftGateStandard", "QuorumWithSoftGate"]:
            ReservedMemoryRequiredSG = CPUCores * 1024
            if ReservedMem < ReservedMemoryRequiredSG:
                report_error("VM Memory reservation is lower than required.\n"
                            " Has: %s MB Required: %s MB" % (ReservedMem, ReservedMemoryRequiredSG), report, quiet)
                if not quiet:
                    print ""
                    print "# Hint: Here's a table of the V7 requirements for SG and Quorum w/ SG:"
                    print "# +-------------------------+-----------------------+"
                    print "# | OpenScape 4000          |         Codecs        |"
                    print "# | V7 R2 SG Mem requirement|   G.711   |   G.729   |"
                    print "# +-------------------------+-----------+-----------+"
                    print "# |          |         SG50 |    2 GB   |    4 GB   |"
                    print "# |          |        SG500 |    4 GB   |    8 GB   |"
                    print "# |          |       SG1000 |    4 GB   |    8 GB   |"
                    print "# | SOCOTYPE |  Quorum+SG50 |    2 GB   |    4 GB   |"
                    print "# |(Channels)| Quorum+SG500 |    4 GB   |    8 GB   |"
                    print "# |          |Quorum+SG1000 |    4 GB   |    8 GB   |"
                    print "# +----------+--------------+-----------+-----------+"
                return False
            return True
        if Deployment in ReservedMemoryRequirement:
            if ReservedMem < ReservedMemoryRequirement[Deployment]:
                report_error("VM Memory reservation is lower than required.\n"
                            " Has: %s MB Required: %s MB" % (ReservedMem, ReservedMemoryRequirement[Deployment]), report, quiet)
                return False
        return True

    # V8 and later

    if Deployment in ["SoftGateStandard", "QuorumWithSoftGate"]:
        ReservedMemoryRequiredSG = CPUCores * 1024
        if ReservedMem < ReservedMemoryRequiredSG:
            report_error("VM Memory reservation is lower than required.\n"
                        " Has: %s MB Required: %s MB" % (ReservedMem, ReservedMemoryRequiredSG), report, quiet)
            return False
        return True

    if Deployment in ReservedMemoryRequirement:
        if ReservedMem < ReservedMemoryRequirement[Deployment]:
            report_error("VM Memory reservation is lower than required.\n"
                        " Has: %s MB Required: %s MB" % (ReservedMem, ReservedMemoryRequirement[Deployment]), report, quiet)
            return False
    return True

def validate_MemoryShares(TotalMemory, MemShares, report=False, quiet=False):
    if TotalMemory <= 0 or MemShares/TotalMemory < 10:
        report_error("VM Memory shares are lower than required.\n"
                     ' Has: %s Required: %s ("Normal" setting)' % (MemShares, TotalMemory * 10), report, quiet)
        return False
    return True

def validate_all(Deployment, PlatformRelease, CPUCores, PhysicalCPUFreq,
                 ReservedCPU, CPUShares, TotalMemory,
                 ReservedMem, MemShares, CalledAutomatically, report=False, quiet=False):
    """ Perform all available checks, return True if all passed """
    cores_valid = validate_CPUCores(Deployment, PlatformRelease, CPUCores, report, quiet)
    cpu_reserved_valid = validate_ReservedCPU(Deployment, PlatformRelease, ReservedCPU, PhysicalCPUFreq, CPUCores, CalledAutomatically, report, quiet)
    cpu_shares_valid = validate_CPUShares(CPUCores, CPUShares, report, quiet)
    memory_valid = validate_Memory(Deployment, PlatformRelease, TotalMemory, CPUCores, report, quiet)
    mem_reservation_valid = validate_MemoryReservation(Deployment, PlatformRelease, ReservedMem, CPUCores, report, quiet)
    mem_shares_valid = validate_MemoryShares(TotalMemory, MemShares, report, quiet)

    if (cores_valid and cpu_reserved_valid and
        cpu_shares_valid and memory_valid and
        mem_reservation_valid and mem_shares_valid):
        return True

    if not quiet:
        print ""
        print "--------------------------------------------------"
        print "Recommended actions:"
        if not cores_valid:
            print "Increase Number of Cores:"
            print "  To change number of vCPU cores, the VM needs to be Powered-Off."
            print "  Once VM is powered-off you can go to VM Settings > Hardware > CPUs."
            print "  Increase number of virtual sockets to the Required value of CPU cores."
            print ""
        if not memory_valid:
            print "Increase Memory size:"
            print "  To change size of Total Memory, the VM needs to be Powered-Off."
            print "  Once VM is powered-off you can go to VM Settings > Hardware > Memory."
            print "  Increase memory size to the Required value."
            print ""
        if not cpu_reserved_valid:
            print "Increase CPU reservation:"
            print "  CPU Reservation can be changed on-the-fly."
            print "  You can go right now to VM Settings > Resources > CPU."
            print "  Increase \"Reservation\" to the Required value."
            print "  Set it to maximum value possible,"
            print "  in case ESXi does not allow to set this exactly to the Required value."
            print ""
        if not cpu_shares_valid:
            print "Increase CPU shares:"
            print "  CPU Shares can be changed on-the-fly."
            print "  You can go right now to VM Settings > Resources > CPU."
            print "  Increase Shares to the Required value."
            print ""
        if not mem_reservation_valid:
            print "Increase Memory Reservation:"
            print "  Memory reservation can be changed on-the-fly."
            print "  You can go right now to VM Settings > Resources > Memory."
            print "  Increase Reservation to the Required value."
            print ""
        if not mem_shares_valid:
            print "Increase Memory Shares:"
            print "  Memory shares can be changed on-the-fly."
            print "  You can go right now to VM Settings > Resources > Memory."
            print "  Increase Shares to the Required value."
            print ""

    return False

def vmware_detected():
    exit_code, output = cmd('vmxcap -i')
    if exit_code != 0:
        return False
    if output.find('vmware_esx') == -1:
        return False
    return True

def GUIMemShareLevel(MemShares, TotalMemory):
    """ Approximate the Memory Shares setting in VMWare GUI. """
    if MemShares/TotalMemory == 20:
        return "High"
    if MemShares/TotalMemory == 10:
        return "Normal"
    if MemShares/TotalMemory == 5:
        return "Low"
    return "Custom"

def GUICpuSharesLevel(CPUShares, CPUCores):
    """ Approximate the CPU Shares setting in VMWare GUI """
    if CPUShares/CPUCores == 2000:
        return "High"
    if CPUShares/CPUCores == 1000:
        return "Normal"
    if CPUShares/CPUCores == 500:
        return "Low"
    return "Custom"

def CheckVMResources(report=False, quiet=True, release=None):
    """
    Returns True if the VM resources match requirements.
    Also returns True if not a VM or if this check is otherwise not relevant.
    Returns False if the checks did not pass.
    """
    if not vmware_detected():
        return True

    Deployment = deployment_name()
    if Deployment == "Irrelevant":
        return True

    CPUCores = GetCPUCores()

    try:
        ReservedCPU = GetReservedCPU()
        CPUShares = GetCPUShares()
        MemShares = GetMemShares()
        ReservedMem = GetReservedMem()
    except VMGuestLibException as e:
        return True

    PhysicalCPUFreq = GetPhysicalCPUSpeed()
    TotalMemory = GetTotalMemory()

    if release is not None:
        PlatformRelease = release[:2].upper()
    else:
        PlatformRelease = platform_major_release()
        PlatformReleaseMajor = int(PlatformRelease.strip('V')) #OSFOURK-16344 check_vmguest tolerance is not working in V10. Make the check against Major version integer

    if PhysicalCPUFreq == "" or TotalMemory == "":
        return True

    if validate_all(Deployment, PlatformRelease, CPUCores, PhysicalCPUFreq,
                    ReservedCPU, CPUShares, TotalMemory,
                    ReservedMem, MemShares, CalledAutomatically, report, quiet):
        return True

    return False

if __name__ == "__main__":
    parser = OptionParser()
    parser.add_option("-r", "--report", dest="report",
                            action="store_true", default=False,
                            help="Report errors to syslog and to HISTA (to Central Host)")
    parser.add_option("-q", "--quiet",
                            action="store_true", dest="quiet", default=False,
                            help="Don't print any output to stdout.")
    parser.add_option("-v", "--version",
                            action="store", dest="release", default=None,
                            help="Override detection of Platform major version release with this parameter.")
    parser.add_option("-d", "--deployment",
                            action="store", dest="deployment", default=None,
                            help="Override detection of Platform deployment with this parameter.")

    (options, args) = parser.parse_args()

    if __file__ == "/etc/cron.hourly/check_vmguest":
        # If executed from cron, there will be no output, only HISTA error report
        report, quiet = True, True
    else:
        report, quiet = options.report, options.quiet

    if __file__ == "/opt/soco-common/check_vmguest":
        # If executed from swupdated or from SG - this is detected if the script is called with full path.
        # The check behaviour is a little different than when it is called manually via "check_vmguest" (symlink /usr/local/bin/check_vmguest).
        CalledAutomatically = True
    else:
        CalledAutomatically = False

    if not sys.stdout.isatty() and os.path.isfile('/disable_check_vmguest'):
        sys.exit(0)

    if not vmware_detected():
        if not quiet: print "Not a VMWare Virtual Machine - checks not possible."
        sys.exit(0)

    if options.deployment is not None:
        Deployment = deployment_name_fi_deployment(options.deployment)
    else:
        Deployment = deployment_name()

    if Deployment == "Irrelevant":
        if not quiet: print "These checks are not relevant for this deployment."
        sys.exit(0)
    if Deployment == "Undefined":
        if not quiet: print "The deployment is not defined. Letting check pass."
        sys.exit(0)

    if options.release is not None:
        PlatformRelease = options.release[:2].upper()
    else:
        PlatformRelease = platform_major_release()
        PlatformReleaseMajor = int(PlatformRelease.strip('V'))  #OSFOURK-16344 check_vmguest tolerance is not working in V10. Make the check against Major version integer

    CPUCores = GetCPUCores()

    try:
        ReservedCPU = GetReservedCPU()
        CPUShares = GetCPUShares()
        MemShares = GetMemShares()
        ReservedMem = GetReservedMem()
        PhysicalCPUFreq = GetPhysicalCPUSpeed()
    except VMGuestLibException as e:
        if not quiet: print "Could not load VM parameters using VMWare Tools API."
        sys.exit(0)

    TotalMemory = GetTotalMemory()

    if PhysicalCPUFreq == "" or TotalMemory == "":
        sys.exit(0)

    CPUSharesLevel = GUICpuSharesLevel(CPUShares, CPUCores)
    MemSharesLevel = GUIMemShareLevel(MemShares, TotalMemory)

    if not quiet:
        print "Current VM resources:"
        print "   Platform Release:", PlatformRelease
        print "      VM Deployment:", Deployment
        print "Number of CPU Cores:", CPUCores
        print "  Physical CPU freq:", PhysicalCPUFreq, "MHz"
        print "       Reserved cpu:", ReservedCPU, "MHz"
        print "         CPU Shares:", CPUShares, "(", CPUSharesLevel, ")"
        print "       Total Memory:", TotalMemory, "MB"
        print "    Memory Reserved:", ReservedMem, "MB"
        print "      Memory shares:", MemShares, "(", MemSharesLevel, ")"
        print ""

    openlog("check_vmguest")

    all_valid = validate_all(Deployment, PlatformRelease, CPUCores, PhysicalCPUFreq,
                             ReservedCPU, CPUShares, TotalMemory,
                             ReservedMem, MemShares, CalledAutomatically, report, quiet)

    if not quiet: print "\nCheck result: ",

    if all_valid:
        if not quiet: print_green('PASSED')
        sys.exit(CHECKS_PASSED)
    else:
        if not quiet: print_red('FAILED')
        sys.exit(CHECKS_FAILED)

