Files from the demo are now available in the sandbox

This commit is contained in:
Prasanna Santhanam 2012-05-17 18:10:55 +05:30
parent 0af5888207
commit 051ba3cd70
14 changed files with 2729 additions and 183 deletions

View File

@ -1,4 +0,0 @@
Demo files for use with the tutorial on "Testing with Python".
testDeployVM.py - to be run against a 2.2.y installation of management server
testSshDeployVM.py - to be run against a 3.0.x installation of management server

View File

@ -0,0 +1,8 @@
Download Marvin source from hudson
Install Marvin:
pip install Marvin-0.1.0.tar.gz
To Run the test:
python -m marvin.deployAndRun -c demo.cfg -t /tmp/t.log -r /tmp/r.log -f testSshDeployVM.py -l

View File

@ -14,77 +14,30 @@
from cloudstackTestCase import *
from remoteSSHClient import remoteSSHClient
import marvin
from marvin.cloudstackTestCase import *
from marvin.remoteSSHClient import remoteSSHClient
import unittest
import hashlib
import random
import string
class TestDeployVm(cloudstackTestCase):
@UserName('demo', 'ROOT', '0')
class TestSshDeployVm(cloudstackTestCase):
"""
This test deploys a virtual machine into a user account
using the small service offering and builtin template
"""
@classmethod
def setUpClass(cls):
"""
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()
acctName = 'bugs-'+''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6)) #randomly generated account
def setUp(self):
self.apiClient = self.testClient.getApiClient()
cls.apiClient = super(TestDeployVm, cls).getClsTestClient().getApiClient()
cls.acct = createAccount.createAccountCmd() #The createAccount command
cls.acct.accounttype = 0 #We need a regular user. admins have accounttype=1
cls.acct.firstname = 'bugs'
cls.acct.lastname = 'bunny' #What's up doc?
cls.acct.password = mdf_pass #The md5 hashed password string
cls.acct.username = acctName
cls.acct.email = 'bugs@rabbithole.com'
cls.acct.account = acctName
cls.acct.domainid = 1 #The default ROOT domain
cls.acctResponse = cls.apiClient.createAccount(cls.acct)
def setUpNAT(self, virtualmachineid):
listSourceNat = listPublicIpAddresses.listPublicIpAddressesCmd()
listSourceNat.account = self.acct.account
listSourceNat.domainid = self.acct.domainid
listSourceNat.issourcenat = True
listsnatresponse = self.apiClient.listPublicIpAddresses(listSourceNat)
self.assertNotEqual(len(listsnatresponse), 0, "Found a source NAT for the acct %s"%self.acct.account)
snatid = listsnatresponse[0].id
snatip = listsnatresponse[0].ipaddress
try:
createFwRule = createFirewallRule.createFirewallRuleCmd()
createFwRule.cidrlist = "0.0.0.0/0"
createFwRule.startport = 22
createFwRule.endport = 22
createFwRule.ipaddressid = snatid
createFwRule.protocol = "tcp"
createfwresponse = self.apiClient.createFirewallRule(createFwRule)
createPfRule = createPortForwardingRule.createPortForwardingRuleCmd()
createPfRule.privateport = 22
createPfRule.publicport = 22
createPfRule.virtualmachineid = virtualmachineid
createPfRule.ipaddressid = snatid
createPfRule.protocol = "tcp"
createpfresponse = self.apiClient.createPortForwardingRule(createPfRule)
except e:
self.debug("Failed to create PF rule in account %s due to %s"%(self.acct.account, e))
raise e
finally:
return snatip
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):
"""
@ -95,11 +48,9 @@ class TestDeployVm(cloudstackTestCase):
The hardcoded values are used only for brevity.
"""
deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd()
deployVmCmd.zoneid = 1
deployVmCmd.account = self.acct.account
deployVmCmd.domainid = self.acct.domainid
deployVmCmd.templateid = 5 #CentOS 5.6 builtin
deployVmCmd.serviceofferingid = 1
deployVmCmd.zoneid = self.zone.uuid
deployVmCmd.templateid = self.template.uuid #CentOS 5.6 builtin
deployVmCmd.serviceofferingid = self.service_offering.uuid
deployVmResponse = self.apiClient.deployVirtualMachine(deployVmCmd)
self.debug("VM %s was deployed in the job %s"%(deployVmResponse.id, deployVmResponse.jobid))
@ -115,6 +66,8 @@ class TestDeployVm(cloudstackTestCase):
returns a non-empty response")
vm = listVmResponse[0]
self.assertEqual(vm.state, "Running", "Check if VM has reached Running state in CS")
hostname = vm.name
nattedip = self.setUpNAT(vm.id)
@ -126,18 +79,46 @@ class TestDeployVm(cloudstackTestCase):
a state of running")
# SSH login and compare hostname
ssh_client = remoteSSHClient(nattedip, 22, "root", "password")
self.debug("Attempting to SSH into %s over %s of %s"%(nattedip, "22", vm.name))
ssh_client = remoteSSHClient(nattedip, "22", "root", "password")
stdout = ssh_client.execute("hostname")
self.assertEqual(hostname, stdout[0], "cloudstack VM name and hostname match")
self.assertEqual(hostname, stdout[0], "cloudstack VM name and hostname \
do not match")
@classmethod
def tearDownClass(cls):
"""
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 = cls.acctResponse.account.id
cls.apiClient.deleteAccount(deleteAcct)
def setUpNAT(self, virtualmachineid):
listSourceNat = listPublicIpAddresses.listPublicIpAddressesCmd()
listSourceNat.issourcenat = True
listsnatresponse = self.apiClient.listPublicIpAddresses(listSourceNat)
self.assertNotEqual(len(listsnatresponse), 0, "Found a source NAT for the account user")
snatid = listsnatresponse[0].id
snatip = listsnatresponse[0].ipaddress
try:
createFwRule = createFirewallRule.createFirewallRuleCmd()
createFwRule.cidrlist = "0.0.0.0/0"
createFwRule.startport = 22
createFwRule.endport = 22
createFwRule.ipaddressid = snatid
createFwRule.protocol = "tcp"
createfwresponse = self.apiClient.createFirewallRule(createFwRule)
createPfRule = createPortForwardingRule.createPortForwardingRuleCmd()
createPfRule.publicport = 22
createPfRule.privateport = 22
createPfRule.virtualmachineid = virtualmachineid
createPfRule.ipaddressid = snatid
createPfRule.protocol = "tcp"
createpfresponse = self.apiClient.createPortForwardingRule(createPfRule)
except e:
self.debug("Failed to create PF rule in the account due to %s"%e)
raise e
finally:
self.debug("Successfully programmed PF rule for :%s"%snatip)
return snatip
def tearDown(self):
self.testClient.close()

View File

@ -0,0 +1,12 @@
To generate the config
Alter the .properties file to point to your simulator installed environment
python simulator_setup.py -i simulatordemo.properties -o simulatordemo.cfg
To deploy the environment and run the tests
python -m marvin.deployAndRun -c simulatordemo.cfg -t /tmp/t.log -r /tmp/r.log -d testcase

View File

@ -0,0 +1,117 @@
#!/usr/bin/env python
from ConfigParser import SafeConfigParser
from optparse import OptionParser
from configGenerator import *
import random
def getGlobalSettings(config):
for k, v in dict(config.items('globals')).iteritems():
cfg = configuration()
cfg.name = k
cfg.value = v
yield cfg
def describeResources(config):
zs = cloudstackConfiguration()
z = zone()
z.dns1 = config.get('environment', 'dns')
z.internaldns1 = config.get('environment', 'dns')
z.name = 'Sandbox-%s'%(config.get('environment', 'hypervisor'))
z.networktype = 'Advanced'
z.guestcidraddress = '10.1.1.0/24'
z.vlan = config.get('cloudstack', 'zone.vlan')
p = pod()
p.name = 'POD0'
p.gateway = config.get('cloudstack', 'private.gateway')
p.startip = config.get('cloudstack', 'private.pod.startip')
p.endip = config.get('cloudstack', 'private.pod.endip')
p.netmask = '255.255.255.0'
v = iprange()
v.gateway = config.get('cloudstack', 'public.gateway')
v.startip = config.get('cloudstack', 'public.vlan.startip')
v.endip = config.get('cloudstack', 'public.vlan.endip')
v.netmask = '255.255.255.0'
v.vlan = config.get('cloudstack', 'public.vlan')
z.ipranges.append(v)
c = cluster()
c.clustername = 'C0'
c.hypervisor = config.get('environment', 'hypervisor')
c.clustertype = 'CloudManaged'
h = host()
h.username = 'root'
h.password = 'password'
h.url = 'http://%s'%(config.get('cloudstack', 'host'))
c.hosts.append(h)
h = host()
h.username = 'root'
h.password = 'password'
h.url = 'http://%s'%(config.get('cloudstack', 'host2'))
c.hosts.append(h)
ps = primaryStorage()
ps.name = 'PS0'
ps.url = config.get('cloudstack', 'pool')
c.primaryStorages.append(ps)
p.clusters.append(c)
z.pods.append(p)
secondary = secondaryStorage()
secondary.url = config.get('cloudstack', 'secondary')
z.secondaryStorages.append(secondary)
'''Add zone'''
zs.zones.append(z)
'''Add mgt server'''
mgt = managementServer()
mgt.mgtSvrIp = config.get('environment', 'mshost')
zs.mgtSvr.append(mgt)
'''Add a database'''
db = dbServer()
db.dbSvr = config.get('environment', 'dbhost')
db.passwd = config.get('environment', 'dbpasswd')
zs.dbSvr = db
'''Add some configuration'''
[zs.globalConfig.append(cfg) for cfg in getGlobalSettings(config)]
''''add loggers'''
testClientLogger = logger()
testClientLogger.name = 'TestClient'
testClientLogger.file = '/var/log/testclient.log'
testCaseLogger = logger()
testCaseLogger.name = 'TestCase'
testCaseLogger.file = '/var/log/testcase.log'
zs.logger.append(testClientLogger)
zs.logger.append(testCaseLogger)
return zs
if __name__ == '__main__':
parser = OptionParser()
parser.add_option('-i', '--input', action='store', default='setup.properties', \
dest='input', help='file containing environment setup information')
parser.add_option('-o', '--output', action='store', default='./sandbox.cfg', \
dest='output', help='path where environment json will be generated')
(opts, args) = parser.parse_args()
cfg_parser = SafeConfigParser()
cfg_parser.read(opts.input)
cfg = describeResources(cfg_parser)
generate_setup_config(cfg, opts.output)

View File

@ -0,0 +1,39 @@
[globals]
expunge.delay=60
expunge.interval=60
storage.cleanup.interval=300
account.cleanup.interval=600
expunge.workers=3
workers=10
use.user.concentrated.pod.allocation=false
vm.allocation.algorithm=random
vm.op.wait.interval=5
guest.domain.suffix=sandbox.simulator
instance.name=QA
direct.agent.load.size=1000
default.page.size=10000
check.pod.cidrs=true
secstorage.allowed.internal.sites=10.147.28.0/24
[environment]
dns=4.2.2.2
mshost=10.223.132.171
dbhost=10.223.132.171
dbpasswd=
hypervisor=simulator
[cloudstack]
zone.vlan=100-200
#pod configuration
private.gateway=172.16.15.1
private.pod.startip=172.16.15.2
private.pod.endip=172.16.15.200
#public vlan range
public.gateway=192.168.2.1
public.vlan=50
public.vlan.startip=192.168.2.2
public.vlan.endip=192.168.2.200
#hosts
host=simulator.host.vmops.com
host2=simulator-2.host.vmops.com
#pools
pool=nfs://172.16.15.30/export/share/primary
secondary=nfs://172.16.15.30/export/share/secondary

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,447 @@
# -*- encoding: utf-8 -*-
#
# Copyright (c) 2012 Citrix. All rights reserved.
#
"""Common functions
"""
#Import Local Modules
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
import marvin.remoteSSHClient
from utils import *
from base import *
#Import System modules
import time
def get_domain(apiclient, services=None):
"Returns a default domain"
cmd = listDomains.listDomainsCmd()
if services:
if "domainid" in services:
cmd.id = services["domainid"]
domains = apiclient.listDomains(cmd)
if isinstance(domains, list):
return domains[0]
else:
raise Exception("Failed to find specified domain.")
def get_zone(apiclient, services=None):
"Returns a default zone"
cmd = listZones.listZonesCmd()
if services:
if "zoneid" in services:
cmd.id = services["zoneid"]
zones = apiclient.listZones(cmd)
if isinstance(zones, list):
return zones[0]
else:
raise Exception("Failed to find specified zone.")
def get_pod(apiclient, zoneid, services=None):
"Returns a default pod for specified zone"
cmd = listPods.listPodsCmd()
cmd.zoneid = zoneid
if services:
if "podid" in services:
cmd.id = services["podid"]
pods = apiclient.listPods(cmd)
if isinstance(pods, list):
return pods[0]
else:
raise Exception("Exception: Failed to find specified pod.")
def get_template(apiclient, zoneid, ostypeid=12, services=None):
"Returns a template"
cmd = listTemplates.listTemplatesCmd()
cmd.templatefilter = 'featured'
cmd.zoneid = zoneid
if services:
if "template" in services:
cmd.id = services["template"]
list_templates = apiclient.listTemplates(cmd)
for template in list_templates:
if template.ostypeid == ostypeid:
return template
raise Exception("Exception: Failed to find template with OSTypeID: %s" %
ostypeid)
return
def download_systemplates_sec_storage(server, services):
"""Download System templates on sec storage"""
try:
# Login to management server
ssh = marvin.remoteSSHClient.remoteSSHClient(
server["ipaddress"],
server["port"],
server["username"],
server["password"]
)
except Exception as e:
raise Exception("SSH access failted for server with IP address: %s" %
server["ipaddess"])
# Mount Secondary Storage on Management Server
cmds = [
"mkdir -p %s" % services["mnt_dir"],
"mount -t nfs %s:/%s %s" % (
services["sec_storage"],
services["path"],
services["mnt_dir"]
),
"%s -m %s -u %s -h %s -F" % (
services["command"],
services["mnt_dir"],
services["download_url"],
services["hypervisor"]
)
]
for c in cmds:
result = ssh.execute(c)
res = str(result)
# Unmount the Secondary storage
ssh.execute("umount %s" % (services["mnt_dir"]))
if res.count("Successfully installed system VM template") == 1:
return
else:
raise Exception("Failed to download System Templates on Sec Storage")
return
def wait_for_ssvms(apiclient, zoneid, podid, interval=60):
"""After setup wait for SSVMs to come Up"""
time.sleep(interval)
timeout = 40
while True:
list_ssvm_response = list_ssvms(
apiclient,
systemvmtype='secondarystoragevm',
zoneid=zoneid,
podid=podid
)
ssvm = list_ssvm_response[0]
if ssvm.state != 'Running':
# Sleep to ensure SSVMs are Up and Running
time.sleep(30)
timeout = timeout - 1
elif ssvm.state == 'Running':
break
elif timeout == 0:
raise Exception("SSVM failed to come up")
break
timeout = 40
while True:
list_ssvm_response = list_ssvms(
apiclient,
systemvmtype='consoleproxy',
zoneid=zoneid,
podid=podid
)
cpvm = list_ssvm_response[0]
if cpvm.state != 'Running':
# Sleep to ensure SSVMs are Up and Running
time.sleep(interval)
timeout = timeout - 1
elif cpvm.state == 'Running':
break
elif timeout == 0:
raise Exception("CPVM failed to come up")
break
return
def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip, interval=60):
"""After setup wait till builtin templates are downloaded"""
# Change IPTABLES Rules
result = get_process_status(
host["ipaddress"],
host["port"],
host["username"],
host["password"],
linklocalip,
"iptables -P INPUT ACCEPT"
)
time.sleep(interval)
# Find the BUILTIN Templates for given Zone, Hypervisor
list_template_response = list_templates(
apiclient,
hypervisor=hypervisor,
zoneid=zoneid,
templatefilter='self'
)
if not isinstance(list_template_response, list):
raise Exception("Failed to download BUILTIN templates")
# Ensure all BUILTIN templates are downloaded
templateid = None
for template in list_template_response:
if template.templatetype == "BUILTIN":
templateid = template.id
# Sleep to ensure that template is in downloading state after adding
# Sec storage
time.sleep(interval)
while True:
template_response = list_templates(
apiclient,
id=templateid,
zoneid=zoneid,
templatefilter='self'
)
template = template_response[0]
# If template is ready,
# template.status = Download Complete
# Downloading - x% Downloaded
# Error - Any other string
if template.status == 'Download Complete':
break
elif 'Downloaded' in template.status:
time.sleep(interval)
elif 'Installing' not in template.status:
raise Exception("ErrorInDownload")
return
def update_resource_limit(apiclient, resourcetype, account=None, domainid=None,
max=None):
"""Updates the resource limit to 'max' for given account"""
cmd = updateResourceLimit.updateResourceLimitCmd()
cmd.resourcetype = resourcetype
if account:
cmd.account = account
if domainid:
cmd.domainid = domainid
if max:
cmd.max = max
apiclient.updateResourceLimit(cmd)
return
def list_routers(apiclient, **kwargs):
"""List all Routers matching criteria"""
cmd = listRouters.listRoutersCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listRouters(cmd))
def list_zones(apiclient, **kwargs):
"""List all Zones matching criteria"""
cmd = listZones.listZonesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listZones(cmd))
def list_networks(apiclient, **kwargs):
"""List all Networks matching criteria"""
cmd = listNetworks.listNetworksCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listNetworks(cmd))
def list_clusters(apiclient, **kwargs):
"""List all Clusters matching criteria"""
cmd = listClusters.listClustersCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listClusters(cmd))
def list_ssvms(apiclient, **kwargs):
"""List all SSVMs matching criteria"""
cmd = listSystemVms.listSystemVmsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listSystemVms(cmd))
def list_storage_pools(apiclient, **kwargs):
"""List all storage pools matching criteria"""
cmd = listStoragePools.listStoragePoolsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listStoragePools(cmd))
def list_virtual_machines(apiclient, **kwargs):
"""List all VMs matching criteria"""
cmd = listVirtualMachines.listVirtualMachinesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVirtualMachines(cmd))
def list_hosts(apiclient, **kwargs):
"""List all Hosts matching criteria"""
cmd = listHosts.listHostsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listHosts(cmd))
def list_configurations(apiclient, **kwargs):
"""List configuration with specified name"""
cmd = listConfigurations.listConfigurationsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listConfigurations(cmd))
def list_publicIP(apiclient, **kwargs):
"""List all Public IPs matching criteria"""
cmd = listPublicIpAddresses.listPublicIpAddressesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listPublicIpAddresses(cmd))
def list_nat_rules(apiclient, **kwargs):
"""List all NAT rules matching criteria"""
cmd = listPortForwardingRules.listPortForwardingRulesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listPortForwardingRules(cmd))
def list_lb_rules(apiclient, **kwargs):
"""List all Load balancing rules matching criteria"""
cmd = listLoadBalancerRules.listLoadBalancerRulesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listLoadBalancerRules(cmd))
def list_lb_instances(apiclient, **kwargs):
"""List all Load balancing instances matching criteria"""
cmd = listLoadBalancerRuleInstances.listLoadBalancerRuleInstancesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listLoadBalancerRuleInstances(cmd))
def list_firewall_rules(apiclient, **kwargs):
"""List all Firewall Rules matching criteria"""
cmd = listFirewallRules.listFirewallRulesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listFirewallRules(cmd))
def list_volumes(apiclient, **kwargs):
"""List all volumes matching criteria"""
cmd = listVolumes.listVolumesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVolumes(cmd))
def list_isos(apiclient, **kwargs):
"""Lists all available ISO files."""
cmd = listIsos.listIsosCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listIsos(cmd))
def list_snapshots(apiclient, **kwargs):
"""List all snapshots matching criteria"""
cmd = listSnapshots.listSnapshotsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listSnapshots(cmd))
def list_templates(apiclient, **kwargs):
"""List all templates matching criteria"""
cmd = listTemplates.listTemplatesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listTemplates(cmd))
def list_domains(apiclient, **kwargs):
"""Lists domains"""
cmd = listDomains.listDomainsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listDomains(cmd))
def list_accounts(apiclient, **kwargs):
"""Lists accounts and provides detailed account information for
listed accounts"""
cmd = listAccounts.listAccountsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listAccounts(cmd))
def list_users(apiclient, **kwargs):
"""Lists users and provides detailed account information for
listed users"""
cmd = listUsers.listUsersCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listUsers(cmd))
def list_snapshot_policy(apiclient, **kwargs):
"""Lists snapshot policies."""
cmd = listSnapshotPolicies.listSnapshotPoliciesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listSnapshotPolicies(cmd))
def list_events(apiclient, **kwargs):
"""Lists events"""
cmd = listEvents.listEventsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listEvents(cmd))
def list_disk_offering(apiclient, **kwargs):
"""Lists all available disk offerings."""
cmd = listDiskOfferings.listDiskOfferingsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listDiskOfferings(cmd))
def list_service_offering(apiclient, **kwargs):
"""Lists all available service offerings."""
cmd = listServiceOfferings.listServiceOfferingsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listServiceOfferings(cmd))
def list_vlan_ipranges(apiclient, **kwargs):
"""Lists all VLAN IP ranges."""
cmd = listVlanIpRanges.listVlanIpRangesCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listVlanIpRanges(cmd))
def list_usage_records(apiclient, **kwargs):
"""Lists usage records for accounts"""
cmd = listUsageRecords.listUsageRecordsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listUsageRecords(cmd))
def list_network_offerings(apiclient, **kwargs):
"""Lists network offerings"""
cmd = listNetworkOfferings.listNetworkOfferingsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listNetworkOfferings(cmd))
def list_resource_limits(apiclient, **kwargs):
"""Lists resource limits"""
cmd = listResourceLimits.listResourceLimitsCmd()
[setattr(cmd, k, v) for k, v in kwargs.items()]
return(apiclient.listResourceLimits(cmd))

View File

@ -0,0 +1,102 @@
# -*- encoding: utf-8 -*-
#
# Copyright (c) 2012 Citrix. All rights reserved.
#
"""Utilities functions
"""
import time
import marvin.remoteSSHClient
from marvin.cloudstackAPI import *
import marvin.cloudstackConnection
from marvin.remoteSSHClient import remoteSSHClient
#from marvin.cloudstackConnection import cloudConnection
import marvin.configGenerator
import logging
import string
import random
def random_gen(size=6, chars=string.ascii_uppercase + string.digits):
"""Generate Random Strings of variable length"""
return ''.join(random.choice(chars) for x in range(size))
def cleanup_resources(api_client, resources):
"""Delete resources"""
for obj in resources:
obj.delete(api_client)
def is_server_ssh_ready(ipaddress, port, username, password, retries=50):
"""Return ssh handle else wait till sshd is running"""
loop_cnt = retries
while True:
try:
ssh = marvin.remoteSSHClient.remoteSSHClient(
ipaddress,
port,
username,
password
)
except Exception as e:
if loop_cnt == 0:
raise e
loop_cnt = loop_cnt - 1
time.sleep(30)
else:
return ssh
def format_volume_to_ext3(ssh_client, device="/dev/sda"):
"""Format attached storage to ext3 fs"""
cmds = [
"echo -e 'n\np\n1\n\n\nw' | fdisk %s" % device,
"mkfs.ext3 %s1" % device,
]
for c in cmds:
ssh_client.execute(c)
def fetch_api_client(config_file='datacenterCfg'):
"""Fetch the Cloudstack API Client"""
config = configGenerator.get_setup_config(config_file)
mgt = config.mgtSvr[0]
testClientLogger = logging.getLogger("testClient")
asyncTimeout = 3600
return cloudstackAPIClient.CloudStackAPIClient(
cloudstackConnection.cloudConnection(
mgt.mgtSvrIp,
mgt.port,
mgt.apiKey,
mgt.securityKey,
asyncTimeout,
testClientLogger
)
)
def get_process_status(hostip, port, username, password, linklocalip, process):
"""Double hop and returns a process status"""
#SSH to the machine
ssh = marvin.remoteSSHClient.remoteSSHClient(
hostip,
port,
username,
password
)
ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no "
ssh_command = ssh_command + "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" \
% (linklocalip, process)
# Double hop into router
timeout = 5
# Ensure the SSH login is successful
while True:
res = ssh.execute(ssh_command)
if res[0] != "Host key verification failed.":
break
elif timeout == 0:
break
time.sleep(5)
timeout = timeout - 1
return res

View File

@ -0,0 +1,519 @@
# -*- encoding: utf-8 -*-
# Copyright 2012 Citrix Systems, Inc. Licensed under the
# Apache License, Version 2.0 (the "License"); you may not use this
# file except in compliance with the License. Citrix Systems, Inc.
# reserves all rights not expressly granted by 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.
#
# Automatically generated by addcopyright.py at 04/03/2012
""" BVT tests for Virtual Machine Life Cycle
"""
#Import Local Modules
import marvin
from marvin.cloudstackTestCase import *
from marvin.cloudstackAPI import *
from marvin.remoteSSHClient import remoteSSHClient
from testcase.libs.utils import *
from testcase.libs.base import *
from testcase.libs.common import *
#Import System modules
import time
class Services:
"""Test VM Life Cycle Services
"""
def __init__(self):
self.services = {
"disk_offering":{
"displaytext": "Small",
"name": "Small",
"disksize": 1
},
"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",
},
"small":
# Create a small virtual machine instance with disk offering
{
"displayname": "testserver",
"username": "root", # VM creds for SSH
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"medium": # Create a medium virtual machine instance
{
"displayname": "testserver",
"username": "root",
"password": "password",
"ssh_port": 22,
"hypervisor": 'XenServer',
"privateport": 22,
"publicport": 22,
"protocol": 'TCP',
},
"service_offerings":
{
"tiny":
{
"name": "Tiny Instance",
"displaytext": "Tiny Instance",
"cpunumber": 1,
"cpuspeed": 100, # in MHz
"memory": 64, # In MBs
},
"small":
{
# Small service offering ID to for change VM
# service offering from medium to small
"name": "Small Instance",
"displaytext": "Small Instance",
"cpunumber": 1,
"cpuspeed": 500,
"memory": 256
},
"medium":
{
# Medium service offering ID to for
# change VM service offering from small to medium
"name": "Medium Instance",
"displaytext": "Medium Instance",
"cpunumber": 1,
"cpuspeed": 1000,
"memory": 1024
}
},
"sleep": 60,
"timeout": 10,
#Migrate VM to hostid
"ostypeid": 'ccde7156-9b8b-4fb9-bf08-530dedf4dc61',
# CentOS 5.3 (64-bit)
"mode":'advanced',
}
class TestDeployVM(cloudstackTestCase):
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
self.services = Services().services
# Get Zone, Domain and templates
domain = get_domain(self.apiclient, self.services)
zone = get_zone(self.apiclient, self.services)
template = get_template(
self.apiclient,
zone.id,
self.services["ostypeid"]
)
# Set Zones and disk offerings
self.services["small"]["zoneid"] = zone.id
self.services["small"]["template"] = template.id
self.services["medium"]["zoneid"] = zone.id
self.services["medium"]["template"] = template.id
# Create Account, VMs, NAT Rules etc
self.account = Account.create(
self.apiclient,
self.services["account"],
domainid=domain.id
)
self.service_offering = ServiceOffering.create(
self.apiclient,
self.services["service_offerings"]["tiny"]
)
# Cleanup
self.cleanup = [
self.service_offering,
self.account
]
def test_deploy_vm(self):
"""Test Deploy Virtual Machine
"""
# Validate the following:
# 1. Virtual Machine is accessible via SSH
# 2. listVirtualMachines returns accurate information
# 3. The Cloud Database contains the valid information
self.virtual_machine = VirtualMachine.create(
self.apiclient,
self.services["small"],
accountid=self.account.account.name,
domainid=self.account.account.domainid,
serviceofferingid=self.service_offering.id
)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.virtual_machine.id
)
self.debug(
"Verify listVirtualMachines response for virtual machine: %s" \
% self.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"
)
vm_response = list_vm_response[0]
self.assertEqual(
vm_response.id,
self.virtual_machine.id,
"Check virtual machine id in listVirtualMachines"
)
self.assertEqual(
vm_response.displayname,
self.virtual_machine.displayname,
"Check virtual machine displayname in listVirtualMachines"
)
return
def tearDown(self):
try:
cleanup_resources(self.apiclient, self.cleanup)
except Exception as e:
self.debug("Warning! Exception in tearDown: %s" % e)
class TestVMLifeCycle(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient()
cls.services = Services().services
# Get Zone, Domain and templates
domain = get_domain(cls.api_client, cls.services)
zone = get_zone(cls.api_client, cls.services)
template = get_template(
cls.api_client,
zone.id,
cls.services["ostypeid"]
)
# Set Zones and disk offerings
cls.services["small"]["zoneid"] = zone.id
cls.services["small"]["template"] = template.id
cls.services["medium"]["zoneid"] = zone.id
cls.services["medium"]["template"] = template.id
# Create VMs, NAT Rules etc
cls.account = Account.create(
cls.api_client,
cls.services["account"],
domainid=domain.id
)
cls.small_offering = ServiceOffering.create(
cls.api_client,
cls.services["service_offerings"]["small"]
)
cls.medium_offering = ServiceOffering.create(
cls.api_client,
cls.services["service_offerings"]["medium"]
)
#create small and large virtual machines
cls.small_virtual_machine = VirtualMachine.create(
cls.api_client,
cls.services["small"],
accountid=cls.account.account.name,
domainid=cls.account.account.domainid,
serviceofferingid=cls.small_offering.id,
mode=cls.services["mode"]
)
cls.medium_virtual_machine = VirtualMachine.create(
cls.api_client,
cls.services["medium"],
accountid=cls.account.account.name,
domainid=cls.account.account.domainid,
serviceofferingid=cls.medium_offering.id,
mode=cls.services["mode"]
)
cls.virtual_machine = VirtualMachine.create(
cls.api_client,
cls.services["small"],
accountid=cls.account.account.name,
domainid=cls.account.account.domainid,
serviceofferingid=cls.small_offering.id,
mode=cls.services["mode"]
)
cls._cleanup = [
cls.small_offering,
cls.medium_offering,
cls.account
]
@classmethod
def tearDownClass(cls):
cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient()
cleanup_resources(cls.api_client, cls._cleanup)
return
def setUp(self):
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
self.cleanup = []
def tearDown(self):
#Clean up, terminate the created ISOs
cleanup_resources(self.apiclient, self.cleanup)
return
def test_01_stop_vm(self):
"""Test Stop Virtual Machine
"""
# Validate the following
# 1. Should Not be able to login to the VM.
# 2. listVM command should return
# this VM.State of this VM should be ""Stopped"".
self.debug("Stopping VM - ID: %s" % self.virtual_machine.id)
self.small_virtual_machine.stop(self.apiclient)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.small_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,
"Stopped",
"Check virtual machine is in stopped state"
)
return
def test_02_start_vm(self):
"""Test Start Virtual Machine
"""
# Validate the following
# 1. listVM command should return this VM.State
# of this VM should be Running".
self.debug("Starting VM - ID: %s" % self.virtual_machine.id)
self.small_virtual_machine.start(self.apiclient)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.small_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 avaliable in List Virtual Machines"
)
self.debug(
"Verify listVirtualMachines response for virtual machine: %s" \
% self.small_virtual_machine.id
)
self.assertEqual(
list_vm_response[0].state,
"Running",
"Check virtual machine is in running state"
)
return
def test_04_change_offering_small(self):
"""Change Offering to a small capacity
"""
# Validate the following
# 1. Log in to the Vm .We should see that the CPU and memory Info of
# this Vm matches the one specified for "Small" service offering.
# 2. Using listVM command verify that this Vm
# has Small service offering Id.
self.debug("Stopping VM - ID: %s" % self.medium_virtual_machine.id)
self.medium_virtual_machine.stop(self.apiclient)
# Poll listVM to ensure VM is stopped properly
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=self.medium_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
self.debug("Change Service offering VM - ID: %s" %
self.medium_virtual_machine.id)
cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
cmd.id = self.medium_virtual_machine.id
cmd.serviceofferingid = self.small_offering.id
self.apiclient.changeServiceForVirtualMachine(cmd)
self.debug("Starting VM - ID: %s" % self.medium_virtual_machine.id)
self.medium_virtual_machine.start(self.apiclient)
# Poll listVM to ensure VM is started properly
timeout = self.services["timeout"]
while True:
time.sleep(self.services["sleep"])
# Ensure that VM is in running state
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.medium_virtual_machine.id
)
if isinstance(list_vm_response, list):
vm = list_vm_response[0]
if vm.state == 'Running':
self.debug("VM state: %s" % vm.state)
break
if timeout == 0:
raise Exception(
"Failed to start VM (ID: %s) after changing service offering" % vm.id)
timeout = timeout - 1
return
def test_06_destroy_vm(self):
"""Test destroy Virtual Machine
"""
# Validate the following
# 1. Should not be able to login to the VM.
# 2. listVM command should return this VM.State
# of this VM should be "Destroyed".
self.debug("Destroy VM - ID: %s" % self.small_virtual_machine.id)
self.small_virtual_machine.delete(self.apiclient)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.small_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 avaliable in List Virtual Machines"
)
self.assertEqual(
list_vm_response[0].state,
"Destroyed",
"Check virtual machine is in destroyed state"
)
return
def test_07_restore_vm(self):
"""Test recover Virtual Machine
"""
# Validate the following
# 1. listVM command should return this VM.
# State of this VM should be "Stopped".
# 2. We should be able to Start this VM successfully.
self.debug("Recovering VM - ID: %s" % self.small_virtual_machine.id)
cmd = recoverVirtualMachine.recoverVirtualMachineCmd()
cmd.id = self.small_virtual_machine.id
self.apiclient.recoverVirtualMachine(cmd)
list_vm_response = list_virtual_machines(
self.apiclient,
id=self.small_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 avaliable in List Virtual Machines"
)
self.assertEqual(
list_vm_response[0].state,
"Stopped",
"Check virtual machine is in Stopped state"
)
return

View File

@ -1,98 +0,0 @@
#!/usr/bin/env python
# Copyright 2012 Citrix Systems, Inc. Licensed under the
# Apache License, Version 2.0 (the "License"); you may not use this
# file except in compliance with the License. Citrix Systems, Inc.
# reserves all rights not expressly granted by 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.
#
# Automatically generated by addcopyright.py at 04/03/2012
from cloudstackTestCase import *
import unittest
import hashlib
import random
class TestDeployVm(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 = 'bugs'
self.acct.lastname = 'bunny' #What's up doc?
self.acct.password = mdf_pass #The md5 hashed password string
self.acct.username = 'bugs'
self.acct.email = 'bugs@rabbithole.com'
self.acct.account = 'bugs'
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
self.debug("successfully created account: %s, user: %s, id: \
%s"%(self.acctResponse.account.account, \
self.acctResponse.account.username, \
self.acctResponse.account.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.
"""
deployVmCmd = deployVirtualMachine.deployVirtualMachineCmd()
deployVmCmd.zoneid = 1
deployVmCmd.account = self.acct.account
deployVmCmd.domainid = self.acct.domainid
deployVmCmd.templateid = 2
deployVmCmd.serviceofferingid = 1
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.id, deployVmResponse.id, "Check if the VM returned \
is the same as the one we deployed")
self.assertEqual(vm.state, "Running", "Check if VM has reached \
a state of running")
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)