# 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.

""" P1 tests for dedicated Host high availability
"""
#Import Local Modules
from nose.plugins.attrib import attr
from marvin.cloudstackTestCase import cloudstackTestCase
import unittest
from marvin.cloudstackAPI import (migrateVirtualMachine,
                                  prepareHostForMaintenance,
                                  cancelHostMaintenance)
from marvin.lib.utils import cleanup_resources
from marvin.lib.base import (Account,
                             VirtualMachine,
                             ServiceOffering,
                             Cluster,
                             Host,
                             Configurations)
from marvin.lib.common import (get_zone,
                               get_domain,
                               get_template,
                               list_hosts,
                               list_virtual_machines,
                               list_service_offering)
import time


class Services:
    """ Dedicated host HA test cases """

    def __init__(self):
        self.services = {
            "account": {
                "email": "test@test.com",
                "firstname": "HA",
                "lastname": "HA",
                "username": "HA",
                # Random characters are appended for unique
                # username
                "password": "password",
            },
            "service_offering_with_ha": {
                "name": "Tiny Instance With HA Enabled",
                "displaytext": "Tiny Instance",
                "cpunumber": 1,
                "cpuspeed": 100, # in MHz
                "memory": 128, # In MBs
            },
            "service_offering_without_ha": {
                "name": "Tiny Instance Without HA",
                "displaytext": "Tiny Instance",
                "cpunumber": 1,
                "cpuspeed": 100, # in MHz
                "memory": 128, # In MBs
            },
            "virtual_machine": {
                "displayname": "VM",
                "username": "root",
                "password": "password",
                "ssh_port": 22,
                "hypervisor": 'XenServer',
                # Hypervisor type should be same as
                # hypervisor type of cluster
                "privateport": 22,
                "publicport": 22,
                "protocol": 'TCP',
            },
            "ostype": 'CentOS 5.3 (64-bit)',
            "timeout": 100,
        }


class TestHostHighAvailability(cloudstackTestCase):
    """ Dedicated host HA test cases """

    @classmethod
    def setUpClass(cls):
        cls.testClient = super(TestHostHighAvailability, cls).getClsTestClient()
        cls.api_client = cls.testClient.getApiClient()

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

        cls.template = get_template(
            cls.api_client,
            cls.zone.id,
            cls.services["ostype"]
        )
        cls.hypervisor = cls.testClient.getHypervisorInfo()
        if cls.hypervisor.lower() in ['lxc']:
            raise unittest.SkipTest("Template creation from root volume is not supported in LXC")


        clusterWithSufficientHosts = None
        clusters = Cluster.list(cls.api_client, zoneid=cls.zone.id)
        for cluster in clusters:
            cls.hosts = Host.list(cls.api_client, clusterid=cluster.id, type="Routing")
            if len(cls.hosts) >= 3:
                clusterWithSufficientHosts = cluster
                break

        if clusterWithSufficientHosts is None:
            raise unittest.SkipTest("No Cluster with 3 hosts found")

        configs = Configurations.list(
                                      cls.api_client,
                                      name='ha.tag'
                                      )

        assert isinstance(configs, list), "Config list not\
                retrieved for ha.tag"

        if configs[0].value != "ha":
            raise unittest.SkipTest("Please set the global config\
                    value for ha.tag as 'ha'")

        Host.update(cls.api_client, id=cls.hosts[2].id, hosttags="ha")

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

        cls.service_offering_with_ha = ServiceOffering.create(
            cls.api_client,
            cls.services["service_offering_with_ha"],
            offerha=True
        )

        cls.service_offering_without_ha = ServiceOffering.create(
            cls.api_client,
            cls.services["service_offering_without_ha"],
            offerha=False
        )

        cls._cleanup = [
            cls.service_offering_with_ha,
            cls.service_offering_without_ha,
        ]
        return

    @classmethod
    def tearDownClass(cls):
        try:
            # Remove the host from HA
            Host.update(cls.api_client, id=cls.hosts[2].id, hosttags="")
            #Cleanup resources used
            cleanup_resources(cls.api_client, 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()
        self.account = Account.create(
            self.apiclient,
            self.services["account"],
            admin=True,
            domainid=self.domain.id
        )
        self.cleanup = [self.account]
        return

    def tearDown(self):
        try:
            #Clean up, terminate the created accounts, domains etc
            cleanup_resources(self.apiclient, self.cleanup)
        except Exception as e:
            raise Exception("Warning: Exception during cleanup : %s" % e)
        return

    @attr(configuration="ha.tag")
    @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator"])
    def test_01_vm_deployment_with_compute_offering_with_ha_enabled(self):
        """ Test VM deployments (Create HA enabled Compute Service Offering and VM) """

        # Steps,
        #1. Create a Compute service offering with the 'Offer HA' option selected.
        #2. Create a Guest VM with the compute service offering created above.
        # Validations,
        #1. Ensure that the offering is created and that in the UI the 'Offer HA' field is enabled (Yes)
        #The listServiceOffering API should list 'offerha' as true.
        #2. Select the newly created VM and ensure that the Compute offering field value lists the compute service offering that was selected.
        #    Also, check that the HA Enabled field is enabled 'Yes'.

        #list and validate above created service offering with Ha enabled
        list_service_response = list_service_offering(
            self.apiclient,
            id=self.service_offering_with_ha.id
        )
        self.assertEqual(
            isinstance(list_service_response, list),
            True,
            "listServiceOfferings returned invalid object in response."
        )
        self.assertNotEqual(
            len(list_service_response),
            0,
            "listServiceOfferings returned empty list."
        )
        self.assertEqual(
            list_service_response[0].offerha,
            True,
            "The service offering is not HA enabled"
        )

        #create virtual machine with the service offering with Ha enabled
        virtual_machine = VirtualMachine.create(
            self.apiclient,
            self.services["virtual_machine"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            serviceofferingid=self.service_offering_with_ha.id
        )
        vms = VirtualMachine.list(
            self.apiclient,
            id=virtual_machine.id,
            listall=True
        )
        self.assertEqual(
            isinstance(vms, list),
            True,
            "listVirtualMachines returned invalid object in response."
        )
        self.assertNotEqual(
            len(vms),
            0,
            "listVirtualMachines returned empty list."
        )
        self.debug("Deployed VM on host: %s" % vms[0].hostid)
        self.assertEqual(
            vms[0].haenable,
            True,
            "VM not created with HA enable tag"
        )

    @attr(configuration="ha.tag")
    @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"])
    def test_02_no_vm_creation_on_host_with_haenabled(self):
        """ Verify you can not create new VMs on hosts with an ha.tag """

        # Steps,
        #1. Fresh install CS (Bonita) that supports this feature
        #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage
        #3. When adding host3, assign the HA host tag.
        #4. You should already have a compute service offering with HA already create from above. If not, create one for HA.
        #5. Create VMs with the service offering with and without the HA tag
        # Validations,
        #Check to make sure the newly created VM is not on any HA enabled hosts
        #The  VM should be created only on host1 or host2 and never host3 (HA enabled)

        #create and verify virtual machine with HA enabled service offering
        virtual_machine_with_ha = VirtualMachine.create(
            self.apiclient,
            self.services["virtual_machine"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            serviceofferingid=self.service_offering_with_ha.id
        )

        vms = VirtualMachine.list(
            self.apiclient,
            id=virtual_machine_with_ha.id,
            listall=True
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "listVirtualMachines returned invalid object in response."
        )

        self.assertNotEqual(
            len(vms),
            0,
            "listVirtualMachines returned empty list."
        )

        vm = vms[0]

        self.debug("Deployed VM on host: %s" % vm.hostid)

        #validate the virtual machine created is host Ha enabled
        list_hosts_response = list_hosts(
            self.apiclient,
            id=vm.hostid
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "listHosts returned invalid object in response."
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "listHosts retuned empty list in response."
        )

        self.assertEqual(
            list_hosts_response[0].hahost,
            False,
            "VM created on HA enabled host."
        )

        #create and verify virtual machine with Ha disabled service offering
        virtual_machine_without_ha = VirtualMachine.create(
            self.apiclient,
            self.services["virtual_machine"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            serviceofferingid=self.service_offering_without_ha.id
        )

        vms = VirtualMachine.list(
            self.apiclient,
            id=virtual_machine_without_ha.id,
            listall=True
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "listVirtualMachines returned invalid object in response."
        )

        self.assertNotEqual(
            len(vms),
            0,
            "listVirtualMachines returned empty list."
        )

        vm = vms[0]

        self.debug("Deployed VM on host: %s" % vm.hostid)

        #verify that the virtual machine created on the host is Ha disabled
        list_hosts_response = list_hosts(
            self.apiclient,
            id=vm.hostid
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "listHosts returned invalid object in response."
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "listHosts returned empty list."
        )

        host = list_hosts_response[0]

        self.assertEqual(
            host.hahost,
            False,
            "VM migrated to HA enabled host."
        )

    @attr(configuration="ha.tag")
    @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"])
    def test_03_cant_migrate_vm_to_host_with_ha_positive(self):
        """ Verify you can not migrate VMs to hosts with an ha.tag (positive) """

        # Steps,
        # 1. Create a Compute service offering with the 'Offer HA' option selected.
        # 2. Create a Guest VM with the compute service offering created above.
        # 3. Select the VM and migrate VM to another host. Choose a 'Suitable' host (i.e. host2)
        # Validations
        # The option from the 'Migrate instance to another host' dialog box' should list host3 as 'Not Suitable' for migration.
        # Confirm that the VM is migrated to the 'Suitable' host you selected
        # (i.e. host2)

        # create and verify the virtual machine with HA enabled service
        # offering
        self.hypervisor = self.testClient.getHypervisorInfo()
        if self.hypervisor.lower() in ['lxc']:
            self.skipTest("vm migrate is not supported in %s" % self.hypervisor)

        virtual_machine_with_ha = VirtualMachine.create(
            self.apiclient,
            self.services["virtual_machine"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            serviceofferingid=self.service_offering_with_ha.id
        )

        vms = VirtualMachine.list(
            self.apiclient,
            id=virtual_machine_with_ha.id,
            listall=True,
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "List VMs should return valid response for deployed VM"
        )

        self.assertNotEqual(
            len(vms),
            0,
            "List VMs should return valid response for deployed VM"
        )

        vm = vms[0]

        self.debug("Deployed VM on host: %s" % vm.hostid)

        # Find out a Suitable host for VM migration
        list_hosts_response = list_hosts(
            self.apiclient,
            virtualmachineid = vm.id
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "The listHosts API returned the invalid list"
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "The listHosts returned nothing."
        )
        suitableHost = None
        for host in list_hosts_response:
            if host.suitableformigration and host.hostid != vm.hostid:
                suitableHost = host
                break

        self.assertTrue(
            suitableHost is not None,
            "suitablehost should not be None")

        # Migration of the VM to a suitable host
        self.debug(
            "Migrating VM-ID: %s to Host: %s" %
            (vm.id, suitableHost.id))

        cmd = migrateVirtualMachine.migrateVirtualMachineCmd()
        cmd.hostid = suitableHost.id
        cmd.virtualmachineid = vm.id
        self.apiclient.migrateVirtualMachine(cmd)

        # Verify that the VM migrated to a targeted Suitable host
        list_vm_response = list_virtual_machines(
            self.apiclient,
            id=vm.id
        )
        self.assertEqual(
            isinstance(list_vm_response, list),
            True,
            "The listVirtualMachines returned the invalid list."
        )

        self.assertNotEqual(
            list_vm_response,
            None,
            "The listVirtualMachines API returned nothing."
        )

        vm_response = list_vm_response[0]

        self.assertEqual(
            vm_response.id,
            vm.id,
            "The virtual machine id and the virtual machine from listVirtualMachines is not matching."
        )

        self.assertEqual(
            vm_response.hostid,
            suitableHost.id,
            "The VM is not migrated to targeted suitable host."
        )

    @attr(configuration="ha.tag")
    @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"])
    def test_04_cant_migrate_vm_to_host_with_ha_negative(self):
        """ Verify you can not migrate VMs to hosts with an ha.tag (negative) """

        # Steps,
        #1. Create a Compute service offering with the 'Offer HA' option selected.
        #2. Create a Guest VM with the compute service offering created above.
        #3. Select the VM and migrate VM to another host. Choose a 'Not Suitable' host.
        # Validations,
        #The option from the 'Migrate instance to another host' dialog box should list host3 as 'Not Suitable' for migration.
        #By design, The Guest VM can STILL can be migrated to host3 if the admin chooses to do so.

        #create and verify virtual machine with HA enabled service offering
        self.hypervisor = self.testClient.getHypervisorInfo()
        if self.hypervisor.lower() in ['lxc']:
            self.skipTest("vm migrate is not supported in %s" % self.hypervisor)
        virtual_machine_with_ha = VirtualMachine.create(
            self.apiclient,
            self.services["virtual_machine"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            serviceofferingid=self.service_offering_with_ha.id
        )

        vms = VirtualMachine.list(
            self.apiclient,
            id=virtual_machine_with_ha.id,
            listall=True
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "The listVirtualMachines returned invalid object in response."
        )

        self.assertNotEqual(
            len(vms),
            0,
            "The listVirtualMachines returned empty response."
        )

        vm = vms[0]

        self.debug("Deployed VM on host: %s" % vm.hostid)

        #Find out Non-Suitable host for VM migration
        list_hosts_response = list_hosts(
            self.apiclient,
            type="Routing"
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "listHosts returned invalid object in response."
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "listHosts returned empty response."
        )

        notSuitableHost = None
        for host in list_hosts_response:
            if not host.suitableformigration and host.id != vm.hostid:
                notSuitableHost = host
                break

        self.assertTrue(notSuitableHost is not None, "notsuitablehost should not be None")

        #Migrate VM to Non-Suitable host
        self.debug("Migrating VM-ID: %s to Host: %s" % (vm.id, notSuitableHost.id))

        cmd = migrateVirtualMachine.migrateVirtualMachineCmd()
        cmd.hostid = notSuitableHost.id
        cmd.virtualmachineid = vm.id
        self.apiclient.migrateVirtualMachine(cmd)

        #Verify that the virtual machine got migrated to targeted Non-Suitable host
        list_vm_response = list_virtual_machines(
            self.apiclient,
            id=vm.id
        )
        self.assertEqual(
            isinstance(list_vm_response, list),
            True,
            "listVirtualMachine returned invalid object in response."
        )

        self.assertNotEqual(
            len(list_vm_response),
            0,
            "listVirtualMachines returned empty response."
        )

        self.assertEqual(
            list_vm_response[0].id,
            vm.id,
            "Virtual machine id with the virtual machine from listVirtualMachine is not matching."
        )

        self.assertEqual(
            list_vm_response[0].hostid,
            notSuitableHost.id,
            "The detination host id of migrated VM is not matching."
        )

    @attr(configuration="ha.tag")
    @attr(speed="slow")
    @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"])
    def test_05_no_vm_with_ha_gets_migrated_to_ha_host_in_live_migration(self):
        """ Verify that none of the VMs with HA enabled migrate to an ha tagged host during live migration """

        # Steps,
        #1. Fresh install CS that supports this feature
        #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage
        #3. When adding host3, assign the HA host tag.
        #4. Create VMs with and without the Compute Service Offering with the HA tag.
        #5. Note the VMs on host1 and whether any of the VMs have their 'HA enabled' flags enabled.
        #6. Put host1 into maintenance mode.
        # Validations,
        #1. Make sure the VMs are created on either host1 or host2 and not on host3
        #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3.

        # create and verify virtual machine with HA disabled service offering
        self.hypervisor = self.testClient.getHypervisorInfo()
        if self.hypervisor.lower() in ['lxc']:
            self.skipTest("vm migrate is not supported in %s" % self.hypervisor)
        virtual_machine_with_ha = VirtualMachine.create(
            self.apiclient,
            self.services["virtual_machine"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            serviceofferingid=self.service_offering_with_ha.id
        )

        vms = VirtualMachine.list(
            self.apiclient,
            id=virtual_machine_with_ha.id,
            listall=True
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "List VMs should return valid response for deployed VM"
        )

        self.assertNotEqual(
            len(vms),
            0,
            "List VMs should return valid response for deployed VM"
        )

        vm_with_ha_enabled = vms[0]

        #Verify the virtual machine got created on non HA host
        list_hosts_response = list_hosts(
            self.apiclient,
            id=vm_with_ha_enabled.hostid
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "Check list response returns a valid list"
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "Check Host is available"
        )

        self.assertEqual(
            list_hosts_response[0].hahost,
            False,
            "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled"
        )

        #put the Host in maintenance mode
        self.debug("Enabling maintenance mode for host %s" % vm_with_ha_enabled.hostid)
        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
        cmd.id = vm_with_ha_enabled.hostid
        self.apiclient.prepareHostForMaintenance(cmd)

        timeout = self.services["timeout"]

        #verify the VM live migration happened to another running host
        self.debug("Waiting for VM to come up")
        time.sleep(timeout)

        vms = VirtualMachine.list(
            self.apiclient,
            id=vm_with_ha_enabled.id,
            listall=True,
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "List VMs should return valid response for deployed VM"
        )

        self.assertNotEqual(
            len(vms),
            0,
            "List VMs should return valid response for deployed VM"
        )

        vm_with_ha_enabled1 = vms[0]

        list_hosts_response = list_hosts(
            self.apiclient,
            id=vm_with_ha_enabled1.hostid
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "Check list response returns a valid list"
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "Check Host is available"
        )

        self.assertEqual(
            list_hosts_response[0].hahost,
            False,
            "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled"
        )

        self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_enabled.hostid)
        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
        cmd.id = vm_with_ha_enabled.hostid
        self.apiclient.cancelHostMaintenance(cmd)

    @attr(configuration="ha.tag")
    @attr(speed="slow")
    @attr(tags=["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"])
    def test_06_no_vm_without_ha_gets_migrated_to_ha_host_in_live_migration(self):
        """ Verify that none of the VMs without HA enabled migrate to an ha tagged host during live migration """

        # Steps,
        #1. Fresh install CS that supports this feature
        #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage
        #3. When adding host3, assign the HA host tag.
        #4. Create VMs with and without the Compute Service Offering with the HA tag.
        #5. Note the VMs on host1 and whether any of the VMs have their 'HA enabled' flags enabled.
        #6. Put host1 into maintenance mode.
        # Validations,
        #1. Make sure the VMs are created on either host1 or host2 and not on host3
        #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3.

        # create and verify virtual machine with HA disabled service offering
        self.hypervisor = self.testClient.getHypervisorInfo()
        if self.hypervisor.lower() in ['lxc']:
            self.skipTest("vm migrate is not supported in %s" % self.hypervisor)
        virtual_machine_without_ha = VirtualMachine.create(
            self.apiclient,
            self.services["virtual_machine"],
            accountid=self.account.name,
            domainid=self.account.domainid,
            serviceofferingid=self.service_offering_without_ha.id
        )

        vms = VirtualMachine.list(
            self.apiclient,
            id=virtual_machine_without_ha.id,
            listall=True
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "List VMs should return valid response for deployed VM"
        )

        self.assertNotEqual(
            len(vms),
            0,
            "List VMs should return valid response for deployed VM"
        )

        vm_with_ha_disabled = vms[0]

        #Verify the virtual machine got created on non HA host
        list_hosts_response = list_hosts(
            self.apiclient,
            id=vm_with_ha_disabled.hostid
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "Check list response returns a valid list"
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "Check Host is available"
        )

        self.assertEqual(
            list_hosts_response[0].hahost,
            False,
            "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled"
        )

        #put the Host in maintenance mode
        self.debug("Enabling maintenance mode for host %s" % vm_with_ha_disabled.hostid)
        cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
        cmd.id = vm_with_ha_disabled.hostid
        self.apiclient.prepareHostForMaintenance(cmd)

        timeout = self.services["timeout"]

        #verify the VM live migration happened to another running host
        self.debug("Waiting for VM to come up")
        time.sleep(timeout)

        vms = VirtualMachine.list(
            self.apiclient,
            id=vm_with_ha_disabled.id,
            listall=True
        )

        self.assertEqual(
            isinstance(vms, list),
            True,
            "List VMs should return valid response for deployed VM"
        )

        self.assertNotEqual(
            len(vms),
            0,
            "List VMs should return valid response for deployed VM"
        )

        list_hosts_response = list_hosts(
            self.apiclient,
            id=vms[0].hostid
        )
        self.assertEqual(
            isinstance(list_hosts_response, list),
            True,
            "Check list response returns a valid list"
        )

        self.assertNotEqual(
            len(list_hosts_response),
            0,
            "Check Host is available"
        )

        self.assertEqual(
            list_hosts_response[0].hahost,
            False,
            "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled"
        )

        self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_disabled.hostid)
        cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
        cmd.id = vm_with_ha_disabled.hostid
        self.apiclient.cancelHostMaintenance(cmd)
