From cb918928e692b9023b68c981e1b88edd1a8e9f8c Mon Sep 17 00:00:00 2001 From: Ashutosh K Date: Wed, 13 Nov 2013 21:51:35 +0530 Subject: [PATCH] Missing tests from QA repo to ASF - 3 tests from test_vmware_drs.py --- test/integration/component/test_vmware_drs.py | 713 ++++++++++++++++++ 1 file changed, 713 insertions(+) create mode 100644 test/integration/component/test_vmware_drs.py diff --git a/test/integration/component/test_vmware_drs.py b/test/integration/component/test_vmware_drs.py new file mode 100644 index 00000000000..8eeb2c322a9 --- /dev/null +++ b/test/integration/component/test_vmware_drs.py @@ -0,0 +1,713 @@ +# 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 for VMware DRS testing +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr + +from marvin.cloudstackTestCase import cloudstackTestCase, unittest + +from marvin.integration.lib.base import (Account, + AffinityGroup, + Host, + VirtualMachine, + ServiceOffering) + +from marvin.integration.lib.commom import (get_zone, + get_template, + get_domain, + get_pod + ) + +from marvin.integration.lib.utils import (validateList, + cleanup_resources, + random_gen) + +from marvin.cloudstackAPI import (prepareHostForMaintenance, + cancelHostMaintenance, + migrateVirtualMachine) + +from marvin.codes import PASS + + +#Import System modules +import time + + +class Services: + """Test vmware DRS services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "password", + }, + "virtual_machine": + { + "displayname": "testserver", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "service_offering": + { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 2048, # In MBs + }, + "service_offering_max_memory": + { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "host_anti_affinity": { + "name": "", + "type": "host anti-affinity", + }, + "host_affinity": { + "name": "", + "type": "host affinity", + }, + "sleep": 60, + "timeout": 10, + "ostype": 'CentOS 5.3 (64-bit)', + # CentOS 5.3 (64-bit) + } + +class TestVMPlacement(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestVMPlacement, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain( + cls.api_client, + cls.services + ) + cls.zone = get_zone( + cls.api_client, + cls.services + ) + cls.pod = get_pod( + cls.api_client, + zoneid=cls.zone.id, + services=cls.services + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + offerha=True + ) + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #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) + #self.testClient.close() + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advanced", "vmware", "multihost"]) + def test_vm_creation_in_fully_automated_mode(self): + """ Test VM Creation in automation mode = Fully automated + This test requires following preconditions: + - DRS Cluster is configured in "Fully automated" mode + """ + # Validate the following + # 1. Create a new VM in a host which is almost fully utilized + # 2 Automatically places VM on the other host + # 3. VM state is running after deployment + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + self.assertGreaterEqual( + len(hosts), + 2, + "There must be two hosts present in a cluster" + ) + + host_1 = hosts[0] + + #Convert available memory( Keep some margin) into MBs and assign to service offering + self.services["service_offering_max_memory"]["memory"] = int((int(hosts[0].memorytotal) - int(hosts[0].memoryused))/1048576 - 1024) + + self.debug("max memory: %s" % self.services["service_offering_max_memory"]["memory"]) + + service_offering_max_memory = ServiceOffering.create( + self.apiclient, + self.services["service_offering_max_memory"] + ) + + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=service_offering_max_memory.id, + hostid = host_1.id + ) + + # Host 1 has only 1024 MB memory available now after deploying the instance + # We are trying to deploy an instance with 2048 MB memory, this should automatically + # get deployed on other host which has the enough capacity + + self.debug("Trying to deploy instance with memory requirement more than that is available on\ + the first host") + + self.debug("Deploying VM in account: %s" % self.account.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.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.assertEqual( + vm.state, + "Running", + "Deployed VM should be in RUnning state" + ) + self.assertNotEqual( + vm.hostid, + host_1.id, + "Host Ids of two should not match as one host is full" + ) + + self.debug("The host ids of two virtual machines are different as expected\ + they are %s and %s" % (vm.hostid, host_1.id)) + return + +@unittest.skip("Skipping... Not tested due to unavailibility of multihosts setup - 3 hosts in a cluster") +class TestAntiAffinityRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestAntiAffinityRules, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain( + cls.api_client, + cls.services + ) + cls.zone = get_zone( + cls.api_client, + cls.services + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + offerha=True + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup = [cls.account] + return + + @classmethod + def tearDownClass(cls): + try: + #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.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + #self.testClient.close() + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def create_aff_grp(self, aff_grp=None, + acc=None, domainid=None): + + aff_grp["name"] = "aff_grp_" + random_gen(size=6) + + try: + aff_grp = AffinityGroup.create(self.apiclient, + aff_grp, acc, domainid) + return aff_grp + except Exception as e: + raise Exception("Error: Creation of Affinity Group failed : %s" %e) + + @attr(tags = ["advanced", "vmware", "multihost"]) + def test_vmware_anti_affinity(self): + """ Test Set up anti-affinity rules + + The test requires following pre-requisites + - VMWare cluster configured in fully automated mode + """ + + # Validate the following + # 1. Deploy VMs on host 1 and 2 + # 2. Enable maintenance mode for host 1 + # 3. VM should be migrated to 3rd host + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + + self.debug(len(hosts)) + + self.assertGreaterEqual( + len(hosts), + 3, + "There must be at least 3 hosts present in a cluster" + ) + + aff_grp = self.create_aff_grp(aff_grp=self.services["host_anti_affinity"], acc=self.account.name, domainid=self.domain.id) + + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + affinitygroupnames=[aff_grp.name] + ) + + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + affinitygroupnames=[aff_grp.name] + ) + + host_1 = vm_1.hostid + + host_2 = vm_2.hostid + + vms = VirtualMachine.list( + self.apiclient, + id=vm_1.id, + listall=True + ) + vm_list_validation_result = validateList(vms) + + self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % + vm_list_validation_result[1]) + + virtual_machine_1 = vm_list_validation_result[1] + + self.debug("VM State: %s" % virtual_machine_1.state) + self.assertEqual( + virtual_machine_1.state, + "Running", + "Deployed VM should be in RUnning state" + ) + + vms = VirtualMachine.list( + self.apiclient, + id=vm_2.id, + listall=True + ) + vm_list_validation_result = validateList(vms) + + self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % + vm_list_validation_result[1]) + + virtual_machine_2 = vm_list_validation_result[1] + + self.debug("VM %s State: %s" % ( + virtual_machine_2.name, + virtual_machine_2.state + )) + self.assertEqual( + virtual_machine_2.state, + "Running", + "Deployed VM should be in RUnning state" + ) + self.debug("Enabling maintenance mode on host_1: %s" % host_1) + + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = host_1 + self.apiclient.prepareHostForMaintenance(cmd) + + timeout = self.services["timeout"] + while True: + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + type='Routing', + id=host_1 + ) + host_list_validation_result = validateList(hosts) + + self.assertEqual(host_list_validation_result[0], PASS, "host list validation failed due to %s" + % host_list_validation_result[2]) + + host = host_list_validation_result[1] + + if host.resourcestate == 'Maintenance': + break + elif timeout == 0: + self.fail("Failed to put host: %s in maintenance mode" % host.name) + + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id, + listall=True + ) + vm_list_validation_result = validateList(vms) + + self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % + vm_list_validation_result[2]) + + vm = vm_list_validation_result[0] + + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in RUnning state" + ) + self.assertNotEqual( + vm.hostid, + host_2, + "The host name should not match with second host name" + ) + + self.debug("Canceling host maintenance for ID: %s" % host_1.id) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = host_1.id + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % host_1.id) + + return + +@unittest.skip("Skipping...Host Affinity feature not available yet in cloudstack") +class TestAffinityRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestAffinityRules, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain( + cls.api_client, + cls.services + ) + cls.zone = get_zone( + cls.api_client, + cls.services + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + offerha=True + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls._cleanup = [cls.account] + return + + @classmethod + def tearDownClass(cls): + try: + #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.cleanup = [] + 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 + + def create_aff_grp(self, aff_grp=None, + acc=None, domainid=None): + + aff_grp["name"] = "aff_grp_" + random_gen(size=6) + + try: + aff_grp = AffinityGroup.create(self.apiclient, + aff_grp, acc, domainid) + return aff_grp + except Exception as e: + raise Exception("Error: Creation of Affinity Group failed : %s" %e) + + @attr(tags = ["advanced", "vmware", "multihost"]) + def test_vmware_affinity(self): + """ Test Set up affinity rules + + The test requires following pre-requisites + - VMWare cluster configured in fully automated mode + """ + + # Validate the following + # 1. Deploy 2 VMs on same hosts + # 2. Migrate one VM from one host to another + # 3. The second VM should also get migrated + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + self.assertGreaterEqual( + len(hosts), + 2, + "There must be two hosts present in a cluster" + ) + + host_1 = hosts[0].id + + host_2 = hosts[1].id + + aff_grp = self.create_aff_grp(aff_grp=self.services["host_affinity"], acc=self.account.name, domainid=self.domain.id) + + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + affinitygroupnames=[aff_grp.name], + hostid = host_1 + ) + + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.name, + domainid=self.domain.id, + serviceofferingid=self.service_offering.id, + affinitygroupnames=[aff_grp.name] + ) + + vms = VirtualMachine.list( + self.apiclient, + id= vm_1.id, + listall=True + ) + + vm_list_validation_result = validateList(vms) + + self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % + vm_list_validation_result[2]) + + virtual_machine_1 = vm_list_validation_result[1] + + self.assertEqual( + virtual_machine_1.state, + "Running", + "Deployed VM should be in RUnning state" + ) + + self.debug("Deploying VM on account: %s" % self.account.name) + + vms = VirtualMachine.list( + self.apiclient, + id=vm_2.id, + listall=True + ) + vm_list_validation_result = validateList(vms) + + self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % + vm_list_validation_result[2]) + + virtual_machine_2 = vm_list_validation_result[1] + + self.assertEqual( + virtual_machine_2.state, + "Running", + "Deployed VM should be in RUnning state" + ) + + self.debug("Migrate VM from host_1 to host_2") + cmd = migrateVirtualMachine.migrateVirtualMachineCmd() + cmd.virtualmachineid = virtual_machine_2.id + cmd.hostid = host_2 + self.apiclient.migrateVirtualMachine(cmd) + self.debug("Migrated VM from host_1 to host_2") + + vms = VirtualMachine.list( + self.apiclient, + hostid=host_2, + listall=True + ) + vm_list_validation_result = validateList(vms) + + self.assertEqual(vm_list_validation_result[0], PASS, "vm list validation failed due to %s" % + vm_list_validation_result[2]) + + vmids = [vm.id for vm in vms] + + self.assertIn( + virtual_machine_1.id, + vmids, + "VM 1 should be successfully migrated to host 2" + ) + self.assertIn( + virtual_machine_2.id, + vmids, + "VM 2 should be automatically migrated to host 2" + ) + return