# -*- coding: UTF-8 -*-

from common import resourceParse
from common.baseFactory import log
from common import cliUtils
import traceback

NEED_CHECK_TYPE = ["2800 V3","5300 V3","5500 V3","5600 V3","5800 V3","6800 V3","6900 V3"]

def execute(dataDict):
    """
            步骤1 以admin用户登录设备；
            步骤2 执行show system general命令，查询设备型号；
            步骤3 执行show upgrade package命令，查询当前系统版本和补丁号；
            步骤4 执行show enclosure命令，查询是否配套V1高密框；
            步骤5 执行show version all命令，查询V1高密框版本号；
            备注：查询配套表版本"Version4=hds_ses.bin"字段后的版本号方法
            步骤1：进入developer模式；
            步骤2：进入minisystem；
            步骤3：cat /startup_disk/image/boot/versions.conf，搜索"Version4=hds_ses.bin"
            例如：
            Version4=hds_ses.bin,29.60T69
            Version4=hds_ses.bin,29.01.60T69
            获取到版本号信息例:"29.60T69"和"29.01.60T69"。
        """
    ##执行补丁后检查
    return preCheck(dataDict)

def preCheck(dataDict):
    sshCon = dataDict["ssh"]
    upgradeErrMsg = ''
    itemState = True
    lang = dataDict['lang']
    resource = resourceParse.execute(lang)
    checkMsgTitle = resource.get("HdsVersionCheck.title") + '\n'
    expModuleInfoDict = {}
    errorKey = "HdsVersionCheck.pass"
    # 记录错误的硬盘框ID
    errExpModuleList = []
    #版本检查
    try:
        errorFlag,checkFlag =  isDevNeedCheck(dataDict)
        if not errorFlag:
            itemState = False
            errorKey = "HdsVersionCheck.error"
            upgradeErrMsg = resource.get(errorKey)
            upgradeErrMsg = checkMsgTitle + upgradeErrMsg
            return (itemState, upgradeErrMsg, None)

        if not checkFlag:
            log.info(dataDict,"The Device not need Hds Check.")
            return (itemState, "", None)

        #获取高密框 show enclosure
        flag,enclosureList = getHighDensityEnclosure(sshCon,dataDict)
        if not flag:
            itemState = False
            errorKey = "HdsVersionCheck.error"
            upgradeErrMsg = resource.get(errorKey)
            upgradeErrMsg = checkMsgTitle + upgradeErrMsg
            return (itemState, upgradeErrMsg, None)

        #不存在V1高密框，检查通过
        if not enclosureList:
            return (itemState, "", None)

        #获取sesversion show version all
        flag = getEnclosureVersion(sshCon, expModuleInfoDict, enclosureList, dataDict)
        if not flag:
            itemState = False
            errorKey = "HdsVersionCheck.error"
            upgradeErrMsg = resource.get(errorKey)
            upgradeErrMsg = checkMsgTitle + upgradeErrMsg
            return (itemState, upgradeErrMsg, None)

        # 获取全部固件版本 cat /startup_disk/image/boot/versions.conf，搜索"Version4=hds_ses.bin"
        flag, fWVersionList = getFWVersion(sshCon,lang,dataDict)
        if not flag:
            itemState = False
            errorKey = "HdsVersionCheck.error"
            upgradeErrMsg = resource.get(errorKey)
            upgradeErrMsg = checkMsgTitle + upgradeErrMsg
            return (itemState, upgradeErrMsg, None)

        # V1高密框级联模块版本检查
        for expModuleId, sesVersion in expModuleInfoDict.items():
            if not sesVersion:
                itemState = False
                upgradeErrMsg += resource.get("HdsVersionCheck.version.error") % (expModuleId) + "\n"
            elif sesVersion not in fWVersionList:
                itemState = False
                upgradeErrMsg += resource.get("HdsVersionCheck.notpass") % (expModuleId, sesVersion, ",".join(fWVersionList)) + "\n"

        #返回检查结果
        if not itemState:
            upgradeErrMsg = checkMsgTitle + upgradeErrMsg
        else:
            upgradeErrMsg = checkMsgTitle + resource.get("HdsVersionCheck.pass")
        return (itemState, upgradeErrMsg, None)
    except:
        log.error(dataDict, "exception=[%s]" % str(traceback.format_exc()))
        errorKey = "HdsVersionCheck.error"
        upgradeErrMsg = resource.get(errorKey)
        upgradeErrMsg = checkMsgTitle + upgradeErrMsg
        return (False, upgradeErrMsg, None)

def getEnclosureVersion(cli, expModuleInfoDict, enclosureList, dataDict):
    """
    获取V1高密框级联模块的版本号
    :param cli:
    :return:
    """
    cmd = "show version all"
    flag, cliRet, errMsg = cliUtils.excuteCmdInCliMode(cli, cmd, True)

    if flag != True:
        log.error(dataDict,"Failed to get all version.")
        return False

    enclosureVersionInfoList = cliUtils.getHorizontalCliRet(
        cliRet[cliRet.find("Expansion Module:"):cliRet.find("BBU")])
    for enclosureVersionInfo in enclosureVersionInfoList:
        sesVer = enclosureVersionInfo.get("SES Version", "")
        expModuleId = enclosureVersionInfo.get("ID", "")
        #记录V1高密框的级联模块的版本信息
        for enclosureId in enclosureList:
            if expModuleId.startswith(enclosureId):
                expModuleInfoDict[expModuleId] = sesVer
    log.info(dataDict, "expModuleInfoDict is:%s" % expModuleInfoDict)
    return True

def getHighDensityEnclosure(sshCon,dataDict):
    """
    获取高密框信息
    :param cli:
    :return:enclosureList
    """
    enclosureList = []
    cmd = "show enclosure"
    flag, cliRet, errMsg = cliUtils.excuteCmdInCliMode(sshCon, cmd, True)

    if flag != True:
        log.error(dataDict,"Failed to get all version.")
        return (False, enclosureList)

    enclosureInfoList = cliUtils.getHorizontalCliRet(cliRet)
    for enclosureInfo in enclosureInfoList:
        type = enclosureInfo.get("Type", "")
        id = enclosureInfo.get("ID", "")
        if type == "4U 75 Slot 3.5 SAS Disks Enclosure":
            enclosureList.append(id)

    return True,enclosureList


def isDevNeedCheck(dataDict):

    dev = dataDict.get('dev')
    devType = str(dev.getDeviceType())
    productVersion = dev.getProductVersion()[:11]
    log.info(dataDict, "Device type is:" + devType)
    log.info(dataDict, "Product version is:" + productVersion)
    # 查询设备当前已安装热补丁版本号
    checkFlag, curHotPatchVer = getHotPatchCurVersion(dataDict)
    curHotPatchVer = curHotPatchVer[-3:]
    # 获取补丁失败
    if not checkFlag:
        log.error(dataDict, "Get Device PathVersion error.")
        return (False, True)

    if productVersion == "V300R001C20" and devType in NEED_CHECK_TYPE and curHotPatchVer >= "211":
        return (True,True)
    if productVersion == "V300R002C10" and devType in NEED_CHECK_TYPE and curHotPatchVer >= "211":
        return (True,True)
    if productVersion == "V300R003C00" and devType in NEED_CHECK_TYPE and curHotPatchVer >= "110":
        return (True,True)
    if productVersion == "V300R003C10" and devType in NEED_CHECK_TYPE and curHotPatchVer >= "117":
        return (True,True)
    if productVersion == "V300R003C20" and devType in NEED_CHECK_TYPE and curHotPatchVer >= "207":
        return (True,True)
    if productVersion == "V300R006C00" and devType in NEED_CHECK_TYPE and curHotPatchVer >= "105":
        return (True,True)

    return (True,False)


def getFWVersion(cli,lang,dataDict):
    """
     获取固件版本
    :param cli:
    :return:
    """
    cmd = "cat /startup_disk/image/boot/versions.conf"
    versionList = []
    flag, cliRet, errMsg = cliUtils.excuteCmdInMinisystemModel(cli, cmd, lang)

    # 回显样例"Version4=hds_ses.bin,29.01.60T64"
    # 回显样例"Version4=hds_ses.bin,29.60T64"
    if flag != True:
        log.error(dataDict,"Failed to get all version.")
        return False, versionList

    cliRetList = cliRet.splitlines()
    for line in cliRetList:
        if "=hds_ses.bin" in line:
            versionList.append(line.split(",")[-1].strip())
    return True, versionList

def getHotPatchCurVersion(dataDict):
    '''
    @summary: 热补丁版本号
    @param context: 上下文对象
    @return: 检查是否成功，补丁版本号，cli回显，errMsg
    '''
    hotPatchVersion = ""
    sshCon = dataDict["ssh"]

    cmd = "show upgrade package"
    checkRet = cliUtils.excuteCmdInCliMode(sshCon, cmd, True)
    if checkRet[0] != True:
        return (checkRet[0], hotPatchVersion)

    cliRet = checkRet[1]
    beginIndex = cliRet.find('HotPatch Version')
    if beginIndex == -1:
        return (False, hotPatchVersion)
    cliRetDictList = cliUtils.getHorizontalCliRet(cliRet[beginIndex:])
    hotPatchVersion = cliRetDictList[0].get('Current Version')
    return (True, hotPatchVersion)