import subprocess
import os
from baseCheck import baseCheck
import openstackUtil

class osramCpuLimits(baseCheck):

    def getHumanName(self):
            return "Confirm assigned CPU and RAM with regard to tenant quota"

    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

        # only 1 server in openstack
        server=config["environment"]["servers"][0]

        # check the ram & cpu limits vs entered values.
        maxRAM = int(server["maxRAM"]) * 1024
        maxCPU = int(server["maxCPU"])

        # determine quota for tenant.

        # get tenant!
        tenantId=""

        # get our tenant id.
        with open('./.ktl.tmp', 'w') as k:
            retval = subprocess.call(['keystone',
                                      '--os-auth-url', server['accessIP'],
                                      '--os-username', server['accessToken1'],
                                      '--os-password', server['accessToken2'],
                                      'tenant-list'], stdout=k)
        if retval != 0:
            self.addFailure("Failed to determine tenant id for account. Error:" + str(retval))
            return 1

        for line in open('./.ktl.tmp', 'r'):
            if 'True' in line:
                tenantId = line.split()[1]
                break
        if debug:
            print(". Tenant Id:" + tenantId)

        # get quota
        with open('./.nqs.tmp','w') as n:
            retval = subprocess.call(['nova',
                                      '--os-auth-url', server['accessIP'],
                                      '--os-username', server['accessToken1'],
                                      '--os-password', server['accessToken2'],
                                      '--os-tenant-id', tenantId,
                                      'quota-show'], stdout=n)
        if retval != 0:
            self.addFailure("Failed to determine quota for tenant")
            return 1

        quotaCPU = 0;
        quotaRAM = 0;
        for line in open('./.nqs.tmp','r'):
            if 'cores' in line:
                quotaCPU = int(line.split()[3])
            if 'ram' in line:
                quotaRAM = int(line.split()[3])

        if debug:
            print (". maxCPU:"+str(maxCPU)+" maxRAM:"+str(maxRAM))
            print (". quotaCPU:"+str(quotaCPU)+" quotaRAM:"+str(quotaRAM))

        abort = False
        # are we over quota?
        if maxCPU > quotaCPU:
            # too much. :(
            self.addFailure("Requested Max CPU of "+str(maxCPU)+" exceeds tenant quota of "+str(quotaCPU)+" Reduce allocated maxCPU to below quota limit")
            abort = True
        if maxRAM > quotaRAM:
            # too much.
            self.addFailure("Requested Max RAM of "+str(maxRAM)+"M exceeds tenant quota of "+str(quotaRAM)+"M Reduce allocated MaxRAM to below quota limit. (maxRAM is in Gig on the UI)")
            abort = True

        if not abort:
            # now check how the ram was given out to the VM's and how that becomes flavors, and whether THAT puts us over the quota limit.

            # determine how much we would give away to each VM - based on available flavors - and check again if we are
            # over/under the quota.

            openstackUtil.populateFlavors(server,tenantId)

            usedCPU=0
            usedRAM=0
            for vm in server["vms"]:
                # which flavor would this vm get?
                flavor=openstackUtil.getFlavorObject(vm)
                if debug:
                    print(". VM "+vm["name"]+" wants cpu:"+vm["cpu"]+" ram: "+vm["ram"]+" but gets "+str(flavor))
                usedCPU += flavor[0]
                usedRAM += flavor[1]
                if flavor[0] < int(vm["cpu"]):
                    # then we're getting less than we requested.
                    self.addWarning("Based on defined openstack flavors - vm "+vm["name"]+" will have less cpu than requested. (gets "+str(flavor[0]) +" requested "+vm["cpu"] + ")")
                if flavor[1] < int(vm["ram"]):
                    # then we're getting less than we requested.
                    self.addWarning("Baed on defined openstack flavors - vm "+vm["name"]+" will have less ram than requested. (gets "+str(flavor[1]) +" requested "+vm["ram"] + ")")

            if usedCPU > quotaCPU:
                self.addFailure("Based on defined openstack flavors - current configuration requires more cpu ("+str(usedCPU)+") than tenant quota allows ("+str(quotaCPU)+"). Reduce CPU allotments.")

            if usedRAM > quotaRAM:
                self.addFailure("Based on defined openstack flavors - current configuration requires more ram ("+str(usedRAM)+"M) than tenant quota allows ("+str(quotaRAM)+"M). Reduce RAM allotments.")

        return 0
