You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by al...@apache.org on 2013/04/11 23:22:59 UTC
[36/47] git commit: updated refs/heads/internallb to 3795048
bvt: marvin test for the affinity groups feature
The test deploys two VMs in the simulator context and verifies that the
default host -antiaffinity processor placed the VMs on two distinct
hosts.
Signed-off-by: Prasanna Santhanam <ts...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/79812c25
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/79812c25
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/79812c25
Branch: refs/heads/internallb
Commit: 79812c253f26841523c9fe3c04ce7c6c47d98314
Parents: e52bf52
Author: Prasanna Santhanam <ts...@apache.org>
Authored: Mon Apr 8 23:18:00 2013 +0530
Committer: Prachi Damle <pr...@cloud.com>
Committed: Thu Apr 11 13:23:32 2013 -0700
----------------------------------------------------------------------
client/tomcatconf/simulatorComponentContext.xml.in | 23 +-
test/integration/smoke/test_affinity_groups.py | 297 ++++++++-------
tools/marvin/marvin/integration/lib/base.py | 29 ++-
3 files changed, 212 insertions(+), 137 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79812c25/client/tomcatconf/simulatorComponentContext.xml.in
----------------------------------------------------------------------
diff --git a/client/tomcatconf/simulatorComponentContext.xml.in b/client/tomcatconf/simulatorComponentContext.xml.in
index fc5cf54..435b9e2 100644
--- a/client/tomcatconf/simulatorComponentContext.xml.in
+++ b/client/tomcatconf/simulatorComponentContext.xml.in
@@ -1,4 +1,3 @@
-
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
@@ -34,8 +33,8 @@
<!--
OSS deployment component configuration
-->
- <bean id="databaseUpgradeChecker" class="com.cloud.upgrade.DatabaseUpgradeChecker" />
- <bean id="configurationDaoImpl" class="com.cloud.configuration.dao.ConfigurationDaoImpl" />
+ <bean id="databaseUpgradeChecker" class="com.cloud.upgrade.DatabaseUpgradeChecker"/>
+ <bean id="configurationDaoImpl" class="com.cloud.configuration.dao.ConfigurationDaoImpl"/>
<!-- simulator components -->
<bean id="SimulatorSecondaryDiscoverer" class="com.cloud.resource.SimulatorSecondaryDiscoverer">
@@ -122,9 +121,9 @@
<bean id="deploymentPlanners" class="com.cloud.utils.component.AdapterList">
<property name="Adapters">
<list>
- <ref bean="FirstFitPlanner" />
- <ref bean="UserDispersingPlanner" />
- <ref bean="UserConcentratedPodPlanner" />
+ <ref bean="FirstFitPlanner"/>
+ <ref bean="UserDispersingPlanner"/>
+ <ref bean="UserConcentratedPodPlanner"/>
<!--
<ref bean="BareMetalPlanner" />
@@ -215,6 +214,16 @@
</property>
</bean>
- <bean id="GlobalLoadBalancingRulesServiceImpl" class ="org.apache.cloudstack.region.gslb.GlobalLoadBalancingRulesServiceImpl" />
+ <bean id="GlobalLoadBalancingRulesServiceImpl"
+ class="org.apache.cloudstack.region.gslb.GlobalLoadBalancingRulesServiceImpl"/>
+
+ <!--
+ AffinityGroup Processors
+ -->
+ <bean id="HostAntiAffinityProcessor" class="org.apache.cloudstack.affinity.HostAntiAffinityProcessor">
+ <property name="name" value="HostAntiAffinityProcessor"/>
+ <property name="type" value="host anti-affinity"/>
+ </bean>
+
</beans>
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79812c25/test/integration/smoke/test_affinity_groups.py
----------------------------------------------------------------------
diff --git a/test/integration/smoke/test_affinity_groups.py b/test/integration/smoke/test_affinity_groups.py
index 432751c..83fccf5 100644
--- a/test/integration/smoke/test_affinity_groups.py
+++ b/test/integration/smoke/test_affinity_groups.py
@@ -16,142 +16,181 @@
# specific language governing permissions and limitations
# under the License.
+from marvin.cloudstackTestCase import *
+from marvin.cloudstackAPI import *
+from marvin.integration.lib.utils import *
+from marvin.integration.lib.base import *
+from marvin.integration.lib.common import *
+from marvin import remoteSSHClient
+from nose.plugins.attrib import attr
+
+class Services:
+ """Test Account Services
+ """
+ def __init__(self):
+ self.services = {
+ "domain": {
+ "name": "Domain",
+ },
+ "account": {
+ "email": "test@test.com",
+ "firstname": "Test",
+ "lastname": "User",
+ "username": "test",
+ # Random characters are appended for unique
+ # username
+ "password": "password",
+ },
+ "service_offering": {
+ "name": "Tiny Instance",
+ "displaytext": "Tiny Instance",
+ "cpunumber": 1,
+ "cpuspeed": 100,
+ # in MHz
+ "memory": 64,
+ # In MBs
+ },
+ "ostype": 'CentOS 5.3 (64-bit)',
+ "mode": 'advanced',
+ "affinity": {
+ "name": "webvms",
+ "type": "host anti-affinity",
+ }
+ }
-import marvin
-from marvin.cloudstackTestCase import *
-from marvin.remoteSSHClient import remoteSSHClient
-import hashlib
-import random
class TestDeployVmWithAffinityGroup(cloudstackTestCase):
"""
This test deploys a virtual machine into a user account
using the small service offering and builtin template
"""
- def setUp(self):
- """
- 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
- strings as follows
- """
- mdf = hashlib.md5()
- mdf.update('password')
- mdf_pass = mdf.hexdigest()
-
- self.apiClient = self.testClient.getApiClient() #Get ourselves an API client
-
- self.acct = createAccount.createAccountCmd() #The createAccount command
- self.acct.accounttype = 0 #We need a regular user. admins have accounttype=1
- self.acct.firstname = 'test'
- self.acct.lastname = 'user' #What's up doc?
- self.acct.password = mdf_pass #The md5 hashed password string
- self.acct.username = 'testuser'
- self.acct.email = 'testuser@xyz.com'
- self.acct.account = 'testacct'
- self.acct.domainid = 1 #The default ROOT domain
- self.acctResponse = self.apiClient.createAccount(self.acct)
- # 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, user: %s, id: \
- %s"%(self.acctResponse.account.account, \
- self.acctResponse.account.username, \
- self.acctResponse.account.id))
-
-
- self.zone = listZones.listZonesCmd()
- self.zone.uuid = self.apiClient.listZones(self.zone)[0].id
-
- self.service_offering = listServiceOfferings.listServiceOfferingsCmd()
- self.service_offering.uuid = self.apiClient.listServiceOfferings(self.service_offering)[0].id
-
- self.template = listTemplates.listTemplatesCmd()
- self.template.templatefilter = 'featured'
- self.template.name = 'CentOS'
- self.template.uuid = self.apiClient.listTemplates(self.template)[0].id
-
- def test_DeployVm(self):
- """
- Let's start by defining the attributes of our VM that we will be
- deploying on CloudStack. We will be assuming a single zone is available
- and is configured and all templates are Ready
-
- The hardcoded values are used only for brevity.
- First create the host anti-affinity group for this account
+ @classmethod
+ def setUpClass(cls):
+ cls.api_client = super(TestDeployVmWithAffinityGroup, 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.disk_offering = DiskOffering.create(
+ cls.api_client,
+ cls.services["disk_offering"]
+ )
+ cls.template = get_template(
+ cls.api_client,
+ cls.zone.id,
+ cls.services["ostype"]
+ )
+ cls.services["virtual_machine"]["zoneid"] = cls.zone.id
+ cls.services["volume"]["zoneid"] = cls.zone.id
+
+ cls.services["template"] = cls.template.id
+ cls.services["zoneid"] = cls.zone.id
+
+ cls.account = Account.create(
+ cls.api_client,
+ cls.services["account"],
+ domainid=cls.domain.id
+ )
+
+ cls.services["account"] = cls.account.account.name
+
+ cls.service_offering = ServiceOffering.create(
+ cls.api_client,
+ cls.services["service_offering"]
+ )
+
+ cls.ag = AffinityGroup.create(cls.api_client, cls.services["affinity"], domainid=cls.domain.id)
+
+ cls._cleanup = [
+ cls.service_offering,
+ cls.disk_offering,
+ cls.account,
+ ]
+ return
+
+ @attr(tags=["simulator", "basic", "advanced"])
+ def test_DeployVmAntiAffinityGroup(self):
+ """
+ Deploys a couple of VMs in the same affinity group and verifies they are not on the same host
"""
- createAGCmd = createAffinityGroup.createAffinityGroupCmd()
- createAGCmd.name = 'webvms1'
- createAGCmd.type = 'host anti-affinity'
- createAGCmd.account = self.acct.account
- createAGCmd.domainid = self.acct.domainid
-
- createAGResponse = self.apiClient.createAffinityGroup(createAGCmd)
- self.debug("AffinityGroup %s was created in the job %s"%(createAGResponse.id, createAGResponse.jobid))
-
-
- deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd()
- deployVmCmd.zoneid = self.zone.uuid
- deployVmCmd.templateid = self.template.uuid #CentOS 5.6 builtin
- deployVmCmd.serviceofferingid = self.service_offering.uuid
- deployVmCmd.account = self.acct.account
- deployVmCmd.domainid = self.acct.domainid
- deployVmCmd.affinitygroupnames=[]
- deployVmCmd.affinitygroupnames.append(str(createAGResponse.name))
- deployVmResponse = self.apiClient.deployVirtualMachine(deployVmCmd)
- self.debug("VM %s was deployed in the job %s"%(deployVmResponse.id, deployVmResponse.jobid))
-
- # At this point our VM is expected to be Running. Let's find out what
- # listVirtualMachines tells us about VMs in this account
-
- listVmCmd = listVirtualMachines.listVirtualMachinesCmd()
- listVmCmd.id = deployVmResponse.id
- listVmResponse = self.apiClient.listVirtualMachines(listVmCmd)
-
- self.assertNotEqual(len(listVmResponse), 0, "Check if the list API \
- returns a non-empty response")
-
- vm = listVmResponse[0]
- self.assertEqual(vm.state, "Running", "Check if VM has reached Running state in CS")
-
- VM1hostid = vm.hostid
-
- #Deploy another VM in same affinity group
- deployVm2Cmd = deployVirtualMachine.deployVirtualMachineCmd()
- deployVm2Cmd.zoneid = self.zone.uuid
- deployVm2Cmd.templateid = self.template.uuid #CentOS 5.6 builtin
- deployVm2Cmd.serviceofferingid = self.service_offering.uuid
- deployVm2Cmd.account = self.acct.account
- deployVm2Cmd.domainid = self.acct.domainid
- deployVm2Cmd.affinitygroupnames=[]
- deployVm2Cmd.affinitygroupnames.append(str(createAGResponse.name))
-
- deployVm2Response = self.apiClient.deployVirtualMachine(deployVm2Cmd)
- self.debug("VM2 %s was deployed in the job %s"%(deployVm2Response.id, deployVm2Response.jobid))
-
- # At this point our VM is expected to be Running. Let's find out what
- # listVirtualMachines tells us about VMs in this account
-
- listVm2Cmd = listVirtualMachines.listVirtualMachinesCmd()
- listVm2Cmd.id = deployVm2Response.id
- listVm2Response = self.apiClient.listVirtualMachines(listVm2Cmd)
-
- self.assertNotEqual(len(listVm2Response), 0, "Check if the list API \
- returns a non-empty response")
-
- vm2 = listVm2Response[0]
- self.assertEqual(vm2.state, "Running", "Check if VM has reached Running state in CS")
-
- VM2hostid = vm2.hostid
-
- self.assertNotEqual(VM1hostid, VM2hostid, "The hosts of the 2 VM's in the host anti-affinity group are not different, test failed")
-
- def tearDown(self):
- """
- And finally let us cleanup the resources we created by deleting the
- account. All good unittests are atomic and rerunnable this way
- """
- deleteAcct = deleteAccount.deleteAccountCmd()
- deleteAcct.id = self.acctResponse.account.id
- self.apiClient.deleteAccount(deleteAcct)
- self.testClient.close()
+ #deploy VM1 in affinity group created in setUp
+ vm1 = VirtualMachine.create(
+ self.api_client,
+ self.services["virtual_machine"],
+ templateid=self.template.id,
+ accountid=self.account.account.name,
+ domainid=self.account.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ affinitygroupnames=self.ag.name,
+ mode=self.services["mode"]
+ )
+
+ list_vm1 = list_virtual_machines(
+ self.api_client,
+ id=vm1.id
+ )
+ self.assertEqual(
+ isinstance(list_vm1, list),
+ True,
+ "Check list response returns a valid list"
+ )
+ self.assertNotEqual(
+ len(list_vm1),
+ 0,
+ "Check VM available in List Virtual Machines"
+ )
+ vm1_response = list_vm1[0]
+ self.assertEqual(
+ vm1_response.state,
+ 'Running',
+ msg="VM is not in Running state"
+ )
+ host_of_vm1 = vm1_response.hostid
+
+ #deploy VM2 in affinity group created in setUp
+ vm2 = VirtualMachine.create(
+ self.api_client,
+ self.services["virtual_machine"],
+ templateid=self.template.id,
+ accountid=self.account.account.name,
+ domainid=self.account.account.domainid,
+ serviceofferingid=self.service_offering.id,
+ affinitygroupnames=self.ag.name,
+ mode=self.services["mode"]
+ )
+ list_vm2 = list_virtual_machines(
+ self.api_client,
+ id=self.vm1.id
+ )
+ self.assertEqual(
+ isinstance(list_vm2, list),
+ True,
+ "Check list response returns a valid list"
+ )
+ self.assertNotEqual(
+ len(list_vm2),
+ 0,
+ "Check VM available in List Virtual Machines"
+ )
+ vm2_response = list_vm2[0]
+ self.assertEqual(
+ vm2_response.state,
+ 'Running',
+ msg="VM is not in Running state"
+ )
+ host_of_vm2 = vm2_response.hostid
+
+ self.assertNotEqual(host_of_vm1, host_of_vm2,
+ msg="Both VMs of affinity group %s are on the same host" % self.ag.name)
+
+
+ @classmethod
+ def tearDown(cls):
+ try:
+ cls.api_client = super(TestDeployVmWithAffinityGroup, cls).getClsTestClient().getApiClient()
+ #Clean up, terminate the created templates
+ cleanup_resources(cls.api_client, cls.cleanup)
+ except Exception as e:
+ raise Exception("Warning: Exception during cleanup : %s" % e)
http://git-wip-us.apache.org/repos/asf/cloudstack/blob/79812c25/tools/marvin/marvin/integration/lib/base.py
----------------------------------------------------------------------
diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py
index f3370eb..8c7470e 100644
--- a/tools/marvin/marvin/integration/lib/base.py
+++ b/tools/marvin/marvin/integration/lib/base.py
@@ -223,7 +223,7 @@ class VirtualMachine:
def create(cls, apiclient, services, templateid=None, accountid=None,
domainid=None, zoneid=None, networkids=None, serviceofferingid=None,
securitygroupids=None, projectid=None, startvm=None,
- diskofferingid=None, hostid=None, mode='basic'):
+ diskofferingid=None, affinitygroupname=None, hostid=None, mode='basic'):
"""Create the instance"""
cmd = deployVirtualMachine.deployVirtualMachineCmd()
@@ -268,6 +268,9 @@ class VirtualMachine:
if "userdata" in services:
cmd.userdata = base64.b64encode(services["userdata"])
+ if "affinitygroupnames" in services:
+ cmd.affinitygroupnames = services["affinitygroupnames"]
+
if projectid:
cmd.projectid = projectid
@@ -2424,3 +2427,27 @@ class VPC:
cmd = listVPCs.listVPCsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVPCs(cmd))
+
+
+class AffinityGroup:
+ def __init__(self, items):
+ self.__dict__.update(items)
+
+ @classmethod
+ def create(cls, apiclient, services, account=None, domainid=None):
+ agCmd = createAffinityGroup.createAffinityGroupCmd()
+ agCmd.name = services['name']
+ agCmd.displayText = services['displaytext'] if 'displaytext' in services else services['name']
+ agCmd.type = services['type']
+ agCmd.account = services['account'] if 'account' in services else account
+ agCmd.domainid = services['domainid'] if 'domainid' in services else domainid
+
+ def update(self):
+ pass
+
+ def delete(self):
+ pass
+
+ @classmethod
+ def list(cls):
+ pass
\ No newline at end of file