# -*- encoding: utf-8 -*-
#
# Copyright  2012 Red Hat, Inc
#
# Author: Eoghan Glynn <eglynn@redhat.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Implementation of Inspector abstraction for libvirt."""

import libvirt
import os,sys,time
import traceback
from lxml import etree
from oslo.config import cfg

from nova.openstack.common import log as logging
from nova import utils

libvirt = None

LOG = logging.getLogger(__name__)

libvirt_opts = [
    cfg.StrOpt('libvirt_type',
               default='kvm',
               help='Libvirt domain type (valid options are: '
                    'kvm, lxc, qemu, uml, xen)'),
    cfg.StrOpt('libvirt_uri',
               default='',
               help='Override the default libvirt URI '
                    '(which is dependent on libvirt_type)'),
    cfg.StrOpt('network_script_path',
               default='/etc/sysconfig/network-scripts/',
               help='Centos 6.6 system network config path ' ),
]

CONF = cfg.CONF
CONF.register_opts(libvirt_opts)


class LibvirtNetwork(object):

    per_type_uris = dict(uml='uml:///system', xen='xen:///', lxc='lxc:///')

    def __init__(self):
        self.uri = self._get_uri()
        self.connection = None

    def _get_uri(self):
        return CONF.libvirt_uri or self.per_type_uris.get(CONF.libvirt_type,
                                                          'qemu:///system')

    def _get_connection(self):
        if not self.connection or not self._test_connection():
            global libvirt
            if libvirt is None:
                libvirt = __import__('libvirt')

            LOG.debug('Connecting to libvirt: %s', self.uri)
            self.connection = libvirt.openReadOnly(self.uri)

        return self.connection

    def _test_connection(self):
        try:
            self.connection.getCapabilities()
            return True
        except libvirt.libvirtError as e:
            print '*' * 100
            if (e.get_error_code() == libvirt.VIR_ERR_SYSTEM_ERROR and
                e.get_error_domain() in (libvirt.VIR_FROM_REMOTE,
                                         libvirt.VIR_FROM_RPC)):
                LOG.debug('Connection to libvirt broke')
                return False
            raise

    def _lookup_by_name(self, instance_name):
        try:
            return self._get_connection().lookupByName(instance_name)
        except Exception as ex:
            if not libvirt or not isinstance(ex, libvirt.libvirtError):
                LOG.error(ex)
            error_code = ex.get_error_code()
            msg = ("Error from libvirt while looking up %(instance_name)s: "
                   "[Error Code %(error_code)s] "
                   "%(ex)s" % {'instance_name': instance_name,
                               'error_code': error_code,
                               'ex': ex})
            LOG.error(msg)


    def get_vnic_name(self, instance_name):
        domain = self._lookup_by_name(instance_name)
        tree = etree.fromstring(domain.XMLDesc(0))
        
        for iface in tree.findall('devices/interface'):
            target = iface.find('target')
            if target is not None:
                vnic_name = target.get('dev')
            else:
                continue
            mac = iface.find('mac')
            if mac is not None:
                mac_address = mac.get('address')
            else:
                continue
            fref = iface.find('filterref')
            if fref is not None:
                fref = fref.get('filter')

        return vnic_name

    #Add william ,Bridge supports multiple vlan technology 
    def bridge_multiple_vlan(self,instance):
        network_info = dict()
        try:
            new_source_dev = instance['hostname'].split('.')[-1]
            if  not new_source_dev:
                new_source_dev = 'br100'
                
            if 'vlan' not in new_source_dev:
                new_source_dev = 'br100'

            network_info['vlan_name'] = new_source_dev
            network_info['instances_name'] = instance['name']
            #network_info['vnet_name'] = self.get_vnic_name(instance['name'])
            network_info['bond_name'] = os.listdir('/proc/net/bonding')[0]
            network_info['bond_dev'] = '%s.%s' %(network_info['bond_name'],new_source_dev.split('vlan')[-1])
            network_info['vlan_id'] = new_source_dev.split('vlan')[-1] 

            check_result = self.check_bridge_vlan(network_info['vlan_name'],network_info['bond_dev'])
            if not check_result:
                self.add_bridge_vlan(network_info)
            else:
                LOG.info("Add william,%s is exists,so is not create  " % network_info['vlan_name'])
        except:
            LOG.error(traceback.format_exc())

    def add_bridge_vlan(self,network_info):
        utils.execute("vconfig" ,"add", network_info['bond_name'], network_info['vlan_id'],run_as_root=True)
        LOG.info("Add william,utils.exeucte vconfig add %s %s " %(network_info['bond_name'], network_info['vlan_id']))

        utils.execute("ifconfig" , network_info['bond_dev'],"up",run_as_root=True)
        LOG.info("Add william,utils.execute ifconfig %s up" % (network_info['bond_dev']))

        utils.execute("brctl" ,"addbr", network_info['vlan_name'],run_as_root=True)
        LOG.info("Add william,utils.execute brctl addbr %s " %(network_info['vlan_name']))

        utils.execute("brctl" ,"addif", network_info['vlan_name'],network_info['bond_dev'],run_as_root=True)
        LOG.info("Add william,utils.execute brctl addif %s %s " %(network_info['vlan_name'],network_info['bond_dev']))

        utils.execute("ifconfig" , network_info['vlan_name'],"up",run_as_root=True)
        LOG.info("")

        #utils.execute("brctl" ,"addif", network_info['vlan_name'],network_info['vnet_name'],run_as_root=True)
        

        bond_script = "%s/ifcfg-%s" % (CONF.network_script_path, network_info['bond_dev'])
        vlan_script = "%s/ifcfg-%s" % (CONF.network_script_path, network_info['vlan_name'])

        utils.execute("chmod","777",CONF.network_script_path, run_as_root=True)
        fp = open(bond_script , 'w')
        fp.write("DEVICE=%s \n" % network_info['bond_dev'])
        fp.write("ONBOOT=yes \n")
        fp.write("NM_CONTROLLED=no \n")
        fp.write("BOOTPROTO=static \n")
        fp.write("VLAN=yes \n")
        fp.close()

        fp = open(vlan_script , 'w')
        fp.write("DEVICE=%s \n" % network_info['vlan_name'])
        fp.write("BOOTPROTO=static \n")
        fp.write("ONBOOT=yes \n")
        fp.write("TYPE=Bridge \n")
        fp.close()
        utils.execute("chmod","755",CONF.network_script_path, run_as_root=True)


    def check_bridge_vlan(self,vlan_dev,bond_dev):
        vlan_list = bond_list = list()
        vlan = bond = False

        vlan_info =  os.popen(" brctl show |grep vlan |  awk '{print $1}' ").readlines()
        for i in vlan_info:
            vlan_list.append(i.strip())
      
        bond_info =  os.popen("ifconfig |grep bond0|awk '{print $1}'").readlines()
        for i in bond_info:
            bond_list.append(i.strip())
        
        if vlan_dev in vlan_list:
            vlan = True
       
        if bond_dev in bond_list:
            bond = True

        if vlan and bond:
            return True
        else:
            return False

if __name__ == "__main__":
    instance = {u'vm_state': u'building', u'internal_id': None, u'availability_zone': u'nova', u'terminated_at': None, u'ephemeral_gb': 100, u'instance_type_id': 26, u'user_data': None, u'cleaned': 0, u'vm_mode': None, u'deleted_at': None, u'reservation_id': u'r-z2zsdcvl', u'id': 299, u'security_groups': [{u'project_id': u'50fd5d79ab184c399cdc22da78b8a7bc', u'user_id': u'373ddabe004846ebba268d7e88d13e16', u'name': u'default', u'deleted': 0, u'created_at': u'2014-09-30T07:49:38.000000', u'updated_at': None, u'rules': [], u'deleted_at': None, u'id': 1, u'description': u'default'}], u'disable_terminate': False, u'root_device_name': u'/dev/vda', u'user_id': u'373ddabe004846ebba268d7e88d13e16', u'uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'default_swap_device': None, u'info_cache': {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': u'2015-04-16T03:36:52.000000', u'network_info': u'[{"ovs_interfaceid": null, "network": {"bridge": "br100", "subnets": [{"ips": [{"meta": {}, "version": 4, "type": "fixed", "floating_ips": [], "address": "192.168.221.164"}], "version": 4, "meta": {"dhcp_server": "192.168.221.11"}, "dns": [{"meta": {}, "version": 4, "type": "dns", "address": "192.168.252.25"}, {"meta": {}, "version": 4, "type": "dns", "address": "192.168.252.24"}], "routes": [], "cidr": "192.168.220.0/19", "gateway": {"meta": {}, "version": 4, "type": "gateway", "address": "192.168.192.1"}}, {"ips": [], "version": null, "meta": {"dhcp_server": "192.168.221.11"}, "dns": [], "routes": [], "cidr": null, "gateway": {"meta": {}, "version": null, "type": "gateway", "address": null}}], "meta": {"tenant_id": "50fd5d79ab184c399cdc22da78b8a7bc", "multi_host": true, "should_create_bridge": true, "should_create_vlan": true, "bridge_interface": "bond0"}, "id": "4a8546f2-3919-445a-9f87-b938491d41a5", "label": "publics"}, "devname": null, "qbh_params": null, "meta": {}, "address": "fa:16:3e:c5:be:93", "type": "bridge", "id": "a7a69211-6aeb-4b54-9a20-803b96df73bf", "qbg_params": null}]', u'deleted_at': None, u'id': 299}, u'hostname': u'gg-esc-web.vlan203', u'launched_on': u'localhost', u'display_description': u'gg-esc-web.vlan201', u'key_data': None, u'deleted': 0, u'scheduled_at': u'2015-04-16T03:36:51.000000', u'power_state': 0, u'default_ephemeral_device': None, u'progress': 0, u'project_id': u'50fd5d79ab184c399cdc22da78b8a7bc', u'launched_at': None, u'config_drive': u'', u'node': u'localhost', u'ramdisk_id': u'', u'access_ip_v6': None, u'access_ip_v4': None, u'kernel_id': u'', u'key_name': None, u'updated_at': u'2015-04-16T03:36:52.727467', u'host': u'localhost', u'display_name': u'gg-esc-web.vlan201', u'system_metadata': [{u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'windows', u'key': u'p_w_picpath_os_type', u'deleted_at': None, u'id': 4889}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'8192', u'key': u'instance_type_memory_mb', u'deleted_at': None, u'id': 4890}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'0', u'key': u'instance_type_swap', u'deleted_at': None, u'id': 4891}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': None, u'key': u'instance_type_vcpu_weight', u'deleted_at': None, u'id': 4892}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'60', u'key': u'instance_type_root_gb', u'deleted_at': None, u'id': 4893}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'26', u'key': u'instance_type_id', u'deleted_at': None, u'id': 4894}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'windows-16-8G-100G', u'key': u'instance_type_name', u'deleted_at': None, u'id': 4895}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'100', u'key': u'instance_type_ephemeral_gb', u'deleted_at': None, u'id': 4896}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'1', u'key': u'instance_type_rxtx_factor', u'deleted_at': None, u'id': 4897}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'qcow2', u'key': u'p_w_picpath_disk_format', u'deleted_at': None, u'id': 4898}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'74c9f78a-06d6-432d-8051-4eeecf8ebff7', u'key': u'instance_type_flavorid', u'deleted_at': None, u'id': 4899}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'ovf', u'key': u'p_w_picpath_container_format', u'deleted_at': None, u'id': 4900}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'16', u'key': u'instance_type_vcpus', u'deleted_at': None, u'id': 4901}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'0', u'key': u'p_w_picpath_min_ram', u'deleted_at': None, u'id': 4902}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'60', u'key': u'p_w_picpath_min_disk', u'deleted_at': None, u'id': 4903}, {u'instance_uuid': u'c4cf7bc1-72bd-4523-bab0-fdd0f837fb46', u'deleted': 0, u'created_at': u'2015-04-16T03:36:51.000000', u'updated_at': None, u'value': u'406c0425-b8d3-4607-beff-8fa529b46b7a', u'key': u'p_w_picpath_base_p_w_picpath_ref', u'deleted_at': None, u'id': 4904}], u'task_state': u'spawning', u'shutdown_terminate': False, u'cell_name': None, u'root_gb': 60, u'locked': False, u'name': u'instance-0000012b', u'created_at': u'2015-04-16T03:36:51.000000', u'locked_by': None, u'launch_index': 0, u'memory_mb': 8192, u'vcpus': 16, u'p_w_picpath_ref': u'406c0425-b8d3-4607-beff-8fa529b46b7a', u'architecture': None, u'auto_disk_config': False, u'os_type': u'windows', u'metadata': []}
    sc = LibvirtNetwork()
    sc.bridge_multiple_vlan(instance)