Refactoring the planner tests

1. Planner tests rewritten to use marvin integration libraries
2. Included verification of multi VM deployment for user dispersion
3. Included a test for user concentrated planner

TODO: firstfit planner test doesn't actually test the planner strategy.
It only deploys a VM using the offering.

Signed-off-by: Prasanna Santhanam <tsp@apache.org>
This commit is contained in:
Prasanna Santhanam 2013-05-22 15:41:35 +05:30
parent 698da2a279
commit 616011020b

View File

@ -1,164 +1,250 @@
# Licensed to the Apache Software Foundation (ASF) under one # Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file # or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information # distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file # regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the # to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance # "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at # with the License. You may obtain a copy of the License at
# #
# http://www.apache.org/licenses/LICENSE-2.0 # http://www.apache.org/licenses/LICENSE-2.0
# #
# Unless required by applicable law or agreed to in writing, # Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an # software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the # KIND, either express or implied. See the License for the
# specific language governing permissions and limitations # specific language governing permissions and limitations
# under the License. # under the License.
#!/usr/bin/env python from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering
import marvin from marvin.integration.lib.common import get_zone, get_domain, get_template, cleanup_resources
from marvin import cloudstackTestCase
from marvin.cloudstackTestCase import * from nose.plugins.attrib import attr
import unittest class Services:
import hashlib def __init__(self):
import random self.services = {
"account": {
class TestDeployVmWithVariedPlanners(cloudstackTestCase): "email": "test@test.com",
""" "firstname": "Test",
This test tests that we can create serviceOfferings with different deployment Planners and deploy virtual machines into a user account "lastname": "User",
using these service offerings and builtin template "username": "test",
""" # Random characters are appended for unique
def setUp(self): # username
""" "password": "password",
CloudStack internally saves its passwords in md5 form and that is how we },
specify it in the API. Python's hashlib library helps us to quickly hash "service_offering": {
strings as follows "name": "Planner Service Offering",
""" "displaytext": "Planner Service Offering",
mdf = hashlib.md5() "cpunumber": 1,
mdf.update('password') "cpuspeed": 100,
mdf_pass = mdf.hexdigest() # in MHz
"memory": 128,
self.apiClient = self.testClient.getApiClient() #Get ourselves an API client # In MBs
},
self.acct = createAccount.createAccountCmd() #The createAccount command "ostype": 'CentOS 5.3 (64-bit)',
self.acct.accounttype = 0 #We need a regular user. admins have accounttype=1 "virtual_machine": {
self.acct.firstname = 'test' "hypervisor": "XenServer",
self.acct.lastname = 'user' #What's up doc? }
self.acct.username = 'testuser' }
self.acct.password = mdf_pass #The md5 hashed password string
self.acct.email = 'test@domain.com'
self.acct.account = 'testacct' class TestDeployVmWithVariedPlanners(cloudstackTestCase):
self.acct.domainid = 1 #The default ROOT domain """ Test to create services offerings for deployment planners
self.acctResponse = self.apiClient.createAccount(self.acct) - firstfit, userdispersing
# And upon successful creation we'll log a helpful message in our logs """
# using the default debug logger of the test framework
self.debug("successfully created account: %s, id: \ @classmethod
%s"%(self.acctResponse.name, \ def setUpClass(cls):
self.acctResponse.id)) cls.apiclient = super(TestDeployVmWithVariedPlanners, cls).getClsTestClient().getApiClient()
cls.services = Services().services
#Create service offerings with varied planners # Get Zone, Domain and templates
self.svcOfferingFirstFit = createServiceOffering.createServiceOfferingCmd() cls.domain = get_domain(cls.apiclient, cls.services)
self.svcOfferingFirstFit.name = 'Tiny Instance FirstFit' cls.zone = get_zone(cls.apiclient, cls.services)
self.svcOfferingFirstFit.displaytext = 'Tiny Instance with FirstFitPlanner' cls.template = get_template(
self.svcOfferingFirstFit.cpuspeed = 100 cls.apiclient,
self.svcOfferingFirstFit.cpunumber = 1 cls.zone.id,
self.svcOfferingFirstFit.memory = 256 cls.services["ostype"]
self.svcOfferingFirstFit.deploymentplanner = 'FirstFitPlanner' )
self.svcOfferingFirstFitResponse = self.apiClient.createServiceOffering(self.svcOfferingFirstFit) cls.services["virtual_machine"]["zoneid"] = cls.zone.id
cls.services["template"] = cls.template.id
self.debug("successfully created serviceofferring name: %s, id: \ cls.services["zoneid"] = cls.zone.id
%s, deploymentPlanner: %s"%(self.svcOfferingFirstFitResponse.name, \
self.svcOfferingFirstFitResponse.id,self.svcOfferingFirstFitResponse.deploymentplanner)) cls.account = Account.create(
cls.apiclient,
#Create service offerings with varied planners cls.services["account"],
self.svcOfferingUserDispersing = createServiceOffering.createServiceOfferingCmd() domainid=cls.domain.id
self.svcOfferingUserDispersing.name = 'Tiny Instance UserDispersing' )
self.svcOfferingUserDispersing.displaytext = 'Tiny Instance with UserDispersingPlanner' cls.services["account"] = cls.account.name
self.svcOfferingUserDispersing.cpuspeed = 100 cls.cleanup = [
self.svcOfferingUserDispersing.cpunumber = 1 cls.account
self.svcOfferingUserDispersing.memory = 256 ]
self.svcOfferingUserDispersing.deploymentplanner = 'FirstFitPlanner'
self.svcOfferingUserDispersingResponse = self.apiClient.createServiceOffering(self.svcOfferingUserDispersing) @attr(tags=["simulator", "advanced", "basic", "sg"])
def test_deployvm_firstfit(self):
self.debug("successfully created serviceofferring name: %s, id: \ """Test to deploy vm with a first fit offering
%s, deploymentPlanner: %s"%(self.svcOfferingUserDispersingResponse.name, \ """
self.svcOfferingUserDispersingResponse.id,self.svcOfferingUserDispersingResponse.deploymentplanner)) #FIXME: How do we know that first fit actually happened?
self.service_offering_firstfit = ServiceOffering.create(
def test_DeployVm(self): self.apiclient,
""" self.services["service_offering"],
Let's start by defining the attributes of our VM that we will be deploymentplanner='FirstFitPlanner'
deploying on CloudStack. We will be assuming a single zone is available )
and is configured and all templates are Ready
self.virtual_machine = VirtualMachine.create(
The hardcoded values are used only for brevity. self.apiclient,
""" self.services["virtual_machine"],
deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd() accountid=self.account.name,
deployVmCmd.zoneid = 1 zoneid=self.zone.id,
deployVmCmd.account = self.acct.account domainid=self.account.domainid,
deployVmCmd.domainid = self.acct.domainid serviceofferingid=self.service_offering_firstfit.id,
deployVmCmd.templateid = 5 #For default template- CentOS 5.6(64 bit) templateid=self.template.id
deployVmCmd.serviceofferingid = self.svcOfferingFirstFitResponse.id )
deployVmResponse = self.apiClient.deployVirtualMachine(deployVmCmd) list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id)
self.debug("VM %s was deployed in the job %s"%(deployVmResponse.id, deployVmResponse.jobid)) self.debug(
"Verify listVirtualMachines response for virtual machine: %s"\
# At this point our VM is expected to be Running. Let's find out what % self.virtual_machine.id
# listVirtualMachines tells us about VMs in this account )
self.assertEqual(
listVmCmd = listVirtualMachines.listVirtualMachinesCmd() isinstance(list_vms, list),
listVmCmd.id = deployVmResponse.id True,
listVmResponse = self.apiClient.listVirtualMachines(listVmCmd) "List VM response was not a valid list"
)
self.assertNotEqual(len(listVmResponse), 0, "Check if the list API \ self.assertNotEqual(
returns a non-empty response") len(list_vms),
0,
vm1 = listVmResponse[0] "List VM response was empty"
)
self.assertEqual(vm1.id, deployVmResponse.id, "Check if the VM returned \
is the same as the one we deployed") vm = list_vms[0]
self.assertEqual(vm1.state, "Running", "Check if VM has reached \ self.assertEqual(
a state of running") vm.state,
"Running",
msg="VM is not in Running state"
deployVm2Cmd = deployVirtualMachine.deployVirtualMachineCmd() )
deployVm2Cmd.zoneid = 1
deployVm2Cmd.account = self.acct.account @attr(tags=["simulator", "advanced", "basic", "sg"])
deployVm2Cmd.domainid = self.acct.domainid def test_deployvm_userdispersing(self):
deployVm2Cmd.templateid = 5 #For default template- CentOS 5.6(64 bit) """Test deploy VMs using user dispersion planner
deployVm2Cmd.serviceofferingid = self.svcOfferingFirstFitResponse.id """
self.service_offering_userdispersing = ServiceOffering.create(
deployVm2Response = self.apiClient.deployVirtualMachine(deployVm2Cmd) self.apiclient,
self.debug("VM %s was deployed in the job %s"%(deployVm2Response.id, deployVm2Response.jobid)) self.services["service_offering"],
deploymentplanner='UserDispersingPlanner'
# At this point our VM is expected to be Running. Let's find out what )
# listVirtualMachines tells us about VMs in this account
self.virtual_machine_1 = VirtualMachine.create(
listVm2Cmd = listVirtualMachines.listVirtualMachinesCmd() self.apiclient,
listVm2Cmd.id = deployVm2Response.id self.services["virtual_machine"],
listVm2Response = self.apiClient.listVirtualMachines(listVm2Cmd) accountid=self.account.name,
self.assertNotEqual(len(listVm2Response), 0, "Check if the list API \ zoneid=self.zone.id,
returns a non-empty response") domainid=self.account.domainid,
vm2 = listVm2Response[0] serviceofferingid=self.service_offering_userdispersing.id,
self.assertEqual(vm2.id, deployVm2Response.id, "Check if the VM returned \ templateid=self.template.id
is the same as the one we deployed") )
self.assertEqual(vm2.state, "Running", "Check if VM has reached \ self.virtual_machine_2 = VirtualMachine.create(
a state of running") self.apiclient,
self.services["virtual_machine"],
accountid=self.account.name,
def tearDown(self): # Teardown will delete the Account as well as the VM once the VM reaches "Running" state zoneid=self.zone.id,
""" domainid=self.account.domainid,
And finally let us cleanup the resources we created by deleting the serviceofferingid=self.service_offering_userdispersing.id,
account. All good unittests are atomic and rerunnable this way templateid=self.template.id
""" )
deleteAcct = deleteAccount.deleteAccountCmd()
deleteAcct.id = self.acctResponse.id list_vm_1 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_1.id)
self.apiClient.deleteAccount(deleteAcct) list_vm_2 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_2.id)
deleteSvcOfferingFirstFit = deleteServiceOffering.deleteServiceOfferingCmd() self.assertEqual(
deleteSvcOfferingFirstFit.id = self.svcOfferingFirstFitResponse.id isinstance(list_vm_1, list),
self.apiClient.deleteServiceOffering(deleteSvcOfferingFirstFit); True,
deleteSvcOfferingUserDispersing = deleteServiceOffering.deleteServiceOfferingCmd() "List VM response was not a valid list"
deleteSvcOfferingUserDispersing.id = self.svcOfferingUserDispersingResponse.id )
self.apiClient.deleteServiceOffering(deleteSvcOfferingUserDispersing); self.assertEqual(
isinstance(list_vm_2, list),
True,
"List VM response was not a valid list"
)
vm1 = list_vm_1[0]
vm2 = list_vm_2[0]
self.assertEqual(
vm1.state,
"Running",
msg="VM is not in Running state"
)
self.assertEqual(
vm2.state,
"Running",
msg="VM is not in Running state"
)
self.assertNotEqual(
vm1.hostid,
vm2.hostid,
msg="VMs meant to be dispersed are deployed on the same host"
)
@attr(tags=["simulator", "advanced", "basic", "sg"])
def test_deployvm_userconcentrated(self):
"""Test deploy VMs using user concentrated planner
"""
self.service_offering_userconcentrated = ServiceOffering.create(
self.apiclient,
self.services["service_offering"],
deploymentplanner='UserConcentratedPodPlanner'
)
self.virtual_machine_1 = VirtualMachine.create(
self.apiclient,
self.services["virtual_machine"],
accountid=self.account.name,
zoneid=self.zone.id,
domainid=self.account.domainid,
serviceofferingid=self.service_offering_userconcentrated.id,
templateid=self.template.id
)
self.virtual_machine_2 = VirtualMachine.create(
self.apiclient,
self.services["virtual_machine"],
accountid=self.account.name,
zoneid=self.zone.id,
domainid=self.account.domainid,
serviceofferingid=self.service_offering_userconcentrated.id,
templateid=self.template.id
)
list_vm_1 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_1.id)
list_vm_2 = VirtualMachine.list(self.apiclient, id=self.virtual_machine_2.id)
self.assertEqual(
isinstance(list_vm_1, list),
True,
"List VM response was not a valid list"
)
self.assertEqual(
isinstance(list_vm_2, list),
True,
"List VM response was not a valid list"
)
vm1 = list_vm_1[0]
vm2 = list_vm_2[0]
self.assertEqual(
vm1.state,
"Running",
msg="VM is not in Running state"
)
self.assertEqual(
vm2.state,
"Running",
msg="VM is not in Running state"
)
self.assertNotEqual(
vm1.hostid,
vm2.hostid,
msg="VMs meant to be concentrated are deployed on the different hosts"
)
@classmethod
def tearDownClass(cls):
try:
cleanup_resources(cls.apiclient, cls.cleanup)
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)