#!/usr/bin/env python
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

import requests
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import cleanup_resources
from marvin.lib.base import (
    PhysicalNetwork,
    NetworkOffering,
    NiciraNvp,
    ServiceOffering,
    NATRule,
    PublicIPAddress,
    Network,
    VirtualMachine
)
from marvin.lib.common import (
    get_domain,
    get_zone,
    get_template,
    list_routers,
    list_hosts,
    findSuitableHostForMigration,
    migrate_router
)
from nose.plugins.attrib import attr
from marvin.codes import (FAILED, PASS)
import time
import logging

class TestNiciraContoller(cloudstackTestCase):

    '''
    Example of marvin config with NSX specific values
        "niciraNvp": {
            "hosts": [ "nsxcon1.cloud.lan", "nsxcon2.cloud.lan", "nsxcon3.cloud.lan" ],
            "shared_network": {
                "l2gatewayserviceuuid": "3595ca67-959f-47d4-8f01-0492a8e96205",
                "iprange" : {
                    "startip": "192.168.26.2",
                    "endip": "192.168.26.20",
                    "netmask": "255.255.255.0",
                    "gateway": "192.168.26.1",
                    "vlan": "50",
                    "vlan_uuid": "5cdaa49d-06cd-488a-9ca4-e954a3181f54"
                }
            }
        }
    '''
    @classmethod
    def setUpClass(cls):
        test_case = super(TestNiciraContoller, cls)

        test_client    = test_case.getClsTestClient()
        cls.config     = test_case.getClsConfig()
        cls.api_client = test_client.getApiClient()

        cls.physical_networks = cls.config.zones[0].physical_networks
        cls.nicira_hosts      = cls.config.niciraNvp.hosts

        cls.nicira_shared_network_iprange = cls.config.niciraNvp.shared_network.iprange
        cls.l2gatewayserviceuuid          = cls.config.niciraNvp.shared_network.l2gatewayserviceuuid

        cls.physical_network_id = cls.get_nicira_enabled_physical_network_id(cls.physical_networks)

        cls.network_offerring_services = [
            {
                'name':              'NiciraEnabledIsolatedNetwork',
                'displaytext':       'NiciraEnabledIsolatedNetwork',
                'guestiptype':       'Isolated',
                'supportedservices': 'SourceNat,Dhcp,Dns,Firewall,PortForwarding,Connectivity',
                'traffictype':       'GUEST',
                'availability':      'Optional',
                'serviceProviderList': {
                        'SourceNat':      'VirtualRouter',
                        'Dhcp':           'VirtualRouter',
                        'Dns':            'VirtualRouter',
                        'Firewall':       'VirtualRouter',
                        'PortForwarding': 'VirtualRouter',
                        'Connectivity':   'NiciraNvp'
                }
            },
            {
                'name':              'NiciraEnabledSharedNetwork',
                'displaytext':       'NiciraEnabledSharedNetwork',
                'guestiptype':       'Shared',
                'supportedservices': 'Connectivity,Dhcp,UserData,SourceNat,StaticNat,Lb,PortForwarding',
                'traffictype':       'GUEST',
                'availability':      'Optional',
                'specifyVlan':        'true',
                'specifyIpRanges':    'true',
                'serviceProviderList': {
                        'Connectivity':   'NiciraNvp',
                        'Dhcp':           'VirtualRouter',
                        'SourceNat':      'VirtualRouter',
                        'StaticNat':      'VirtualRouter',
                        'Lb':             'VirtualRouter',
                        'PortForwarding': 'VirtualRouter',
                        'UserData':       'VirtualRouter'
                }
            }
        ]

        cls.network_offering_isolated = NetworkOffering.create(cls.api_client, cls.network_offerring_services[0])
        cls.network_offering_isolated.update(cls.api_client, state='Enabled')

        cls.network_offering_shared = NetworkOffering.create(cls.api_client, cls.network_offerring_services[1])
        cls.network_offering_shared.update(cls.api_client, state='Enabled')

        cls.nicira_credentials = {
            'username': 'admin',
            'password': 'admin'
        }

        cls.nicira_primary_controller = cls.determine_primary_controller(
            cls.nicira_hosts,
            cls.nicira_credentials
        )

        cls.transport_zone_uuid = cls.get_transport_zone_from_controller(
            cls.nicira_primary_controller,
            cls.nicira_credentials
        )

        cls.admin_account   = 'admin'
        cls.admin_domain    = get_domain(cls.api_client)

        cls.zone   = get_zone(cls.api_client, test_client.getZoneForTests())

        template = get_template(
            cls.api_client,
            cls.zone.id
        )
        if template == FAILED:
            raise Exception("get_template() failed to return template with description %s" % cls.services['ostype'])

        cls.vm_services = {
            'mode': cls.zone.networktype,
            'small': {
                'zoneid':      cls.zone.id,
                'template':    template.id,
                'displayname': 'testserver',
                'username':    cls.config.zones[0].pods[0].clusters[0].hosts[0].username,
                'password':    cls.config.zones[0].pods[0].clusters[0].hosts[0].password,
                'ssh_port':    22,
                'hypervisor':  cls.config.zones[0].pods[0].clusters[0].hypervisor,
                'privateport': 22,
                'publicport':  22,
                'protocol':    'TCP',
            },
            'service_offerings': {
                'tiny': {
                    'name':        'Tiny Instance',
                    'displaytext': 'Tiny Instance',
                    'cpunumber':   1,
                    'cpuspeed':    100,
                    'memory':      64,
                    'offerha':     'true'
                }
            }
        }

        if cls.zone.localstorageenabled == True:
            cls.vm_services['service_offerings']['tiny']['storagetype'] = 'local'

        cls.service_offering = ServiceOffering.create(
            cls.api_client,
            cls.vm_services['service_offerings']['tiny']
        )

        cls.cleanup = [
            cls.network_offering_isolated,
            cls.service_offering,
            cls.network_offering_shared
        ]

        cls.logger = logging.getLogger('TestNiciraContoller')
        cls.stream_handler = logging.StreamHandler()
        cls.logger.setLevel(logging.DEBUG)
        cls.logger.addHandler(cls.stream_handler)


    @classmethod
    def tearDownClass(cls):
        try:
            cleanup_resources(cls.api_client, reversed(cls.cleanup))
        except Exception as e:
            raise Exception("Warning: Exception during class cleanup : %s" % e)

    def setUp(self):
        self.test_cleanup = []

    def tearDown(self):
        try:
            cleanup_resources(self.api_client, reversed(self.test_cleanup))
        except Exception as e:
            raise Exception("Warning: Exception during test cleanup : %s" % e)


    @classmethod
    def determine_primary_controller(cls, hosts, credentials):
        for host in hosts:
            r1 = requests.post("https://%s/ws.v1/login" % host, credentials, verify=False)
            r2 = requests.get("https://%s/ws.v1/control-cluster/status" % host, verify=False, cookies=r1.cookies)
            status_code = r2.status_code
            if status_code == 401:
                continue
            elif status_code == 200:
                return host
        raise Exception("None of the supplied hosts (%s) is a Nicira controller" % hosts)


    @classmethod
    def get_transport_zone_from_controller(cls, controller_host, credentials):
        r1 = requests.post("https://%s/ws.v1/login" % controller_host, credentials, verify=False)
        r2 = requests.get("https://%s/ws.v1/transport-zone" % controller_host, verify=False, cookies=r1.cookies)
        status_code = r2.status_code
        if status_code == 200:
            list_transport_zone_response = r2.json()
            result_count = list_transport_zone_response['result_count']
            if result_count == 0:
                raise Exception('Nicira controller did not return any Transport Zones')
            elif result_count > 1:
                cls.logger.debug("Nicira controller returned %s Transport Zones, picking first one" % resultCount)
            transport_zone_api_url = list_transport_zone_response['results'][0]['_href']
            r3 = requests.get(
                "https://%s%s" % (controller_host, transport_zone_api_url),
                verify=False,
                cookies=r1.cookies
            )
            return r3.json()['uuid']
        else:
            raise Exception("Unexpected response from Nicira controller. Status code = %s, content = %s" % status_code)


    @classmethod
    def get_nicira_enabled_physical_network_id(cls, physical_networks):
        nicira_physical_network_name = None
        for physical_network in physical_networks:
            for provider in physical_network.providers:
                if provider.name == 'NiciraNvp':
                    nicira_physical_network_name = physical_network.name
        if nicira_physical_network_name is None:
            raise Exception('Did not find a Nicira enabled physical network in configuration')
        return PhysicalNetwork.list(cls.api_client, name=nicira_physical_network_name)[0].id


    def determine_secondary_conroller(self, hosts, primary_controller):
        secondary = [ s for s in hosts if s != primary_controller ]
        if len(secondary) > 0:
            return secondary[0]
        else:
            raise Exception("None of the supplied hosts (%s) is a Nicira secondary" % hosts)


    def add_nicira_device(self, hostname, l2gatewayserviceuuid=None):
        nicira_device = NiciraNvp.add(
            self.api_client,
            None,
            self.physical_network_id,
            hostname=hostname,
            username=self.nicira_credentials['username'],
            password=self.nicira_credentials['password'],
            transportzoneuuid=self.transport_zone_uuid,
            l2gatewayserviceuuid=l2gatewayserviceuuid
        )
        self.test_cleanup.append(nicira_device)

    def create_guest_isolated_network(self):
        network_services = {
            'name'            : 'nicira_enabled_network_isolated',
            'displaytext'     : 'nicira_enabled_network_isolated',
            'zoneid'          : self.zone.id,
            'networkoffering' : self.network_offering_isolated.id
        }
        network = Network.create(
            self.api_client,
            network_services,
            accountid=self.admin_account,
            domainid=self.admin_domain.id
        )
        self.test_cleanup.append(network)
        return network

    def create_guest_shared_network_numerical_vlanid(self):
        network_services = {
            'name'            : 'nicira_enabled_network_shared',
            'displaytext'     : 'nicira_enabled_network_shared',
            'zoneid'          : self.zone.id,
            'networkoffering' : self.network_offering_shared.id,
            'startip'         : self.nicira_shared_network_iprange.startip,
            'endip'           : self.nicira_shared_network_iprange.endip,
            'netmask'         : self.nicira_shared_network_iprange.netmask,
            'gateway'         : self.nicira_shared_network_iprange.gateway,
            'vlan'            : self.nicira_shared_network_iprange.vlan
        }
        network = Network.create(
            self.api_client,
            network_services,
            accountid=self.admin_account,
            domainid=self.admin_domain.id
        )
        self.test_cleanup.append(network)
        return network

    def create_guest_shared_network_uuid_vlanid(self):
        network_services = {
            'name'            : 'nicira_enabled_network_shared',
            'displaytext'     : 'nicira_enabled_network_shared',
            'zoneid'          : self.zone.id,
            'networkoffering' : self.network_offering_shared.id,
            'startip'         : self.nicira_shared_network_iprange.startip,
            'endip'           : self.nicira_shared_network_iprange.endip,
            'netmask'         : self.nicira_shared_network_iprange.netmask,
            'gateway'         : self.nicira_shared_network_iprange.gateway,
            'vlan'            : self.nicira_shared_network_iprange.vlan_uuid
        }
        network = Network.create(
            self.api_client,
            network_services,
            accountid=self.admin_account,
            domainid=self.admin_domain.id
        )
        self.test_cleanup.append(network)
        return network

    def create_guest_shared_network_services(self):
        network_services = {
            'name'            : 'nicira_enabled_network_shared',
            'displaytext'     : 'nicira_enabled_network_shared',
            'zoneid'          : self.zone.id,
            'networkoffering' : self.network_offering_shared.id,
            'startip'         : self.nicira_shared_network_iprange.startip,
            'endip'           : self.nicira_shared_network_iprange.endip,
            'netmask'         : self.nicira_shared_network_iprange.netmask,
            'gateway'         : self.nicira_shared_network_iprange.gateway
        }
        network = Network.create(
            self.api_client,
            network_services,
            accountid=self.admin_account,
            domainid=self.admin_domain.id,
        )
        self.test_cleanup.append(network)
        return network


    def create_virtual_machine(self, network):
        virtual_machine = VirtualMachine.create(
            self.api_client,
            self.vm_services['small'],
            accountid=self.admin_account,
            domainid=self.admin_domain.id,
            serviceofferingid=self.service_offering.id,
            networkids=[network.id],
            mode=self.vm_services['mode']
        )
        self.test_cleanup.append(virtual_machine)
        return virtual_machine

    def create_virtual_machine_shared_networks(self, network):
        virtual_machine = VirtualMachine.create(
            self.api_client,
            self.vm_services['small'],
            accountid=self.admin_account,
            domainid=self.admin_domain.id,
            serviceofferingid=self.service_offering.id,
            networkids=[network.id],
            mode='BASIC'
        )
        self.test_cleanup.append(virtual_machine)
        return virtual_machine


    def get_routers_for_network(self, network):
        return list_routers(
            self.api_client,
            accountid=self.admin_account,
            domainid=self.admin_domain.id,
            networkid=network.id
        )


    def get_hosts(self):
        return list_hosts(
            self.api_client,
            accountid=self.admin_account,
            domainid=self.admin_domain.id
        )


    def get_primary_router(self, routers):
        primary = [r for r in routers if r.redundantstate == 'PRIMARY']
        self.logger.debug("Found %s primary router(s): %s" % (primary.size(), primary))
        return primary[0]


    def distribute_vm_and_routers_by_hosts(self, virtual_machine, routers):
        if len(routers) > 1:
            router = self.get_router(routers)
            self.logger.debug("Primary Router VM is %s" % router)
        else:
            router = routers[0]

        if router.hostid == virtual_machine.hostid:
            self.logger.debug("Primary Router VM is on the same host as VM")
            host = findSuitableHostForMigration(self.api_client, router.id)
            if host is not None:
                migrate_router(self.api_client, router.id, host.id)
                self.logger.debug("Migrated Primary Router VM to host %s" % host.name)
            else:
                self.fail('No suitable host to migrate Primary Router VM to')
        else:
            self.logger.debug("Primary Router VM is not on the same host as VM: %s, %s" % (router.hostid, virtual_machine.hostid))


    def acquire_publicip(self, network):
        self.logger.debug("Associating public IP for network: %s" % network.name)
        public_ip = PublicIPAddress.create(
            self.api_client,
            accountid=self.admin_account,
            zoneid=self.zone.id,
            domainid=self.admin_domain.id,
            networkid=network.id
        )
        self.logger.debug("Associated %s with network %s" % (public_ip.ipaddress.ipaddress, network.id))
        self.test_cleanup.append(public_ip)
        return public_ip


    def create_natrule(self, vm, public_ip, network):
        self.logger.debug("Creating NAT rule in network for vm with public IP")
        nat_rule = NATRule.create(
            self.api_client,
            vm,
            self.vm_services['small'],
            ipaddressid=public_ip.ipaddress.id,
            openfirewall=True,
            networkid=network.id
        )
        self.test_cleanup.append(nat_rule)
        return nat_rule


    @attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
    def test_01_nicira_controller(self):
        self.add_nicira_device(self.nicira_primary_controller)

        network         = self.create_guest_isolated_network()
        virtual_machine = self.create_virtual_machine(network)

        list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
        self.logger.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)

        self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
        self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')

        vm_response = list_vm_response[0]
        self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
        self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')


    @attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
    def test_02_nicira_controller_redirect(self):
        """
            Nicira clusters will redirect clients (in this case ACS) to the primary node.
            This test assumes that a Nicira cluster is present and configured properly, and
            that it has at least two controller nodes. The test will check that ASC follows
            redirects by:
                - adding a Nicira Nvp device that points to one of the cluster's secondary controllers,
                - create a VM in a Nicira backed network
            If all is well, no matter what controller is specified (secondary or primary), the vm (and respective router VM)
            should be created without issues.
        """
        nicira_secondary = self.determine_secondary_conroller(self.nicira_hosts, self.nicira_primary_controller)
        self.logger.debug("Nicira secondary controller is: %s " % nicira_secondary)

        self.add_nicira_device(nicira_secondary)

        network         = self.create_guest_isolated_network()
        virtual_machine = self.create_virtual_machine(network)

        list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
        self.logger.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)

        self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
        self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')

        vm_response = list_vm_response[0]
        self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
        self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')


    @attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
    def test_03_nicira_tunnel_guest_network(self):
        self.add_nicira_device(self.nicira_primary_controller)
        network         = self.create_guest_isolated_network()
        virtual_machine = self.create_virtual_machine(network)
        public_ip       = self.acquire_publicip(network)
        nat_rule        = self.create_natrule(virtual_machine, public_ip, network)

        list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
        self.logger.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)

        self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
        self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')

        vm_response = list_vm_response[0]
        self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
        self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')

        routers = self.get_routers_for_network(network)

        self.distribute_vm_and_routers_by_hosts(virtual_machine, routers)

        ssh_command = 'ping -c 3 google.com'
        result = 'failed'
        try:
            self.logger.debug("SSH into VM: %s" % public_ip.ipaddress.ipaddress)
            ssh = virtual_machine.get_ssh_client(ipaddress=public_ip.ipaddress.ipaddress)
            self.logger.debug('Ping to google.com from VM')
            result = str(ssh.execute(ssh_command))
            self.logger.debug("SSH result: %s; COUNT is ==> %s" % (result, result.count("3 packets received")))
        except Exception as e:
            self.fail("SSH Access failed for %s: %s" % (virtual_machine.get_ip(), e))

        self.assertEqual(result.count('3 packets received'), 1, 'Ping to outside world from VM should be successful')

    @attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
    def test_04_nicira_shared_networks_numerical_vlanid(self):
        """
            Shared Networks Support
            CASE 1) Numerical VLAN_ID provided in network creation
        """
        self.debug("Starting test case 1 for Shared Networks")
        self.add_nicira_device(self.nicira_primary_controller, self.l2gatewayserviceuuid)
        network = self.create_guest_shared_network_numerical_vlanid()
        virtual_machine = self.create_virtual_machine_shared_networks(network)

        list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
        self.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)

        self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
        self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')

        vm_response = list_vm_response[0]
        self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
        self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')

    @attr(tags = ["advanced", "smoke", "nicira"], required_hardware="true")
    def test_05_nicira_shared_networks_lrouter_uuid_vlan_id(self):
        """
            Shared Networks Support
            CASE 2) Logical Router's UUID as VLAN_ID provided in network creation
        """
        self.debug("Starting test case 2 for Shared Networks")
        self.add_nicira_device(self.nicira_primary_controller, self.l2gatewayserviceuuid)
        network = self.create_guest_shared_network_uuid_vlanid()
        virtual_machine = self.create_virtual_machine_shared_networks(network)

        list_vm_response = VirtualMachine.list(self.api_client, id=virtual_machine.id)
        self.debug("Verify listVirtualMachines response for virtual machine: %s" % virtual_machine.id)

        self.assertEqual(isinstance(list_vm_response, list), True, 'Response did not return a valid list')
        self.assertNotEqual(len(list_vm_response), 0, 'List of VMs is empty')

        vm_response = list_vm_response[0]
        self.assertEqual(vm_response.id, virtual_machine.id, 'Virtual machine in response does not match request')
        self.assertEqual(vm_response.state, 'Running', 'VM is not in Running state')
