# -*- coding: UTF-8 -*-
from com.huawei.ism.tlv.lang import UnsignedInt32
from com.huawei.ism.tlv.bean import Param
from com.huawei.ism.tlv.docoder import ParamType
from com.huawei.ism.tlv.bean import Record
from com.huawei.ism.tlv import TLVUtils
from com.huawei.ism.exception import IsmException
import java.lang.Exception as JException
from constant import *
import sys
import re
import time
import threading

import constant

PROCESS_STATE_CHECKING = "checking"
PROCESS_UPGRADE_FINISHED = "finished"
TLV_RECORD_END_INDEX = 4095
RETRY_TIMES = 3 #建立连接时重试次数
ERR_CODE_SLAVE_NODE_HANDLE_MSG_IGNORE = "67108849"

'''
日志记录类：提供各种级别的日志记录入口，并打印日志记录函数信息，方便问题定位
'''
class log():
    
    """
            功能：日志记录函数的子函数，用于获取调用函数和调用行号
            参数： MAX_CALLER_LEVEL：最大调用关系层数
            返回值：调用函数信息
    """
    @staticmethod
    def getCallerInfo(MAX_CALLER_LEVEL=5, skipLastLevel=True):
        #从堆栈中获取调用函数和行号
        
        #初始化参数
        funcBack = sys._getframe().f_back
        if True == skipLastLevel: #忽略最近的调用关系
            funcBack = funcBack.f_back
            MAX_CALLER_LEVEL -= 1
        
        #生成函数调用关系
        callerInfo = ""    
        for i in range(0, MAX_CALLER_LEVEL):
        
            #获取该级调用函数和行号
            if hasattr(funcBack, "f_code") and hasattr(funcBack, "f_lineno"):
                funcName = funcBack.f_code.co_name
                lineNumber = funcBack.f_lineno
                callerInfo = " [" + str(funcName) + ":" +  str(lineNumber) + "]" + callerInfo
            else:
                break
            
            #刷新Back函数
            if hasattr(funcBack, "f_back"):
                funcBack = funcBack.f_back
            else:
                break
        
        '''原始实现方法
        funcName = sys._getframe().f_back.f_back.f_code.co_name
        lineNumber = sys._getframe().f_back.f_back.f_lineno
        callerInfo = " [" + str(funcName) + ":" +  str(lineNumber) + "]"
        '''
        #返回函数调用关系
        return callerInfo
        
    
    """
            功能：记录调试信息info到工具日志中
            参数：context=工具上下文；info=要记录的信息
            返回值：True=成功；False=失败
    """
    @staticmethod
    def debug(context, info):
        logInfo = info + log.getCallerInfo()
        if "logger" in context:
            context.get("logger").debug('[ToolLog]:' + logInfo)
            return True
        else:
            raise Exception("[failed]: logger is inexisted. info=" + logInfo)
    
    """
            功能：记录错误信息info到工具日志中
            参数：context=工具上下文；info=要记录的信息
            返回值：True=成功；False=失败
    """
    @staticmethod
    def error(context, info):
        logInfo = info + log.getCallerInfo()
        if "logger" in context:
            context.get("logger").error('[ToolLog]:' + logInfo)
            return True
        else:
            raise Exception("[failed]: logger is inexisted. info=" + logInfo)
        
    @staticmethod
    def info(context, info):
        logInfo = info + log.getCallerInfo()
        if "logger" in context:
            context.get("logger").info('[ToolLog]:' + logInfo)
            return True
        else:
            raise Exception("[failed]: logger is inexisted. info=" + logInfo)
        
    @staticmethod
    def warn(context, info):
        logInfo = info + log.getCallerInfo()
        if "logger" in context:
            context.get("logger").warn('[ToolLog]:' + logInfo)
            return True
        else:
            raise Exception("[failed]: logger is inexisted. info=" + logInfo)
        


"""
    执行升级前后检查
"""
def executeCheck(dataDict, command, locationId):
        tlvCon = dataDict["tlv"]
        
        msgParam0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(0))
        msgParam1 = Param(1, ParamType.STRING, "")
        msgParam2 = Param(2, ParamType.UNSIGN_INT, UnsignedInt32(0))
        msgParam3 = Param(3, ParamType.STRING, "")
        msgParam4 = Param(4, ParamType.STRING, "")
        msgParam5 = Param(5, ParamType.STRING, "")
        msgParam6 = Param(6, ParamType.STRING, "")
        msgParam7 = Param(7, ParamType.STRING, "")
        msgParam8 = Param(8, ParamType.STRING, "")
        msgParam9 = Param(9, ParamType.STRING, "")
        msgParam12 = Param(12, ParamType.STRING, command)
        msgParam13 = Param(13, ParamType.UNSIGN_INT, UnsignedInt32(locationId))
        params = TLVUtils.paramList(msgParam0, msgParam1, msgParam2, msgParam3, msgParam4, msgParam5, msgParam6, msgParam7, msgParam8, msgParam9,msgParam12,msgParam13)
        recs = tlvCon.getBatch(TLV_CMD.EXC_UPD, params, CMD_DEFAULT_TIMEOUT)
        log.info(dataDict, 'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.EXC_UPD, str(params), str(recs)))
        return recs

def execCmd(tlv, cmd, paramList, isBatch=False, getBatch=False, timeOut=CMD_DEFAULT_TIMEOUT):
    '''
    @summary: 执行tlv命令
    @param tlv: tlv对象
    @param cmd: 命令字
    @param params: 参数列表
    @param isBatch: 是否为批量处理（参考GET_BATCH_NEXT的实现的批量处理，批处理最后一条记录有结束符标记）
    @param getBatch: 是否为获取批量内容（参考非GET_BATCH_NEXT的实现的批量处理，批处理最后一条记录没有结束符标记）
    @param timeOut: 超时时间
    '''
    try:
        records = None
        
        if isBatch:
            records = tlv.bacthNext(cmd, paramList, timeOut, RETRY_TIMES)
            if records is not None and len(records) > 1:
                lastRecord = records[-1]
                lastRecordParamList = lastRecord.getParams()
                if lastRecordParamList[0].getIndex() == TLV_RECORD_END_INDEX:
                    records.pop()
            return records
        
        if getBatch:
            return tlv.getBatch(cmd, paramList, timeOut, RETRY_TIMES)
        
        return tlv.invoke(cmd, paramList, timeOut, RETRY_TIMES)

    except IsmException, ismException:
        errCode = ismException.getErrorId()
        #往从节点下发消息失败，可以忽略。
        if ERR_CODE_SLAVE_NODE_HANDLE_MSG_IGNORE in str(errCode):
            return None
        raise


class CliParser():
    def __init__(self, cliText,logger, cliType='list', cliTextType='string'):
        if cliTextType == 'list':#CLI echo text can be a string containing multi-line or a list contains multi-line
            self.cliEcho = '\n'.join(cliText)
        else:    
            self.cliEcho = cliText
            
        self.logger = logger
        self.cliType = cliType
    
    def genDict(self):
        '''
        Function describe:    Format CLI echo text to a dictionary.
        Return value:         dictionary
        Revision History:     1. Created 2014-01-10 
        Remark:               
        '''
        cliEcho = self.cliEcho
        logger = self.logger
        
        if not cliEcho:
            logger.error('Input CLI echo message empty!')
            return {} 
        
        dictList = []
        lines = cliEcho.splitlines()
        lineNum = len(lines)
        cliDict = {}
        
        promptExp = ('admin:' + '|' + 'developer:' + '|' + 'diagnose>' + '|' + 'Storage:~ #')
        
        for i in range(0, lineNum):
            if re.search(promptExp, lines[i], re.IGNORECASE):
                dictList.append(cliDict)
                break
            if lines[i].count('-') > 0 and lines[i].count('-') == len(lines[i]):
                    logger.error('All match:' + str(lines[i]))
                    dictList.append(cliDict)
                    cliDict = {}
            if re.search(':', lines[i]):
                key = lines[i].split(':')[0].strip()
                val = lines[i].split(':')[1].strip()
                cliDict[key] = val
        if cliDict:
            dictList.append(cliDict)
        return dictList        
          
    def genDictList(self):
        '''
        Function describe:    Format CLI echo text to a list containing dictionaries.
        Return value:         dictionary
        Revision History:     1. Created 2014-01-10 
        Remark:               
        '''        
        cliEcho = self.cliEcho
        logger = self.logger
        
        if not cliEcho:
            logger.error('Input CLI echo message empty!')
            return {}
        
        lines = cliEcho.splitlines()
        lineNum = len(lines)
        
        for i in range(lineNum):
            if lines[i].count('-') > 0 and lines[i].count('-') + lines[i].count(' ') == len(lines[i]):
                logger.info('All match:' + str(lines[i]))
                break
            else:
                i += 1
        else:
            logger.error('Delimiters of fields not found, input CLI echo may be wrong!')
            return {}
        
        dictList = []

        ########################
        strVals = lines[i] 
        valsIndex = [strVals.find('-')]
        while valsIndex[-1] != -1:
            #依次取出“ -”所在的位置并添加到valsIndex，直到取到-1为止
            valsIndex.append(strVals.find(" -", valsIndex[-1] + 1))    
        #将最后一位设为字符串长度，最后一次取值直接取到末尾
        valsIndex[-1] = len(strVals)
        spanList = [(valsIndex[index], valsIndex[index + 1]) for index in range(len(valsIndex) - 1)]
        logger.info('spanList:' + str(spanList))
        ######################
        
        
        keyNum = len(spanList)
        keyLine = lines[i - 1]
        keyList = [keyLine[start:end].strip() for (start, end) in spanList]
        
        for j in range(i + 1, lineNum):
            valueList = []
            if len(lines[j].split()) < keyNum:
                j += 1
            else:
                valueList = [lines[j][start:end].strip() for (start, end) in spanList]
                dictItem = dict(zip(keyList, valueList))
                dictList.append(dictItem)
                j += 1
            
        return dictList     
    

    def formatList(self, descStr=None):
        '''
        Function describe:    将list样式字符串转换成list对象
        Return value:         由多个dict对象组成的list
        Revision History:     1. Created 2014-02-26 
        Remark:               可选输入参数descStr，若不传此参数则默认解析成员变量cliEcho
        '''
        
        
        if not descStr:
            descStr = self.cliEcho 
        # 由---和空格构成行的行号，大于等于1
        REF_LINE_NO = None                              
        # 最后需要返回的结果
        result = []
        # 存放各列数据的开始位置/结束位置
        valsIndex = []
        # 将字符串拆成单行并存放在list对象中
        lsts = descStr.splitlines()                    
        #正则表达式，以空格隔开的由多个-构成的字符串（首尾空格不限）
        pattern = re.compile("^\s*-+(\s+-+)*\s*$")    
    
        # 尝试找到符合正则表达式的行
        for i in range(len(lsts)):
            if  pattern.match(lsts[i]):
                # 确定行号
                REF_LINE_NO = i
                # 确定列取值的开始位置
                valsIndex.append(lsts[i].find("-"))
                break
            
        # 如果没有找到符合正则表达式的行号，意味着格式不符合，不再继续解析，直接返回空结果    
        if not REF_LINE_NO:
            return result
    
        # 取出---和空格构成的行
        strVals = lsts[REF_LINE_NO] 
    
        while valsIndex[-1] != -1:
            #依次取出“ -”所在的位置并添加到valsIndex，直到取到-1为止
            valsIndex.append(strVals.find(" -", valsIndex[-1] + 1))    
        #将最后一位设为字符串长度，最后一次取值直接取到末尾
        valsIndex[-1] = len(strVals)
        
        # 在各dict中作为键值的list
        keys = []   
        # 计算key值，以valsIndex中的两个相临值作为开始位置和结束位置，并去除空格
        for i in range(1, len(valsIndex), 1):
            key = lsts[REF_LINE_NO - 1][valsIndex[i - 1]:valsIndex[i]].strip()
            #判断是否有重复存在的列名，若存在则追加一个下标
            if keys.count(key) > 0:
                temp = 1
                while keys.count(key + "_" + str(temp)) != 0:
                    temp += 1
                key = key + "_" + str(temp)
      
            keys.append(key)
    
        # 取出---下面的单行进行解析
        for i in range(REF_LINE_NO + 1, len(lsts), 1):
            
            # 排除最后一行，若遇到最后一行则退出循环
            if self.isEndLine(lsts[i]):            
                break
            #遇到空行时忽略
            if re.compile("^\s*$").match(lsts[i]):
                continue
            
            # 单行dict中作为value值的list        
            vals = []    
            # 计算单行的value值，以valsIndex中的两个相临值作为开始位置和结束位置，并去除空格
            for j in range(1, len(valsIndex), 1):
                vals.append(lsts[i][valsIndex[j - 1]:valsIndex[j]].strip())
    
            # 单行value计算完成后，与key值合并成dict添加到result结果集中
            result.append(dict(zip(keys, vals)))  
        
        # 所有行解析完成后返回result结果集
        return result
    
    # **************************************
    def formatDict(self, descStr=None, simpleMode=False):
        '''
        Function describe:    将dict样式字符串转换成由dict构成的List对象
        Return value:         由多个dict对象组成的list
        Revision History:     1. Created 2014-02-26 
        Remark:               1.可选输入参数descStr，若不传此参数则默认解析成员变量cliEcho
                              2.可选输入参数simpleMode，以若不传此参数则默认False,是否为简单模式，
                                                                                    若为True则所有Value值解析成字符串,若为False则会对Value作进一步的解析
        '''
        
        
        if not descStr:
            descStr = self.cliEcho 
        # 最后需要返回的结果
        result = []
        # 将字符串拆成单行并存放在list对象中
        lsts = descStr.splitlines()
        # 用于分隔两个字典的单行，整行都由---构成
        pattern = re.compile("^\s*[-]*-\s*$")
        # 用于匹配”--------  xxx Key : ---------“这类字符串以作为Key值
        pattern_key_str = "^\s*-+\s*([a-zA-z0-9]+\s*)+:\s*-+\s*$"
        pattern_key = re.compile(pattern_key_str)
        # dict中的键集合
        keys = []
        # dict中的值集合
        vals = []                               
    
        #当前所读取的行号
        i = 0 
        while i < len(lsts):
            
            str_line = lsts[i] #缓存此行
            
            #遇到最后一行则退出while循环
            if self.isEndLine(str_line):
                break
            
            i += 1 #行号+1，准备读取下一行数据
    
            # 如果遇到整行都是---，将键值对添加到result中并重新初始化key和val
            if pattern.match(str_line): 
                result.append(dict(zip(keys, vals)))
                keys = []
                vals = []
                continue
            
            # 找到冒号所在的位置   
            index = str_line.find(":")        
            # 当冒号存在时，将冒号前的字符串添加到key中，冒号后的字符串添加到val中，均需要去除前后的字符串
            if index != -1:
                
                #该行中格式类似”------  key:  ------“
                from com.huawei.ism.tool.obase.utils import StringUtils
                if StringUtils.checkRegexReDos(str_line, pattern_key_str) \
                        and pattern_key.match(str_line) and not simpleMode:
                    key = str_line[:index].strip('-').strip()
                    val = ""
                    #追加键
                    keys.append(key)
                    #此while语句用于拼接字符串
                    while i < len(lsts):
                        str_line = lsts[i]
    
                        if str_line.endswith(":") or pattern_key.match(str_line) or str_line.find(":/>") != -1:
                            break
                        else:
                            val = val + "\r\n" + str_line               
                            i += 1 #行号+1，准备读取下一行数据
                    val = self.formatStr(val) #退出while循环时需要对key值进行格式化,递归调用
                    vals.append(val)             
                    continue
                #else中处理Key ： value的结构,value可以为空
                else:
                    key = str_line[:index].strip()
                    #因为有时候键后面为一堆空格，这里为特殊处理，空格不当成空处理，但保存时仍然存空（即else中的处理）
                    val = str_line[index + 1:]
                    #追加键
                    keys.append(key)
                    #若同行取到的value值为空，则认为从下一行开始才是该key的value值，在这种情况下value又将是一个Dict或List对象
                    if val == "":
                        #此while语句用于拼接字符串，直到再次遇到以冒号结尾或者包含":/>"情况
                        while i < len(lsts):
                            str_line = lsts[i]
                            if str_line.endswith(":") or self.isEndLine(str_line):
                                break
                            else:
                                val = val + "\r\n" + str_line               
                                i += 1 #行号+1，准备读取下一行数据
                        if not simpleMode:
                            val = self.formatStr(val) #退出while循环时需要对key值进行格式化,递归调用
                    else:
                        val = val.strip() 
                    vals.append(val)               
                    continue        
            
            # 若某行是[Board Properties]的集合时暂时未做处理，会忽略掉后面的行
            
        #此行已退出while循环
            
        # 退出while循环时判断result是否为空，若为空则返回字典，否则返回由字典组成的序列    
        result.append(dict(zip(keys, vals)))
        return result
    
    
    def formatStr(self, descStr=None):
        '''
        Function describe:    在不确定字符串样式自动判断样式并转换成dict构成的List对象（也可能直接返回字符串）
        Return value:         由多个dict对象组成的list，或者字符串
        Revision History:     1. Created 2014-02-26 
        Remark:               1.可选输入参数descStr，若不传此参数则默认解析成员变量cliEcho
        '''
        
        if not descStr:
            descStr = self.cliEcho 
        
        pattern = re.compile("^\s*-+(\s+-+)*\s*$") 
        lsts = descStr.strip().splitlines()
        if len(lsts) == 0:
            return ""
        #以show开头的认为是命令行，直接排除
        if lsts[0].startswith("show "):
            lsts.pop(0)
            
        for i in range(len(lsts)):
            if "" != lsts[i].strip():
                          
                #若字符串中带有冒号，则认为是
                if lsts[i].find(":") != -1:
                    return self.formatDict(descStr)
                
                #当不带冒号且次行符合由多个---与空格组成的格式
                elif i + 1 < len(lsts) - 1:
                    if pattern.match(lsts[i + 1].strip()):                
                        return self.formatList(descStr)
                    
                #若无法确定格式则直接返回该字符串（去除命令行,最后的结束及前后的空白）
                else:
                    if self.isEndLine(lsts[-1]):
                        lsts.pop()
                        
                return "\r\n".join(lsts).strip()
    
    def splitByblanckLine(self, descStr=None):
        '''
        Function describe:    按空行分隔字符串
        Return value:         字符串组成的序列
        Revision History:     1. Created 2014-02-26 
        Remark:               1.可选输入参数descStr，若不传此参数则默认解析成员变量cliEcho
        '''
        if not descStr:
            descStr = self.cliEcho 
        pattern = re.compile("\r\n\s*\r\n")
        
        list = descStr.splitlines()
        #去除前端空行
        while len(list) > 0:
            if re.compile("^\s*$",).match(list[0]):
                list.pop(0)
            elif re.compile("^\s*$",).match(list[-1]):
                list.pop()
            else:
                break
            
        descStr = "\r\n".join(list)
        result = re.split(pattern, descStr)
    
        return result
    
    def isEndLine(self, descStr):
        '''
        Function describe:    判断是否为结束行
        Return value:         True/False
        Revision History:     1. Created 2014-02-26 
        Remark:               
        '''
        patternEndflag = re.compile(r".*:/.*>.*")
        return patternEndflag.match(descStr)
    
def getCurSystemVersion(dataDict):
    '''
    Function describe:    Get the system version of controller by TLV.
    Return value:         tuple(boolean, string)
                                  boolean-true if command executed success, false if command executed failed.
                                  string-device product model, e.g., S5500T.
    Revision History:     1. Created 2014-01-07 
    '''
    tlvCon = dataDict["tlv"]
    msgParam0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(TLV_PACKAGE_TYPE.SYS_UPGRADE_PKG))
    params = TLVUtils.paramList(msgParam0)
    retRecs = tlvCon.getBatchWithRetry(
        constant.TLV_CMD.OM_MSG_OP_LST_VER, params,
        constant.AFTER_UPGRADE_TIMEOUT, constant.AFTER_UPGRADE_RETRYTIMES,
        constant.AFTER_UPGRADE_INTERVAL)
    log.info(dataDict,
             'TLV cmd [%d] send[%s] receive[%s]'
             % (constant.TLV_CMD.OM_MSG_OP_LST_VER,
                str(params), str(retRecs)))
    retRec = retRecs[0]
    curSystemVersion = retRec.getParamStrValue(7)
    if not curSystemVersion:
        log.error(dataDict,'Get curSystemVersion failed')
        return (False,'--')
    return (True,curSystemVersion)

def getCurProductModel(dataDict):
    '''
    Function describe:    Get the product model of controller by TLV.
    Return value:         tuple(boolean, string)
                                  boolean-true if command executed success, false if command executed failed.
                                  string-device product model, e.g., S5500T.
    Revision History:     1. Created 2014-01-07 
    '''
    tlvCon = dataDict["tlv"]
    msgParam0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(TLV_OM_OBJ_E.SYSTEM))
    params = TLVUtils.paramList(msgParam0)
    retRec = tlvCon.invoke(TLV_CMD.GET, params, CMD_DEFAULT_TIMEOUT)
    log.info(dataDict, 'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.GET, str(params), str(retRec)))
    curProductModelEnum = retRec.getParamIntValue(64).intValue()
    curProductModel = ProductModel.modelMap.get(curProductModelEnum)
    if not curProductModel:
        log.error(dataDict, 'Get cur product model failed!')
        return (False, '--')
    return (True, curProductModel)
 
def getHotPatchCurVersion(dataDict):
    """
    功能说明：查询当前阵列已安装的热补丁版本号
    输入：工具框架上下文
    返回：bool查询成功结果False/True，str热补丁版本号
    """
    tlvCon = dataDict["tlv"]
    msgParam0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(TLV_PACKAGE_TYPE.HOT_PATCH_PKG))
    params = TLVUtils.paramList(msgParam0)
    retRecs = tlvCon.getBatchWithRetry(
        constant.TLV_CMD.OM_MSG_OP_LST_VER, params,
        constant.AFTER_UPGRADE_TIMEOUT, constant.AFTER_UPGRADE_RETRYTIMES,
        constant.AFTER_UPGRADE_INTERVAL)
    log.info(dataDict,
             'TLV cmd [%d] send[%s] receive[%s]'
             % (constant.TLV_CMD.OM_MSG_OP_LST_VER,
                str(params), str(retRecs)))
    retRec = retRecs[0]
    curHotPatchVersion = retRec.getParamStrValue(4)
    if not curHotPatchVersion:
        log.error(dataDict, 'Get curHotPatchVersion failed')
        return (True, '--')
    return (True, curHotPatchVersion)   

def isExecuteLunAlignCheck(dataDict):
    """
    功能说明：判断是否需要执行非4k对齐LUN检查
  输入：工具框架上下文
  返回：bool结果
  False 不执行
  True  执行
    """
    CurSystemVersion = getCurSystemVersion(dataDict)[1]
    
    log.info(dataDict, "CurSystemVersion:%s"%CurSystemVersion)
    
    if CurSystemVersion != "V300R003C00SPC100":
        return False
    return True


def getFanCtrlModuleRecords(dataDict):
    '''
    @summary: 获取当前集群辅助散热模块列表
    @param dataDict: 上下文对象
    '''
    tlvCon = dataDict["tlv"]
    msgParam0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(TLV_OM_OBJ_E.FAN_CTRL_MODULE))
    paramList = TLVUtils.paramList(msgParam0)
    retRec = execCmd(tlvCon, TLV_CMD.GET_BATCH_NEXT, paramList, isBatch=True)
    log.info(dataDict,'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.GET_BATCH_NEXT, str(paramList), str(retRec)))
    return retRec


def getUpgErrMsg(resource, nodeId, errorKey, params=None):
    ##获取界面显示信息
    if params:
        return u"%s--%s\n" % (nodeId, resource.get(errorKey) % params)
    return u"%s--%s\n" %(nodeId,resource.get(errorKey))


def getElabelDict(elabelStr):
    '''
            功能：获取指电子标签字典，无电子标签返回空字典
    Params: elabelStr：电子标签字符串
    Return: elabelDict：电子标签字典
    '''
    ITEM_SPLIT_FLAG = "="
    elabelDict = {}
    if "" == elabelStr or 0 == len(elabelStr):
        return elabelDict

    elabelList = elabelStr.encode("utf8").splitlines()
    for field in elabelList:
        if None == field or 0 == len(field):
            continue

        fields = field.split(ITEM_SPLIT_FLAG)
        if len(fields) > 1:
            key = fields[0].strip()
            elabelDict[key] = fields[-1].strip()

    return elabelDict

def setProgress(context, progress, remainTime, item):
    try:
        log.info(context, "setProgress is start")
        observer = context.get("progressObserver")
        if observer != None:
            log.info(context, "progress" + str(progress))
            observer.updateItemProgress(context.get("dev"), int(progress), str(remainTime), item)
            log.info(context, "setProgress is over")
    except (JException, Exception), exption:
        log.error(context, "setProgress is error")
        pass


def updateProcess(context, item, totalTime):
    # 剩余时间总数
    context["checkState"] = PROCESS_STATE_CHECKING
    log.info(context, "threading is starting")
    oneProgress = 95
    totalReaminTime = totalTime

    UPGRADE_PROCESS_INTEVAL_TIME = 1
    currentPro = 0

    setProgress(context, currentPro, totalTime, item)

    while context["checkState"] == PROCESS_STATE_CHECKING:
        # 更新进度条
        if totalReaminTime > 1:
            totalReaminTime -= UPGRADE_PROCESS_INTEVAL_TIME
            currentPro = int(oneProgress * (totalTime - totalReaminTime) / totalTime)
            safeSleep(UPGRADE_PROCESS_INTEVAL_TIME)
        else:
            safeSleep(UPGRADE_PROCESS_INTEVAL_TIME)
            continue

        setProgress(context, currentPro, totalReaminTime, item)
        safeSleep(UPGRADE_PROCESS_INTEVAL_TIME)
    log.info(context, "threading is over")
    return


def safeSleep(seconds):
    '''
    @summary: 安全睡眠时间
    @param param: seconds为睡眠时间，单位：秒；数据类型：整数或小数
    '''
    try:
        if type(seconds) not in [int, long, float] or seconds <= 0:
            return

        startTime = time.clock()
        while True:
            if (time.clock() - startTime) >= seconds:
                return

            # 睡眠一下，避免长时间占用cpu，该时间设置过长会影响睡眠时间精度
            try:
                time.sleep(0.1)
            except:
                pass
    except:
        return


def threadUp(context, item, totalTime):
    try:
        log.info(context, "threadUp is start")
        t = threading.Thread(target=updateProcess, args=(context, item, totalTime))
        t.start()
        context["thread"] = t
    except:
        log.error(context, "the thread is error")
        pass


def threadJoin(context):
    try:
        if context.get("thread") != None:
            context["thread"].join()
    except:
        log.error(context, "the threadJoin is error")
        pass


def finishProcess(context, item):
    context["checkState"] = PROCESS_UPGRADE_FINISHED
    threadJoin(context)
    setProgress(context, 99, 1, item)
    return