# -*- coding: UTF-8 -*-
from com.huawei.ism.tlv.docoder import ParamType
from com.huawei.ism.tlv.bean import Param
from com.huawei.ism.tlv.lang import UnsignedInt32
from com.huawei.ism.tlv import TLVUtils
from com.huawei.ism.tool.protocol.tlv.exception import TLVException
from common import resourceParse
from common.constant import *
from common.baseFactory import log, threadUp, finishProcess
from service.func_utils import upload_timeout_callback
from cbb.frame.base.funcUtils import time_out_decorator
from cbb.business.operate.checkitems import check_non_array_ip
import traceback
import time
import os

totalRemainTime = 34

def execute(dataDict):
    """
    功能说明：校验阵列状态是否支持升级，将补丁包上传到整列端，并获取阵列端处理结果（入口函数）
    """
    uploadErrMsg = ''
    hotPatchTgzPkgName = dataDict['packagePath']
    lang = dataDict['lang']
    tlvCon = dataDict['tlv']
    """解析resource文件并保存"""
    resource = resourceParse.execute(lang)
    dataDict["resource"] = resource

    # 判断工具连接的IP是否是阵列IP
    flag, err_msg = check_non_array_ip.execute(dataDict)
    log.info(dataDict, "flag={},err_msg={}".format(flag, err_msg))
    if not flag:
        return (False, err_msg)

    if checkUploadState(dataDict) == OM_MSG_OP_UPD_LST_SYS_PROGRESS.UPD_DLDING:
        return(False, resource.get("upgrade.notsupport"))
    try:
        threadUp(dataDict, "importpackage", totalRemainTime)
        """上传补丁包"""
        errMsg = ''
        processRet = upload(dataDict,hotPatchTgzPkgName)
        if not processRet[0]:
            uploadErrMsg = processRet[1]
            return (False, uploadErrMsg)
        try:
            time.sleep(5)
        except KeyboardInterrupt:
            log.error(dataDict,"Interrupted" )
        status = None
        """轮询获取阵列端处理状态"""
        DEVEICE_DLD_QUERY_TIME = 0 #轮询计数器
        while (OM_MSG_OP_UPD_LST_SYS_PROGRESS.UPD_DLD_SUCCESS != status):
            DEVEICE_DLD_QUERY_TIME = DEVEICE_DLD_QUERY_TIME + 1
            if DEVEICE_DLD_QUERY_TIME > UPLOAD_PACKAGE_POLL_TIMES:
                return (False, resource.get("upload.failed"))
            #查询处理状态
            rec = tlvCon.invoke(TLV_CMD.OM_MSG_OP_UPD_LST_SYS_PROGRESS, TLVUtils.paramList(), CMD_DEFAULT_TIMEOUT)
            log.info(dataDict,'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.OM_MSG_OP_UPD_LST_SYS_PROGRESS,str(TLVUtils.paramList()),str(rec)))
            status = rec.getParamIntValue(3).intValue()
            if status == OM_MSG_OP_UPD_LST_SYS_PROGRESS.UPD_DLD_FAIL:
                #查询处理详细信息
                recs = tlvCon.getBatch(TLV_CMD.OM_MSG_OP_UPD_LIST_DETAILINFO, TLVUtils.paramList(), CMD_DEFAULT_TIMEOUT)
                log.info(dataDict,'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.OM_MSG_OP_UPD_LIST_DETAILINFO,str(TLVUtils.paramList()),str(recs)))
                #解析处理详细信息，生成返回信息
                itemNum = recs.size()
                for index in range(0,itemNum):
                    rec = recs.get(index)
                    nameKey = rec.getParamStrValue(0)
                    errorKey = rec.getParamStrValue(2)
                    nodeId = rec.getParamStrValue(3)
                    errMsg += "%s--%s--%s\n" % (nodeId, resource.get(nameKey), resource.get(errorKey))
                return (False, errMsg)
            try:
                time.sleep(UPLOAD_PACKAGE_POLL_INTERVAL)
            except KeyboardInterrupt:
                log.error(dataDict,"Interrupted" )
    except TLVException as e:
        log.error(dataDict,"notify upgrade package upload over error!"+str(traceback.format_exc()) + str(e))
        return(False, e.getErrorMessage())
    finally:
        finishProcess(dataDict, "importpackage")
    return (True, "")


@time_out_decorator(time_out=1800,
                    timeout_callback_func=upload_timeout_callback)
def upload(dataDict,hotPatchTgzPkgName):
    """
    功能说明：查询阵列段补丁包路径，sftp上传补丁包到阵列端，通知阵列端分发补丁包
    输入：工具框架上下文，补丁包路径
    输出：bool执行结果，str错误信息
    """
    dev = dataDict["dev"]
    sftp = dataDict['sftp']
    tlvCon = dataDict["tlv"]
    resource = dataDict["resource"]
    context = dataDict['context']
    deviceSN = str(dataDict.get('dev').getDeviceSerialNumber())
    patchType = context["patchType_%s"%deviceSN]

    if False == os.path.isfile(hotPatchTgzPkgName):
        log.error(dataDict,'patchPath is follow')
        log.error(dataDict, hotPatchTgzPkgName)
        errMsg = resource.get('upload.pkgPathAbnormality')
        return (False,errMsg)
    #校验补丁包大小是否安全
    patchSize = os.stat(hotPatchTgzPkgName).st_size

    if patchType == PATCH_TYPE.HOT_PATCH:
        pkgType = TLV_PACKAGE_TYPE.HOT_PATCH_PKG
    elif patchType == PATCH_TYPE.ASL_PATCH:
        pkgType = TLV_PACKAGE_TYPE.ASL_PATCH_PKG

    param0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(pkgType))
    param2 = Param(2, ParamType.UNSIGN_INT, UnsignedInt32(patchSize))
    params = TLVUtils.paramList(param0,param2)
    log.info(dataDict, 'Execute cmd [%d] [%s]'%(TLV_CMD.OM_MSG_OP_GET_PACKAGE_UPLOADPATH, str(params)))
    #获取补丁包上传路径
    retRec = tlvCon.invoke(TLV_CMD.OM_MSG_OP_GET_PACKAGE_UPLOADPATH, params, CMD_DEFAULT_TIMEOUT)
    uploadPath = retRec.getParamStrValue(1)

    log.info(dataDict,"pkg upload ip = " + str(dev.getIp()))

    #上传升级包
    try:
        sftp.putFile(dev.getIp(), hotPatchTgzPkgName, uploadPath, dev.getLoginUser(), None)
    except:
        return (False, resource.get('upload.sftpup'))

    #通知其他控制器同步升级包
    devPkgPath = dev.getIp() + ":" + uploadPath
    pkgPathParam0 = Param(0, ParamType.STRING, devPkgPath)
    params = TLVUtils.paramList(pkgPathParam0)

    retRec = tlvCon.invoke(TLV_CMD.OM_MSG_OP_NOTIFY_PACKAGE_PATH, params, CMD_DEFAULT_TIMEOUT)
    #处理正常返回
    return (True, "")


def checkUploadState(dataDict):

    """
        功能说明：查询阵列状态
       输入：工具框架上下文
      输出：int阵列端状态
    """
    tlvCon = dataDict.get("tlv")
    rec = tlvCon.invoke(TLV_CMD.OM_MSG_OP_UPD_LST_SYS_PROGRESS, TLVUtils.paramList(), CMD_DEFAULT_TIMEOUT)
    log.info(dataDict,'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.OM_MSG_OP_UPD_LST_SYS_PROGRESS,str(TLVUtils.paramList()),str(rec)))
    status = rec.getParamIntValue(3).intValue()
    log.info(dataDict,"upload statusIndex is :" + str(rec))
    return status
