import os
import shutil
import re
from novaclient import client as nova_client
from SSHTestAgent import SSHTestAgent
from CordTestUtils import *
from CordTestUtils import log_test as log

log.setLevel('INFO')

class VSGAccess(object):

    vcpe_map = {}
    interface_map = {}
    ip_addr_pattern = re.compile('[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$')

    @classmethod
    def setUp(cls):
        try:
            shutil.copy('/etc/resolv.conf', '/etc/resolv.conf.orig')
        except:
            pass

    @classmethod
    def tearDown(cls):
        try:
            shutil.copy('/etc/resolv.conf.orig', '/etc/resolv.conf')
        except:
            pass

    '''
    @method: get_nova_credentials_v2
    @Description: Get nova credentials
    @params:
    returns credential from env
    '''
    @classmethod
    def get_nova_credentials_v2(cls):
        credential = {}
        credential['username'] = os.environ['OS_USERNAME']
        credential['api_key'] = os.environ['OS_PASSWORD']
        credential['auth_url'] = os.environ['OS_AUTH_URL']
        credential['project_id'] = os.environ['OS_TENANT_NAME']
        return credential

    '''
    @method: get_compute_nodes
    @Description: Get the list of compute nodes
    @params:
    returns  node list
    '''
    @classmethod
    def get_compute_nodes(cls):
        credentials = cls.get_nova_credentials_v2()
        nvclient = nova_client.Client('2', **credentials)
        return nvclient.hypervisors.list()

    '''
    @method: get_vsgs
    @Description: Get list of vsg's running in compute node
    @params: status of vsg
    returns vsg wrappers
    '''
    @classmethod
    def get_vsgs(cls, active = True):
        credentials = cls.get_nova_credentials_v2()
        nvclient = nova_client.Client('2', **credentials)
        vsgs = nvclient.servers.list(search_opts = {'all_tenants': 1})
        if active is True:
            vsgs = filter(lambda vsg: vsg.status == 'ACTIVE', vsgs)
        vsg_wrappers = []
        for vsg in vsgs:
            vsg_wrappers.append(VSGWrapper(vsg))
        return vsg_wrappers

    '''
    @method: open_mgmt
    @Description: Bringing up Interface for access to management
    @params: intf = "Interface to open"
    returns Gateway
    '''
    @classmethod
    def open_mgmt(cls, intf = 'eth0'):
        if intf in cls.interface_map:
            gw = cls.interface_map[intf]['gw']
            ip = cls.interface_map[intf]['ip']
            if gw != '0.0.0.0':
                current_gw, _ = get_default_gw()
                cmds = [ 'route del default gw {}'.format(current_gw),
                         'ifconfig {} {} up'.format(intf, ip),
                         'route add default gw {}'.format(gw) ]
                for cmd in cmds:
                    os.system(cmd)
                shutil.copy('/etc/resolv.conf', '/etc/resolv.conf.lastdhcp')
                shutil.copy('/etc/resolv.conf.orig', '/etc/resolv.conf')
                return current_gw
        return None

    '''
    @method: close_mgmt
    @Description: Bringing up gateway deleting default
    @params: intf = "Interface to open"
             dict2 = retrieved data from GET method
    returns: NA
    '''
    @classmethod
    def close_mgmt(cls, restore_gw, intf = 'eth0'):
        if restore_gw:
            cmds = [ 'route del default gw 0.0.0.0',
                     'route add default gw {}'.format(restore_gw),
                     'cp /etc/resolv.conf.lastdhcp /etc/resolv.conf',
                     'rm -f /etc/resolv.conf.lastdhcp'
                     ]
            for cmd in cmds:
                os.system(cmd)

    '''
    @method: health_check
    @Description: Check if vsgs are reachable
    @params:
    returns True
    '''
    @classmethod
    def health_check(cls):
        '''Returns 0 if all active vsgs are reachable through the compute node'''
        vsgs = cls.get_vsgs()
        vsg_status = []
        for vsg in vsgs:
            vsg_status.append(vsg.get_health())
        unreachable = filter(lambda st: st == False, vsg_status)
        return len(unreachable) == 0

    '''
    @method: get_vcpe_vsg
    @Description: Getting vsg vm instance info from given vcpe
    @params: vcpe = "vcpe name"
    returns vsg
    '''
    @classmethod
    def get_vcpe_vsg(cls, vcpe):
        '''Find the vsg hosting the vcpe service'''
        if vcpe in cls.vcpe_map:
            return cls.vcpe_map[vcpe]['vsg']
        vsgs = cls.get_vsgs()
        for vsg in vsgs:
            cmd = 'sudo docker exec {} ls 2>/dev/null'.format(vcpe)
            st, _ = vsg.run_cmd(cmd, timeout = 30)
            if st == True:
                return vsg
        return None

    '''
    @method: save_vcpe_config
    @Description: Saving vcpe config with lan & wan side info
    @params: vsg
             vcpe
    returns True
    '''
    @classmethod
    def save_vcpe_config(cls, vsg, vcpe):
        if vcpe not in cls.vcpe_map:
            cmd_gw = "sudo docker exec %s ip route show | grep default | head -1 | awk '{print $3}'" %(vcpe)
            vsg_ip = vsg.ip
            if vsg_ip is None:
                return False
            st, output = vsg.run_cmd(cmd_gw, timeout = 30)
            if st == False or not output:
                return False
            gw = output
            cmd_wan = "sudo docker exec %s ip addr show eth0 |grep inet |head -1 | tr -s ' ' | awk '{print $2}' | awk '{print $1}'" %(vcpe)
            cmd_lan = "sudo docker exec %s ip addr show eth1 |grep inet |head -1 | tr -s ' ' | awk '{print $2}' | awk '{print $1}'" %(vcpe)
            st, output = vsg.run_cmd(cmd_wan, timeout = 30)
            ip_wan = '0.0.0.0/24'
            ip_lan = '0.0.0.0/24'
            if st and output:
                if cls.ip_addr_pattern.match(output):
                    ip_wan = output

            st, output = vsg.run_cmd(cmd_lan, timeout = 30)
            if st and output:
                if cls.ip_addr_pattern.match(output):
                    ip_lan = output

            cls.vcpe_map[vcpe] = { 'vsg': vsg, 'gw': gw, 'wan': ip_wan, 'lan': ip_lan }

        return True

    '''
    @method: restore_vcpe_config
    @Description: Restoring saved config for lan & wan
    @params: vcpe
             gw
             wan
             lan
    returns True/False
    '''
    @classmethod
    def restore_vcpe_config(cls, vcpe, gw = True, wan = False, lan = False):
        if vcpe in cls.vcpe_map:
            vsg = cls.vcpe_map[vcpe]['vsg']
            cmds = []
            if gw is True:
                #restore default gw
                gw = cls.vcpe_map[vcpe]['gw']
                cmds.append('sudo docker exec {} ip link set eth0 up'.format(vcpe))
                cmds.append('sudo docker exec {} route add default gw {} dev eth0'.format(vcpe, gw))
            if wan is True:
                ip_wan = cls.vcpe_map[vcpe]['wan']
                cmds.append('sudo docker exec {} ip addr set {} dev eth0'.format(vcpe, ip_wan))
            if lan is True:
                ip_lan = cls.vcpe_map[vcpe]['lan']
                cmds.append('sudo docker exec {} ip addr set {} dev eth1'.format(vcpe, ip_lan))
            ret_status = True
            for cmd in cmds:
                st, _ = vsg.run_cmd(cmd, timeout = 30)
                if st == False:
                    ret_status = False
            return ret_status
        return False

    '''
    @method: get_vcpe_gw
    @Description: Get gw of vcpe from created map
    @params: vcpe
    returns gw
    '''
    @classmethod
    def get_vcpe_gw(cls, vcpe):
        if vcpe in cls.vcpe_map:
            return cls.vcpe_map[vcpe]['gw']
        return None

    '''
    @method: get_vcpe_wan
    @Description:
    @params:
    return wan side of vcpe
    '''
    @classmethod
    def get_vcpe_wan(cls, vcpe):
        if vcpe in cls.vcpe_map:
            return cls.vcpe_map[vcpe]['wan']
        return None

    '''
    @method: get_vcpe_lan
    @Description:
    @params:
    returns True if contents of dict1 exists in dict2
    '''
    @classmethod
    def get_vcpe_lan(cls, vcpe):
        if vcpe in cls.vcpe_map:
            return cls.vcpe_map[vcpe]['lan']
        return None

    '''
    @method: vcpe_wan_up
    @Description:
    @params:
    returns status
    '''
    @classmethod
    def vcpe_wan_up(cls, vcpe):
        return cls.restore_vcpe_config(vcpe)

    '''
    @method: vcpe_lan_up
    @Description:
    @params:
    returns status
    '''
    @classmethod
    def vcpe_lan_up(cls, vcpe, vsg = None):
        if vsg is None:
            vsg = cls.get_vcpe_vsg(vcpe)
            if vsg is None:
                return False
        cmd = 'sudo docker exec {} ip link set eth1 up'.format(vcpe)
        st, _ = vsg.run_cmd(cmd, timeout = 30)
        return st

    '''
    @method: vcpe_port_down
    @Description:
    @params:
    returns status
    '''
    #we cannot access compute node if the vcpe port gets dhcp as default would be through fabric
    @classmethod
    def vcpe_port_down(cls, vcpe, port, vsg = None):
        if vsg is None:
            vsg = cls.get_vcpe_vsg(vcpe)
            if vsg is None:
                return False
        if not cls.save_vcpe_config(vsg, vcpe):
            return False
        cmd = 'sudo docker exec {} ip link set {} down'.format(vcpe, port)
        st, _ = vsg.run_cmd(cmd, timeout = 30)
        if st is False:
            cls.restore_vcpe_config(vcpe)
            return False
        return st

    '''
    @method: vcpe_wan_down
    @Description:
    @params:
    returns status
    '''
    @classmethod
    def vcpe_wan_down(cls, vcpe, vsg = None):
        return cls.vcpe_port_down(vcpe, 'eth0', vsg = vsg)

    '''
    @method: vcpe_lan_down
    @Description:
    @params:
    returns status
    '''
    @classmethod
    def vcpe_lan_down(cls, vcpe, vsg = None):
        return cls.vcpe_port_down(vcpe, 'eth1', vsg = vsg)

    '''
    @method: save_interface_config
    @Description:
    @params:
    returns NA
    '''
    @classmethod
    def save_interface_config(cls, intf):
        if intf not in cls.interface_map:
            ip = get_ip(intf)
            if ip is None:
                ip = '0.0.0.0'
            default_gw, default_gw_device = get_default_gw()
            if default_gw_device != intf:
                default_gw = '0.0.0.0'
            cls.interface_map[intf] = { 'ip' : ip, 'gw': default_gw }
            #bounce the interface to remove default gw
            cmds = ['ifconfig {} 0 down'.format(intf),
                    'ifconfig {} 0 up'.format(intf)
                    ]
            for cmd in cmds:
                os.system(cmd)

    '''
    @method: restore_interface_config
    @Description:
    @params:
    returns NA
    '''
    #open up access to compute node
    @classmethod
    def restore_interface_config(cls, intf, vcpe = None):
        if intf in cls.interface_map:
            ip = cls.interface_map[intf]['ip']
            gw = cls.interface_map[intf]['gw']
            del cls.interface_map[intf]
            cmds = []
            if vcpe is not None:
                shutil.copy('/etc/resolv.conf.orig', '/etc/resolv.conf')
                #bounce the vcpes to clear default gw
                cmds.append('ifconfig {} 0 down'.format(vcpe))
                cmds.append('ifconfig {} 0 up'.format(vcpe))
            cmds.append('ifconfig {} {} up'.format(intf, ip))
            if gw and gw != '0.0.0.0':
                cmds.append('route add default gw {} dev {}'.format(gw, intf))
            for cmd in cmds:
                os.system(cmd)

    '''
    @method: vcpe_get_dhcp
    @Description: Get DHCP from vcpe dhcp interface.
    @params:
    returns vcpe ip
    '''
    @classmethod
    def vcpe_get_dhcp(cls, vcpe, mgmt = 'eth0'):
        '''Get DHCP from vcpe dhcp interface.'''
        '''We have to also save the management interface config for restoration'''
        cls.save_interface_config(mgmt)
        getstatusoutput('pkill -9 dhclient')
        st, output = getstatusoutput('dhclient -q {}'.format(vcpe))
        getstatusoutput('pkill -9 dhclient')
        vcpe_ip = get_ip(vcpe)
        if vcpe_ip is None:
            cls.restore_interface_config(mgmt)
            return None
        if output:
            #workaround for docker container apparmor that prevents moving dhclient resolv.conf
            start = output.find('/etc/resolv.conf')
            if start >= 0:
                end = output.find("'", start)
                dns_file = output[start:end]
                if os.access(dns_file, os.F_OK):
                    shutil.copy(dns_file, '/etc/resolv.conf')

        default_gw, default_gw_device = get_default_gw()
        if default_gw and default_gw_device == vcpe:
            return vcpe_ip
        cls.restore_interface_config(mgmt, vcpe = vcpe)
        return None

class VSGWrapper(object):

    def __init__(self, vsg):
        self.vsg = vsg
        self.name = self.vsg.name
        self.compute_node = self.get_compute_node()
        self.ip = self.get_ip()

    '''
    @method: get_compute_node
    @Description:
    @params:
    returns compute node name
    '''
    def get_compute_node(self):
        return self.vsg._info['OS-EXT-SRV-ATTR:hypervisor_hostname']

    '''
    @method: get_ip
    @Description:
    @params:
    returns ip of network
    '''
    def get_ip(self):
        if 'management' in self.vsg.networks:
            ips = self.vsg.networks['management']
            if len(ips) > 0:
                return ips[0]
        return None

    '''
    @method: run_cmd_compute
    @Description:
    @params:
    returns Status & output
    '''
    def run_cmd_compute(self, cmd, timeout = 5):
        ssh_agent = SSHTestAgent(self.compute_node)
        st, output = ssh_agent.run_cmd(cmd, timeout = timeout)
        if st == True and output:
            output = output.strip()
        else:
            output = None

        return st, output

    '''
    @method: run_cmd
    @Description:
    @params:
    returns status & output
    '''
    def run_cmd(self, cmd, timeout = 5, mgmt = 'eth0'):
        last_gw = VSGAccess.open_mgmt(mgmt)
        ssh_agent = SSHTestAgent(self.compute_node)
        ssh_cmd = 'ssh {} {}'.format(self.ip, cmd)
        st, output = ssh_agent.run_cmd(ssh_cmd, timeout = timeout)
        if st == True and output:
            output = output.strip()
        else:
            output = None
        VSGAccess.close_mgmt(last_gw, mgmt)
        return st, output

    '''
    @method: get_health
    @Description:
    @params:
    returns Status
    '''
    def get_health(self):
        if self.ip is None:
            return True
        cmd = 'ping -c 1 {}'.format(self.ip)
        log.info('Pinging VSG %s at IP %s' %(self.name, self.ip))
        st, _ = self.run_cmd_compute(cmd)
        log.info('VSG %s at IP %s is %s' %(self.name, self.ip, 'reachable' if st == True else 'unreachable'))
        return st

    '''
    @method: check_access
    @Description: validates access
    @params:
    returns Status
    '''
    def check_access(self):
        if self.ip is None:
            return True
        ssh_agent = SSHTestAgent(self.compute_node)
        st, _ = ssh_agent.run_cmd('ls', timeout=10)
        if st == False:
            log.error('Compute node at %s is not accessible' %(self.compute_node))
            return st
        log.info('Checking if VSG at %s is accessible from compute node %s' %(self.ip, self.compute_node))
        st, _ = ssh_agent.run_cmd('ssh {} ls'.format(self.ip), timeout=30)
        if st == True:
            log.info('OK')
        return st
