import subprocess
import os
from baseCheck import baseCheck

class ramCpuLimits(baseCheck):

    def getHumanName(self):
            return "Confirm Max CPU and RAM Values"

    def runCheck(self, config, debug):
        # do whatever is desired to check here.
        # return non-zero if an internal error is detected (equivilent to raising an exception)
        # return 0 for both check pass and check fail.
        #    call self.addWarning(text) or self.addWarning(rawText,humanText) for every warning to be logged
        #    call self.addFailure(text) or self.addFailure(rawText,humanText) for every failure to be logged

        # make sure the
        returnCode=0

        for server in config["environment"]["servers"]:
            # check the ram & cpu limits vs entered values.
            maxRAM = int(server["maxRAM"])
            maxCPU = int(server["maxCPU"])
            actualmaxCPU = 0
            actualmaxRAM = 0

            # Check Max CPU value
            actualmaxCPUstr = '(Invalid ssh return)'
            try:
                actualmaxCPUstr = subprocess.Popen(['ssh',server["accessIP"],'-o','StrictHostKeyChecking=no','/usr/bin/nproc'], stdout=subprocess.PIPE).communicate()[0]
                actualmaxCPU = int(actualmaxCPUstr.strip())

                sumCPU = 0
                for vm in server["vms"]:
                    sumCPU += int(vm["cpu"])

                if maxCPU > actualmaxCPU:
                    # we have a problem.
                    self.addFailure("Requested number of CPUs [%d] exceeds the %d CPUs available on KVM host %s. Please reduce Max CPU to less than %d." % (maxCPU,actualmaxCPU,server["accessIP"],actualmaxCPU))
                elif sumCPU > actualmaxCPU:
                    self.addFailure("Total number of requested CPUs for VMs [%d] exceeds the %d CPUs available on KVM host %s. Please verify the number of CPUs assigned to each VM." % (sumCPU,actualmaxCPU,server["accessIP"]))

                self.logMsg("KVM host %s has %d CPUs, %d CPUs assigned [%d CPUs to VMs]" % (server["accessIP"],actualmaxCPU,maxCPU,sumCPU))

            except Exception as e:
                self.addFailure("Unable to verify CPU limits on %s." % server["accessIP"])
                self.logMsg("Return from /usr/bin/nproc on %s: %s" % (server["accessIP"],actualmaxCPUstr))
                self.logMsg("Exception: %s" % str(e))

            # Check Max RAM value
            actualmaxRAMstr = '(Invalid ssh return)'
            try:
                actualmaxRAMstr = subprocess.Popen(['ssh',server["accessIP"],'/usr/bin/free','-m','-o'], stdout=subprocess.PIPE).communicate()[0]
                for line in actualmaxRAMstr.split("\n"):
                    if line[0:3] == 'Mem':
                        actualmaxRAMstr = line.split()[1]
                        break
                actualmaxRAM = int(actualmaxRAMstr) / 1024

                sumRAM = 0
                for vm in server["vms"]:
                    sumRAM += int(vm["ram"])
                sumRAM = sumRAM / 1024

                if maxRAM > actualmaxRAM:
                    # we have a problem.
                    self.addFailure("Requested amount of RAM [%d GB] exceeds the %d GB RAM available on KVM host %s. Please reduce Max RAM to less than %d." % (maxRAM,actualmaxRAM,server["accessIP"],actualmaxRAM))
                elif sumRAM > actualmaxRAM:                  
                    self.addFailure("Total amount of RAM assigned to VMs [%d GB] exceeds the %d GB RAM available on KVM host %s. Please verify the amount of RAM assigned to each VM." % (sumRAM,actualmaxRAM,server["accessIP"]))
                    
                self.logMsg("KVM host %s has %d GB RAM, %d GB RAM assigned [%d GB RAM to VMs]" % (server["accessIP"],actualmaxRAM,maxRAM,sumRAM))

            except Exception as e:
                self.addFailure("Unable to verify RAM limits on %s." % server["accessIP"])
                self.logMsg("Return from /usr/bin/free on %s: %s" % (server["accessIP"],actualmaxRAMstr))
                self.logMsg("Exception: %s" % str(e))

        return 0
