# 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 Local Modules
from marvin.codes import FAILED, KVM, PASS, XEN_SERVER, RUNNING
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import random_gen, cleanup_resources, validateList, is_snapshot_on_nfs, isAlmostEqual
from marvin.lib.base import (Account,
                             ServiceOffering,
                             VirtualMachine,
                             VmSnapshot)
from marvin.lib.common import (get_zone,
                               get_domain,
                               get_suitable_test_template,
                               list_snapshots,
                               list_virtual_machines)
import time


class TestVmSnapshot(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        testClient = super(TestVmSnapshot, cls).getClsTestClient()
        cls.apiclient = testClient.getApiClient()
        cls._cleanup = []
        cls.unsupportedHypervisor = False
        cls.hypervisor = testClient.getHypervisorInfo()
        if cls.hypervisor.lower() in ("hyperv", "lxc"):
            cls.unsupportedHypervisor = True
            return

        cls.services = testClient.getParsedTestDataConfig()
        # Get Zone, Domain and templates
        cls.domain = get_domain(cls.apiclient)
        cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests())

        template = get_suitable_test_template(
            cls.apiclient,
            cls.zone.id,
            cls.services["ostype"],
            cls.hypervisor
        )
        if template == FAILED:
            assert False, "get_suitable_test_template() failed to return template\
                    with description %s" % cls.services["ostype"]

        cls.services["domainid"] = cls.domain.id
        cls.services["small"]["zoneid"] = cls.zone.id
        cls.services["templates"]["ostypeid"] = template.ostypeid
        cls.services["zoneid"] = cls.zone.id

        # Create VMs, NAT Rules etc
        cls.account = Account.create(
            cls.apiclient,
            cls.services["account"],
            domainid=cls.domain.id
        )
        cls._cleanup.append(cls.account)

        cls.service_offering = ServiceOffering.create(
            cls.apiclient,
            cls.services["service_offerings"]["tiny"]
        )
        cls._cleanup.append(cls.service_offering)
        cls.virtual_machine = VirtualMachine.create(
            cls.apiclient,
            cls.services["small"],
            templateid=template.id,
            accountid=cls.account.name,
            domainid=cls.account.domainid,
            serviceofferingid=cls.service_offering.id,
            mode=cls.zone.networktype
        )
        cls.random_data_0 = random_gen(size=100)
        cls.test_dir = "$HOME"
        cls.random_data = "random.data"
        return

    @classmethod
    def tearDownClass(cls):
        try:
            # Cleanup resources used
            cleanup_resources(cls.apiclient, cls._cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()

        if self.unsupportedHypervisor:
            self.skipTest("Skipping test because unsupported hypervisor\
                    %s" % self.hypervisor)
        return

    def tearDown(self):
        return

    @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true")
    def test_01_create_vm_snapshots(self):
        """Test to create VM snapshots
        """

        try:
            # Login to VM and write data to file system
            ssh_client = self.virtual_machine.get_ssh_client()

            cmds = [
                "echo %s > %s/%s" %
                (self.random_data_0, self.test_dir, self.random_data),
                "cat %s/%s" %
                (self.test_dir, self.random_data)]

            for c in cmds:
                self.debug(c)
                result = ssh_client.execute(c)
                self.debug(result)

        except Exception:
            self.fail("SSH failed for Virtual machine: %s" %
                      self.virtual_machine.ipaddress)
        self.assertEqual(
            self.random_data_0,
            result[0],
            "Check the random data has be write into temp file!"
        )

        time.sleep(self.services["sleep"])

        #KVM VM Snapshot needs to set snapshot with memory
        MemorySnapshot = False
        if self.hypervisor.lower() in (KVM.lower()):
           MemorySnapshot = True

        vm_snapshot = VmSnapshot.create(
            self.apiclient,
            self.virtual_machine.id,
            MemorySnapshot,
            "TestSnapshot",
            "Display Text"
        )
        self.assertEqual(
            vm_snapshot.state,
            "Ready",
            "Check the snapshot of vm is ready!"
        )

        return

    @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true")
    def test_02_revert_vm_snapshots(self):
        """Test to revert VM snapshots
        """

        try:
            ssh_client = self.virtual_machine.get_ssh_client()

            cmds = [
                "rm -rf %s/%s" % (self.test_dir, self.random_data),
                "ls %s/%s" % (self.test_dir, self.random_data)
            ]

            for c in cmds:
                self.debug(c)
                result = ssh_client.execute(c)
                self.debug(result)

        except Exception:
            self.fail("SSH failed for Virtual machine: %s" %
                      self.virtual_machine.ipaddress)

        if str(result[0]).index("No such file or directory") == -1:
            self.fail("Check the random data has be delete from temp file!")

        time.sleep(self.services["sleep"])

        list_snapshot_response = VmSnapshot.list(
            self.apiclient,
            vmid=self.virtual_machine.id,
            listall=True)

        self.assertEqual(
            isinstance(list_snapshot_response, list),
            True,
            "Check list response returns a valid list"
        )
        self.assertNotEqual(
            list_snapshot_response,
            None,
            "Check if snapshot exists in ListSnapshot"
        )

        self.assertEqual(
            list_snapshot_response[0].state,
            "Ready",
            "Check the snapshot of vm is ready!"
        )

        #We don't need to stop the VM when taking a VM Snapshot on KVM
        if self.hypervisor.lower() in (KVM.lower()):
           pass
        else:
           self.virtual_machine.stop(self.apiclient)

        VmSnapshot.revertToSnapshot(
            self.apiclient,
            list_snapshot_response[0].id)

        #We don't need to start the VM when taking a VM Snapshot on KVM
        if self.hypervisor.lower() in (KVM.lower()):
           pass
        else:
           self.virtual_machine.start(self.apiclient)

        try:
            ssh_client = self.virtual_machine.get_ssh_client(reconnect=True)

            cmds = [
                "cat %s/%s" % (self.test_dir, self.random_data)
            ]

            for c in cmds:
                self.debug(c)
                result = ssh_client.execute(c)
                self.debug(result)

        except Exception:
            self.fail("SSH failed for Virtual machine: %s" %
                      self.virtual_machine.ipaddress)

        self.assertEqual(
            self.random_data_0,
            result[0],
            "Check the random data is equal with the ramdom file!"
        )

    @attr(tags=["advanced", "advancedns", "smoke"], required_hardware="true")
    def test_03_delete_vm_snapshots(self):
        """Test to delete vm snapshots
        """

        list_snapshot_response = VmSnapshot.list(
            self.apiclient,
            vmid=self.virtual_machine.id,
            listall=True)

        self.assertEqual(
            isinstance(list_snapshot_response, list),
            True,
            "Check list response returns a valid list"
        )
        self.assertNotEqual(
            list_snapshot_response,
            None,
            "Check if snapshot exists in ListSnapshot"
        )
        VmSnapshot.deleteVMSnapshot(
            self.apiclient,
            list_snapshot_response[0].id)

        time.sleep(self.services["sleep"] * 3)

        list_snapshot_response = VmSnapshot.list(
            self.apiclient,
            vmid=self.virtual_machine.id,
            listall=True)

        self.assertEqual(
            list_snapshot_response,
            None,
            "Check list vm snapshot has be deleted"
        )

class Utils:

    def __init__(self):
        self.added_service_offerings = {
            'testOffering1' : {'displaytext': 'Test Offering 1', 'cpuspeed': 600, 'cpunumber': 1, 'name': 'Test Offering 1', 'memory': 256},
            'testOffering2' : {'displaytext': 'Test Offering 2', 'cpuspeed': 600, 'cpunumber': 2, 'name': 'Test Offering 2', 'memory': 512}
        }

class TestChangeServiceOfferingForVmWithSnapshots(cloudstackTestCase):

    @classmethod
    def setUpClass(cls):
        try:
            cls._cleanup = []
            cls.testClient = super(TestChangeServiceOfferingForVmWithSnapshots, cls).getClsTestClient()
            cls.api_client = cls.testClient.getApiClient()
            cls.services = cls.testClient.getParsedTestDataConfig()
            cls.hypervisor = cls.testClient.getHypervisorInfo()
            cls.unsupportedHypervisor = False
            if cls.hypervisor.lower() in (KVM.lower(), "hyperv", "lxc"):
                cls.unsupportedHypervisor = True
                return

            cls.domain = get_domain(cls.api_client)
            cls.zone = get_zone(
                cls.api_client,
                cls.testClient.getZoneForTests()
            )
            cls.services["small"]["zoneid"] = cls.zone.id

            cls.template = get_suitable_test_template(
                cls.api_client,
                cls.zone.id,
                cls.services["ostype"],
                cls.hypervisor
            )
            if cls.template == FAILED:
                assert False, "get_suitable_test_template() failed to return template\
                    with description %s" % cls.services["ostype"]

            test_offerings = Utils().added_service_offerings
            for offering in test_offerings:
                cls.services["service_offerings"][offering] = test_offerings[offering]

            # Create 2 different service offerings
            cls.service_offering_1 = ServiceOffering.create(
                cls.api_client,
                cls.services["service_offerings"]["testOffering1"]
            )
            cls._cleanup.append(cls.service_offering_1)

            cls.service_offering_2 = ServiceOffering.create(
                cls.api_client,
                cls.services["service_offerings"]["testOffering2"]
            )
            cls._cleanup.append(cls.service_offering_2)

            cls.account = Account.create(
                cls.api_client,
                cls.services["account"],
                domainid=cls.domain.id
            )
            cls._cleanup.append(cls.account)

        except Exception as e:
            cls.tearDownClass()
            raise Exception("Warning: Exception in setup : %s" % e)
        return

    def setUp(self):
        self.apiclient = self.testClient.getApiClient()
        self.dbclient = self.testClient.getDbConnection()
        self.cleanup = []

        if self.unsupportedHypervisor:
            self.skipTest("Skipping test because unsupported hypervisor\
                    %s" % self.hypervisor)

    def tearDown(self):
        # Clean up, terminate the created resources
        cleanup_resources(self.apiclient, self.cleanup)
        return

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

        return

    def wait_vm_start(self, apiclient, vmid, timeout, sleep):
        while timeout:
            vms = VirtualMachine.list(apiclient, id=vmid)
            vm_list_validation_result = validateList(vms)
            if vm_list_validation_result[0] == PASS and vm_list_validation_result[1].state == RUNNING:
                return timeout
            time.sleep(sleep)
            timeout = timeout - 1

        return timeout

    def checkCPUAndMemory(self, ssh, service_offering):
        cpuinfo = ssh.execute("cat /proc/cpuinfo")
        cpu_cnt = len([i for i in cpuinfo if "processor" in i])
        # 'cpu MHz\t\t: 2660.499'
        cpu_speed = [i for i in cpuinfo if "cpu MHz" in i][0].split()[3]
        meminfo = ssh.execute("cat /proc/meminfo")
        # MemTotal:        1017464 kB
        total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1]

        self.debug(
            "CPU count: %s, CPU Speed: %s, Mem Info: %s" % (cpu_cnt, cpu_speed, total_mem)
        )
        self.assertAlmostEqual(
            int(cpu_cnt),
            service_offering.cpunumber,
            "Check CPU Count for service offering"
        )

        range = 40
        if self.hypervisor.lower() == "hyperv":
            range = 200
        self.assertTrue(
            isAlmostEqual(int(int(total_mem) / 1024),
                          int(service_offering.memory),
                          range=range
            ),
            "Check Memory(kb) for service offering"
        )

    @attr(tags=["advanced", "smoke"], required_hardware="true")
    def test_change_service_offering_for_vm_with_snapshots(self):
        """Test to change service offering for instances with vm snapshots
        """

        # 1) Create Virtual Machine using service offering 1
        self.debug("Creating VM using Service Offering 1")
        virtual_machine = VirtualMachine.create(
            self.apiclient,
            self.services["small"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            templateid=self.template.id,
            zoneid=self.zone.id,
            hypervisor=self.hypervisor,
            mode=self.zone.networktype,
            serviceofferingid=self.service_offering_1.id
        )

        # Verify Service OFfering 1 CPU cores and memory
        try:
            ssh_client = virtual_machine.get_ssh_client(reconnect=True)
            self.checkCPUAndMemory(ssh_client, self.service_offering_1)
        except Exception as e:
            self.fail("SSH failed for virtual machine: %s - %s" % (virtual_machine.ipaddress, e))

        # 2) Take VM Snapshot
        self.debug("Taking VM Snapshot for VM - ID: %s" % virtual_machine.id)
        vm_snapshot = VmSnapshot.create(
            self.apiclient,
            virtual_machine.id,
        )

        # 3) Stop Virtual Machine
        self.debug("Stopping VM - ID: %s" % virtual_machine.id)
        try:
            virtual_machine.stop(self.apiclient)

            timeout = self.services["timeout"]

            while True:
                time.sleep(self.services["sleep"])

                # Ensure that VM is in stopped state
                list_vm_response = list_virtual_machines(
                    self.apiclient,
                    id=virtual_machine.id
                )

                if isinstance(list_vm_response, list):
                    vm = list_vm_response[0]
                    if vm.state == 'Stopped':
                        self.debug("VM state: %s" % vm.state)
                        break

                if timeout == 0:
                    raise Exception(
                        "Failed to stop VM (ID: %s) in change service offering" % vm.id)

                timeout = timeout - 1
        except Exception as e:
            self.fail("Failed to stop VM: %s" % e)

        # 4) Change service offering for VM with snapshots from Service Offering 1 to Service Offering 2
        self.debug("Changing service offering from Service Offering 1 to Service Offering 2 for VM - ID: %s" % virtual_machine.id)
        virtual_machine.change_service_offering(self.apiclient, self.service_offering_2.id)

        # 5) Start VM
        self.debug("Starting VM - ID: %s" % virtual_machine.id)
        try:
            virtual_machine.start(self.apiclient)
        except Exception as e:
            self.fail("Failed to start virtual machine: %s, %s" % (virtual_machine.name, e))

        # Wait for vm to start
        timeout = self.wait_vm_start(self.apiclient, virtual_machine.id, self.services["timeout"],
                            self.services["sleep"])
        if timeout == 0:
            self.fail("The virtual machine %s failed to start even after %s minutes"
                   % (virtual_machine.name, self.services["timeout"]))

        list_vm_response = list_virtual_machines(
            self.apiclient,
            id=virtual_machine.id
        )
        self.assertEqual(
            isinstance(list_vm_response, list),
            True,
            "Check list response returns a valid list"
        )
        self.assertNotEqual(
            len(list_vm_response),
            0,
            "Check VM available in List Virtual Machines"
        )
        self.assertEqual(
            list_vm_response[0].state,
            "Running",
            "Check virtual machine is in running state"
        )
        self.assertEqual(
            list_vm_response[0].id,
            virtual_machine.id,
            "Check virtual machine id"
        )

        # 6) Verify service offering has changed
        try:
            ssh_client_2 = virtual_machine.get_ssh_client(reconnect=True)
            self.checkCPUAndMemory(ssh_client_2, self.service_offering_2)
        except Exception as e:
            self.fail("SSH failed for virtual machine: %s - %s" % (virtual_machine.ipaddress, e))

        # 7) Stop Virtual Machine
        self.debug("Stopping VM - ID: %s" % virtual_machine.id)
        try:
            virtual_machine.stop(self.apiclient)
        except Exception as e:
            self.fail("Failed to stop VM: %s" % e)

        time.sleep(30)
        # 8) Revert to VM Snapshot
        self.debug("Revert to vm snapshot: %s" % vm_snapshot.id)
        try:
            VmSnapshot.revertToSnapshot(
                self.apiclient,
                vm_snapshot.id
            )
        except Exception as e:
            self.fail("Failed to revert to VM Snapshot: %s - %s" % (vm_snapshot.id, e))

        # 9) Start VM
        self.debug("Starting VM - ID: %s" % virtual_machine.id)
        try:
            virtual_machine.start(self.apiclient)
        except Exception as e:
            self.fail("Failed to start virtual machine: %s, %s" % (virtual_machine.name, e))

        # 10) Verify service offering has changed to Service Offering 1 (from VM Snapshot)
        try:
            ssh_client_3 = virtual_machine.get_ssh_client(reconnect=True)
            self.checkCPUAndMemory(ssh_client_3, self.service_offering_1)
        except Exception as e:
            self.fail("SSH failed for virtual machine: %s - %s" % (virtual_machine.ipaddress, e))

        return
