#!/usr/bin/python

"""
    This module contains the deployment script to flash the BMC in WinPE
"""

import string, os, os.path, shutil, sys, popen2, systemMgr
from logMgr import addLogRecord,CRITICAL,ERROR,WARNING,INFO,DEBUG
from config import DeploymentStore, DeployPath
from deploymentData import ATSTATE,FAILURE,UPDATE,REFRESH,REBOOT,UNSUPPORTED,UPDATEMGMT
import time
try:
    __file__
except:
    __file__ = __name__

def checkState(restore=0):
    """
        checkState() returns ATSTATE if at desired state
        checkState() returns FAILURE if state can't be achieved
        checkState() returns REFRESH if system info refresh is needed once configured
    """
    if not sys.platform == 'win32':
        print 'fwpiaupd is intended for WinPE systems only'
        addLogRecord(0,__file__, INFO,'fwpiaupd is intended for WinPE systems only')
        return FAILURE
    ret, system = systemMgr.queryProperty(0,'IntelBIOSID','BoardFamilyID','',{})
    if not system or ret:
        print 'Intel board family unavailable: ret = %d'%ret
        addLogRecord(0,__file__, ERROR,'Intel board family unavailable: ret = %d'%ret)
        return FAILURE
    if system == 'S3000':
        print 'no BMC on S3000 systems'
        addLogRecord(0,__file__, INFO,'no BMC on S3000 systems')
        return FAILURE
    ret, BMCver = systemMgr.queryProperty(0,'SDR','BMC version','',{})
    if not BMCver or ret:
        addLogRecord(0,__file__, ERROR,'BMC version unavailable: ret = %d'%ret)
        return FAILURE
    ret, chassis = systemMgr.queryProperty(0,'FRU','Chassis OEM Field','',{'info':'Mainboard FRU'})
    if not chassis or ret:
        addLogRecord(0,__file__, ERROR,'chassis unavailable: ret = %d'%ret)
        return FAILURE
    if not chassis or ret:
        print 'chassis unavailable: ret = %d'%ret
        addLogRecord(0,__file__, ERROR,'chassis unavailable: ret = %d'%ret)
        return FAILURE
    from flash import getChassisSpec
    chassis, chassisSpec = getChassisSpec(restore)
    if not chassisSpec:
        return FAILURE
    updateVersion = chassisSpec[1]
    if BMCver == updateVersion:
        print 'BMC at correct version(%s)'%(BMCver)
        addLogRecord(0,__file__, INFO,'BMC at correct version(%s)'%(BMCver))
        return ATSTATE
    return REFRESH

def bmcUpdate(restore=0):
    state = checkState(restore)
    if state < UPDATE:
        return state
    from flash import getChassisSpec,extractUpdate
    chassis, chassisSpec = getChassisSpec(restore)
    if not chassisSpec:
        return FAILURE
    filePath = extractUpdate(restore)
    if not filePath:
        return FAILURE
    BMCfile = os.path.join(filePath,'HB_BMC%s.HEX'%chassisSpec[UPDATEMGMT].split('.')[1])
    
    print "running an example of flashing the BMC using fwpiaupd ..."
    
    from config import getstatusoutput
    flashdir = os.path.join(DeployPath,'win32')
    cwd = os.getcwd()
    os.chdir(flashdir)
    #status, output = getstatusoutput("fwpiaupd -ni -p -u -o -pia %s"%BMCfile)
    status, output = getstatusoutput("fwpiaupd -ni -u -o -pia %s"%BMCfile)
    os.chdir(cwd)
    if status:
        print 'fwpiaupd failed: status = 0x%x, %s'%(status,output)
        addLogRecord(0,__file__, ERROR,'fwpiaupd failed: status = 0x%x, %s'%(status,output))
        return FAILURE
    return REFRESH

if __name__ == '__main__':
    """
    this script assumed these enviroment variables have been set:
    (see deploy.sh or deploy.cmd)
        DeployPath
        DeploymentStore
        PATH
        LD_LIBRARY_PATH (Linux)
        PYTHONPATH
    and this script has been run:
        prepareDeployment
    """
    import time
    if len(sys.argv) == 1:
        restore = 0
    elif len(sys.argv) == 2 and sys.argv[1] == '0':
        restore = 0
    else:
        restore = 1
    state = checkState(restore)
    if state < UPDATE:
        sys.exit(state)
    for i in [1,2,3]:   # try 3 time to get to state
        state = bmcUpdate(restore)
        if state == ATSTATE:
            print 'BMC update succeeded'
            addLogRecord(0,__file__, INFO,'BMC update succeeded')
            break
        if state == FAILURE:
            break
        time.sleep(5)
        os.system('prepareDeployment refresh')
    else:
        print 'BMC update failed after 3 retries'
        addLogRecord(0,__file__, ERROR,'BMC update failed after 3 retries')
        state = FAILURE
    sys.exit(state)

