# 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.
""" Tests for Nested Virtualization
"""
#Import Local Modules
from marvin.codes import FAILED
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import (cleanup_resources,
                              get_hypervisor_type,
                              get_process_status)
from marvin.lib.base import (Account,
                             ServiceOffering,
                             NetworkOffering,
                             Configurations,
                             VirtualMachine,
                             Network)
from marvin.lib.common import (get_zone,
                               get_domain,
                               get_test_template)
from nose.plugins.attrib import attr
from marvin.sshClient import SshClient
import logging

class TestNestedVirtualization(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        testClient = super(TestNestedVirtualization, cls).getClsTestClient()
        cls.apiclient = testClient.getApiClient()
        cls.services = testClient.getParsedTestDataConfig()

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

        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())
        cls.hypervisor = get_hypervisor_type(cls.apiclient)
        cls.services['mode'] = cls.zone.networktype
        cls.services["isolated_network"]["zoneid"] = cls.zone.id
        cls.domain = get_domain(cls.apiclient)
        cls.service_offering = ServiceOffering.create(
            cls.apiclient,
            cls.services["service_offerings"]["tiny"]
        )
        cls.account = Account.create(cls.apiclient, services=cls.services["account"])
        cls.template = get_test_template(
            cls.apiclient,
            cls.zone.id,
            cls.hypervisor
        )

        cls.isolated_network_offering = NetworkOffering.create(
                                                cls.apiclient,
                                                cls.services["isolated_network_offering"])
        # Enable Isolated Network offering
        cls.isolated_network_offering.update(cls.apiclient, state='Enabled')

        if cls.template == FAILED:
            assert False, "get_test_template() failed to return template"

        cls.services["small"]["zoneid"] = cls.zone.id
        cls.services["small"]["template"] = cls.template.id

        cls.cleanup = [cls.account]

    @attr(tags=["advanced"], required_hardware="true")
    def test_nested_virtualization_vmware(self):
        """Test nested virtualization on Vmware hypervisor"""
        if self.hypervisor.lower() not in ["vmware"]:
             self.skipTest("Skipping test because suitable hypervisor/host not present")

        # 1) Update nested virtualization configurations, if needed
        configs = Configurations.list(self.apiclient, name="vmware.nested.virtualization")
        rollback_nv = False
        rollback_nv_per_vm = False
        for conf in configs:
            if (conf.name == "vmware.nested.virtualization" and conf.value == "false"):
                config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization", "true")
                self.logger.debug("Updated global setting vmware.nested.virtualization to true")
                rollback_nv = True
            elif (conf.name == "vmware.nested.virtualization.perVM" and conf.value == "false"):
                config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization.perVM", "true")
                self.logger.debug("Updated global setting vmware.nested.virtualization.perVM to true")
                rollback_nv_per_vm = True

        try:
            # 2) Deploy a vm
            virtual_machine = VirtualMachine.create(
                self.apiclient,
                self.services["small"],
                accountid=self.account.name,
                domainid=self.account.domainid,
                serviceofferingid=self.service_offering.id,
                mode=self.services['mode']
            )
            self.assertTrue(virtual_machine is not None, "VM failed to deploy")
            self.assertTrue(virtual_machine.state == 'Running', "VM is not running")
            self.logger.debug("Deployed vm: %s" % virtual_machine.id)

            isolated_network = Network.create(
                self.apiclient,
                self.services["isolated_network"],
                self.account.name,
                self.account.domainid,
                networkofferingid=self.isolated_network_offering.id)

            virtual_machine.stop(self.apiclient)
            virtual_machine.add_nic(self.apiclient, isolated_network.id)
            virtual_machine.start(self.apiclient)

            # 3) SSH into vm
            ssh_client = virtual_machine.get_ssh_client()

            if ssh_client:
                # run ping test
                result = ssh_client.execute("cat /proc/cpuinfo | grep flags")
                self.logger.debug(result)
            else:
                self.fail("Failed to setup ssh connection to %s" % virtual_machine.public_ip)

            # 4) Revert configurations, if needed
            self.rollback_nested_configurations(rollback_nv, rollback_nv_per_vm)

            #5) Check for CPU flags: vmx for Intel and svm for AMD indicates nested virtualization is enabled
            self.assertTrue(result is not None, "Empty result for CPU flags")
            res = str(result)
            self.assertTrue('vmx' in res or 'svm' in res)
        except Exception as e:
            self.debug('Error=%s' % e)
            self.rollback_nested_configurations(rollback_nv, rollback_nv_per_vm)
            raise e

    def rollback_nested_configurations(self, rollback_nv, rollback_nv_per_vm):
        if rollback_nv:
            config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization", "false")
            self.logger.debug("Reverted global setting vmware.nested.virtualization back to false")
        if rollback_nv_per_vm:
            config_update = Configurations.update(self.apiclient, "vmware.nested.virtualization.perVM", "false")
            self.logger.debug("Reverted global setting vmware.nested.virtualization.perVM back to false")

    @classmethod
    def tearDownClass(cls):
        try:
            cleanup_resources(cls.apiclient, cls.cleanup)
        except Exception as e:
            raise Exception("Cleanup failed with %s" % e)
