#coding:utf-8
'''
Created on Sep 26, 2014

@author: root
'''
import time

from PyQt4.QtCore import QObject, QString
from PyQt4.QtXml import QDomDocument, QDomNode, QDomElement

from baseinfostruct import VMInfoStruct, InfoStruct
from common import commondata
from desktop.userapi import UserApi
from networkaccessmanager import NetworkAccessManager


class NetworkAccessXmlParser(QObject):
    _instance = 0 
    def __init__(self,parent=None):
        super(NetworkAccessXmlParser,self).__init__(parent)
        self.urlParserDir = {
                                commondata.DOMAIN_CENTER_URL: (self.domainXmlParser, False),
                                commondata.VM_CENTER_URL: (self.vmInfoXmlParser, True),
                                commondata.TERMINAL_LOGIN_CENTER_URL: (self.vmInfoXmlParser, True),
                                commondata.USER_ROLE_CENTER_URL: (self.userRoleXmlParser, True),
                                commondata.VMS_CENTER_URL: (self.vmsListInfoXmlParser, True),
                                commondata.VM_POOL_CENTER_URL: (self.vmPoolInfoXmlParser, True),
                                commondata.OFFLINEVM_INFO_CENTER_URL: (self.offlineVmImageInfoXmlParser, True),
                                commondata.VM_DISK_INFO_CENTER_URL: (self.vmDisksInfoXmlParser, True),
                                commondata.VM_TEMPLATE_DISK_INFO_CENTER_URL: (self.vmTemplateDisksXmlParser, True),
                                commondata.CONTROL_VM_ACTION_CENTER_URL: (self.controlVMActionXmlParser, True),
                                commondata.TERMINAL_INFO_CENTER_URL: (self.terminalInfoXmlParser, True),
                                commondata.TERMINAL_STATE_CENTER_URL: (self.terminalStateXmlParser, False),
                                commondata.VM_PASSWORD_CENTER_URL: (self.vmPasswordXmlParser, True),
                                commondata.GET_USER_PASSWORD_CENTER_URL: (self.userPasswordUrlXmlParser, True), 
                                commondata.UPDATE_USER_PASSWORD_CENTER_URL: (self.updateUserPasswordXmlParser, True),
                                commondata.TERMINAL_VALIDATE_CENTER_URL: (self.terminalValidateXmlParser, True),
                                      }
        
        
    @classmethod 
    def instance(cls):
        if (cls._instance == 0):
            cls._instance = NetworkAccessXmlParser()
            
        return cls._instance
    
    def xmlParser(self, path, exactPath=None, functionType="get", postData=None):
        urlPath = exactPath if exactPath else path
        value = self.urlParserDir.get(path, None)
        if value is None:
            return None
        
        function, auth = value[0], value[1]
        xmlContent = None
        for i in range(3):
            xmlContent = NetworkAccessManager.getRequestContext(urlPath, functionType, auth, postData)
            if xmlContent:
                break
            time.sleep(1)
        if not xmlContent:
            return None
        
        return function(xmlContent)
        
    def domainXmlParser(self, xmlContent):
        result = []
        dom = QDomDocument()
        dom.setContent(xmlContent)
        domElem = QDomElement(dom.documentElement())#返回跟节点
        n = QDomNode(domElem.firstChild())#返回跟节点的第一个子节点
        while not n.isNull():
            if n.isElement():
                e = QDomElement()#如果节点为元素，则转为元素
                e = n.toElement()
                childlist = e.childNodes()
                for i in range(len(childlist)):
                    node = QDomNode()
                    node = childlist.at(i)
                    elm = QDomElement()
                    if(node.isElement()):
                        elm = QDomElement()
                        elm = node.toElement()
                        if(not QString.compare("name", elm.tagName())):
                            result.append(str(elm.text()))
                    node = elm.nextSibling()
            n = n.nextSibling()
        return result
        
    
        
    def vmInfoXmlParser(self, xmlContent):
        return self.vmXmlParser(xmlContent)
        
    
    
    def vmXmlParser(self, xmlContent, isVms=False):
        vmInfoList = []
        dom = QDomDocument()
        dom.setContent(xmlContent)
        vm_list = dom.elementsByTagName("vm")
        num = len(vm_list)
        for i in range(num):
            vmInfo = VMInfoStruct()
            node = vm_list.at(i)
            vmInfo["id"] = node.toElement().attribute("id")
            
            itemlist = node.childNodes()
            for j in range(len(itemlist)):
                mynode = itemlist.at(j)
                if( mynode.toElement().tagName() == "name" ):
                    vmInfo["name"] = mynode.toElement().text()
                elif (mynode.toElement().tagName() == "type"):
                    vmInfo["type"] = mynode.toElement().text()
                elif( mynode.toElement().tagName() == "ismonitor" ):
                    vmInfo["ismonitor"] = mynode.toElement().text()
                elif( mynode.toElement().tagName()=="status" ):
                    status_c = len(mynode.toElement().childNodes())
                    for m in range(status_c):
                        status_cn = mynode.toElement().childNodes().at(m)
                        if(status_cn.toElement().tagName()=="state"):
                            vmInfo["status"] = status_cn.toElement().text()
    
                elif(mynode.toElement().tagName()=="display"):
                    status_c = len(mynode.toElement().childNodes())
                    for m in range(status_c):
                        status_cn = mynode.toElement().childNodes().at(m)
                        if(status_cn.toElement().tagName()=="address"):
                            vmInfo["hostIp"] = status_cn.toElement().text()
                        if(status_cn.toElement().tagName()=="port"):
                            vmInfo["hostPort"] =status_cn.toElement().text()
                        if(status_cn.toElement().tagName()=="secure_port"):
                            vmInfo["hostSPort"] = status_cn.toElement().text()
                elif(mynode.toElement().tagName()=="os"):
                    vmInfo["osType"] = mynode.toElement().attribute("type")
                elif(mynode.toElement().tagName()=="start_time"):
                    stime = mynode.toElement().text()
                    timeList = stime.split("T")
                    time1 = timeList[0]
                    time2 = timeList[1]
                    timeList2 = time2.split(".");
                    qtime = time1 + " " + timeList2[0];
                    vmInfo["startTime"] = qtime
                elif mynode.toElement().tagName()=="stateless":
                    vmInfo["stateless"] = mynode.toElement().text()
                elif(mynode.toElement().tagName()=="vmpool"):
                    vmInfo["atPool"]=mynode.toElement().attribute("id")
                    vmInfo["inPool"] = True
                elif( mynode.toElement().tagName()=="domain" ):
                    domain_c = len(mynode.toElement().childNodes())
                    for l in range(domain_c):
                        domain_cn = mynode.toElement().childNodes().at(l)
                        if(domain_cn.toElement().tagName()=="name"):
                            vmInfo["vmDomain"] = domain_cn.toElement().text()
                elif  (mynode.toElement().tagName()=="guest_info"):
                    status_c = len(mynode.toElement().childNodes())
                    for m in range(status_c):
                        status_cn = mynode.toElement().childNodes().at(m)
                        if(status_cn.toElement().tagName()=="ips"):
                            ipscon = len(status_cn.toElement().childNodes())
                            for j in range(ipscon):
                                ip_cn = status_cn.toElement().childNodes().at(j)
                                if(ip_cn.toElement().tagName() == "ip"):
                                    vmInfo["vmip"] = []
                                    vmInfo["vmip"].append(ip_cn.toElement().attribute("address"))
                elif mynode.toElement().tagName() == "currentuserrole":
                    userRoleList = [role for role in mynode.toElement().text().split(";") if role]
                    for role in userRoleList:
                        if role in ["MonitorUserRole", "MutiClientUserRole"]:
                            vmInfo["userRole"] = role
                    if not vmInfo["userRole"]:
                        vmInfo["userRole"] = "UserRole"
                elif(mynode.toElement().tagName() == "offlinedesktopavailable"):
                    vmInfo["offlinedesktopavailable"] = mynode.toElement().text()
                elif(mynode.toElement().tagName() == "usetype"):
                    vmInfo["usetype"] = mynode.toElement().text()
                elif(mynode.toElement().tagName() == "isCache"):
                    vmInfo["vm_cache"] = mynode.toElement().text()
                    
            vmInfoList.append(vmInfo)
            
        if not isVms:
            return vmInfoList[0] if vmInfoList else VMInfoStruct()
        else:
            return vmInfoList
    
        
    def userRoleXmlParser(self,xmlContent):
        dom = QDomDocument()
        dom.setContent(xmlContent)
 
        #遍历该上下文中的所有用户信息，查找出和当前用户名相同的用户所对于的用户角色
        pms_list = dom.elementsByTagName("permission")
 
        pmsCount = len(pms_list)
        for i in range(pmsCount):
            userRole = ""
            node = pms_list.at(i)
 
            itemlist = node.childNodes()
            for j in range(len(itemlist)):
                mynode = itemlist.at(j)
                #获取用户角色和用户名
                if (mynode.toElement().tagName() == "role" or mynode.toElement().tagName() == "user"):
                    href = mynode.toElement().attribute("href")
                    if (not href.isEmpty() and not href.isNull()):
                        roleInfo = QString()
                        for i in range(3):
                            roleInfo = NetworkAccessManager.getRequestContext(href)
                            if roleInfo:
                                break
                        if (not roleInfo.isEmpty() and not roleInfo.isNull()):
                            roleDom = QDomDocument()
                            roleDom.setContent(roleInfo)
                            nodeList = roleDom.elementsByTagName("name");
                            num = len(nodeList)
                            for k in range(num):
                                subNode = nodeList.at(k)
                                if (subNode.toElement().tagName() == "name"):
                                    name = subNode.toElement().text()
                                    tagName = mynode.toElement().tagName()
                                    if (tagName == "role"):
                                        userRole = name
                                    elif (tagName == "user"):
                                        loginUserName = UserApi.instance().getUserName()
                                         
                                        if (name == loginUserName):
                                            if userRole == "MonitorUserRole":
                                                return "MonitorUserRole"
                                            elif userRole == "MutiClientUserRole":
                                                return "MutiClientUserRole"
                                    break
                 
        return "UserRole"
        
    def vmsListInfoXmlParser(self, xmlContent):

        return self.vmXmlParser(xmlContent, isVms=True)
        
        
    def vmPoolInfoXmlParser(self, xmlContent):
        vmPoolList = []
        dom = QDomDocument() 
        dom.setContent(xmlContent)
    
        vmpol_list = dom.elementsByTagName("vmpool")
        for i in range(len(vmpol_list)):
            vmPoolInfo = InfoStruct()
            node = vmpol_list.at(i)
            vmPoolInfo["poolid"] = node.toElement().attribute("id")
            itemlist = node.childNodes()
            for j in range(len(itemlist)):
                mynode = itemlist.at(j)
                if( mynode.toElement().tagName() == "name" ):
                    vmPoolInfo["poolname"] = mynode.toElement().text()
                if( mynode.toElement().tagName()=="size" ):
                    vmPoolInfo["size"] = mynode.toElement().text()
                if( mynode.toElement().tagName()=="prestarted_vms" ):
                    vmPoolInfo["preStartVM"] = mynode.toElement().text()
            vmPoolList.append(vmPoolInfo)
            
        return vmPoolList
        
    def offlineVmImageInfoXmlParser(self, xmlContent):
        offLineVMInfo = InfoStruct()
        dom = QDomDocument()
        dom.setContent(xmlContent)
        nodelist = dom.elementsByTagName('vm')
        for j in range(len(nodelist)):
            node = nodelist.at(j)
            itemlist = node.childNodes()
            for i in range(len(itemlist)):
                each_node = itemlist.at(i)
                if (each_node.toElement().tagName() == 'name'):
                    offLineVMInfo['name'] = each_node.toElement().text()
                elif (each_node.toElement().tagName() == 'type'):
                    offLineVMInfo['type'] = each_node.toElement().text()
                elif (each_node.toElement().tagName() == 'status'):
                    childlist = each_node.toElement().childNodes()
                    for n in range(len(childlist)):
                        child = childlist.at(n)
                        if(child.toElement().tagName()=="state"):
                            offLineVMInfo["status_state"] = child.toElement().text()
                elif(each_node.toElement().tagName() == 'memory'):
                    offLineVMInfo['memory'] = each_node.toElement().text()
                elif(each_node.toElement().tagName() == 'cpu'):
                    childlist = each_node.toElement().childNodes()
                    for n in range(len(childlist)):
                        child = childlist.at(n)
                        if(child.toElement().tagName() == 'topology'):
                            offLineVMInfo['cpu_topology_sockets'] = child.toElement().attribute('sockets')
                            offLineVMInfo['cpu_topology_cores'] = child.toElement().attribute('cores')
                        elif(child.toElement().tagName() == 'architecture'):
                            offLineVMInfo['cpu_architecture'] = child.toElement().text()
                        else:
                            pass
                elif(each_node.toElement().tagName() == 'os'):
                    offLineVMInfo['os_type'] = each_node.toElement().attribute('type')
                    childlist = each_node.toElement().childNodes()
                    for n in range(len(childlist)):
                        child = childlist.at(n)
                        if child.toElement().tagName() == 'boot':
                            offLineVMInfo['os_boot_dev'] = child.toElement().attribute('dev')
                elif(each_node.toElement().tagName() == 'template'):
                    offLineVMInfo['template_id'] = each_node.toElement().attribute('id')
                else:
                    pass
        return offLineVMInfo
        
        
    def vmDisksInfoXmlParser(self, xmlContent):        
        diskInfoList = []
        dom = QDomDocument() 
        dom.setContent(xmlContent)
        diskList = dom.elementsByTagName("disk")
        for i in range(len(diskList)):
            diskInfo = {}
            node = diskList.at(i)
            diskInfo["id"] = node.toElement().attribute("id")
            itemlist = node.childNodes()
            for j in range(len(itemlist)):
                mynode = itemlist.at(j)
                if (mynode.toElement().tagName() == 'name'):
                    diskInfo['name'] = mynode.toElement().text()
                elif (mynode.toElement().tagName() == 'alias'):
                    diskInfo['alias'] = mynode.toElement().text()
                elif(mynode.toElement().tagName() == 'image_id'):
                    diskInfo['image_id'] = mynode.toElement().text()
                elif(mynode.toElement().tagName() == 'storage_domains'):
                    childlist = mynode.toElement().childNodes()
                    for n in range(len(childlist)):
                        child = childlist.at(n)
                        if(child.toElement().tagName() == 'storage_domain'):
                            diskInfo['storage_domain'] = child.toElement().text()
                elif(mynode.toElement().tagName() == 'size'):
                    diskInfo['size'] = mynode.toElement().text()
                elif(mynode.toElement().tagName() == 'provisioned_size'):
                    diskInfo['provisioned_size'] = mynode.toElement().text()
                elif(mynode.toElement().tagName() == 'actual_size'):
                    diskInfo['actual_size'] = mynode.toElement().text()
                elif(mynode.toElement().tagName() == 'format'):
                    diskInfo['format'] = mynode.toElement().text()
                elif( mynode.toElement().tagName() == "bootable" ):
                    diskInfo["bootable"] = mynode.toElement().text()
                else:
                    pass
            diskInfoList.append(diskInfo)

        return diskInfoList
        
    def vmTemplateDisksXmlParser(self, xmlContent):
        templateDisks = []
        dom = QDomDocument() 
        dom.setContent(xmlContent)
        templateDiskList = dom.elementsByTagName("disk")
        for i in range(len(templateDiskList)):
            disk = templateDiskList.at(i)
            diskInfo = {}
            diskInfo['disk_id'] = disk.toElement().attribute('id')
            nodelist = disk.toElement().childNodes()
            for j in range(len(nodelist)):
                each_node = nodelist.at(j)
                if (each_node.toElement().tagName() == 'name'):
                    diskInfo['disk_name'] = each_node.toElement().text()
                elif (each_node.toElement().tagName() == 'alias'):
                    diskInfo['disk_alias'] = each_node.toElement().text()
                elif(each_node.toElement().tagName() == 'image_id'):
                    diskInfo['disk_image_id'] = each_node.toElement().text()
                elif (each_node.toElement().tagName() == 'size'):
                    diskInfo['disk_size'] = each_node.toElement().text()
                elif(each_node.toElement().tagName() == 'provisioned_size'):
                    diskInfo['disk_provisioned_size'] = each_node.toElement().text()
                elif(each_node.toElement().tagName() == 'actual_size'):
                    diskInfo['disk_actual_size'] = each_node.toElement().text()
                elif(each_node.toElement().tagName() == 'interface'):
                    diskInfo['disk_interface'] = each_node.toElement().text()
                elif(each_node.toElement().tagName() == 'bootable'):
                    diskInfo['disk_bootable'] = each_node.toElement().text()
               
            templateDisks.append(diskInfo)
        return templateDisks
    
    def controlVMActionXmlParser(self, xmlContent):
        print ("start:", xmlContent)
        dom_sre = QDomDocument()
        dom_sre.setContent(xmlContent)
    
        actions_re = dom_sre.elementsByTagName("action")
        for i in range(len(actions_re)):
            node_action = actions_re.at(i)
            resu_list = node_action.childNodes()
            for j in range(len(resu_list)):
                resu_list_ = resu_list.at(j)
                if(resu_list_.toElement().tagName()=="status"):
                    status_c = len(resu_list_.toElement().childNodes())
                    for m in range(status_c):
                        status_cn_s = resu_list_.toElement().childNodes().at(m)
                        if(status_cn_s.toElement().tagName()=="state"):
                            status = status_cn_s.toElement().text()
                            if( status == "complete" or status == "pending" ):
                                return True,"msg"
                            elif( status == "failed" ):
                                #虚拟机操作失败,取得失败信息，通知
                                resu_list_f = resu_list.at(1)
                                if(resu_list_f.toElement().tagName()=="fault"):
                                    fail_re=len(resu_list_f.toElement().childNodes())
                                    for n in range(fail_re):
                                        fail_re_node= resu_list_f.toElement().childNodes().at(n)
                                        if(fail_re_node.toElement().tagName()=="detail"):
                                            vm_start_detail = fail_re_node.toElement().text()
                                            msg=vm_start_detail
                                            return False,msg
                                    
        msg=u"操作失败!"
        return False,msg
    
    def terminalInfoXmlParser(self, xmlContent):

        pass
    
    def terminalStateXmlParser(self, xmlContent):

        pass
    
    
    def vmPasswordXmlParser(self, xmlContent):
        dom_sre = QDomDocument()
        dom_sre.setContent(xmlContent)
        ticket_value=""
        get_ticket=False
    
        actions_re = dom_sre.elementsByTagName("action")
        for i in range(len(actions_re)):
            node_action = actions_re.at(i)
            resu_list = node_action.childNodes()
            for j in range(len(resu_list)):
                resu_list_ = resu_list.at(j)
                if(resu_list_.toElement().tagName()=="ticket"):
                    status_c = len(resu_list_.toElement().childNodes())
                    for m in range(status_c):
                        status_cn_s = resu_list_.toElement().childNodes().at(m)
                        if(status_cn_s.toElement().tagName()=="value"):
                            ticket_value = status_cn_s.toElement().text()
                #判断该动作是否成功
                if(resu_list_.toElement().tagName()=="status"):
                    status_c = len(resu_list_.toElement().childNodes())
                    for m in range(status_c):
                        status_cn_s = resu_list_.toElement().childNodes().at(m)
                        if(status_cn_s.toElement().tagName()=="state"):
                            status = status_cn_s.toElement().text()
                            if( status == "complete"):
                                get_ticket=True
    
                #有fault字段，说明失败
                if(resu_list_.toElement().tagName()=="fault"):
                    fail_re= len(resu_list_.toElement().childNodes())
                    for n in range(fail_re):
                        fail_re_node= resu_list_.toElement().childNodes().at(n)
                        if(fail_re_node.toElement().tagName()=="detail"):
                            ticket=fail_re_node.toElement().text()
                            return ""
        #/end i
        if(get_ticket==True and ticket_value != ""):
            ticket=ticket_value
            return ticket
        else:
            ticket=u"获取密码错误!"
        return ""
        
    def userPasswordUrlXmlParser(self, xmlContent):

        dom = QDomDocument()
        dom.setContent(xmlContent)
        userList = dom.elementsByTagName("internalUser")
        for j in range(len(userList)):
            node = userList.at(j)
            updatePasswordUrl = str(node.toElement().attribute("href")) + "/updateInternalUserPassword"
            itemlist = node.childNodes()
            for i in range(len(itemlist)):
                each_node = itemlist.at(i)
                if (each_node.toElement().tagName() == 'username'):
                    if UserApi.instance().getUserName() == each_node.toElement().text().split("@")[0]:
                        return updatePasswordUrl
                    
                    if each_node.toElement().text().split("@")[0] == "sysadmin":
                        return updatePasswordUrl
        return None
        
    def updateUserPasswordXmlParser(self, xmlContent):
        return True if "complete" in xmlContent else False
    

    def terminalValidateXmlParser(self, xmlContent):
        print ("terminal validate:", xmlContent)
        dom_sre = QDomDocument()
        dom_sre.setContent(xmlContent)
        
        actions_re = dom_sre.elementsByTagName("action")
        for i in range(len(actions_re)):
            node_action = actions_re.at(i)
            resu_list = node_action.childNodes()
            for j in range(len(resu_list)):
                resu_list_ = resu_list.at(j)
                if(resu_list_.toElement().tagName()=="status"):
                    status_c = len(resu_list_.toElement().childNodes())
                    for m in range(status_c):
                        status_cn_s = resu_list_.toElement().childNodes().at(m)
                        if(status_cn_s.toElement().tagName()=="state"):
                            status = status_cn_s.toElement().text()
                
            return str(status)
        
                    
        detail = ""            
        actions_re = dom_sre.elementsByTagName("fault")
        for i in range(len(actions_re)):
            node_action = actions_re.at(i)
            resu_list = node_action.childNodes()
            for j in range(len(resu_list)):
                resu_list_ = resu_list.at(j)
                if(resu_list_.toElement().tagName()=="detail"):
                    status_c = len(resu_list_.toElement().childNodes())
                    detail = resu_list_.toElement().text()
            
            return detail
        
        return None
        
