# -*- 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 common.baseFactory import *
from common import resourceParse
from common.baseFactory import log 
from common import cliUtils


LUN_4K_SIZE_BYTE = 4096

CMD_TIMEOUT = 120

GET_BATCH_NEXT = 55834624000

DISK_ENUM = UnsignedInt32(10)

LUN_ENUM = UnsignedInt32(11)

RETRY_TIMES = 5

diskSectorSizeIndex = 67

lunCapacityIndex = 65

lunSectorSizeIndex = 68

lunUsageTypeIndex = 119

objIDIndex = 1

INTERNAL_ENUM = 0

EXTERNAL_ENUM = 1

SHOW_LUN_NUM = 10

def execute(dataDict):
    ##执行升级前检查
    try:
        return preCheck(dataDict)
    except Exception, e:
        lang = dataDict['lang']
        resource = resourceParse.execute(lang)
        log.error(dataDict, "LunAlignCheck illegalLunList Exception: %s." % unicode(e))
        errorKey = "LunAlignCheck.error"
        return (False, resource.get(errorKey), None)
    
def preCheck(dataDict):
    
    lang = dataDict['lang']
    resource = resourceParse.execute(lang)
    
    #解析每个LUN是否为Internal属性
    non4KLunList = getNon4KLunList(dataDict)
    log.info(dataDict,"LunAlignCheck non4KLunList:%s."%unicode(non4KLunList))
    
    #对检查结果进行处理
    if len(non4KLunList) == 0:
        errorKey = "LunAlignCheck.pass"
        return (True, resource.get(errorKey), None)
    else:
        if isExist4KDisk(dataDict):
            errorKey = "LunAlignCheckExist4KDisk.notpass"
        else:
            errorKey = "LunAlignCheckNoExist4KDisk.notpass"
        error_msg = resource.get(errorKey)
        return (False, error_msg, None)

def getNon4KLunList(dataDict):
    '''
    @sunmmary:解析获取非4K整数倍LUN ID列表
    @参数：回显
    '''
    non4kLUNList = []
    tlvCon = dataDict["tlv"]
    param0 = Param(0, ParamType.ENUM, LUN_ENUM) 
    params = TLVUtils.paramList(param0)
    log.info(dataDict,"getNot4KLunList_params:%s"%str(params))
    recs = tlvCon.bacthNext(GET_BATCH_NEXT, params, CMD_TIMEOUT, RETRY_TIMES)
    if len(recs) <= 20:
        log.info(dataDict,"getNot4KLunList_recs:%s"%str(recs))
    for rec in recs:
        lunID = str(rec.getParamStrValue(objIDIndex))
        capacity = rec.getParamIntValue(lunCapacityIndex).longValue()
        sectorSize = rec.getParamIntValue(lunSectorSizeIndex).intValue()
        usageType = rec.getParamIntValue(lunUsageTypeIndex).intValue()
        is4kLUN = capacity*sectorSize%4096
        if is4kLUN and usageType == INTERNAL_ENUM:
            non4kLUNList.append(lunID)
    return non4kLUNList

def isExist4KDisk(dataDict):
    tlvCon = dataDict["tlv"]
    param0 = Param(0, ParamType.ENUM, DISK_ENUM) 
    params = TLVUtils.paramList(param0)
    log.info(dataDict,"isExist4KDisk_params:%s"%str(params))
    recs = tlvCon.bacthNext(GET_BATCH_NEXT, params, CMD_TIMEOUT, RETRY_TIMES)
    if len(recs) <= 20:
        log.info(dataDict,"isExist4KDisk_recs:%s"%str(recs))
    for rec in recs:
       sectorSize = rec.getParamIntValue(diskSectorSizeIndex).intValue()
       if 4096 == sectorSize or 4160 == sectorSize:
           return True
    return False
    
    
