mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Moving smoke tests and component tests into the test folder
Reviewed-by: pychecker
This commit is contained in:
parent
a32f675875
commit
e29b0dafb6
0
test/integration/__init__.py
Normal file
0
test/integration/__init__.py
Normal file
41
test/integration/component/README
Normal file
41
test/integration/component/README
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
P1 Cases
|
||||||
|
--------------------------------------
|
||||||
|
These test cases are the core functionality tests that ensure the application is stable and can be tested thoroughly.
|
||||||
|
These P1 cases definitions are located at : https://docs.google.com/a/clogeny.com/spreadsheet/ccc?key=0Aq5M2ldK6eyedDJBa0EzM0RPNmdVNVZOWnFnOVJJcHc&hl=en_US
|
||||||
|
|
||||||
|
|
||||||
|
Guidelines
|
||||||
|
----------
|
||||||
|
P1 test cases are being developed using Python's unittests2. Following are certain guidelines being followed
|
||||||
|
1. Tests exercised for the same resource should ideally be present under a single suite or file.
|
||||||
|
|
||||||
|
2. Time-consuming operations that create new cloud resources like server creation, volume creation etc
|
||||||
|
should not necessarily be exercised per unit test. The resources can be shared by creating them at
|
||||||
|
the class-level using setUpClass and shared across all instances during a single run.
|
||||||
|
|
||||||
|
3. Certain tests pertaining to NAT, Firewall and Load Balancing warrant fresh resources per test. Hence a call should be
|
||||||
|
taken by the stakeholders regarding sharing resources.
|
||||||
|
|
||||||
|
4. Ensure that the tearDown/tearDownClass functions clean up all the resources created during the test run.
|
||||||
|
|
||||||
|
For more information about unittests: http://docs.python.org/library/unittest.html
|
||||||
|
|
||||||
|
|
||||||
|
P1 Tests
|
||||||
|
----------
|
||||||
|
The following files contain these P1 cases:
|
||||||
|
|
||||||
|
1. test_snapshots.py - Snapshots related tests
|
||||||
|
2. test_routers.py - Router related tests
|
||||||
|
3. test_usage.py - Usage realted tests
|
||||||
|
4. test_account.py - Account related tests
|
||||||
|
5. test_resource_limits.py - Resource limits tests
|
||||||
|
6. test_security_groups.py - Security groups related tests
|
||||||
|
7. test_templates.py - templates related tests
|
||||||
|
8. test_volumes.py - Volumes related tests
|
||||||
|
9. test_blocker_bugs.py - Blocker bugs tests
|
||||||
|
10. test_project_configs.py - Project global configuration related tests
|
||||||
|
11. test_project_limits.py - Project resource limits related tests
|
||||||
|
12. test_project_resources.py - Project resource creation related tests
|
||||||
|
13. test_project_usage.py - Project usage related tests
|
||||||
|
14. test_projects - Projects functionality tests
|
||||||
13
test/integration/component/__init__.py
Normal file
13
test/integration/component/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# -*- 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
|
||||||
1091
test/integration/component/test_accounts.py
Normal file
1091
test/integration/component/test_accounts.py
Normal file
File diff suppressed because it is too large
Load Diff
1273
test/integration/component/test_blocker_bugs.py
Normal file
1273
test/integration/component/test_blocker_bugs.py
Normal file
File diff suppressed because it is too large
Load Diff
2336
test/integration/component/test_egress_rules.py
Normal file
2336
test/integration/component/test_egress_rules.py
Normal file
File diff suppressed because it is too large
Load Diff
969
test/integration/component/test_high_availability.py
Normal file
969
test/integration/component/test_high_availability.py
Normal file
@ -0,0 +1,969 @@
|
|||||||
|
# -*- 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
|
||||||
|
|
||||||
|
""" P1 tests for high availability
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
from marvin.remoteSSHClient import remoteSSHClient
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test network offering Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
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": {
|
||||||
|
"name": "Tiny Instance",
|
||||||
|
"displaytext": "Tiny Instance",
|
||||||
|
"cpunumber": 1,
|
||||||
|
"cpuspeed": 100, # in MHz
|
||||||
|
"memory": 64, # In MBs
|
||||||
|
},
|
||||||
|
"lbrule": {
|
||||||
|
"name": "SSH",
|
||||||
|
"alg": "roundrobin",
|
||||||
|
# Algorithm used for load balancing
|
||||||
|
"privateport": 22,
|
||||||
|
"publicport": 2222,
|
||||||
|
},
|
||||||
|
"natrule": {
|
||||||
|
"privateport": 22,
|
||||||
|
"publicport": 22,
|
||||||
|
"protocol": "TCP"
|
||||||
|
},
|
||||||
|
"fw_rule":{
|
||||||
|
"startport": 1,
|
||||||
|
"endport": 6000,
|
||||||
|
"cidr": '55.55.0.0/11',
|
||||||
|
# Any network (For creating FW rule)
|
||||||
|
},
|
||||||
|
"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',
|
||||||
|
},
|
||||||
|
"ostypeid": '9958b10f-9e5d-4ef1-908d-a047372d823b',
|
||||||
|
# Cent OS 5.3 (64 bit)
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 100,
|
||||||
|
"mode":'advanced'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestHighAvailability(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
cls.api_client = super(
|
||||||
|
TestHighAvailability,
|
||||||
|
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["ostypeid"]
|
||||||
|
)
|
||||||
|
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
|
||||||
|
|
||||||
|
def test_01_host_maintenance_mode(self):
|
||||||
|
"""Test host maintenance mode
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Create Vms. Acquire IP. Create port forwarding & load balancing
|
||||||
|
# rules for Vms.
|
||||||
|
# 2. Host 1: put to maintenance mode. All Vms should failover to Host
|
||||||
|
# 2 in cluster. Vms should be in running state. All port forwarding
|
||||||
|
# rules and load balancing Rules should work.
|
||||||
|
# 3. After failover to Host 2 succeeds, deploy Vms. Deploy Vms on host
|
||||||
|
# 2 should succeed.
|
||||||
|
# 4. Host 1: cancel maintenance mode.
|
||||||
|
# 5. Host 2 : put to maintenance mode. All Vms should failover to
|
||||||
|
# Host 1 in cluster.
|
||||||
|
# 6. After failover to Host 1 succeeds, deploy VMs. Deploy Vms on
|
||||||
|
# host 1 should succeed.
|
||||||
|
|
||||||
|
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.assertEqual(
|
||||||
|
len(hosts),
|
||||||
|
2,
|
||||||
|
"There must be two hosts present in a cluster"
|
||||||
|
)
|
||||||
|
self.debug("Checking HA with hosts: %s, %s" % (
|
||||||
|
hosts[0].name,
|
||||||
|
hosts[1].name
|
||||||
|
))
|
||||||
|
self.debug("Deploying VM in account: %s" % self.account.account.name)
|
||||||
|
# Spawn an instance in that network
|
||||||
|
virtual_machine = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.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.debug("Deployed VM on host: %s" % vm.hostid)
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in RUnning state"
|
||||||
|
)
|
||||||
|
networks = Network.list(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(networks, list),
|
||||||
|
True,
|
||||||
|
"List networks should return valid list for the account"
|
||||||
|
)
|
||||||
|
network = networks[0]
|
||||||
|
|
||||||
|
self.debug("Associating public IP for account: %s" %
|
||||||
|
self.account.account.name)
|
||||||
|
public_ip = PublicIPAddress.create(
|
||||||
|
self.apiclient,
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
networkid=network.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Associated %s with network %s" % (
|
||||||
|
public_ip.ipaddress.ipaddress,
|
||||||
|
network.id
|
||||||
|
))
|
||||||
|
self.debug("Creating PF rule for IP address: %s" %
|
||||||
|
public_ip.ipaddress.ipaddress)
|
||||||
|
nat_rule= NATRule.create(
|
||||||
|
self.apiclient,
|
||||||
|
virtual_machine,
|
||||||
|
self.services["natrule"],
|
||||||
|
ipaddressid=public_ip.ipaddress.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Creating LB rule on IP with NAT: %s" %
|
||||||
|
public_ip.ipaddress.ipaddress)
|
||||||
|
|
||||||
|
# Create Load Balancer rule on IP already having NAT rule
|
||||||
|
lb_rule = LoadBalancerRule.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["lbrule"],
|
||||||
|
ipaddressid=public_ip.ipaddress.id,
|
||||||
|
accountid=self.account.account.name
|
||||||
|
)
|
||||||
|
self.debug("Created LB rule with ID: %s" % lb_rule.id)
|
||||||
|
|
||||||
|
# Should be able to SSH VM
|
||||||
|
try:
|
||||||
|
self.debug("SSH into VM: %s" % virtual_machine.id)
|
||||||
|
ssh = virtual_machine.get_ssh_client(
|
||||||
|
ipaddress=public_ip.ipaddress.ipaddress)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH Access failed for %s: %s" % \
|
||||||
|
(virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
|
||||||
|
first_host = vm.hostid
|
||||||
|
self.debug("Enabling maintenance mode for host %s" % vm.hostid)
|
||||||
|
cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
|
||||||
|
cmd.id = first_host
|
||||||
|
self.apiclient.prepareHostForMaintenance(cmd)
|
||||||
|
|
||||||
|
self.debug("Waiting for SSVMs to come up")
|
||||||
|
wait_for_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
# Poll and check state of VM while it migrates from one host to another
|
||||||
|
while True:
|
||||||
|
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.debug("VM 1 state: %s" % vm.state)
|
||||||
|
if vm.state in ["Stopping", "Stopped", "Running", "Starting"]:
|
||||||
|
if vm.state == "Running":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
else:
|
||||||
|
self.fail(
|
||||||
|
"VM migration from one-host-to-other failed while enabling maintenance"
|
||||||
|
)
|
||||||
|
second_host = vm.hostid
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"VM should be in Running state after enabling host maintenance"
|
||||||
|
)
|
||||||
|
# Should be able to SSH VM
|
||||||
|
try:
|
||||||
|
self.debug("SSH into VM: %s" % virtual_machine.id)
|
||||||
|
ssh = virtual_machine.get_ssh_client(
|
||||||
|
ipaddress=public_ip.ipaddress.ipaddress)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH Access failed for %s: %s" % \
|
||||||
|
(virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
self.debug("Deploying VM in account: %s" % self.account.account.name)
|
||||||
|
# Spawn an instance on other host
|
||||||
|
virtual_machine_2 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
serviceofferingid=self.service_offering.id
|
||||||
|
)
|
||||||
|
vms = VirtualMachine.list(
|
||||||
|
self.apiclient,
|
||||||
|
id=virtual_machine_2.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)
|
||||||
|
self.debug("VM 2 state: %s" % vm.state)
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in Running state"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Canceling host maintenance for ID: %s" % first_host)
|
||||||
|
cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
|
||||||
|
cmd.id = first_host
|
||||||
|
self.apiclient.cancelHostMaintenance(cmd)
|
||||||
|
self.debug("Maintenance mode canceled for host: %s" % first_host)
|
||||||
|
|
||||||
|
self.debug("Enabling maintenance mode for host %s" % second_host)
|
||||||
|
cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
|
||||||
|
cmd.id = second_host
|
||||||
|
self.apiclient.prepareHostForMaintenance(cmd)
|
||||||
|
self.debug("Maintenance mode enabled for host: %s" % second_host)
|
||||||
|
|
||||||
|
self.debug("Waiting for SSVMs to come up")
|
||||||
|
wait_for_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Poll and check the status of VMs
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
vms = VirtualMachine.list(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
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(
|
||||||
|
"VM state after enabling maintenance on first host: %s" %
|
||||||
|
vm.state)
|
||||||
|
if vm.state in ["Stopping", "Stopped", "Running", "Starting"]:
|
||||||
|
if vm.state == "Running":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
else:
|
||||||
|
self.fail(
|
||||||
|
"VM migration from one-host-to-other failed while enabling maintenance"
|
||||||
|
)
|
||||||
|
|
||||||
|
for vm in vms:
|
||||||
|
self.debug(
|
||||||
|
"VM states after enabling maintenance mode on host: %s - %s" %
|
||||||
|
(first_host, vm.state))
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in Running state"
|
||||||
|
)
|
||||||
|
# Spawn an instance on other host
|
||||||
|
virtual_machine_3 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
serviceofferingid=self.service_offering.id
|
||||||
|
)
|
||||||
|
vms = VirtualMachine.list(
|
||||||
|
self.apiclient,
|
||||||
|
id=virtual_machine_3.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)
|
||||||
|
self.debug("VM 3 state: %s" % vm.state)
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in Running state"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Should be able to SSH VM
|
||||||
|
try:
|
||||||
|
self.debug("SSH into VM: %s" % virtual_machine.id)
|
||||||
|
ssh = virtual_machine.get_ssh_client(
|
||||||
|
ipaddress=public_ip.ipaddress.ipaddress)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH Access failed for %s: %s" % \
|
||||||
|
(virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Canceling host maintenance for ID: %s" % second_host)
|
||||||
|
cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
|
||||||
|
cmd.id = second_host
|
||||||
|
self.apiclient.cancelHostMaintenance(cmd)
|
||||||
|
self.debug("Maintenance mode canceled for host: %s" % second_host)
|
||||||
|
self.debug("Waiting for SSVMs to come up")
|
||||||
|
wait_for_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_host_maintenance_mode_with_activities(self):
|
||||||
|
"""Test host maintenance mode with activities
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Create Vms. Acquire IP. Create port forwarding & load balancing
|
||||||
|
# rules for Vms.
|
||||||
|
# 2. While activities are ongoing: Create snapshots, recurring
|
||||||
|
# snapshots, create templates, download volumes, Host 1: put to
|
||||||
|
# maintenance mode. All Vms should failover to Host 2 in cluster
|
||||||
|
# Vms should be in running state. All port forwarding rules and
|
||||||
|
# load balancing Rules should work.
|
||||||
|
# 3. After failover to Host 2 succeeds, deploy Vms. Deploy Vms on host
|
||||||
|
# 2 should succeed. All ongoing activities in step 3 should succeed
|
||||||
|
# 4. Host 1: cancel maintenance mode.
|
||||||
|
# 5. While activities are ongoing: Create snapshots, recurring
|
||||||
|
# snapshots, create templates, download volumes, Host 2: put to
|
||||||
|
# maintenance mode. All Vms should failover to Host 1 in cluster.
|
||||||
|
# 6. After failover to Host 1 succeeds, deploy VMs. Deploy Vms on
|
||||||
|
# host 1 should succeed. All ongoing activities in step 6 should
|
||||||
|
# succeed.
|
||||||
|
|
||||||
|
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.assertEqual(
|
||||||
|
len(hosts),
|
||||||
|
2,
|
||||||
|
"There must be two hosts present in a cluster"
|
||||||
|
)
|
||||||
|
self.debug("Checking HA with hosts: %s, %s" % (
|
||||||
|
hosts[0].name,
|
||||||
|
hosts[1].name
|
||||||
|
))
|
||||||
|
self.debug("Deploying VM in account: %s" % self.account.account.name)
|
||||||
|
# Spawn an instance in that network
|
||||||
|
virtual_machine = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.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.debug("Deployed VM on host: %s" % vm.hostid)
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in RUnning state"
|
||||||
|
)
|
||||||
|
networks = Network.list(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(networks, list),
|
||||||
|
True,
|
||||||
|
"List networks should return valid list for the account"
|
||||||
|
)
|
||||||
|
network = networks[0]
|
||||||
|
|
||||||
|
self.debug("Associating public IP for account: %s" %
|
||||||
|
self.account.account.name)
|
||||||
|
public_ip = PublicIPAddress.create(
|
||||||
|
self.apiclient,
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
networkid=network.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Associated %s with network %s" % (
|
||||||
|
public_ip.ipaddress.ipaddress,
|
||||||
|
network.id
|
||||||
|
))
|
||||||
|
self.debug("Creating PF rule for IP address: %s" %
|
||||||
|
public_ip.ipaddress.ipaddress)
|
||||||
|
nat_rule= NATRule.create(
|
||||||
|
self.apiclient,
|
||||||
|
virtual_machine,
|
||||||
|
self.services["natrule"],
|
||||||
|
ipaddressid=public_ip.ipaddress.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Creating LB rule on IP with NAT: %s" %
|
||||||
|
public_ip.ipaddress.ipaddress)
|
||||||
|
|
||||||
|
# Create Load Balancer rule on IP already having NAT rule
|
||||||
|
lb_rule = LoadBalancerRule.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["lbrule"],
|
||||||
|
ipaddressid=public_ip.ipaddress.id,
|
||||||
|
accountid=self.account.account.name
|
||||||
|
)
|
||||||
|
self.debug("Created LB rule with ID: %s" % lb_rule.id)
|
||||||
|
|
||||||
|
# Should be able to SSH VM
|
||||||
|
try:
|
||||||
|
self.debug("SSH into VM: %s" % virtual_machine.id)
|
||||||
|
ssh = virtual_machine.get_ssh_client(
|
||||||
|
ipaddress=public_ip.ipaddress.ipaddress)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH Access failed for %s: %s" % \
|
||||||
|
(virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
# Get the Root disk of VM
|
||||||
|
volumes = list_volumes(
|
||||||
|
self.apiclient,
|
||||||
|
virtualmachineid=virtual_machine.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
volume = volumes[0]
|
||||||
|
self.debug(
|
||||||
|
"Root volume of VM(%s): %s" % (
|
||||||
|
virtual_machine.name,
|
||||||
|
volume.name
|
||||||
|
))
|
||||||
|
# Create a snapshot from the ROOTDISK
|
||||||
|
self.debug("Creating snapshot on ROOT volume: %s" % volume.name)
|
||||||
|
snapshot = Snapshot.create(self.apiclient, volumes[0].id)
|
||||||
|
self.debug("Snapshot created: ID - %s" % snapshot.id)
|
||||||
|
|
||||||
|
snapshots = list_snapshots(
|
||||||
|
self.apiclient,
|
||||||
|
id=snapshot.id,
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(snapshots, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
snapshots,
|
||||||
|
None,
|
||||||
|
"Check if result exists in list snapshots call"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
snapshots[0].id,
|
||||||
|
snapshot.id,
|
||||||
|
"Check snapshot id in list resources call"
|
||||||
|
)
|
||||||
|
# Generate template from the snapshot
|
||||||
|
self.debug("Generating template from snapshot: %s" % snapshot.name)
|
||||||
|
template = Template.create_from_snapshot(
|
||||||
|
self.apiclient,
|
||||||
|
snapshot,
|
||||||
|
self.services["templates"]
|
||||||
|
)
|
||||||
|
self.cleanup.append(template)
|
||||||
|
self.debug("Created template from snapshot: %s" % template.id)
|
||||||
|
|
||||||
|
templates = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templates"]["templatefilter"],
|
||||||
|
id=template.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(templates, list),
|
||||||
|
True,
|
||||||
|
"List template call should return the newly created template"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
templates[0].isready,
|
||||||
|
True,
|
||||||
|
"The newly created template should be in ready state"
|
||||||
|
)
|
||||||
|
|
||||||
|
first_host = vm.hostid
|
||||||
|
self.debug("Enabling maintenance mode for host %s" % vm.hostid)
|
||||||
|
cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
|
||||||
|
cmd.id = first_host
|
||||||
|
self.apiclient.prepareHostForMaintenance(cmd)
|
||||||
|
|
||||||
|
self.debug("Waiting for SSVMs to come up")
|
||||||
|
wait_for_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
# Poll and check state of VM while it migrates from one host to another
|
||||||
|
while True:
|
||||||
|
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.debug("VM 1 state: %s" % vm.state)
|
||||||
|
if vm.state in ["Stopping", "Stopped", "Running", "Starting"]:
|
||||||
|
if vm.state == "Running":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
else:
|
||||||
|
self.fail(
|
||||||
|
"VM migration from one-host-to-other failed while enabling maintenance"
|
||||||
|
)
|
||||||
|
second_host = vm.hostid
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"VM should be in Running state after enabling host maintenance"
|
||||||
|
)
|
||||||
|
# Should be able to SSH VM
|
||||||
|
try:
|
||||||
|
self.debug("SSH into VM: %s" % virtual_machine.id)
|
||||||
|
ssh = virtual_machine.get_ssh_client(
|
||||||
|
ipaddress=public_ip.ipaddress.ipaddress)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH Access failed for %s: %s" % \
|
||||||
|
(virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
self.debug("Deploying VM in account: %s" % self.account.account.name)
|
||||||
|
# Spawn an instance on other host
|
||||||
|
virtual_machine_2 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
serviceofferingid=self.service_offering.id
|
||||||
|
)
|
||||||
|
vms = VirtualMachine.list(
|
||||||
|
self.apiclient,
|
||||||
|
id=virtual_machine_2.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)
|
||||||
|
self.debug("VM 2 state: %s" % vm.state)
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in Running state"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Canceling host maintenance for ID: %s" % first_host)
|
||||||
|
cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
|
||||||
|
cmd.id = first_host
|
||||||
|
self.apiclient.cancelHostMaintenance(cmd)
|
||||||
|
self.debug("Maintenance mode canceled for host: %s" % first_host)
|
||||||
|
|
||||||
|
# Get the Root disk of VM
|
||||||
|
volumes = list_volumes(
|
||||||
|
self.apiclient,
|
||||||
|
virtualmachineid=virtual_machine_2.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
volume = volumes[0]
|
||||||
|
self.debug(
|
||||||
|
"Root volume of VM(%s): %s" % (
|
||||||
|
virtual_machine_2.name,
|
||||||
|
volume.name
|
||||||
|
))
|
||||||
|
# Create a snapshot from the ROOTDISK
|
||||||
|
self.debug("Creating snapshot on ROOT volume: %s" % volume.name)
|
||||||
|
snapshot = Snapshot.create(self.apiclient, volumes[0].id)
|
||||||
|
self.debug("Snapshot created: ID - %s" % snapshot.id)
|
||||||
|
|
||||||
|
snapshots = list_snapshots(
|
||||||
|
self.apiclient,
|
||||||
|
id=snapshot.id,
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(snapshots, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
snapshots,
|
||||||
|
None,
|
||||||
|
"Check if result exists in list snapshots call"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
snapshots[0].id,
|
||||||
|
snapshot.id,
|
||||||
|
"Check snapshot id in list resources call"
|
||||||
|
)
|
||||||
|
# Generate template from the snapshot
|
||||||
|
self.debug("Generating template from snapshot: %s" % snapshot.name)
|
||||||
|
template = Template.create_from_snapshot(
|
||||||
|
self.apiclient,
|
||||||
|
snapshot,
|
||||||
|
self.services["templates"]
|
||||||
|
)
|
||||||
|
self.cleanup.append(template)
|
||||||
|
self.debug("Created template from snapshot: %s" % template.id)
|
||||||
|
|
||||||
|
templates = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templates"]["templatefilter"],
|
||||||
|
id=template.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(templates, list),
|
||||||
|
True,
|
||||||
|
"List template call should return the newly created template"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
templates[0].isready,
|
||||||
|
True,
|
||||||
|
"The newly created template should be in ready state"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Enabling maintenance mode for host %s" % second_host)
|
||||||
|
cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd()
|
||||||
|
cmd.id = second_host
|
||||||
|
self.apiclient.prepareHostForMaintenance(cmd)
|
||||||
|
self.debug("Maintenance mode enabled for host: %s" % second_host)
|
||||||
|
|
||||||
|
self.debug("Waiting for SSVMs to come up")
|
||||||
|
wait_for_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Poll and check the status of VMs
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
vms = VirtualMachine.list(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
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(
|
||||||
|
"VM state after enabling maintenance on first host: %s" %
|
||||||
|
vm.state)
|
||||||
|
if vm.state in ["Stopping", "Stopped", "Running", "Starting"]:
|
||||||
|
if vm.state == "Running":
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
else:
|
||||||
|
self.fail(
|
||||||
|
"VM migration from one-host-to-other failed while enabling maintenance"
|
||||||
|
)
|
||||||
|
|
||||||
|
for vm in vms:
|
||||||
|
self.debug(
|
||||||
|
"VM states after enabling maintenance mode on host: %s - %s" %
|
||||||
|
(first_host, vm.state))
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in Running state"
|
||||||
|
)
|
||||||
|
# Spawn an instance on other host
|
||||||
|
virtual_machine_3 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
serviceofferingid=self.service_offering.id
|
||||||
|
)
|
||||||
|
vms = VirtualMachine.list(
|
||||||
|
self.apiclient,
|
||||||
|
id=virtual_machine_3.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)
|
||||||
|
self.debug("VM 3 state: %s" % vm.state)
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
"Running",
|
||||||
|
"Deployed VM should be in Running state"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Should be able to SSH VM
|
||||||
|
try:
|
||||||
|
self.debug("SSH into VM: %s" % virtual_machine.id)
|
||||||
|
ssh = virtual_machine.get_ssh_client(
|
||||||
|
ipaddress=public_ip.ipaddress.ipaddress)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH Access failed for %s: %s" % \
|
||||||
|
(virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Canceling host maintenance for ID: %s" % second_host)
|
||||||
|
cmd = cancelHostMaintenance.cancelHostMaintenanceCmd()
|
||||||
|
cmd.id = second_host
|
||||||
|
self.apiclient.cancelHostMaintenance(cmd)
|
||||||
|
self.debug("Maintenance mode canceled for host: %s" % second_host)
|
||||||
|
self.debug("Waiting for SSVMs to come up")
|
||||||
|
wait_for_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id,
|
||||||
|
)
|
||||||
|
return
|
||||||
1783
test/integration/component/test_network_offering.py
Normal file
1783
test/integration/component/test_network_offering.py
Normal file
File diff suppressed because it is too large
Load Diff
1231
test/integration/component/test_project_configs.py
Normal file
1231
test/integration/component/test_project_configs.py
Normal file
File diff suppressed because it is too large
Load Diff
881
test/integration/component/test_project_limits.py
Normal file
881
test/integration/component/test_project_limits.py
Normal file
@ -0,0 +1,881 @@
|
|||||||
|
# -*- 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
|
||||||
|
""" P1 tests for Resource limits
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Resource Limits Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"domain": {
|
||||||
|
"name": "Domain",
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"name": "Project",
|
||||||
|
"displaytext": "Test project",
|
||||||
|
},
|
||||||
|
"account": {
|
||||||
|
"email": "administrator@clogeny.com",
|
||||||
|
"firstname": "Test",
|
||||||
|
"lastname": "User",
|
||||||
|
"username": "test",
|
||||||
|
# Random characters are appended for unique
|
||||||
|
# username
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"email": "administrator@clogeny.com",
|
||||||
|
"firstname": "User",
|
||||||
|
"lastname": "User",
|
||||||
|
"username": "User",
|
||||||
|
# Random characters are appended for unique
|
||||||
|
# username
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"service_offering": {
|
||||||
|
"name": "Tiny Instance",
|
||||||
|
"displaytext": "Tiny Instance",
|
||||||
|
"cpunumber": 1,
|
||||||
|
"cpuspeed": 100, # in MHz
|
||||||
|
"memory": 64, # In MBs
|
||||||
|
},
|
||||||
|
"disk_offering": {
|
||||||
|
"displaytext": "Tiny Disk Offering",
|
||||||
|
"name": "Tiny Disk Offering",
|
||||||
|
"disksize": 1
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"diskname": "Test Volume",
|
||||||
|
},
|
||||||
|
"server": {
|
||||||
|
"displayname": "TestVM",
|
||||||
|
"username": "root",
|
||||||
|
"password": "password",
|
||||||
|
"ssh_port": 22,
|
||||||
|
"hypervisor": 'XenServer',
|
||||||
|
"privateport": 22,
|
||||||
|
"publicport": 22,
|
||||||
|
"protocol": 'TCP',
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"displaytext": "Cent OS Template",
|
||||||
|
"name": "Cent OS Template",
|
||||||
|
"ostypeid": '471a4b5b-5523-448f-9608-7d6218995733',
|
||||||
|
"templatefilter": 'self',
|
||||||
|
},
|
||||||
|
"ostypeid": '471a4b5b-5523-448f-9608-7d6218995733',
|
||||||
|
# Cent OS 5.3 (64 bit)
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 10,
|
||||||
|
"mode": 'advanced',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestProjectLimits(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.api_client = super(
|
||||||
|
TestProjectLimits,
|
||||||
|
cls
|
||||||
|
).getClsTestClient().getApiClient()
|
||||||
|
cls.services = Services().services
|
||||||
|
# Get Zone
|
||||||
|
cls.zone = get_zone(cls.api_client, cls.services)
|
||||||
|
|
||||||
|
# Create domains, account etc.
|
||||||
|
cls.domain = Domain.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["domain"]
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.admin = Account.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["account"],
|
||||||
|
admin=True,
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
cls.user = Account.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["user"],
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.admin,
|
||||||
|
cls.user,
|
||||||
|
cls.domain
|
||||||
|
]
|
||||||
|
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 test_01_project_limits(self):
|
||||||
|
""" Test project limits
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Create a Project. Verify once projects are created, they inherit
|
||||||
|
# a default set of resource limits as configured by the Cloud Stack
|
||||||
|
# ROOT admin.
|
||||||
|
# 2. Reduce Project resources limits. Verify limits can be reduced by
|
||||||
|
# the Project Owner of each project and project limit applies to
|
||||||
|
# number of virtual instances, disk volumes, snapshots, IP address.
|
||||||
|
# Also, verify resource limits for the project are independent of
|
||||||
|
# account resource limits
|
||||||
|
# 3. Increase Projects Resources limits above domains limit. Verify
|
||||||
|
# project can’t have more resources than domain level limit allows.
|
||||||
|
# 4. Create Resource more than its set limit for a project. Verify
|
||||||
|
# resource allocation should fail giving proper message
|
||||||
|
|
||||||
|
# Create project as a domain admin
|
||||||
|
project = Project.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["project"],
|
||||||
|
account=self.admin.account.name,
|
||||||
|
domainid=self.admin.account.domainid
|
||||||
|
)
|
||||||
|
# Cleanup created project at end of test
|
||||||
|
self.cleanup.append(project)
|
||||||
|
self.debug("Created project with domain admin with ID: %s" %
|
||||||
|
project.id)
|
||||||
|
|
||||||
|
list_projects_reponse = Project.list(
|
||||||
|
self.apiclient,
|
||||||
|
id=project.id,
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_projects_reponse, list),
|
||||||
|
True,
|
||||||
|
"Check for a valid list projects response"
|
||||||
|
)
|
||||||
|
list_project = list_projects_reponse[0]
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_projects_reponse),
|
||||||
|
0,
|
||||||
|
"Check list project response returns a valid project"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
project.name,
|
||||||
|
list_project.name,
|
||||||
|
"Check project name from list response"
|
||||||
|
)
|
||||||
|
# Get the resource limits for ROOT domain
|
||||||
|
resource_limits = list_resource_limits(self.apiclient)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(resource_limits, list),
|
||||||
|
True,
|
||||||
|
"List resource API should return a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(resource_limits),
|
||||||
|
0,
|
||||||
|
"List resource API response should not be empty"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Reduce resource limits for project
|
||||||
|
# Resource: 0 - Instance. Number of instances a user can create.
|
||||||
|
# Resource: 1 - IP. Number of public IP addresses a user can own.
|
||||||
|
# Resource: 2 - Volume. Number of disk volumes a user can create.
|
||||||
|
# Resource: 3 - Snapshot. Number of snapshots a user can create.
|
||||||
|
# Resource: 4 - Template. Number of templates that a user can
|
||||||
|
# register/create
|
||||||
|
for resource in resource_limits:
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
resource.resourcetype,
|
||||||
|
max=1,
|
||||||
|
projectid=project.id
|
||||||
|
)
|
||||||
|
self.debug(
|
||||||
|
"Updating resource (ID: %s) limit for project: %s" % (
|
||||||
|
resource,
|
||||||
|
project.id
|
||||||
|
))
|
||||||
|
resource_limits = list_resource_limits(
|
||||||
|
self.apiclient,
|
||||||
|
projectid=project.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(resource_limits, list),
|
||||||
|
True,
|
||||||
|
"List resource API should return a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(resource_limits),
|
||||||
|
0,
|
||||||
|
"List resource API response should not be empty"
|
||||||
|
)
|
||||||
|
for resource in resource_limits:
|
||||||
|
self.assertEqual(
|
||||||
|
resource.max,
|
||||||
|
1,
|
||||||
|
"Resource limit should be updated to 1"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the resource limits for domain
|
||||||
|
resource_limits = list_resource_limits(
|
||||||
|
self.apiclient,
|
||||||
|
domainid=self.domain.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(resource_limits, list),
|
||||||
|
True,
|
||||||
|
"List resource API should return a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(resource_limits),
|
||||||
|
0,
|
||||||
|
"List resource API response should not be empty"
|
||||||
|
)
|
||||||
|
|
||||||
|
for resource in resource_limits:
|
||||||
|
# Update domain resource limits to 2
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
resource.resourcetype,
|
||||||
|
domainid=self.domain.id,
|
||||||
|
max=2
|
||||||
|
)
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
self.debug(
|
||||||
|
"Attempting to update project: %s resource limit to: %s" % (
|
||||||
|
project.id,
|
||||||
|
max_value
|
||||||
|
))
|
||||||
|
# Update project resource limits to 3
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
resource.resourcetype,
|
||||||
|
max=3,
|
||||||
|
projectid=project.id
|
||||||
|
)
|
||||||
|
return
|
||||||
|
@unittest.skip("No provision for updating resource limits from account through API")
|
||||||
|
def test_02_project_limits_normal_user(self):
|
||||||
|
""" Test project limits
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Create a Project
|
||||||
|
# 2. Reduce the projects limits as a domain admin. Verify resource
|
||||||
|
# count is updated
|
||||||
|
# 3. Reduce the projects limits as a project user owner who is not a
|
||||||
|
# domain admin. Resource count should fail
|
||||||
|
|
||||||
|
# Create project as a domain admin
|
||||||
|
project = Project.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["project"],
|
||||||
|
account=self.admin.account.name,
|
||||||
|
domainid=self.admin.account.domainid
|
||||||
|
)
|
||||||
|
# Cleanup created project at end of test
|
||||||
|
self.cleanup.append(project)
|
||||||
|
self.debug("Created project with domain admin with ID: %s" %
|
||||||
|
project.id)
|
||||||
|
|
||||||
|
list_projects_reponse = Project.list(
|
||||||
|
self.apiclient,
|
||||||
|
id=project.id,
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_projects_reponse, list),
|
||||||
|
True,
|
||||||
|
"Check for a valid list projects response"
|
||||||
|
)
|
||||||
|
list_project = list_projects_reponse[0]
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_projects_reponse),
|
||||||
|
0,
|
||||||
|
"Check list project response returns a valid project"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
project.name,
|
||||||
|
list_project.name,
|
||||||
|
"Check project name from list response"
|
||||||
|
)
|
||||||
|
# Get the resource limits for ROOT domain
|
||||||
|
resource_limits = list_resource_limits(self.apiclient)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(resource_limits, list),
|
||||||
|
True,
|
||||||
|
"List resource API should return a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(resource_limits),
|
||||||
|
0,
|
||||||
|
"List resource API response should not be empty"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Reduce resource limits for project
|
||||||
|
# Resource: 0 - Instance. Number of instances a user can create.
|
||||||
|
# Resource: 1 - IP. Number of public IP addresses a user can own.
|
||||||
|
# Resource: 2 - Volume. Number of disk volumes a user can create.
|
||||||
|
# Resource: 3 - Snapshot. Number of snapshots a user can create.
|
||||||
|
# Resource: 4 - Template. Number of templates that a user can
|
||||||
|
# register/create
|
||||||
|
for resource in resource_limits:
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
resource.resourcetype,
|
||||||
|
max=1,
|
||||||
|
projectid=project.id
|
||||||
|
)
|
||||||
|
self.debug(
|
||||||
|
"Updating resource (ID: %s) limit for project: %s" % (
|
||||||
|
resource,
|
||||||
|
project.id
|
||||||
|
))
|
||||||
|
resource_limits = list_resource_limits(
|
||||||
|
self.apiclient,
|
||||||
|
projectid=project.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(resource_limits, list),
|
||||||
|
True,
|
||||||
|
"List resource API should return a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(resource_limits),
|
||||||
|
0,
|
||||||
|
"List resource API response should not be empty"
|
||||||
|
)
|
||||||
|
for resource in resource_limits:
|
||||||
|
self.assertEqual(
|
||||||
|
resource.max,
|
||||||
|
1,
|
||||||
|
"Resource limit should be updated to 1"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Adding %s user to project: %s" % (
|
||||||
|
self.user.account.name,
|
||||||
|
project.name
|
||||||
|
))
|
||||||
|
|
||||||
|
# Add user to the project
|
||||||
|
project.addAccount(
|
||||||
|
self.apiclient,
|
||||||
|
self.user.account.name,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the resource limits for domain
|
||||||
|
resource_limits = list_resource_limits(
|
||||||
|
self.apiclient,
|
||||||
|
domainid=self.domain.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(resource_limits, list),
|
||||||
|
True,
|
||||||
|
"List resource API should return a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(resource_limits),
|
||||||
|
0,
|
||||||
|
"List resource API response should not be empty"
|
||||||
|
)
|
||||||
|
|
||||||
|
for resource in resource_limits:
|
||||||
|
#with self.assertRaises(Exception):
|
||||||
|
self.debug(
|
||||||
|
"Attempting to update resource limit by user: %s" % (
|
||||||
|
self.user.account.name
|
||||||
|
))
|
||||||
|
# Update project resource limits to 3
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
resource.resourcetype,
|
||||||
|
account=self.user.account.name,
|
||||||
|
domainid=self.user.account.domainid,
|
||||||
|
max=3,
|
||||||
|
projectid=project.id
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class TestResourceLimitsProject(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.api_client = super(TestResourceLimitsProject, cls).getClsTestClient().getApiClient()
|
||||||
|
cls.services = Services().services
|
||||||
|
# Get Zone, Domain and templates
|
||||||
|
cls.zone = get_zone(cls.api_client, cls.services)
|
||||||
|
|
||||||
|
cls.template = get_template(
|
||||||
|
cls.api_client,
|
||||||
|
cls.zone.id,
|
||||||
|
cls.services["ostypeid"]
|
||||||
|
)
|
||||||
|
cls.services["server"]["zoneid"] = cls.zone.id
|
||||||
|
|
||||||
|
# Create Domains, Account etc
|
||||||
|
cls.domain = Domain.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["domain"]
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.account = Account.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["account"],
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
# Create project as a domain admin
|
||||||
|
cls.project = Project.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["project"],
|
||||||
|
account=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid
|
||||||
|
)
|
||||||
|
cls.services["account"] = cls.account.account.name
|
||||||
|
|
||||||
|
# Create Service offering and disk offerings etc
|
||||||
|
cls.service_offering = ServiceOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["service_offering"]
|
||||||
|
)
|
||||||
|
cls.disk_offering = DiskOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["disk_offering"]
|
||||||
|
)
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.project,
|
||||||
|
cls.service_offering,
|
||||||
|
cls.disk_offering,
|
||||||
|
cls.account,
|
||||||
|
cls.domain
|
||||||
|
]
|
||||||
|
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 instance, volumes and snapshots
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_vm_per_project(self):
|
||||||
|
"""Test VM limit per project
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Set max VM per project to 2
|
||||||
|
# 2. Create account and start 2 VMs. Verify VM state is Up and Running
|
||||||
|
# 3. Try to create 3rd VM instance. The appropriate error or alert
|
||||||
|
# should be raised
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Updating instance resource limits for project: %s" %
|
||||||
|
self.project.id)
|
||||||
|
# Set usage_vm=1 for Account 1
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
0, # Instance
|
||||||
|
max=2,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Deploying VM for project: %s" % self.project.id)
|
||||||
|
virtual_machine_1 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["server"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(virtual_machine_1)
|
||||||
|
# Verify VM state
|
||||||
|
self.assertEqual(
|
||||||
|
virtual_machine_1.state,
|
||||||
|
'Running',
|
||||||
|
"Check VM state is Running or not"
|
||||||
|
)
|
||||||
|
self.debug("Deploying VM for project: %s" % self.project.id)
|
||||||
|
virtual_machine_2 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["server"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(virtual_machine_2)
|
||||||
|
# Verify VM state
|
||||||
|
self.assertEqual(
|
||||||
|
virtual_machine_2.state,
|
||||||
|
'Running',
|
||||||
|
"Check VM state is Running or not"
|
||||||
|
)
|
||||||
|
# Exception should be raised for second instance
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["server"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_04_publicip_per_project(self):
|
||||||
|
"""Test Public IP limit per project
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. set max no of IPs per project to 2.
|
||||||
|
# 2. Create an account in this domain
|
||||||
|
# 3. Create 1 VM in this domain
|
||||||
|
# 4. Acquire 1 IP in the domain. IP should be successfully acquired
|
||||||
|
# 5. Try to acquire 3rd IP in this domain. It should give the user an
|
||||||
|
# appropriate error and an alert should be generated.
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Updating public IP resource limits for project: %s" %
|
||||||
|
self.project.id)
|
||||||
|
# Set usage_vm=1 for Account 1
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
1, # Public Ip
|
||||||
|
max=2,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Deploying VM for Project: %s" % self.project.id)
|
||||||
|
virtual_machine_1 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["server"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(virtual_machine_1)
|
||||||
|
# Verify VM state
|
||||||
|
self.assertEqual(
|
||||||
|
virtual_machine_1.state,
|
||||||
|
'Running',
|
||||||
|
"Check VM state is Running or not"
|
||||||
|
)
|
||||||
|
networks = Network.list(
|
||||||
|
self.apiclient,
|
||||||
|
projectid=self.project.id,
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(networks, list),
|
||||||
|
True,
|
||||||
|
"Check list networks response returns a valid response"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(networks),
|
||||||
|
0,
|
||||||
|
"Check list networks response returns a valid network"
|
||||||
|
)
|
||||||
|
network = networks[0]
|
||||||
|
self.debug("Associating public IP for project: %s" %
|
||||||
|
self.project.id)
|
||||||
|
public_ip_1 = PublicIPAddress.create(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=virtual_machine_1.zoneid,
|
||||||
|
services=self.services["server"],
|
||||||
|
networkid=network.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(public_ip_1)
|
||||||
|
# Verify Public IP state
|
||||||
|
self.assertEqual(
|
||||||
|
public_ip_1.ipaddress.state in [
|
||||||
|
'Allocated',
|
||||||
|
'Allocating'
|
||||||
|
],
|
||||||
|
True,
|
||||||
|
"Check Public IP state is allocated or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Exception should be raised for second Public IP
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
public_ip_2 = PublicIPAddress.create(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=virtual_machine_1.zoneid,
|
||||||
|
services=self.services["server"],
|
||||||
|
networkid=network.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_05_snapshots_per_project(self):
|
||||||
|
"""Test Snapshot limit per project
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. set max no of snapshots per project to 1.
|
||||||
|
# 2. Create one snapshot in the project. Snapshot should be
|
||||||
|
# successfully created
|
||||||
|
# 5. Try to create another snapshot in this project. It should give
|
||||||
|
# user an appropriate error and an alert should be generated.
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Updating snapshot resource limits for project: %s" %
|
||||||
|
self.project.id)
|
||||||
|
# Set usage_vm=1 for Account 1
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
3, # Snapshot
|
||||||
|
max=1,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Deploying VM for account: %s" % self.account.account.name)
|
||||||
|
virtual_machine_1 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["server"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(virtual_machine_1)
|
||||||
|
# Verify VM state
|
||||||
|
self.assertEqual(
|
||||||
|
virtual_machine_1.state,
|
||||||
|
'Running',
|
||||||
|
"Check VM state is Running or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get the Root disk of VM
|
||||||
|
volumes = list_volumes(
|
||||||
|
self.apiclient,
|
||||||
|
projectid=self.project.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(volumes, list),
|
||||||
|
True,
|
||||||
|
"Check for list volume response return valid data"
|
||||||
|
)
|
||||||
|
volume = volumes[0]
|
||||||
|
|
||||||
|
self.debug("Creating snapshot from volume: %s" % volumes[0].id)
|
||||||
|
# Create a snapshot from the ROOTDISK
|
||||||
|
snapshot_1 = Snapshot.create(self.apiclient,
|
||||||
|
volumes[0].id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(snapshot_1)
|
||||||
|
# Verify Snapshot state
|
||||||
|
self.assertEqual(
|
||||||
|
snapshot_1.state in [
|
||||||
|
'BackedUp',
|
||||||
|
'CreatedOnPrimary'
|
||||||
|
],
|
||||||
|
True,
|
||||||
|
"Check Snapshot state is Running or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Exception should be raised for second snapshot
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
Snapshot.create(self.apiclient,
|
||||||
|
volumes[0].id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_06_volumes_per_project(self):
|
||||||
|
"""Test Volumes limit per project
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. set max no of volume per project to 1.
|
||||||
|
# 2. Create 1 VM in this project
|
||||||
|
# 4. Try to Create another VM in the project. It should give the user
|
||||||
|
# an appropriate error that Volume limit is exhausted and an alert
|
||||||
|
# should be generated.
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Updating volume resource limits for project: %s" %
|
||||||
|
self.project.id)
|
||||||
|
# Set usage_vm=1 for Account 1
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
2, # Volume
|
||||||
|
max=2,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Deploying VM for project: %s" % self.project.id)
|
||||||
|
virtual_machine_1 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["server"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(virtual_machine_1)
|
||||||
|
# Verify VM state
|
||||||
|
self.assertEqual(
|
||||||
|
virtual_machine_1.state,
|
||||||
|
'Running',
|
||||||
|
"Check VM state is Running or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Exception should be raised for second volume
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
Volume.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["volume"],
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
diskofferingid=self.disk_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_07_templates_per_project(self):
|
||||||
|
"""Test Templates limit per project
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. set max no of templates per project to 1.
|
||||||
|
# 2. Create a template in this project. Both template should be in
|
||||||
|
# ready state
|
||||||
|
# 3. Try create 2nd template in the project. It should give the user
|
||||||
|
# appropriate error and an alert should be generated.
|
||||||
|
|
||||||
|
# Reset the volume limits
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
2, # Volume
|
||||||
|
max=5,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.debug(
|
||||||
|
"Updating template resource limits for domain: %s" %
|
||||||
|
self.account.account.domainid)
|
||||||
|
# Set usage_vm=1 for Account 1
|
||||||
|
update_resource_limit(
|
||||||
|
self.apiclient,
|
||||||
|
4, # Template
|
||||||
|
max=1,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Deploying VM for account: %s" % self.account.account.name)
|
||||||
|
virtual_machine_1 = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["server"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(virtual_machine_1)
|
||||||
|
# Verify VM state
|
||||||
|
self.assertEqual(
|
||||||
|
virtual_machine_1.state,
|
||||||
|
'Running',
|
||||||
|
"Check VM state is Running or not"
|
||||||
|
)
|
||||||
|
virtual_machine_1.stop(self.apiclient)
|
||||||
|
# Get the Root disk of VM
|
||||||
|
volumes = list_volumes(
|
||||||
|
self.apiclient,
|
||||||
|
projectid=self.project.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(volumes, list),
|
||||||
|
True,
|
||||||
|
"Check for list volume response return valid data"
|
||||||
|
)
|
||||||
|
volume = volumes[0]
|
||||||
|
|
||||||
|
self.debug("Creating template from volume: %s" % volume.id)
|
||||||
|
# Create a template from the ROOTDISK
|
||||||
|
template_1 = Template.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["template"],
|
||||||
|
volumeid=volume.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.cleanup.append(template_1)
|
||||||
|
# Verify Template state
|
||||||
|
self.assertEqual(
|
||||||
|
template_1.isready,
|
||||||
|
True,
|
||||||
|
"Check Template is in ready state or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Exception should be raised for second template
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
Template.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["template"],
|
||||||
|
volumeid=volume.id,
|
||||||
|
projectid=self.project.id
|
||||||
|
)
|
||||||
|
return
|
||||||
1314
test/integration/component/test_project_resources.py
Normal file
1314
test/integration/component/test_project_resources.py
Normal file
File diff suppressed because it is too large
Load Diff
1711
test/integration/component/test_project_usage.py
Normal file
1711
test/integration/component/test_project_usage.py
Normal file
File diff suppressed because it is too large
Load Diff
1809
test/integration/component/test_projects.py
Normal file
1809
test/integration/component/test_projects.py
Normal file
File diff suppressed because it is too large
Load Diff
1472
test/integration/component/test_resource_limits.py
Normal file
1472
test/integration/component/test_resource_limits.py
Normal file
File diff suppressed because it is too large
Load Diff
1201
test/integration/component/test_routers.py
Normal file
1201
test/integration/component/test_routers.py
Normal file
File diff suppressed because it is too large
Load Diff
1628
test/integration/component/test_security_groups.py
Normal file
1628
test/integration/component/test_security_groups.py
Normal file
File diff suppressed because it is too large
Load Diff
1396
test/integration/component/test_snapshots.py
Normal file
1396
test/integration/component/test_snapshots.py
Normal file
File diff suppressed because it is too large
Load Diff
612
test/integration/component/test_templates.py
Normal file
612
test/integration/component/test_templates.py
Normal file
@ -0,0 +1,612 @@
|
|||||||
|
# -*- 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
|
||||||
|
""" P1 tests for Templates
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
import urllib
|
||||||
|
from random import random
|
||||||
|
#Import System modules
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Templates Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"account": {
|
||||||
|
"email": "test@test.com",
|
||||||
|
"firstname": "Test",
|
||||||
|
"lastname": "User",
|
||||||
|
"username": "test",
|
||||||
|
# Random characters are appended for unique
|
||||||
|
# username
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"service_offering": {
|
||||||
|
"name": "Tiny Instance",
|
||||||
|
"displaytext": "Tiny Instance",
|
||||||
|
"cpunumber": 1,
|
||||||
|
"cpuspeed": 100, # in MHz
|
||||||
|
"memory": 64, # In MBs
|
||||||
|
},
|
||||||
|
"disk_offering": {
|
||||||
|
"displaytext": "Small",
|
||||||
|
"name": "Small",
|
||||||
|
"disksize": 1
|
||||||
|
},
|
||||||
|
"virtual_machine": {
|
||||||
|
"displayname": "testVM",
|
||||||
|
"hypervisor": 'XenServer',
|
||||||
|
"protocol": 'TCP',
|
||||||
|
"ssh_port": 22,
|
||||||
|
"username": "root",
|
||||||
|
"password": "password",
|
||||||
|
"privateport": 22,
|
||||||
|
"publicport": 22,
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"diskname": "Test Volume",
|
||||||
|
},
|
||||||
|
"templates": {
|
||||||
|
# Configs for different Template formats
|
||||||
|
# For Eg. raw image, zip etc
|
||||||
|
0:{
|
||||||
|
"displaytext": "Public Template",
|
||||||
|
"name": "Public template",
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2",
|
||||||
|
"hypervisor": 'XenServer',
|
||||||
|
"format" : 'VHD',
|
||||||
|
"isfeatured": True,
|
||||||
|
"ispublic": True,
|
||||||
|
"isextractable": True,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"displaytext": "Cent OS Template",
|
||||||
|
"name": "Cent OS Template",
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"templatefilter": 'self',
|
||||||
|
},
|
||||||
|
"templatefilter": 'self',
|
||||||
|
"destzoneid": 2, # For Copy template (Destination zone)
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 10,
|
||||||
|
"mode": 'advanced', # Networking mode: Advanced, basic
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skip("Open questions")
|
||||||
|
class TestCreateTemplate(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.services = Services().services
|
||||||
|
cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient()
|
||||||
|
|
||||||
|
# Get Zone, Domain and templates
|
||||||
|
cls.domain = get_domain(cls.api_client, cls.services)
|
||||||
|
cls.zone = get_zone(cls.api_client, cls.services)
|
||||||
|
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
||||||
|
|
||||||
|
cls.service_offering = ServiceOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["service_offering"]
|
||||||
|
)
|
||||||
|
cls.account = Account.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["account"],
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
cls.services["account"] = cls.account.account.name
|
||||||
|
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.account,
|
||||||
|
cls.service_offering
|
||||||
|
]
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient()
|
||||||
|
#Cleanup resources used
|
||||||
|
cleanup_resources(cls.api_client, cls._cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_create_template(self):
|
||||||
|
"""Test create public & private template
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. Upload a templates in raw img format. Create a Vm instances from
|
||||||
|
# raw img template.
|
||||||
|
# 2. Upload a templates in zip file format. Create a Vm instances from
|
||||||
|
# zip template.
|
||||||
|
# 3. Upload a templates in tar format.Create a Vm instances from tar
|
||||||
|
# template.
|
||||||
|
# 4. Upload a templates in tar gzip format.Create a Vm instances from
|
||||||
|
# tar gzip template.
|
||||||
|
# 5. Upload a templates in tar bzip format. Create a Vm instances from
|
||||||
|
# tar bzip template.
|
||||||
|
# 6. Verify VMs & Templates is up and in ready state
|
||||||
|
|
||||||
|
for k, v in self.services["templates"].items():
|
||||||
|
|
||||||
|
# Register new template
|
||||||
|
template = Template.register(
|
||||||
|
self.apiclient,
|
||||||
|
v,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.debug(
|
||||||
|
"Registered a template of format: %s with ID: %s" % (
|
||||||
|
v["format"],
|
||||||
|
template.id
|
||||||
|
))
|
||||||
|
# Wait for template to download
|
||||||
|
template.download(self.apiclient)
|
||||||
|
self.cleanup.append(template)
|
||||||
|
|
||||||
|
# Wait for template status to be changed across
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templatefilter"],
|
||||||
|
id=template.id,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
if isinstance(list_template_response, list):
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List template failed!")
|
||||||
|
|
||||||
|
time.sleep(5)
|
||||||
|
timeout = timeout - 1
|
||||||
|
#Verify template response to check whether template added successfully
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check for list template response return valid data"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List Templates"
|
||||||
|
)
|
||||||
|
|
||||||
|
template_response = list_template_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.isready,
|
||||||
|
True,
|
||||||
|
"Check display text of newly created template"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Deploy new virtual machine using template
|
||||||
|
virtual_machine = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
templateid=template.id,
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
mode=self.services["mode"]
|
||||||
|
)
|
||||||
|
self.debug("creating an instance with template ID: %s" % template.id)
|
||||||
|
vm_response = list_virtual_machines(
|
||||||
|
self.apiclient,
|
||||||
|
id=virtual_machine.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(vm_response, list),
|
||||||
|
True,
|
||||||
|
"Check for list VMs response after VM deployment"
|
||||||
|
)
|
||||||
|
#Verify VM response to check whether VM deployment was successful
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(vm_response),
|
||||||
|
0,
|
||||||
|
"Check VMs available in List VMs response"
|
||||||
|
)
|
||||||
|
vm = vm_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
'Running',
|
||||||
|
"Check the state of VM created from Template"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class TestTemplates(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
cls.services = Services().services
|
||||||
|
cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient()
|
||||||
|
|
||||||
|
# Get Zone, templates etc
|
||||||
|
cls.domain = get_domain(cls.api_client, cls.services)
|
||||||
|
cls.zone = get_zone(cls.api_client, cls.services)
|
||||||
|
|
||||||
|
template = get_template(
|
||||||
|
cls.api_client,
|
||||||
|
cls.zone.id,
|
||||||
|
cls.services["ostypeid"]
|
||||||
|
)
|
||||||
|
cls.services["virtual_machine"]["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"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# create virtual machine
|
||||||
|
cls.virtual_machine = VirtualMachine.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["virtual_machine"],
|
||||||
|
templateid=template.id,
|
||||||
|
accountid=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid,
|
||||||
|
serviceofferingid=cls.service_offering.id,
|
||||||
|
)
|
||||||
|
#Stop virtual machine
|
||||||
|
cls.virtual_machine.stop(cls.api_client)
|
||||||
|
|
||||||
|
timeout = cls.services["timeout"]
|
||||||
|
#Wait before server has be successfully stopped
|
||||||
|
time.sleep(cls.services["sleep"])
|
||||||
|
|
||||||
|
while True:
|
||||||
|
list_volume = list_volumes(
|
||||||
|
cls.api_client,
|
||||||
|
virtualmachineid=cls.virtual_machine.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
if isinstance(list_volume, list):
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List volumes failed.")
|
||||||
|
|
||||||
|
time.sleep(5)
|
||||||
|
timeout = timeout -1
|
||||||
|
|
||||||
|
cls.volume = list_volume[0]
|
||||||
|
|
||||||
|
#Create template from volume
|
||||||
|
cls.template = Template.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["template"],
|
||||||
|
cls.volume.id
|
||||||
|
)
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.service_offering,
|
||||||
|
cls.account,
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient()
|
||||||
|
#Cleanup created resources such as templates and VMs
|
||||||
|
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 templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_create_template_volume(self):
|
||||||
|
"""Test Create template from volume
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. Deploy new VM using the template created from Volume
|
||||||
|
# 2. VM should be in Up and Running state
|
||||||
|
|
||||||
|
virtual_machine = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
templateid=self.template.id,
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("creating an instance with template ID: %s" % self.template.id)
|
||||||
|
self.cleanup.append(virtual_machine)
|
||||||
|
vm_response = list_virtual_machines(
|
||||||
|
self.apiclient,
|
||||||
|
id=virtual_machine.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
#Verify VM response to check whether VM deployment was successful
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(vm_response),
|
||||||
|
0,
|
||||||
|
"Check VMs available in List VMs response"
|
||||||
|
)
|
||||||
|
vm = vm_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
'Running',
|
||||||
|
"Check the state of VM created from Template"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_copy_template(self):
|
||||||
|
"""Test for copy template from one zone to another"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. copy template should be successful and
|
||||||
|
# secondary storage should contain new copied template.
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Copying template from zone: %s to %s" % (
|
||||||
|
self.template.id,
|
||||||
|
self.services["destzoneid"]
|
||||||
|
))
|
||||||
|
cmd = copyTemplate.copyTemplateCmd()
|
||||||
|
cmd.id = self.template.id
|
||||||
|
cmd.destzoneid = self.services["destzoneid"]
|
||||||
|
cmd.sourcezoneid = self.zone.id
|
||||||
|
self.apiclient.copyTemplate(cmd)
|
||||||
|
|
||||||
|
# Verify template is copied to another zone using ListTemplates
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templatefilter"],
|
||||||
|
id=self.template.id,
|
||||||
|
zoneid=self.services["destzoneid"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check for list template response return valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template extracted in List Templates"
|
||||||
|
)
|
||||||
|
|
||||||
|
template_response = list_template_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.id,
|
||||||
|
self.template.id,
|
||||||
|
"Check ID of the downloaded template"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.zoneid,
|
||||||
|
self.services["destzoneid"],
|
||||||
|
"Check zone ID of the copied template"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Cleanup- Delete the copied template
|
||||||
|
cmd = deleteTemplate.deleteTemplateCmd()
|
||||||
|
cmd.id = self.template.id
|
||||||
|
cmd.zoneid = self.services["destzoneid"]
|
||||||
|
self.apiclient.deleteTemplate(cmd)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_delete_template(self):
|
||||||
|
"""Test Delete template
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. Create a template and verify it is shown in list templates response
|
||||||
|
# 2. Delete the created template and again verify list template response
|
||||||
|
|
||||||
|
# Verify template response for updated attributes
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["template"]["templatefilter"],
|
||||||
|
id=self.template.id,
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check for list template response return valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List Templates"
|
||||||
|
)
|
||||||
|
template_response = list_template_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.id,
|
||||||
|
self.template.id,
|
||||||
|
"Check display text of updated template"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Deleting template: %s" % self.template)
|
||||||
|
# Delete the template
|
||||||
|
self.template.delete(self.apiclient)
|
||||||
|
self.debug("Delete template: %s successful" % self.template)
|
||||||
|
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["template"]["templatefilter"],
|
||||||
|
id=self.template.id,
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_template_response,
|
||||||
|
None,
|
||||||
|
"Check template available in List Templates"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_04_template_from_snapshot(self):
|
||||||
|
"""Create Template from snapshot
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 2. Snapshot the Root disk
|
||||||
|
# 3. Create Template from snapshot
|
||||||
|
# 4. Deploy Virtual machine using this template
|
||||||
|
# 5. VM should be in running state
|
||||||
|
|
||||||
|
volumes = list_volumes(
|
||||||
|
self.apiclient,
|
||||||
|
virtualmachineid=self.virtual_machine.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
volume = volumes[0]
|
||||||
|
|
||||||
|
self.debug("Creating a snapshot from volume: %s" % volume.id)
|
||||||
|
#Create a snapshot of volume
|
||||||
|
snapshot = Snapshot.create(
|
||||||
|
self.apiclient,
|
||||||
|
volume.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.debug("Creating a template from snapshot: %s" % snapshot.id)
|
||||||
|
# Generate template from the snapshot
|
||||||
|
template = Template.create_from_snapshot(
|
||||||
|
self.apiclient,
|
||||||
|
snapshot,
|
||||||
|
self.services["template"]
|
||||||
|
)
|
||||||
|
self.cleanup.append(template)
|
||||||
|
# Verify created template
|
||||||
|
templates = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["template"]["templatefilter"],
|
||||||
|
id=template.id
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
templates,
|
||||||
|
None,
|
||||||
|
"Check if result exists in list item call"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
templates[0].id,
|
||||||
|
template.id,
|
||||||
|
"Check new template id in list resources call"
|
||||||
|
)
|
||||||
|
self.debug("Deploying a VM from template: %s" % template.id)
|
||||||
|
# Deploy new virtual machine using template
|
||||||
|
virtual_machine = VirtualMachine.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["virtual_machine"],
|
||||||
|
templateid=template.id,
|
||||||
|
accountid=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
serviceofferingid=self.service_offering.id,
|
||||||
|
)
|
||||||
|
self.cleanup.append(virtual_machine)
|
||||||
|
|
||||||
|
vm_response = list_virtual_machines(
|
||||||
|
self.apiclient,
|
||||||
|
id=virtual_machine.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(vm_response, list),
|
||||||
|
True,
|
||||||
|
"Check for list VM response return valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Verify VM response to check whether VM deployment was successful
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(vm_response),
|
||||||
|
0,
|
||||||
|
"Check VMs available in List VMs response"
|
||||||
|
)
|
||||||
|
vm = vm_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
vm.state,
|
||||||
|
'Running',
|
||||||
|
"Check the state of VM created from Template"
|
||||||
|
)
|
||||||
|
return
|
||||||
1574
test/integration/component/test_usage.py
Normal file
1574
test/integration/component/test_usage.py
Normal file
File diff suppressed because it is too large
Load Diff
1019
test/integration/component/test_volumes.py
Normal file
1019
test/integration/component/test_volumes.py
Normal file
File diff suppressed because it is too large
Load Diff
13
test/integration/lib/__init__.py
Normal file
13
test/integration/lib/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# -*- 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
|
||||||
1862
test/integration/lib/base.py
Normal file
1862
test/integration/lib/base.py
Normal file
File diff suppressed because it is too large
Load Diff
472
test/integration/lib/common.py
Normal file
472
test/integration/lib/common.py
Normal file
@ -0,0 +1,472 @@
|
|||||||
|
# -*- 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
|
||||||
|
"""Common functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from marvin.remoteSSHClient import 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 = 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(interval)
|
||||||
|
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, projectid=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
|
||||||
|
if projectid:
|
||||||
|
cmd.projectid = projectid
|
||||||
|
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_nw_service_prividers(apiclient, **kwargs):
|
||||||
|
"""Lists Network service providers"""
|
||||||
|
|
||||||
|
cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd()
|
||||||
|
[setattr(cmd, k, v) for k, v in kwargs.items()]
|
||||||
|
return(apiclient.listNetworkServiceProviders(cmd))
|
||||||
|
|
||||||
|
def list_virtual_router_elements(apiclient, **kwargs):
|
||||||
|
"""Lists Virtual Router elements"""
|
||||||
|
|
||||||
|
cmd = listVirtualRouterElements.listVirtualRouterElementsCmd()
|
||||||
|
[setattr(cmd, k, v) for k, v in kwargs.items()]
|
||||||
|
return(apiclient.listVirtualRouterElements(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))
|
||||||
176
test/integration/lib/utils.py
Normal file
176
test/integration/lib/utils.py
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
# -*- 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
|
||||||
|
"""Utilities functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
import marvin
|
||||||
|
import time
|
||||||
|
from marvin.remoteSSHClient import remoteSSHClient
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from marvin import cloudstackConnection
|
||||||
|
#from cloudstackConnection import cloudConnection
|
||||||
|
from marvin import configGenerator
|
||||||
|
import logging
|
||||||
|
import string
|
||||||
|
import random
|
||||||
|
import imaplib
|
||||||
|
import email
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
def restart_mgmt_server(server):
|
||||||
|
"""Restarts the management server"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Get the SSH client
|
||||||
|
ssh = is_server_ssh_ready(
|
||||||
|
server["ipaddress"],
|
||||||
|
server["port"],
|
||||||
|
server["username"],
|
||||||
|
server["password"],
|
||||||
|
)
|
||||||
|
result = ssh.execute("/etc/init.d/cloud-management restart")
|
||||||
|
res = str(result)
|
||||||
|
# Server Stop - OK
|
||||||
|
# Server Start - OK
|
||||||
|
if res.count("OK") != 2:
|
||||||
|
raise ("ErrorInReboot!")
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
return
|
||||||
|
|
||||||
|
def fetch_latest_mail(services, from_mail):
|
||||||
|
"""Fetch mail"""
|
||||||
|
|
||||||
|
# Login to mail server to verify email
|
||||||
|
mail = imaplib.IMAP4_SSL(services["server"])
|
||||||
|
mail.login(
|
||||||
|
services["email"],
|
||||||
|
services["password"]
|
||||||
|
)
|
||||||
|
mail.list()
|
||||||
|
mail.select(services["folder"])
|
||||||
|
date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y")
|
||||||
|
|
||||||
|
result, data = mail.uid(
|
||||||
|
'search',
|
||||||
|
None,
|
||||||
|
'(SENTSINCE {date} HEADER FROM "{mail}")'.format(
|
||||||
|
date=date,
|
||||||
|
mail=from_mail
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Return False if email is not present
|
||||||
|
if data == []:
|
||||||
|
return False
|
||||||
|
|
||||||
|
latest_email_uid = data[0].split()[-1]
|
||||||
|
result, data = mail.uid('fetch', latest_email_uid, '(RFC822)')
|
||||||
|
raw_email = data[0][1]
|
||||||
|
email_message = email.message_from_string(raw_email)
|
||||||
|
result = get_first_text_block(email_message)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_first_text_block(email_message_instance):
|
||||||
|
"""fetches first text block from the mail"""
|
||||||
|
maintype = email_message_instance.get_content_maintype()
|
||||||
|
if maintype == 'multipart':
|
||||||
|
for part in email_message_instance.get_payload():
|
||||||
|
if part.get_content_maintype() == 'text':
|
||||||
|
return part.get_payload()
|
||||||
|
elif maintype == 'text':
|
||||||
|
return email_message_instance.get_payload()
|
||||||
|
|
||||||
|
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 = 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 = 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
|
||||||
41
test/integration/smoke/README
Normal file
41
test/integration/smoke/README
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
Build Verification Testing (BVT) Cases
|
||||||
|
--------------------------------------
|
||||||
|
These test cases are the core functionality tests that ensure the application is stable and can be tested thoroughly.
|
||||||
|
These BVT cases definitions are located at : https://docs.google.com/a/cloud.com/spreadsheet/ccc?key=0Ak8acbfxQG8ndEppOGZSLV9mUF9idjVkTkZkajhTZkE&invite=CPij0K0L
|
||||||
|
|
||||||
|
|
||||||
|
Guidelines
|
||||||
|
----------
|
||||||
|
BVT test cases are being developed using Python's unittests2. Following are certain guidelines being followed
|
||||||
|
1. Tests exercised for the same resource should ideally be present under a single suite or file.
|
||||||
|
|
||||||
|
2. Time-consuming operations that create new cloud resources like server creation, volume creation etc
|
||||||
|
should not necessarily be exercised per unit test. The resources can be shared by creating them at
|
||||||
|
the class-level using setUpClass and shared across all instances during a single run.
|
||||||
|
|
||||||
|
3. Certain tests pertaining to NAT, Firewall and Load Balancing warrant fresh resources per test. Hence a call should be
|
||||||
|
taken by the stakeholders regarding sharing resources.
|
||||||
|
|
||||||
|
4. Ensure that the tearDown/tearDownClass functions clean up all the resources created during the test run.
|
||||||
|
|
||||||
|
For more information about unittests: http://docs.python.org/library/unittest.html
|
||||||
|
|
||||||
|
|
||||||
|
BVT Tests
|
||||||
|
----------
|
||||||
|
The following files contain these BVT cases:
|
||||||
|
|
||||||
|
1. test_vm_life_cycle.py - VM Life Cycle tests
|
||||||
|
2. test_volumes.py - Volumes related tests
|
||||||
|
3. test_snapshots.py - Snapshots related tests
|
||||||
|
4. test_disk_offerings.py - Disk Offerings related tests
|
||||||
|
5. test_service_offerings.py - Service Offerings related tests
|
||||||
|
6. test_hosts.py - Hosts and Clusters related tests
|
||||||
|
7. test_iso.py - ISO related tests
|
||||||
|
8. test_network.py - Network related tests
|
||||||
|
9. test_primary_storage.py - Primary storage related tests
|
||||||
|
10. test_secondary_storage.py - Secondary storage related tests
|
||||||
|
11. test_ssvm.py - SSVM & CPVM related tests
|
||||||
|
12. test_templates.py - Templates related tests
|
||||||
|
13. test_routers.py - Router related tests
|
||||||
|
|
||||||
13
test/integration/smoke/__init__.py
Normal file
13
test/integration/smoke/__init__.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# -*- 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
|
||||||
213
test/integration/smoke/test_disk_offerings.py
Normal file
213
test/integration/smoke/test_disk_offerings.py
Normal file
@ -0,0 +1,213 @@
|
|||||||
|
# -*- 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 Disk offerings"""
|
||||||
|
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Disk offerings Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"off": {
|
||||||
|
"name": "Disk offering",
|
||||||
|
"displaytext": "Disk offering",
|
||||||
|
"disksize": 1 # in GB
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestCreateDiskOffering(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.services = Services().services
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_create_disk_offering(self):
|
||||||
|
"""Test to create disk offering"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. createDiskOfferings should return valid info for new offering
|
||||||
|
# 2. The Cloud Database contains the valid information
|
||||||
|
|
||||||
|
disk_offering = DiskOffering.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["off"]
|
||||||
|
)
|
||||||
|
self.cleanup.append(disk_offering)
|
||||||
|
|
||||||
|
self.debug("Created Disk offering with ID: %s" % disk_offering.id)
|
||||||
|
|
||||||
|
list_disk_response = list_disk_offering(
|
||||||
|
self.apiclient,
|
||||||
|
id=disk_offering.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_disk_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_disk_response),
|
||||||
|
0,
|
||||||
|
"Check Disk offering is created"
|
||||||
|
)
|
||||||
|
disk_response = list_disk_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
disk_response.displaytext,
|
||||||
|
self.services["off"]["displaytext"],
|
||||||
|
"Check server id in createServiceOffering"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
disk_response.name,
|
||||||
|
self.services["off"]["name"],
|
||||||
|
"Check name in createServiceOffering"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class TestDiskOfferings(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.services = Services().services
|
||||||
|
cls.api_client = super(TestDiskOfferings, cls).getClsTestClient().getApiClient()
|
||||||
|
cls.disk_offering_1 = DiskOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["off"]
|
||||||
|
)
|
||||||
|
cls.disk_offering_2 = DiskOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["off"]
|
||||||
|
)
|
||||||
|
cls._cleanup = [cls.disk_offering_1]
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestDiskOfferings, cls).getClsTestClient().getApiClient()
|
||||||
|
cleanup_resources(cls.api_client, cls._cleanup)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_edit_disk_offering(self):
|
||||||
|
"""Test to update existing disk offering"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. updateDiskOffering should return
|
||||||
|
# a valid information for newly created offering
|
||||||
|
|
||||||
|
#Generate new name & displaytext from random data
|
||||||
|
random_displaytext = random_gen()
|
||||||
|
random_name = random_gen()
|
||||||
|
|
||||||
|
self.debug("Updating Disk offering with ID: %s" %
|
||||||
|
self.disk_offering_1.id)
|
||||||
|
|
||||||
|
cmd = updateDiskOffering.updateDiskOfferingCmd()
|
||||||
|
cmd.id = self.disk_offering_1.id
|
||||||
|
cmd.displaytext = random_displaytext
|
||||||
|
cmd.name = random_name
|
||||||
|
|
||||||
|
self.apiclient.updateDiskOffering(cmd)
|
||||||
|
|
||||||
|
list_disk_response = list_disk_offering(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.disk_offering_1.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_disk_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_disk_response),
|
||||||
|
0,
|
||||||
|
"Check disk offering is updated"
|
||||||
|
)
|
||||||
|
|
||||||
|
disk_response = list_disk_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
disk_response.displaytext,
|
||||||
|
random_displaytext,
|
||||||
|
"Check service displaytext in updateServiceOffering"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
disk_response.name,
|
||||||
|
random_name,
|
||||||
|
"Check service name in updateServiceOffering"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_delete_disk_offering(self):
|
||||||
|
"""Test to delete disk offering"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. deleteDiskOffering should return
|
||||||
|
# a valid information for newly created offering
|
||||||
|
|
||||||
|
self.disk_offering_2.delete(self.apiclient)
|
||||||
|
|
||||||
|
self.debug("Deleted Disk offering with ID: %s" %
|
||||||
|
self.disk_offering_2.id)
|
||||||
|
list_disk_response = list_disk_offering(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.disk_offering_2.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
list_disk_response,
|
||||||
|
None,
|
||||||
|
"Check if disk offering exists in listDiskOfferings"
|
||||||
|
)
|
||||||
|
return
|
||||||
224
test/integration/smoke/test_hosts.py
Normal file
224
test/integration/smoke/test_hosts.py
Normal file
@ -0,0 +1,224 @@
|
|||||||
|
# -*- 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 Hosts and Clusters
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
|
||||||
|
#Import System modules
|
||||||
|
import time
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Hosts & Clusters Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"clusters": {
|
||||||
|
0: {
|
||||||
|
"clustername": "Xen Cluster",
|
||||||
|
"clustertype": "CloudManaged",
|
||||||
|
# CloudManaged or ExternalManaged"
|
||||||
|
"hypervisor": "XenServer",
|
||||||
|
# Hypervisor type
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
"clustername": "KVM Cluster",
|
||||||
|
"clustertype": "CloudManaged",
|
||||||
|
# CloudManaged or ExternalManaged"
|
||||||
|
"hypervisor": "KVM",
|
||||||
|
# Hypervisor type
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"hypervisor": 'VMware',
|
||||||
|
# Hypervisor type
|
||||||
|
"clustertype": 'ExternalManaged',
|
||||||
|
# CloudManaged or ExternalManaged"
|
||||||
|
"username": 'administrator',
|
||||||
|
"password": 'fr3sca',
|
||||||
|
"url": 'http://192.168.100.17/CloudStack-Clogeny-Pune/Pune-1',
|
||||||
|
# Format:http://vCenter Host/Datacenter/Cluster
|
||||||
|
"clustername": 'VMWare Cluster',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"hosts": {
|
||||||
|
"xenserver": {
|
||||||
|
# Must be name of corresponding Hypervisor type
|
||||||
|
# in cluster in small letters
|
||||||
|
"hypervisor": 'XenServer',
|
||||||
|
# Hypervisor type
|
||||||
|
"clustertype": 'CloudManaged',
|
||||||
|
# CloudManaged or ExternalManaged"
|
||||||
|
"url": 'http://192.168.100.211',
|
||||||
|
"username": "root",
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"kvm": {
|
||||||
|
"hypervisor": 'KVM',
|
||||||
|
# Hypervisor type
|
||||||
|
"clustertype": 'CloudManaged',
|
||||||
|
# CloudManaged or ExternalManaged"
|
||||||
|
"url": 'http://192.168.100.212',
|
||||||
|
"username": "root",
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"vmware": {
|
||||||
|
"hypervisor": 'VMware',
|
||||||
|
# Hypervisor type
|
||||||
|
"clustertype": 'ExternalManaged',
|
||||||
|
# CloudManaged or ExternalManaged"
|
||||||
|
"url": 'http://192.168.100.203',
|
||||||
|
"username": "administrator",
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestHosts(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.services = Services().services
|
||||||
|
self.zone = get_zone(self.apiclient, self.services)
|
||||||
|
self.pod = get_pod(self.apiclient, self.zone.id, self.services)
|
||||||
|
self.cleanup = []
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_clusters(self):
|
||||||
|
"""Test Add clusters & hosts - XEN, KVM, VWARE
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. Verify hypervisortype returned by API is Xen/KVM/VWare
|
||||||
|
# 2. Verify that the cluster is in 'Enabled' allocation state
|
||||||
|
# 3. Verify that the host is added successfully and in Up state
|
||||||
|
# with listHosts API response
|
||||||
|
|
||||||
|
#Create clusters with Hypervisor type XEN/KVM/VWare
|
||||||
|
for k, v in self.services["clusters"].items():
|
||||||
|
cluster = Cluster.create(
|
||||||
|
self.apiclient,
|
||||||
|
v,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id
|
||||||
|
)
|
||||||
|
self.debug(
|
||||||
|
"Created Cluster for hypervisor type %s & ID: %s" %(
|
||||||
|
v["hypervisor"],
|
||||||
|
cluster.id
|
||||||
|
))
|
||||||
|
self.assertEqual(
|
||||||
|
cluster.hypervisortype,
|
||||||
|
v["hypervisor"],
|
||||||
|
"Check hypervisor type is " + v["hypervisor"] + " or not"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
cluster.allocationstate,
|
||||||
|
'Enabled',
|
||||||
|
"Check whether allocation state of cluster is enabled"
|
||||||
|
)
|
||||||
|
|
||||||
|
#If host is externally managed host is already added with cluster
|
||||||
|
response = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
clusterid=cluster.id
|
||||||
|
)
|
||||||
|
|
||||||
|
if not response:
|
||||||
|
hypervisor_type = str(cluster.hypervisortype.lower())
|
||||||
|
host = Host.create(
|
||||||
|
self.apiclient,
|
||||||
|
cluster,
|
||||||
|
self.services["hosts"][hypervisor_type],
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id
|
||||||
|
)
|
||||||
|
self.debug(
|
||||||
|
"Created host (ID: %s) in cluster ID %s" %(
|
||||||
|
host.id,
|
||||||
|
cluster.id
|
||||||
|
))
|
||||||
|
|
||||||
|
#Cleanup Host & Cluster
|
||||||
|
self.cleanup.append(host)
|
||||||
|
self.cleanup.append(cluster)
|
||||||
|
|
||||||
|
list_hosts_response = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
clusterid=cluster.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_hosts_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_hosts_response),
|
||||||
|
0,
|
||||||
|
"Check list Hosts response"
|
||||||
|
)
|
||||||
|
|
||||||
|
host_response = list_hosts_response[0]
|
||||||
|
#Check if host is Up and running
|
||||||
|
self.assertEqual(
|
||||||
|
host_response.state,
|
||||||
|
'Up',
|
||||||
|
"Check if state of host is Up or not"
|
||||||
|
)
|
||||||
|
#Verify List Cluster Response has newly added cluster
|
||||||
|
list_cluster_response = list_clusters(
|
||||||
|
self.apiclient,
|
||||||
|
id=cluster.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_cluster_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_cluster_response),
|
||||||
|
0,
|
||||||
|
"Check list Hosts response"
|
||||||
|
)
|
||||||
|
|
||||||
|
cluster_response = list_cluster_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
cluster_response.id,
|
||||||
|
cluster.id,
|
||||||
|
"Check cluster ID with list clusters response"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
cluster_response.hypervisortype,
|
||||||
|
cluster.hypervisortype,
|
||||||
|
"Check hypervisor type with is " + v["hypervisor"] + " or not"
|
||||||
|
)
|
||||||
|
return
|
||||||
500
test/integration/smoke/test_iso.py
Normal file
500
test/integration/smoke/test_iso.py
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
# -*- 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 Templates ISO
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
import urllib
|
||||||
|
from random import random
|
||||||
|
#Import System modules
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test ISO 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": "fr3sca",
|
||||||
|
},
|
||||||
|
"iso_1":
|
||||||
|
{
|
||||||
|
"displaytext": "Test ISO 1",
|
||||||
|
"name": "ISO 1",
|
||||||
|
"url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso",
|
||||||
|
# Source URL where ISO is located
|
||||||
|
"isextractable": True,
|
||||||
|
"isfeatured": True,
|
||||||
|
"ispublic": True,
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
},
|
||||||
|
"iso_2":
|
||||||
|
{
|
||||||
|
"displaytext": "Test ISO 2",
|
||||||
|
"name": "ISO 2",
|
||||||
|
"url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso",
|
||||||
|
# Source URL where ISO is located
|
||||||
|
"isextractable": True,
|
||||||
|
"isfeatured": True,
|
||||||
|
"ispublic": True,
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"mode": 'HTTP_DOWNLOAD',
|
||||||
|
# Used in Extract template, value must be HTTP_DOWNLOAD
|
||||||
|
},
|
||||||
|
"destzoneid": 5,
|
||||||
|
# Copy ISO from one zone to another (Destination Zone)
|
||||||
|
"isfeatured": True,
|
||||||
|
"ispublic": True,
|
||||||
|
"isextractable": True,
|
||||||
|
"bootable": True, # For edit template
|
||||||
|
"passwordenabled": True,
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 10,
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
# CentOS 5.3 (64 bit)
|
||||||
|
"mode": 'advanced'
|
||||||
|
# Networking mode: Basic or Advanced
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateIso(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.services = Services().services
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
# Get Zone, Domain and templates
|
||||||
|
self.domain = get_domain(self.apiclient, self.services)
|
||||||
|
self.zone = get_zone(self.apiclient, self.services)
|
||||||
|
self.services["domainid"] = self.domain.id
|
||||||
|
self.services["iso_2"]["zoneid"] = self.zone.id
|
||||||
|
|
||||||
|
self.account = Account.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["account"],
|
||||||
|
domainid=self.domain.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.cleanup = [self.account]
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created ISOs
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_create_iso(self):
|
||||||
|
"""Test create public & private ISO
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. database (vm_template table) should be
|
||||||
|
# updated with newly created ISO
|
||||||
|
# 2. UI should show the newly added ISO
|
||||||
|
# 3. listIsos API should show the newly added ISO
|
||||||
|
|
||||||
|
iso = Iso.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["iso_2"],
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.debug("ISO created with ID: %s" % iso.id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
iso.download(self.apiclient)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Exception while downloading ISO %s: %s"\
|
||||||
|
% (iso.id, e))
|
||||||
|
|
||||||
|
list_iso_response = list_isos(
|
||||||
|
self.apiclient,
|
||||||
|
id=iso.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_iso_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_iso_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List ISOs"
|
||||||
|
)
|
||||||
|
iso_response = list_iso_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.displaytext,
|
||||||
|
self.services["iso_2"]["displaytext"],
|
||||||
|
"Check display text of newly created ISO"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.name,
|
||||||
|
self.services["iso_2"]["name"],
|
||||||
|
"Check name of newly created ISO"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.zoneid,
|
||||||
|
self.services["iso_2"]["zoneid"],
|
||||||
|
"Check zone ID of newly created ISO"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class TestISO(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.services = Services().services
|
||||||
|
cls.api_client = super(TestISO, cls).getClsTestClient().getApiClient()
|
||||||
|
|
||||||
|
# Get Zone, Domain and templates
|
||||||
|
cls.domain = get_domain(cls.api_client, cls.services)
|
||||||
|
cls.zone = get_zone(cls.api_client, cls.services)
|
||||||
|
|
||||||
|
cls.services["domainid"] = cls.domain.id
|
||||||
|
cls.services["iso_1"]["zoneid"] = cls.zone.id
|
||||||
|
cls.services["iso_2"]["zoneid"] = cls.zone.id
|
||||||
|
cls.services["sourcezoneid"] = cls.zone.id
|
||||||
|
|
||||||
|
#Create an account, ISOs etc.
|
||||||
|
cls.account = Account.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["account"],
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
cls.services["account"] = cls.account.account.name
|
||||||
|
cls.iso_1 = Iso.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["iso_1"],
|
||||||
|
account=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
cls.iso_1.download(cls.api_client)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Exception while downloading ISO %s: %s"\
|
||||||
|
% (cls.iso_1.id, e))
|
||||||
|
|
||||||
|
cls.iso_2 = Iso.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["iso_2"],
|
||||||
|
account=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
cls.iso_2.download(cls.api_client)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Exception while downloading ISO %s: %s"\
|
||||||
|
% (cls.iso_2.id, e))
|
||||||
|
|
||||||
|
cls._cleanup = [cls.account]
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestISO, 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)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created ISOs, VMs
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_edit_iso(self):
|
||||||
|
"""Test Edit ISO
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. UI should show the edited values for ISO
|
||||||
|
# 2. database (vm_template table) should have updated values
|
||||||
|
|
||||||
|
#Generate random values for updating ISO name and Display text
|
||||||
|
new_displayText = random_gen()
|
||||||
|
new_name = random_gen()
|
||||||
|
|
||||||
|
self.debug("Updating ISO permissions for ISO: %s" % self.iso_1.id)
|
||||||
|
|
||||||
|
cmd = updateIso.updateIsoCmd()
|
||||||
|
#Assign new values to attributes
|
||||||
|
cmd.id = self.iso_1.id
|
||||||
|
cmd.displaytext = new_displayText
|
||||||
|
cmd.name = new_name
|
||||||
|
cmd.bootable = self.services["bootable"]
|
||||||
|
cmd.passwordenabled = self.services["passwordenabled"]
|
||||||
|
|
||||||
|
self.apiclient.updateIso(cmd)
|
||||||
|
|
||||||
|
#Check whether attributes are updated in ISO using listIsos
|
||||||
|
list_iso_response = list_isos(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.iso_1.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_iso_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_iso_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List ISOs"
|
||||||
|
)
|
||||||
|
|
||||||
|
iso_response = list_iso_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.displaytext,
|
||||||
|
new_displayText,
|
||||||
|
"Check display text of updated ISO"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.name,
|
||||||
|
new_name,
|
||||||
|
"Check name of updated ISO"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.bootable,
|
||||||
|
self.services["bootable"],
|
||||||
|
"Check if image is bootable of updated ISO"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.ostypeid,
|
||||||
|
self.services["ostypeid"],
|
||||||
|
"Check OSTypeID of updated ISO"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_delete_iso(self):
|
||||||
|
"""Test delete ISO
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. UI should not show the deleted ISP
|
||||||
|
# 2. database (vm_template table) should not contain deleted ISO
|
||||||
|
|
||||||
|
self.debug("Deleting ISO with ID: %s" % self.iso_1.id)
|
||||||
|
self.iso_1.delete(self.apiclient)
|
||||||
|
|
||||||
|
# Sleep to ensure that ISO state is reflected in other calls
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
#ListIsos to verify deleted ISO is properly deleted
|
||||||
|
list_iso_response = list_isos(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.iso_1.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
list_iso_response,
|
||||||
|
None,
|
||||||
|
"Check if ISO exists in ListIsos"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_04_extract_Iso(self):
|
||||||
|
"Test for extract ISO"
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Admin should able extract and download the ISO
|
||||||
|
# 2. ListIsos should display all the public templates
|
||||||
|
# for all kind of users
|
||||||
|
# 3 .ListIsos should not display the system templates
|
||||||
|
|
||||||
|
self.debug("Extracting ISO with ID: %s" % self.iso_2.id)
|
||||||
|
|
||||||
|
cmd = extractIso.extractIsoCmd()
|
||||||
|
cmd.id = self.iso_2.id
|
||||||
|
cmd.mode = self.services["iso_2"]["mode"]
|
||||||
|
cmd.zoneid = self.services["iso_2"]["zoneid"]
|
||||||
|
list_extract_response = self.apiclient.extractIso(cmd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
#Format URL to ASCII to retrieve response code
|
||||||
|
formatted_url = urllib.unquote_plus(list_extract_response.url)
|
||||||
|
url_response = urllib.urlopen(formatted_url)
|
||||||
|
response_code = url_response.getcode()
|
||||||
|
except Exception:
|
||||||
|
self.fail(
|
||||||
|
"Extract ISO Failed with invalid URL %s (ISO id: %s)" \
|
||||||
|
% (formatted_url, self.iso_2.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
list_extract_response.id,
|
||||||
|
self.iso_2.id,
|
||||||
|
"Check ID of the downloaded ISO"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_extract_response.extractMode,
|
||||||
|
self.services["iso_2"]["mode"],
|
||||||
|
"Check mode of extraction"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_extract_response.zoneid,
|
||||||
|
self.services["iso_2"]["zoneid"],
|
||||||
|
"Check zone ID of extraction"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
response_code,
|
||||||
|
200,
|
||||||
|
"Check for a valid response of download URL"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_05_iso_permissions(self):
|
||||||
|
"""Update & Test for ISO permissions"""
|
||||||
|
|
||||||
|
# validate the following
|
||||||
|
# 1. listIsos returns valid permissions set for ISO
|
||||||
|
# 2. permission changes should be reflected in vm_template
|
||||||
|
# table in database
|
||||||
|
|
||||||
|
self.debug("Updating permissions for ISO: %s" % self.iso_2.id)
|
||||||
|
|
||||||
|
cmd = updateIsoPermissions.updateIsoPermissionsCmd()
|
||||||
|
cmd.id = self.iso_2.id
|
||||||
|
#Update ISO permissions
|
||||||
|
cmd.isfeatured = self.services["isfeatured"]
|
||||||
|
cmd.ispublic = self.services["ispublic"]
|
||||||
|
cmd.isextractable = self.services["isextractable"]
|
||||||
|
self.apiclient.updateIsoPermissions(cmd)
|
||||||
|
|
||||||
|
#Verify ListIsos have updated permissions for the ISO for normal user
|
||||||
|
list_iso_response = list_isos(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.iso_2.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_iso_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
iso_response = list_iso_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.id,
|
||||||
|
self.iso_2.id,
|
||||||
|
"Check ISO ID"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.ispublic,
|
||||||
|
self.services["ispublic"],
|
||||||
|
"Check ispublic permission of ISO"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.isfeatured,
|
||||||
|
self.services["isfeatured"],
|
||||||
|
"Check isfeatured permission of ISO"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_06_copy_iso(self):
|
||||||
|
"""Test for copy ISO from one zone to another"""
|
||||||
|
|
||||||
|
#Validate the following
|
||||||
|
#1. copy ISO should be successful and secondary storage
|
||||||
|
# should contain new copied ISO.
|
||||||
|
|
||||||
|
self.debug("Copy ISO from %s to %s" % (
|
||||||
|
self.zone.id,
|
||||||
|
self.services["destzoneid"]
|
||||||
|
))
|
||||||
|
|
||||||
|
cmd = copyIso.copyIsoCmd()
|
||||||
|
cmd.id = self.iso_2.id
|
||||||
|
cmd.destzoneid = self.services["destzoneid"]
|
||||||
|
cmd.sourcezoneid = self.zone.id
|
||||||
|
self.apiclient.copyIso(cmd)
|
||||||
|
|
||||||
|
#Verify ISO is copied to another zone using ListIsos
|
||||||
|
list_iso_response = list_isos(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.iso_2.id,
|
||||||
|
zoneid=self.services["destzoneid"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_iso_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_iso_response),
|
||||||
|
0,
|
||||||
|
"Check template extracted in List ISO"
|
||||||
|
)
|
||||||
|
iso_response = list_iso_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.id,
|
||||||
|
self.iso_2.id,
|
||||||
|
"Check ID of the downloaded ISO"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
iso_response.zoneid,
|
||||||
|
self.services["destzoneid"],
|
||||||
|
"Check zone ID of the copied ISO"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Cleanup copied ISO: %s" % iso_response.id)
|
||||||
|
# Cleanup- Delete the copied ISO
|
||||||
|
cmd = deleteIso.deleteIsoCmd()
|
||||||
|
cmd.id = iso_response.id
|
||||||
|
cmd.zoneid = self.services["destzoneid"]
|
||||||
|
self.apiclient.deleteIso(cmd)
|
||||||
|
return
|
||||||
1712
test/integration/smoke/test_network.py
Normal file
1712
test/integration/smoke/test_network.py
Normal file
File diff suppressed because it is too large
Load Diff
238
test/integration/smoke/test_primary_storage.py
Normal file
238
test/integration/smoke/test_primary_storage.py
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
# -*- 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 Primary Storage
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
|
||||||
|
#Import System modules
|
||||||
|
import time
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Primary storage Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"nfs": {
|
||||||
|
0: {
|
||||||
|
"url": "nfs://192.168.100.131/testprimary",
|
||||||
|
# Format: File_System_Type/Location/Path
|
||||||
|
"name": "Primary XEN",
|
||||||
|
"hypervisor": 'XEN',
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
"url": "nfs://192.168.100.131/Primary",
|
||||||
|
"name": "Primary KVM",
|
||||||
|
"hypervisor": 'KVM',
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"url": "nfs://192.168.100.131/Primary",
|
||||||
|
"name": "Primary VMWare",
|
||||||
|
"hypervisor": 'VMWare',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"iscsi": {
|
||||||
|
0: {
|
||||||
|
"url": "iscsi://192.168.100.21/iqn.2012-01.localdomain.clo-cstack-cos6:iser/1",
|
||||||
|
# Format : iscsi://IP Address/IQN number/LUN#
|
||||||
|
"name": "Primary iSCSI",
|
||||||
|
"hypervisor": 'XEN',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestPrimaryStorageServices(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.services = Services().services
|
||||||
|
self.cleanup = []
|
||||||
|
# Get Zone and pod
|
||||||
|
self.zone = get_zone(self.apiclient, self.services)
|
||||||
|
self.pod = get_pod(self.apiclient, self.zone.id)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_primary_storage(self):
|
||||||
|
"""Test primary storage pools - XEN, KVM, VMWare
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. verify hypervisortype returned by api is Xen/KVM/VMWare
|
||||||
|
# 2. verify that the cluster is in 'Enabled' allocation state
|
||||||
|
# 3. verify that the host is added successfully and
|
||||||
|
# in Up state with listHosts api response
|
||||||
|
|
||||||
|
#Create NFS storage pools with on XEN/KVM/VMWare clusters
|
||||||
|
for k, v in self.services["nfs"].items():
|
||||||
|
|
||||||
|
clusters = list_clusters(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
hypervisortype=v["hypervisor"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(clusters, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
cluster = clusters[0]
|
||||||
|
#Host should be present before adding primary storage
|
||||||
|
list_hosts_response = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
clusterid=cluster.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_hosts_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_hosts_response),
|
||||||
|
0,
|
||||||
|
"Check list Hosts for hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
|
||||||
|
storage = StoragePool.create(self.apiclient,
|
||||||
|
v,
|
||||||
|
clusterid=cluster.id,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(storage)
|
||||||
|
|
||||||
|
self.debug("Created storage pool in cluster: %s" % cluster.id)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
storage.state,
|
||||||
|
'Up',
|
||||||
|
"Check primary storage state for hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
storage.type,
|
||||||
|
'NetworkFilesystem',
|
||||||
|
"Check storage pool type for hypervisor : " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
|
||||||
|
#Verify List Storage pool Response has newly added storage pool
|
||||||
|
storage_pools_response = list_storage_pools(
|
||||||
|
self.apiclient,
|
||||||
|
id=storage.id,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(storage_pools_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(storage_pools_response),
|
||||||
|
0,
|
||||||
|
"Check list Hosts response"
|
||||||
|
)
|
||||||
|
|
||||||
|
storage_response = storage_pools_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
storage_response.id,
|
||||||
|
storage.id,
|
||||||
|
"Check storage pool ID for hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
storage.type,
|
||||||
|
storage_response.type,
|
||||||
|
"Check storage pool type for hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
# Call cleanup for reusing primary storage
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
self.cleanup = []
|
||||||
|
|
||||||
|
# Create iSCSI storage pools with on XEN/KVM clusters
|
||||||
|
for k, v in self.services["iscsi"].items():
|
||||||
|
clusters = list_clusters(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
hypervisortype=v["hypervisor"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(clusters, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
cluster = clusters[0]
|
||||||
|
|
||||||
|
storage = StoragePool.create(self.apiclient,
|
||||||
|
v,
|
||||||
|
clusterid=cluster.id,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id
|
||||||
|
)
|
||||||
|
self.cleanup.append(storage)
|
||||||
|
|
||||||
|
self.debug("Created iSCSI storage pool in cluster: %s" % cluster.id)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
storage.state,
|
||||||
|
'Up',
|
||||||
|
"Check primary storage state for hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
|
||||||
|
#Verify List Storage pool Response has newly added storage pool
|
||||||
|
storage_pools_response = list_storage_pools(
|
||||||
|
self.apiclient,
|
||||||
|
id=storage.id,
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(storage_pools_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(storage_pools_response),
|
||||||
|
0,
|
||||||
|
"Check Hosts response for hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
|
||||||
|
storage_response = storage_pools_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
storage_response.id,
|
||||||
|
storage.id,
|
||||||
|
"Check storage pool ID for hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
storage.type,
|
||||||
|
storage_response.type,
|
||||||
|
"Check storage pool type hypervisor: " + v["hypervisor"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Call cleanup for reusing primary storage
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
self.cleanup = []
|
||||||
|
return
|
||||||
820
test/integration/smoke/test_routers.py
Normal file
820
test/integration/smoke/test_routers.py
Normal file
@ -0,0 +1,820 @@
|
|||||||
|
# -*- 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 routers
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from marvin.remoteSSHClient import remoteSSHClient
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
|
||||||
|
#Import System modules
|
||||||
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test router Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"service_offering": {
|
||||||
|
"name": "Tiny Instance",
|
||||||
|
"displaytext": "Tiny Instance",
|
||||||
|
"cpunumber": 1,
|
||||||
|
"cpuspeed": 100, # in MHz
|
||||||
|
"memory": 64, # In MBs
|
||||||
|
},
|
||||||
|
"virtual_machine":
|
||||||
|
{
|
||||||
|
"displayname": "Test VM",
|
||||||
|
"username": "root",
|
||||||
|
"password": "fr3sca",
|
||||||
|
"ssh_port": 22,
|
||||||
|
"hypervisor": 'XenServer',
|
||||||
|
"privateport": 22,
|
||||||
|
"publicport": 22,
|
||||||
|
"protocol": 'TCP',
|
||||||
|
},
|
||||||
|
"account": {
|
||||||
|
"email": "test@test.com",
|
||||||
|
"firstname": "Test",
|
||||||
|
"lastname": "User",
|
||||||
|
"username": "testuser",
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"ostypeid":'5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 10,
|
||||||
|
"mode": 'advanced', #Networking mode: Basic, Advanced
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestRouterServices(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
cls.api_client = super(
|
||||||
|
TestRouterServices,
|
||||||
|
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)
|
||||||
|
template = get_template(
|
||||||
|
cls.api_client,
|
||||||
|
cls.zone.id,
|
||||||
|
cls.services["ostypeid"]
|
||||||
|
)
|
||||||
|
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
||||||
|
|
||||||
|
#Create an account, network, VM and IP addresses
|
||||||
|
cls.account = Account.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["account"],
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
cls.service_offering = ServiceOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["service_offering"]
|
||||||
|
)
|
||||||
|
cls.vm_1 = VirtualMachine.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["virtual_machine"],
|
||||||
|
templateid=template.id,
|
||||||
|
accountid=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid,
|
||||||
|
serviceofferingid=cls.service_offering.id
|
||||||
|
)
|
||||||
|
cls.cleanup = [
|
||||||
|
cls.vm_1,
|
||||||
|
cls.account,
|
||||||
|
cls.service_offering
|
||||||
|
]
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(
|
||||||
|
TestRouterServices,
|
||||||
|
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)
|
||||||
|
return
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_router_internal_basic(self):
|
||||||
|
"""Test router internal basic zone
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. Router only does dhcp
|
||||||
|
# 2. Verify that ports 67 (DHCP) and 53 (DNS) are open on UDP
|
||||||
|
# by checking status of dnsmasq process
|
||||||
|
|
||||||
|
# Find router associated with user account
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=router.zoneid,
|
||||||
|
type='Routing',
|
||||||
|
state='Up',
|
||||||
|
virtualmachineid=self.vm_1.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list host returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
self.debug("Router ID: %s, state: %s" % (router.id, router.state))
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
router.state,
|
||||||
|
'Running',
|
||||||
|
"Check list router response for router state"
|
||||||
|
)
|
||||||
|
|
||||||
|
result = get_process_status(
|
||||||
|
host.ipaddress,
|
||||||
|
self.services['virtual_machine']["publicport"],
|
||||||
|
self.vm_1.username,
|
||||||
|
self.vm_1.password,
|
||||||
|
router.linklocalip,
|
||||||
|
"service dnsmasq status"
|
||||||
|
)
|
||||||
|
res = str(result)
|
||||||
|
self.debug("Dnsmasq process status: %s" % res)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
res.count("running"),
|
||||||
|
1,
|
||||||
|
"Check dnsmasq service is running or not"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_router_internal_adv(self):
|
||||||
|
"""Test router internal advanced zone
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. Router does dhcp, dns, gateway, LB, PF, FW
|
||||||
|
# 2. verify that dhcp, dns ports are open on UDP
|
||||||
|
# 3. dnsmasq, haproxy processes should be running
|
||||||
|
|
||||||
|
# Find router associated with user account
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=router.zoneid,
|
||||||
|
type='Routing',
|
||||||
|
state='Up',
|
||||||
|
virtualmachineid=self.vm_1.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
self.debug("Router ID: %s, state: %s" % (router.id, router.state))
|
||||||
|
self.assertEqual(
|
||||||
|
router.state,
|
||||||
|
'Running',
|
||||||
|
"Check list router response for router state"
|
||||||
|
)
|
||||||
|
|
||||||
|
result = get_process_status(
|
||||||
|
host.ipaddress,
|
||||||
|
self.services['virtual_machine']["publicport"],
|
||||||
|
self.vm_1.username,
|
||||||
|
self.vm_1.password,
|
||||||
|
router.linklocalip,
|
||||||
|
"service dnsmasq status"
|
||||||
|
)
|
||||||
|
res = str(result)
|
||||||
|
self.debug("Dnsmasq process status: %s" % res)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
res.count("running"),
|
||||||
|
1,
|
||||||
|
"Check dnsmasq service is running or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
result = get_process_status(
|
||||||
|
host.ipaddress,
|
||||||
|
self.services['virtual_machine']["publicport"],
|
||||||
|
self.vm_1.username,
|
||||||
|
self.vm_1.password,
|
||||||
|
router.linklocalip,
|
||||||
|
"service haproxy status"
|
||||||
|
)
|
||||||
|
res = str(result)
|
||||||
|
self.assertEqual(
|
||||||
|
res.count("running"),
|
||||||
|
1,
|
||||||
|
"Check haproxy service is running or not"
|
||||||
|
)
|
||||||
|
self.debug("Haproxy process status: %s" % res)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_restart_network_cleanup(self):
|
||||||
|
"""Test restart network
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. When cleanup = true, router is destroyed and a new one created
|
||||||
|
# 2. New router will have new publicIp and linkLocalIp and
|
||||||
|
# all it's services should resume
|
||||||
|
|
||||||
|
# Find router associated with user account
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
#Store old values before restart
|
||||||
|
old_linklocalip = router.linklocalip
|
||||||
|
|
||||||
|
timeout = 10
|
||||||
|
# Network should be in Implemented or Setup stage before restart
|
||||||
|
while True:
|
||||||
|
networks = list_networks(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(networks, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
network = networks[0]
|
||||||
|
if network.state in ["Implemented", "Setup"]:
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Restarting network with ID: %s, Network state: %s" % (
|
||||||
|
network.id,
|
||||||
|
network.state
|
||||||
|
))
|
||||||
|
cmd = restartNetwork.restartNetworkCmd()
|
||||||
|
cmd.id = network.id
|
||||||
|
cmd.cleanup = True
|
||||||
|
self.apiclient.restartNetwork(cmd)
|
||||||
|
|
||||||
|
# Get router details after restart
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
router.linklocalip,
|
||||||
|
old_linklocalip,
|
||||||
|
"Check link-local IP after restart"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_04_restart_network_wo_cleanup(self):
|
||||||
|
"""Test restart network without cleanup
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. When cleanup = false, router is restarted and
|
||||||
|
# all services inside the router are restarted
|
||||||
|
# 2. check 'uptime' to see if the actual restart happened
|
||||||
|
|
||||||
|
timeout = 10
|
||||||
|
# Network should be in Implemented or Setup stage before restart
|
||||||
|
while True:
|
||||||
|
networks = list_networks(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(networks, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
network = networks[0]
|
||||||
|
if network.state in ["Implemented", "Setup"]:
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Restarting network with ID: %s, Network state: %s" % (
|
||||||
|
network.id,
|
||||||
|
network.state
|
||||||
|
))
|
||||||
|
cmd = restartNetwork.restartNetworkCmd()
|
||||||
|
cmd.id = network.id
|
||||||
|
cmd.cleanup = False
|
||||||
|
self.apiclient.restartNetwork(cmd)
|
||||||
|
|
||||||
|
# Get router details after restart
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=router.zoneid,
|
||||||
|
type='Routing',
|
||||||
|
state='Up',
|
||||||
|
virtualmachineid=self.vm_1.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
res = get_process_status(
|
||||||
|
host.ipaddress,
|
||||||
|
self.services['virtual_machine']["publicport"],
|
||||||
|
self.vm_1.username,
|
||||||
|
self.vm_1.password,
|
||||||
|
router.linklocalip,
|
||||||
|
"uptime"
|
||||||
|
)
|
||||||
|
|
||||||
|
# res = 12:37:14 up 1 min, 0 users, load average: 0.61, 0.22, 0.08
|
||||||
|
# Split result to check the uptime
|
||||||
|
result = res[0].split()
|
||||||
|
self.debug("Router Uptime: %s" % result)
|
||||||
|
self.assertEqual(
|
||||||
|
str(result[1]),
|
||||||
|
'up',
|
||||||
|
"Check router is running or not"
|
||||||
|
)
|
||||||
|
if str(result[3]) == "min,":
|
||||||
|
self.assertEqual(
|
||||||
|
(int(result[2]) < 3),
|
||||||
|
True,
|
||||||
|
"Check uptime is less than 3 mins or not"
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.assertEqual(
|
||||||
|
str(result[3]),
|
||||||
|
'sec,',
|
||||||
|
"Check uptime is in seconds"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_05_router_basic(self):
|
||||||
|
"""Test router basic setup
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. verify that listRouters returned a 'Running' router
|
||||||
|
# 2. router will have dns same as that seen in listZones
|
||||||
|
# 3. router will have a guestIP and a linkLocalIp"
|
||||||
|
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_router_response),
|
||||||
|
0,
|
||||||
|
"Check list router response"
|
||||||
|
)
|
||||||
|
for router in list_router_response:
|
||||||
|
self.assertEqual(
|
||||||
|
router.state,
|
||||||
|
'Running',
|
||||||
|
"Check list router response for router state"
|
||||||
|
)
|
||||||
|
|
||||||
|
zones = list_zones(
|
||||||
|
self.apiclient,
|
||||||
|
id=router.zoneid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(zones, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
zone = zones[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
router.dns1,
|
||||||
|
zone.dns1,
|
||||||
|
"Compare DNS1 of router and zone"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
router.dns2,
|
||||||
|
zone.dns2,
|
||||||
|
"Compare DNS2 of router and zone"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(router, 'guestipaddress'),
|
||||||
|
True,
|
||||||
|
"Check whether router has guest IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(router, 'linklocalip'),
|
||||||
|
True,
|
||||||
|
"Check whether router has link local IP field"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_06_router_advanced(self):
|
||||||
|
"""Test router advanced setup
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. verify that listRouters returned a 'Running' router
|
||||||
|
# 2. router will have dns and gateway as in listZones, listVlanIpRanges
|
||||||
|
# 3. router will have guest,public and linklocal IPs
|
||||||
|
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_router_response),
|
||||||
|
0,
|
||||||
|
"Check list router response"
|
||||||
|
)
|
||||||
|
for router in list_router_response:
|
||||||
|
self.assertEqual(
|
||||||
|
router.state,
|
||||||
|
'Running',
|
||||||
|
"Check list router response for router state"
|
||||||
|
)
|
||||||
|
|
||||||
|
zones = list_zones(
|
||||||
|
self.apiclient,
|
||||||
|
id=router.zoneid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(zones, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
zone = zones[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
router.dns1,
|
||||||
|
zone.dns1,
|
||||||
|
"Compare DNS1 of router and zone"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
router.dns2,
|
||||||
|
zone.dns2,
|
||||||
|
"Compare DNS2 of router and zone"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(router, 'guestipaddress'),
|
||||||
|
True,
|
||||||
|
"Check whether router has guest IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(router, 'linklocalip'),
|
||||||
|
True,
|
||||||
|
"Check whether router has link local IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Fetch corresponding ip ranges information from listVlanIpRanges
|
||||||
|
ipranges_response = list_vlan_ipranges(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=router.zoneid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(ipranges_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
iprange = ipranges_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
router.gateway,
|
||||||
|
iprange.gateway,
|
||||||
|
"Check gateway with that of corresponding IP range"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_07_stop_router(self):
|
||||||
|
"""Test stop router
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. listRouter should report the router for the account as stopped
|
||||||
|
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
self.debug("Stopping the router with ID: %s" % router.id)
|
||||||
|
#Stop the router
|
||||||
|
cmd = stopRouter.stopRouterCmd()
|
||||||
|
cmd.id = router.id
|
||||||
|
self.apiclient.stopRouter(cmd)
|
||||||
|
|
||||||
|
#List routers to check state of router
|
||||||
|
router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
id=router.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
#List router should have router in stopped state
|
||||||
|
self.assertEqual(
|
||||||
|
router_response[0].state,
|
||||||
|
'Stopped',
|
||||||
|
"Check list router response for router state"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_08_start_router(self):
|
||||||
|
"""Test start router
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. listRouter should report the router for the account as stopped
|
||||||
|
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
self.debug("Starting the router with ID: %s" % router.id)
|
||||||
|
|
||||||
|
#Start the router
|
||||||
|
cmd = startRouter.startRouterCmd()
|
||||||
|
cmd.id = router.id
|
||||||
|
self.apiclient.startRouter(cmd)
|
||||||
|
|
||||||
|
#List routers to check state of router
|
||||||
|
router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
id=router.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
#List router should have router in running state
|
||||||
|
self.assertEqual(
|
||||||
|
router_response[0].state,
|
||||||
|
'Running',
|
||||||
|
"Check list router response for router state"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_09_reboot_router(self):
|
||||||
|
"""Test reboot router
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. listRouter should report the router for the account as stopped
|
||||||
|
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
public_ip = router.publicip
|
||||||
|
|
||||||
|
self.debug("Rebooting the router with ID: %s" % router.id)
|
||||||
|
|
||||||
|
#Reboot the router
|
||||||
|
cmd = rebootRouter.rebootRouterCmd()
|
||||||
|
cmd.id = router.id
|
||||||
|
self.apiclient.rebootRouter(cmd)
|
||||||
|
|
||||||
|
#List routers to check state of router
|
||||||
|
router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
id=router.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
#List router should have router in running state and same public IP
|
||||||
|
self.assertEqual(
|
||||||
|
router_response[0].state,
|
||||||
|
'Running',
|
||||||
|
"Check list router response for router state"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
router_response[0].publicip,
|
||||||
|
public_ip,
|
||||||
|
"Check list router response for router public IP"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_10_network_gc(self):
|
||||||
|
"""Test network GC
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. stop All User VMs in the account
|
||||||
|
# 2. wait for network.gc.interval time"
|
||||||
|
# 3. After network.gc.interval, router should be stopped
|
||||||
|
# 4. ListRouters should return the router in Stopped state
|
||||||
|
|
||||||
|
list_vms = list_virtual_machines(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_vms, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_vms),
|
||||||
|
0,
|
||||||
|
"Check length of list VM response"
|
||||||
|
)
|
||||||
|
|
||||||
|
for vm in list_vms:
|
||||||
|
self.debug("Stopping the VM with ID: %s" % vm.id)
|
||||||
|
# Stop all virtual machines associated with that account
|
||||||
|
cmd = stopVirtualMachine.stopVirtualMachineCmd()
|
||||||
|
cmd.id = vm.id
|
||||||
|
self.apiclient.stopVirtualMachine(cmd)
|
||||||
|
|
||||||
|
# Get network.gc.interval config value
|
||||||
|
config = list_configurations(
|
||||||
|
self.apiclient,
|
||||||
|
name='network.gc.interval'
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(config, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
gcinterval = config[0]
|
||||||
|
|
||||||
|
# Get network.gc.wait config value
|
||||||
|
config = list_configurations(
|
||||||
|
self.apiclient,
|
||||||
|
name='network.gc.wait'
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(config, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
gcwait = config[0]
|
||||||
|
|
||||||
|
total_wait = int(gcinterval.value) + int(gcwait.value)
|
||||||
|
# Wait for wait_time * 2 time to cleanup all the resources
|
||||||
|
time.sleep(total_wait * 2)
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
#Check status of network router
|
||||||
|
list_router_response = list_routers(
|
||||||
|
self.apiclient,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
if isinstance(list_router_response, list):
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List router call failed!")
|
||||||
|
time.sleep(5)
|
||||||
|
timeout = timeout -1
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_router_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
router = list_router_response[0]
|
||||||
|
|
||||||
|
self.debug("Router state after network.gc.interval: %s" % router.state)
|
||||||
|
self.assertEqual(
|
||||||
|
router.state,
|
||||||
|
'Stopped',
|
||||||
|
"Check state of the router after stopping all VMs associated"
|
||||||
|
)
|
||||||
|
return
|
||||||
380
test/integration/smoke/test_secondary_storage.py
Normal file
380
test/integration/smoke/test_secondary_storage.py
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
# -*- 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 Secondary Storage
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
|
||||||
|
#Import System modules
|
||||||
|
import time
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test secondary storage Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"storage": {
|
||||||
|
"url": "nfs://192.168.100.131/SecStorage"
|
||||||
|
# Format: File_System_Type/Location/Path
|
||||||
|
},
|
||||||
|
"hypervisors": {
|
||||||
|
0: {
|
||||||
|
"hypervisor": "XenServer",
|
||||||
|
"templatefilter": "self",
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
"hypervisor": "KVM",
|
||||||
|
"templatefilter": "self",
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
"hypervisor": "VMWare",
|
||||||
|
"templatefilter": "self",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestSecStorageServices(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.api_client = super(TestSecStorageServices, cls).getClsTestClient().getApiClient()
|
||||||
|
cls.services = Services().services
|
||||||
|
cls._cleanup = []
|
||||||
|
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.cleanup = []
|
||||||
|
self.services = Services().services
|
||||||
|
# Get Zone and pod
|
||||||
|
self.domain = get_domain(self.apiclient, self.services)
|
||||||
|
self.zone = get_zone(self.apiclient, self.services)
|
||||||
|
self.pod = get_pod(self.apiclient, self.zone.id)
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_add_sec_storage(self):
|
||||||
|
"""Test secondary storage
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. secondary storage should be added to the zone.
|
||||||
|
# 2. Verify with listHosts and type secondarystorage
|
||||||
|
|
||||||
|
cmd = addSecondaryStorage.addSecondaryStorageCmd()
|
||||||
|
cmd.zoneid = self.zone.id
|
||||||
|
cmd.url = self.services["storage"]["url"]
|
||||||
|
sec_storage = self.apiclient.addSecondaryStorage(cmd)
|
||||||
|
|
||||||
|
self.debug("Added secondary storage to zone: %s" % self.zone.id)
|
||||||
|
# Cleanup at the end
|
||||||
|
self._cleanup.append(sec_storage)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
sec_storage.zoneid,
|
||||||
|
self.zone.id,
|
||||||
|
"Check zoneid where sec storage is added"
|
||||||
|
)
|
||||||
|
|
||||||
|
list_hosts_response = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
type='SecondaryStorage',
|
||||||
|
id=sec_storage.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_hosts_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_hosts_response),
|
||||||
|
0,
|
||||||
|
"Check list Hosts response"
|
||||||
|
)
|
||||||
|
|
||||||
|
host_response = list_hosts_response[0]
|
||||||
|
#Check if host is Up and running
|
||||||
|
self.assertEqual(
|
||||||
|
host_response.id,
|
||||||
|
sec_storage.id,
|
||||||
|
"Check ID of secondary storage"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
sec_storage.type,
|
||||||
|
host_response.type,
|
||||||
|
"Check type of host from list hosts response"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_sys_vm_start(self):
|
||||||
|
"""Test system VM start
|
||||||
|
"""
|
||||||
|
|
||||||
|
# 1. verify listHosts has all 'routing' hosts in UP state
|
||||||
|
# 2. verify listStoragePools shows all primary storage pools
|
||||||
|
# in UP state
|
||||||
|
# 3. verify that secondary storage was added successfully
|
||||||
|
|
||||||
|
list_hosts_response = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
type='Routing',
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_hosts_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
# ListHosts has all 'routing' hosts in UP state
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_hosts_response),
|
||||||
|
0,
|
||||||
|
"Check list host response"
|
||||||
|
)
|
||||||
|
for host in list_hosts_response:
|
||||||
|
self.assertEqual(
|
||||||
|
host.state,
|
||||||
|
'Up',
|
||||||
|
"Check state of routing hosts is Up or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ListStoragePools shows all primary storage pools in UP state
|
||||||
|
list_storage_response = list_storage_pools(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_storage_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_storage_response),
|
||||||
|
0,
|
||||||
|
"Check list storage pools response"
|
||||||
|
)
|
||||||
|
|
||||||
|
for primary_storage in list_hosts_response:
|
||||||
|
self.assertEqual(
|
||||||
|
primary_storage.state,
|
||||||
|
'Up',
|
||||||
|
"Check state of primary storage pools is Up or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Secondary storage is added successfully
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_hosts_response = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
type='SecondaryStorage',
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not isinstance(list_hosts_response, list):
|
||||||
|
# Sleep to ensure Secondary storage is Up
|
||||||
|
time.sleep(int(self.services["sleep"]))
|
||||||
|
timeout = timeout - 1
|
||||||
|
elif timeout == 0 or isinstance(list_hosts_response, list):
|
||||||
|
break
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_hosts_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_hosts_response),
|
||||||
|
0,
|
||||||
|
"Check list Hosts response"
|
||||||
|
)
|
||||||
|
|
||||||
|
host_response = list_hosts_response[0]
|
||||||
|
#Check if host is Up and running
|
||||||
|
self.assertEqual(
|
||||||
|
host_response.state,
|
||||||
|
'Up',
|
||||||
|
"Check state of secondary storage"
|
||||||
|
)
|
||||||
|
self.debug("Checking SSVM status in zone: %s" % self.zone.id)
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
|
||||||
|
while True:
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='secondarystoragevm',
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
podid=self.pod.id
|
||||||
|
)
|
||||||
|
if not isinstance(list_ssvm_response, list):
|
||||||
|
# Sleep to ensure SSVMs are Up and Running
|
||||||
|
time.sleep(int(self.services["sleep"]))
|
||||||
|
timeout = timeout - 1
|
||||||
|
elif timeout == 0 or isinstance(list_ssvm_response, list):
|
||||||
|
break
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_ssvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
#Verify SSVM response
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_ssvm_response),
|
||||||
|
0,
|
||||||
|
"Check list System VMs response"
|
||||||
|
)
|
||||||
|
|
||||||
|
for ssvm in list_ssvm_response:
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm.state,
|
||||||
|
'Running',
|
||||||
|
"Check whether state of SSVM is running"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_sys_template_ready(self):
|
||||||
|
"""Test system templates are ready
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# If SSVM is in UP state and running
|
||||||
|
# 1. wait for listTemplates to show all builtin templates
|
||||||
|
# downloaded for all added hypervisors and in “Ready” state"
|
||||||
|
|
||||||
|
for k, v in self.services["hypervisors"].items():
|
||||||
|
|
||||||
|
self.debug("Downloading BUILTIN templates in zone: %s" %
|
||||||
|
self.zone.id)
|
||||||
|
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
hypervisor=v["hypervisor"],
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
templatefilter=v["templatefilter"],
|
||||||
|
listall=True,
|
||||||
|
account='system',
|
||||||
|
domainid=self.domain.id
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ensure all BUILTIN templates are downloaded
|
||||||
|
templateid = None
|
||||||
|
for template in list_template_response:
|
||||||
|
if template.templatetype == "BUILTIN":
|
||||||
|
templateid = template.id
|
||||||
|
|
||||||
|
# Wait to start a downloading of template
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
while True and (templateid != None):
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
id=templateid,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
templatefilter=v["templatefilter"],
|
||||||
|
listall=True,
|
||||||
|
account='system',
|
||||||
|
domainid=self.domain.id
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(template_response, list):
|
||||||
|
template = template_response[0]
|
||||||
|
break
|
||||||
|
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List template API call failed.")
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
# If template is ready,
|
||||||
|
# template.status = Download Complete
|
||||||
|
# Downloading - x% Downloaded
|
||||||
|
# Error - Any other string
|
||||||
|
if template.status == 'Download Complete' :
|
||||||
|
break
|
||||||
|
elif 'Downloaded' not in template.status.split():
|
||||||
|
raise Exception
|
||||||
|
elif 'Downloaded' in template.status.split():
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
#Ensuring the template is in ready state
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
id=templateid,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
templatefilter=v["templatefilter"],
|
||||||
|
listall=True,
|
||||||
|
account='system',
|
||||||
|
domainid=self.domain.id
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(template_response, list):
|
||||||
|
template = template_response[0]
|
||||||
|
break
|
||||||
|
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List template API call failed.")
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(template_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
template = template_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
template.isready,
|
||||||
|
True,
|
||||||
|
"Check whether state of template is ready or not"
|
||||||
|
)
|
||||||
|
return
|
||||||
238
test/integration/smoke/test_service_offerings.py
Normal file
238
test/integration/smoke/test_service_offerings.py
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
# -*- 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 Service offerings"""
|
||||||
|
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Service offerings Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"off":
|
||||||
|
{
|
||||||
|
"name": "Service Offering",
|
||||||
|
"displaytext": "Service Offering",
|
||||||
|
"cpunumber": 1,
|
||||||
|
"cpuspeed": 100, # MHz
|
||||||
|
"memory": 64, # in MBs
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestCreateServiceOffering(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
self.services = Services().services
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_create_service_offering(self):
|
||||||
|
"""Test to create service offering"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. createServiceOfferings should return a valid information for newly created offering
|
||||||
|
# 2. The Cloud Database contains the valid information
|
||||||
|
|
||||||
|
service_offering = ServiceOffering.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["off"]
|
||||||
|
)
|
||||||
|
self.cleanup.append(service_offering)
|
||||||
|
|
||||||
|
self.debug("Created service offering with ID: %s" % service_offering.id)
|
||||||
|
|
||||||
|
list_service_response = list_service_offering(
|
||||||
|
self.apiclient,
|
||||||
|
id=service_offering.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_service_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_service_response),
|
||||||
|
0,
|
||||||
|
"Check Service offering is created"
|
||||||
|
)
|
||||||
|
service_response = list_service_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response[0].cpunumber,
|
||||||
|
self.services["off"]["cpunumber"],
|
||||||
|
"Check server id in createServiceOffering"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response[0].cpuspeed,
|
||||||
|
self.services["off"]["cpuspeed"],
|
||||||
|
"Check cpuspeed in createServiceOffering"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response[0].displaytext,
|
||||||
|
self.services["off"]["displaytext"],
|
||||||
|
"Check server displaytext in createServiceOfferings"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response[0].memory,
|
||||||
|
self.services["off"]["memory"],
|
||||||
|
"Check memory in createServiceOffering"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response[0].name,
|
||||||
|
self.services["off"]["name"],
|
||||||
|
"Check name in createServiceOffering"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class TestServiceOfferings(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.services = Services().services
|
||||||
|
cls.api_client = super(TestServiceOfferings, cls).getClsTestClient().getApiClient()
|
||||||
|
cls.service_offering_1 = ServiceOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["off"]
|
||||||
|
)
|
||||||
|
cls.service_offering_2 = ServiceOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["off"]
|
||||||
|
)
|
||||||
|
cls._cleanup = [cls.service_offering_1]
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestServiceOfferings, 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)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_edit_service_offering(self):
|
||||||
|
"""Test to update existing service offering"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. updateServiceOffering should return
|
||||||
|
# a valid information for newly created offering
|
||||||
|
|
||||||
|
#Generate new name & displaytext from random data
|
||||||
|
random_displaytext = random_gen()
|
||||||
|
random_name = random_gen()
|
||||||
|
|
||||||
|
self.debug("Updating service offering with ID: %s" %
|
||||||
|
self.service_offering_1.id)
|
||||||
|
|
||||||
|
cmd = updateServiceOffering.updateServiceOfferingCmd()
|
||||||
|
#Add parameters for API call
|
||||||
|
cmd.id = self.service_offering_1.id
|
||||||
|
cmd.displaytext = random_displaytext
|
||||||
|
cmd.name = random_name
|
||||||
|
self.apiclient.updateServiceOffering(cmd)
|
||||||
|
|
||||||
|
list_service_response = list_service_offering(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.service_offering_1.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_service_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_service_response),
|
||||||
|
0,
|
||||||
|
"Check Service offering is updated"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response[0].displaytext,
|
||||||
|
random_displaytext,
|
||||||
|
"Check server displaytext in updateServiceOffering"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response[0].name,
|
||||||
|
random_name,
|
||||||
|
"Check server name in updateServiceOffering"
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_delete_service_offering(self):
|
||||||
|
"""Test to delete service offering"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. deleteServiceOffering should return
|
||||||
|
# a valid information for newly created offering
|
||||||
|
|
||||||
|
self.debug("Deleting service offering with ID: %s" %
|
||||||
|
self.service_offering_2.id)
|
||||||
|
|
||||||
|
self.service_offering_2.delete(self.apiclient)
|
||||||
|
|
||||||
|
list_service_response = list_service_offering(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.service_offering_2.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
list_service_response,
|
||||||
|
None,
|
||||||
|
"Check if service offering exists in listDiskOfferings"
|
||||||
|
)
|
||||||
|
|
||||||
|
return
|
||||||
1159
test/integration/smoke/test_snapshots.py
Normal file
1159
test/integration/smoke/test_snapshots.py
Normal file
File diff suppressed because it is too large
Load Diff
916
test/integration/smoke/test_ssvm.py
Normal file
916
test/integration/smoke/test_ssvm.py
Normal file
@ -0,0 +1,916 @@
|
|||||||
|
# -*- 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 SSVM
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from marvin.remoteSSHClient import remoteSSHClient
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
import telnetlib
|
||||||
|
|
||||||
|
#Import System modules
|
||||||
|
import time
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test SSVM Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"host": {
|
||||||
|
"username": 'root', # Credentials for SSH
|
||||||
|
"password": 'fr3sca',
|
||||||
|
"publicport": 22,
|
||||||
|
},
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestSSVMs(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.cleanup = []
|
||||||
|
self.services = Services().services
|
||||||
|
self.zone = get_zone(self.apiclient, self.services)
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_list_sec_storage_vm(self):
|
||||||
|
"""Test List secondary storage VMs
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. listSystemVM (systemvmtype=secondarystoragevm)
|
||||||
|
# should return only ONE SSVM per zone
|
||||||
|
# 2. The returned SSVM should be in Running state
|
||||||
|
# 3. listSystemVM for secondarystoragevm should list publicip,
|
||||||
|
# privateip and link-localip
|
||||||
|
# 4. The gateway programmed on the ssvm by listSystemVm should be
|
||||||
|
# the same as the gateway returned by listVlanIpRanges
|
||||||
|
# 5. DNS entries must match those given for the zone
|
||||||
|
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='secondarystoragevm',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_ssvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
#Verify SSVM response
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_ssvm_response),
|
||||||
|
0,
|
||||||
|
"Check list System VMs response"
|
||||||
|
)
|
||||||
|
|
||||||
|
list_zones_response = list_zones(self.apiclient)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_zones_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Number of zones: %s" % len(list_zones_response))
|
||||||
|
self.debug("Number of SSVMs: %s" % len(list_ssvm_response))
|
||||||
|
# Number of Sec storage VMs = No of Zones
|
||||||
|
self.assertEqual(
|
||||||
|
len(list_ssvm_response),
|
||||||
|
len(list_zones_response),
|
||||||
|
"Check number of SSVMs with number of zones"
|
||||||
|
)
|
||||||
|
#For each secondary storage VM check private IP,
|
||||||
|
#public IP, link local IP and DNS
|
||||||
|
for ssvm in list_ssvm_response:
|
||||||
|
|
||||||
|
self.debug("SSVM state: %s" % ssvm.state)
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm.state,
|
||||||
|
'Running',
|
||||||
|
"Check whether state of SSVM is running"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(ssvm, 'privateip'),
|
||||||
|
True,
|
||||||
|
"Check whether SSVM has private IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(ssvm, 'linklocalip'),
|
||||||
|
True,
|
||||||
|
"Check whether SSVM has link local IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(ssvm, 'publicip'),
|
||||||
|
True,
|
||||||
|
"Check whether SSVM has public IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Fetch corresponding ip ranges information from listVlanIpRanges
|
||||||
|
ipranges_response = list_vlan_ipranges(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=ssvm.zoneid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(ipranges_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
iprange = ipranges_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm.gateway,
|
||||||
|
iprange.gateway,
|
||||||
|
"Check gateway with that of corresponding ip range"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Fetch corresponding zone information from listZones
|
||||||
|
zone_response = list_zones(
|
||||||
|
self.apiclient,
|
||||||
|
id=ssvm.zoneid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(zone_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm.dns1,
|
||||||
|
zone_response[0].dns1,
|
||||||
|
"Check DNS1 with that of corresponding zone"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm.dns2,
|
||||||
|
zone_response[0].dns2,
|
||||||
|
"Check DNS2 with that of corresponding zone"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_list_cpvm_vm(self):
|
||||||
|
"""Test List console proxy VMs
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. listSystemVM (systemvmtype=consoleproxy) should return
|
||||||
|
# at least ONE CPVM per zone
|
||||||
|
# 2. The returned ConsoleProxyVM should be in Running state
|
||||||
|
# 3. listSystemVM for console proxy should list publicip, privateip
|
||||||
|
# and link-localip
|
||||||
|
# 4. The gateway programmed on the console proxy should be the same
|
||||||
|
# as the gateway returned by listZones
|
||||||
|
# 5. DNS entries must match those given for the zone
|
||||||
|
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='consoleproxy',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_cpvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
#Verify CPVM response
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_cpvm_response),
|
||||||
|
0,
|
||||||
|
"Check list System VMs response"
|
||||||
|
)
|
||||||
|
list_zones_response = list_zones(self.apiclient)
|
||||||
|
# Number of Console Proxy VMs = No of Zones
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_zones_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Number of zones: %s" % len(list_zones_response))
|
||||||
|
self.debug("Number of CPVMs: %s" % len(list_cpvm_response))
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
len(list_cpvm_response),
|
||||||
|
len(list_zones_response),
|
||||||
|
"Check number of CPVMs with number of zones"
|
||||||
|
)
|
||||||
|
#For each CPVM check private IP, public IP, link local IP and DNS
|
||||||
|
for cpvm in list_cpvm_response:
|
||||||
|
|
||||||
|
self.debug("CPVM state: %s" % cpvm.state)
|
||||||
|
self.assertEqual(
|
||||||
|
cpvm.state,
|
||||||
|
'Running',
|
||||||
|
"Check whether state of CPVM is running"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(cpvm, 'privateip'),
|
||||||
|
True,
|
||||||
|
"Check whether CPVM has private IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(cpvm, 'linklocalip'),
|
||||||
|
True,
|
||||||
|
"Check whether CPVM has link local IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(cpvm, 'publicip'),
|
||||||
|
True,
|
||||||
|
"Check whether CPVM has public IP field"
|
||||||
|
)
|
||||||
|
#Fetch corresponding ip ranges information from listVlanIpRanges
|
||||||
|
ipranges_response = list_vlan_ipranges(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=cpvm.zoneid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(ipranges_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
iprange = ipranges_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
cpvm.gateway,
|
||||||
|
iprange.gateway,
|
||||||
|
"Check gateway with that of corresponding ip range"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Fetch corresponding zone information from listZones
|
||||||
|
zone_response = list_zones(
|
||||||
|
self.apiclient,
|
||||||
|
id=cpvm.zoneid
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
cpvm.dns1,
|
||||||
|
zone_response[0].dns1,
|
||||||
|
"Check DNS1 with that of corresponding zone"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
cpvm.dns2,
|
||||||
|
zone_response[0].dns2,
|
||||||
|
"Check DNS2 with that of corresponding zone"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_ssvm_internals(self):
|
||||||
|
"""Test SSVM Internals"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. The SSVM check script should not return any
|
||||||
|
# WARN|ERROR|FAIL messages
|
||||||
|
# 2. If you are unable to login to the SSVM with the signed key
|
||||||
|
# then test is deemed a failure
|
||||||
|
# 3. There should be only one ""cloud"" process running within the SSVM
|
||||||
|
# 4. If no process is running/multiple process are running
|
||||||
|
# then the test is a failure
|
||||||
|
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='secondarystoragevm',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_ssvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
ssvm = list_ssvm_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
id=ssvm.hostid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
self.debug("Running SSVM check script")
|
||||||
|
|
||||||
|
result = get_process_status(
|
||||||
|
host.ipaddress,
|
||||||
|
self.services['host']["publicport"],
|
||||||
|
self.services['host']["username"],
|
||||||
|
self.services['host']["password"],
|
||||||
|
ssvm.linklocalip,
|
||||||
|
"/usr/local/cloud/systemvm/ssvm-check.sh |grep -e ERROR -e WARNING -e FAIL"
|
||||||
|
)
|
||||||
|
res = str(result)
|
||||||
|
self.debug("SSVM script output: %s" % res)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
res.count("ERROR"),
|
||||||
|
1,
|
||||||
|
"Check for Errors in tests"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
res.count("WARNING"),
|
||||||
|
1,
|
||||||
|
"Check for warnings in tests"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Check status of cloud service
|
||||||
|
result = get_process_status(
|
||||||
|
host.ipaddress,
|
||||||
|
self.services['host']["publicport"],
|
||||||
|
self.services['host']["username"],
|
||||||
|
self.services['host']["password"],
|
||||||
|
ssvm.linklocalip,
|
||||||
|
"service cloud status"
|
||||||
|
)
|
||||||
|
res = str(result)
|
||||||
|
self.debug("Cloud Process status: %s" % res)
|
||||||
|
# cloud.com service (type=secstorage) is running: process id: 2346
|
||||||
|
self.assertEqual(
|
||||||
|
res.count("is running"),
|
||||||
|
1,
|
||||||
|
"Check cloud service is running or not"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_04_cpvm_internals(self):
|
||||||
|
"""Test CPVM Internals"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. test that telnet access on 8250 is available to
|
||||||
|
# the management server for the CPVM
|
||||||
|
# 2. No telnet access, test FAIL
|
||||||
|
# 3. Service cloud status should report cloud agent status to be
|
||||||
|
# running
|
||||||
|
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='consoleproxy',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_cpvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
cpvm = list_cpvm_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
id=cpvm.hostid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
try:
|
||||||
|
telnet = telnetlib.Telnet(
|
||||||
|
str(self.apiclient.connection.mgtSvr),
|
||||||
|
'8250'
|
||||||
|
)
|
||||||
|
self.debug("Telnet management server (IP: %s)" %
|
||||||
|
self.apiclient.connection.mgtSvr)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail(
|
||||||
|
"Telnet Access failed for %s: %s" % \
|
||||||
|
(self.apiclient.connection.mgtSvr, e)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Checking cloud process status")
|
||||||
|
|
||||||
|
result = get_process_status(
|
||||||
|
host.ipaddress,
|
||||||
|
self.services['host']["publicport"],
|
||||||
|
self.services['host']["username"],
|
||||||
|
self.services['host']["password"],
|
||||||
|
cpvm.linklocalip,
|
||||||
|
"service cloud status"
|
||||||
|
)
|
||||||
|
res = str(result)
|
||||||
|
self.debug("Cloud Process status: %s" % res)
|
||||||
|
self.assertEqual(
|
||||||
|
res.count("is running"),
|
||||||
|
1,
|
||||||
|
"Check cloud service is running or not"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_05_stop_ssvm(self):
|
||||||
|
"""Test stop SSVM
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. The SSVM should go to stop state
|
||||||
|
# 2. After a brief delay of say one minute, the SSVM should be
|
||||||
|
# restarted once again and return to Running state with previous two
|
||||||
|
# test cases still passing
|
||||||
|
# 3. If either of the two above steps fail the test is a failure
|
||||||
|
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='secondarystoragevm',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_ssvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
ssvm = list_ssvm_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
id=ssvm.hostid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
self.debug("Stopping SSVM: %s" % ssvm.id)
|
||||||
|
cmd = stopSystemVm.stopSystemVmCmd()
|
||||||
|
cmd.id = ssvm.id
|
||||||
|
self.apiclient.stopSystemVm(cmd)
|
||||||
|
|
||||||
|
# Sleep to ensure that VM is in proper state
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
id=ssvm.id
|
||||||
|
)
|
||||||
|
if isinstance(list_ssvm_response, list):
|
||||||
|
if list_ssvm_response[0].state == 'Running':
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List SSVM call failed!")
|
||||||
|
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_ssvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
ssvm_response = list_ssvm_response[0]
|
||||||
|
self.debug("SSVM state after debug: %s" % ssvm_response.state)
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm_response.state,
|
||||||
|
'Running',
|
||||||
|
"Check whether SSVM is running or not"
|
||||||
|
)
|
||||||
|
# Call above tests to ensure SSVM is properly running
|
||||||
|
self.test_01_list_sec_storage_vm()
|
||||||
|
self.test_03_ssvm_internals()
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_06_stop_cpvm(self):
|
||||||
|
"""Test stop CPVM
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. The CPVM should go to stop state
|
||||||
|
# 2. After a brief delay of say one minute, the SSVM should be
|
||||||
|
# restarted once again and return to Running state with previous
|
||||||
|
# two test cases still passing
|
||||||
|
# 3. If either of the two above steps fail the test is a failure
|
||||||
|
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='consoleproxy',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_cpvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
cpvm = list_cpvm_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
id=cpvm.hostid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
self.debug("Stopping CPVM: %s" % cpvm.id)
|
||||||
|
cmd = stopSystemVm.stopSystemVmCmd()
|
||||||
|
cmd.id = cpvm.id
|
||||||
|
self.apiclient.stopSystemVm(cmd)
|
||||||
|
|
||||||
|
# Sleep to ensure that VM is in proper state
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
id=cpvm.id
|
||||||
|
)
|
||||||
|
if isinstance(list_cpvm_response, list):
|
||||||
|
if list_cpvm_response[0].state == 'Running':
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List CPVM call failed!")
|
||||||
|
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
cpvm_response = list_cpvm_response[0]
|
||||||
|
|
||||||
|
self.debug("CPVM state after debug: %s" % cpvm_response.state)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
cpvm_response.state,
|
||||||
|
'Running',
|
||||||
|
"Check whether CPVM is running or not"
|
||||||
|
)
|
||||||
|
# Call above tests to ensure CPVM is properly running
|
||||||
|
self.test_02_list_cpvm_vm()
|
||||||
|
self.test_04_cpvm_internals()
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_07_reboot_ssvm(self):
|
||||||
|
"""Test reboot SSVM
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. The SSVM should go to stop and return to Running state
|
||||||
|
# 2. SSVM's public-ip and private-ip must remain the same
|
||||||
|
# before and after reboot
|
||||||
|
# 3. The cloud process should still be running within the SSVM
|
||||||
|
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='secondarystoragevm',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_ssvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
ssvm_response = list_ssvm_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
id=ssvm_response.hostid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
#Store the public & private IP values before reboot
|
||||||
|
old_public_ip = ssvm_response.publicip
|
||||||
|
old_private_ip = ssvm_response.privateip
|
||||||
|
|
||||||
|
self.debug("Rebooting SSVM: %s" % ssvm_response.id)
|
||||||
|
cmd = rebootSystemVm.rebootSystemVmCmd()
|
||||||
|
cmd.id = ssvm_response.id
|
||||||
|
self.apiclient.rebootSystemVm(cmd)
|
||||||
|
|
||||||
|
# Sleep to ensure that VM is in proper state
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
id=ssvm_response.id
|
||||||
|
)
|
||||||
|
if isinstance(list_ssvm_response, list):
|
||||||
|
if list_ssvm_response[0].state == 'Running':
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List SSVM call failed!")
|
||||||
|
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
ssvm_response = list_ssvm_response[0]
|
||||||
|
self.debug("SSVM State: %s" % ssvm_response.state)
|
||||||
|
self.assertEqual(
|
||||||
|
'Running',
|
||||||
|
str(ssvm_response.state),
|
||||||
|
"Check whether CPVM is running or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm_response.publicip,
|
||||||
|
old_public_ip,
|
||||||
|
"Check Public IP after reboot with that of before reboot"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
ssvm_response.privateip,
|
||||||
|
old_private_ip,
|
||||||
|
"Check Private IP after reboot with that of before reboot"
|
||||||
|
)
|
||||||
|
#Call to verify cloud process is running
|
||||||
|
self.test_03_ssvm_internals()
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_08_reboot_cpvm(self):
|
||||||
|
"""Test reboot CPVM
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. The CPVM should go to stop and return to Running state
|
||||||
|
# 2. CPVM's public-ip and private-ip must remain
|
||||||
|
# the same before and after reboot
|
||||||
|
# 3. the cloud process should still be running within the CPVM
|
||||||
|
|
||||||
|
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='consoleproxy',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_cpvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
cpvm_response = list_cpvm_response[0]
|
||||||
|
|
||||||
|
hosts = list_hosts(
|
||||||
|
self.apiclient,
|
||||||
|
id=cpvm_response.hostid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
#Store the public & private IP values before reboot
|
||||||
|
old_public_ip = cpvm_response.publicip
|
||||||
|
old_private_ip = cpvm_response.privateip
|
||||||
|
|
||||||
|
self.debug("Rebooting CPVM: %s" % cpvm_response.id)
|
||||||
|
|
||||||
|
cmd = rebootSystemVm.rebootSystemVmCmd()
|
||||||
|
cmd.id = cpvm_response.id
|
||||||
|
self.apiclient.rebootSystemVm(cmd)
|
||||||
|
|
||||||
|
# Sleep to ensure that VM is in proper state
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
id=cpvm_response.id
|
||||||
|
)
|
||||||
|
if isinstance(list_cpvm_response, list):
|
||||||
|
if list_cpvm_response[0].state == 'Running':
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List CPVM call failed!")
|
||||||
|
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
cpvm_response = list_cpvm_response[0]
|
||||||
|
|
||||||
|
self.debug("CPVM state: %s" % cpvm_response.state)
|
||||||
|
self.assertEqual(
|
||||||
|
'Running',
|
||||||
|
str(cpvm_response.state),
|
||||||
|
"Check whether CPVM is running or not"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
cpvm_response.publicip,
|
||||||
|
old_public_ip,
|
||||||
|
"Check Public IP after reboot with that of before reboot"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
cpvm_response.privateip,
|
||||||
|
old_private_ip,
|
||||||
|
"Check Private IP after reboot with that of before reboot"
|
||||||
|
)
|
||||||
|
#Call to verify cloud process is running
|
||||||
|
self.test_04_cpvm_internals()
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_09_destroy_ssvm(self):
|
||||||
|
"""Test destroy SSVM
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. SSVM should be completely destroyed and a new one will spin up
|
||||||
|
# 2. listSystemVMs will show a different name for the
|
||||||
|
# systemVM from what it was before
|
||||||
|
# 3. new SSVM will have a public/private and link-local-ip
|
||||||
|
# 4. cloud process within SSVM must be up and running
|
||||||
|
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='secondarystoragevm',
|
||||||
|
state='Running',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_ssvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
ssvm_response = list_ssvm_response[0]
|
||||||
|
|
||||||
|
old_name = ssvm_response.name
|
||||||
|
|
||||||
|
self.debug("Destroying SSVM: %s" % ssvm_response.id)
|
||||||
|
cmd = destroySystemVm.destroySystemVmCmd()
|
||||||
|
cmd.id = ssvm_response.id
|
||||||
|
self.apiclient.destroySystemVm(cmd)
|
||||||
|
|
||||||
|
# Sleep to ensure that VM is in proper state
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_ssvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
systemvmtype='secondarystoragevm'
|
||||||
|
)
|
||||||
|
if isinstance(list_ssvm_response, list):
|
||||||
|
if list_ssvm_response[0].state == 'Running':
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List SSVM call failed!")
|
||||||
|
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
ssvm_response = list_ssvm_response[0]
|
||||||
|
|
||||||
|
# Verify Name, Public IP, Private IP and Link local IP
|
||||||
|
# for newly created SSVM
|
||||||
|
self.assertNotEqual(
|
||||||
|
ssvm_response.name,
|
||||||
|
old_name,
|
||||||
|
"Check SSVM new name with name of destroyed SSVM"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(ssvm_response, 'privateip'),
|
||||||
|
True,
|
||||||
|
"Check whether SSVM has private IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(ssvm_response, 'linklocalip'),
|
||||||
|
True,
|
||||||
|
"Check whether SSVM has link local IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(ssvm_response, 'publicip'),
|
||||||
|
True,
|
||||||
|
"Check whether SSVM has public IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Call to verify cloud process is running
|
||||||
|
self.test_03_ssvm_internals()
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_10_destroy_cpvm(self):
|
||||||
|
"""Test destroy CPVM
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. CPVM should be completely destroyed and a new one will spin up
|
||||||
|
# 2. listSystemVMs will show a different name for the systemVM from
|
||||||
|
# what it was before
|
||||||
|
# 3. new CPVM will have a public/private and link-local-ip
|
||||||
|
# 4. cloud process within CPVM must be up and running
|
||||||
|
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='consoleproxy',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_cpvm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
cpvm_response = list_cpvm_response[0]
|
||||||
|
|
||||||
|
old_name = cpvm_response.name
|
||||||
|
|
||||||
|
self.debug("Destroying CPVM: %s" % cpvm_response.id)
|
||||||
|
cmd = destroySystemVm.destroySystemVmCmd()
|
||||||
|
cmd.id = cpvm_response.id
|
||||||
|
self.apiclient.destroySystemVm(cmd)
|
||||||
|
|
||||||
|
# Sleep to ensure that VM is in proper state
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
list_cpvm_response = list_ssvms(
|
||||||
|
self.apiclient,
|
||||||
|
systemvmtype='consoleproxy',
|
||||||
|
zoneid=self.zone.id
|
||||||
|
)
|
||||||
|
if isinstance(list_cpvm_response, list):
|
||||||
|
if list_cpvm_response[0].state == 'Running':
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List CPVM call failed!")
|
||||||
|
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
cpvm_response = list_cpvm_response[0]
|
||||||
|
|
||||||
|
# Verify Name, Public IP, Private IP and Link local IP
|
||||||
|
# for newly created CPVM
|
||||||
|
self.assertNotEqual(
|
||||||
|
cpvm_response.name,
|
||||||
|
old_name,
|
||||||
|
"Check SSVM new name with name of destroyed CPVM"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(cpvm_response, 'privateip'),
|
||||||
|
True,
|
||||||
|
"Check whether CPVM has private IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(cpvm_response, 'linklocalip'),
|
||||||
|
True,
|
||||||
|
"Check whether CPVM has link local IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
hasattr(cpvm_response, 'publicip'),
|
||||||
|
True,
|
||||||
|
"Check whether CPVM has public IP field"
|
||||||
|
)
|
||||||
|
|
||||||
|
#Call to verify cloud process is running
|
||||||
|
self.test_04_cpvm_internals()
|
||||||
|
return
|
||||||
753
test/integration/smoke/test_templates.py
Normal file
753
test/integration/smoke/test_templates.py
Normal file
@ -0,0 +1,753 @@
|
|||||||
|
# -*- 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 Templates ISO
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
import urllib
|
||||||
|
from random import random
|
||||||
|
#Import System modules
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Templates Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"account": {
|
||||||
|
"email": "test@test.com",
|
||||||
|
"firstname": "Test",
|
||||||
|
"lastname": "User",
|
||||||
|
"username": "test",
|
||||||
|
# Random characters are appended for unique
|
||||||
|
# username
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"service_offering": {
|
||||||
|
"name": "Tiny Instance",
|
||||||
|
"displaytext": "Tiny Instance",
|
||||||
|
"cpunumber": 1,
|
||||||
|
"cpuspeed": 100, # in MHz
|
||||||
|
"memory": 64, # In MBs
|
||||||
|
},
|
||||||
|
"disk_offering": {
|
||||||
|
"displaytext": "Small",
|
||||||
|
"name": "Small",
|
||||||
|
"disksize": 1
|
||||||
|
},
|
||||||
|
"virtual_machine": {
|
||||||
|
"displayname": "testVM",
|
||||||
|
"hypervisor": 'XenServer',
|
||||||
|
"protocol": 'TCP',
|
||||||
|
"ssh_port": 22,
|
||||||
|
"username": "root",
|
||||||
|
"password": "password",
|
||||||
|
"privateport": 22,
|
||||||
|
"publicport": 22,
|
||||||
|
},
|
||||||
|
"volume": {
|
||||||
|
"diskname": "Test Volume",
|
||||||
|
},
|
||||||
|
"template_1": {
|
||||||
|
"displaytext": "Cent OS Template",
|
||||||
|
"name": "Cent OS Template",
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
},
|
||||||
|
"template_2": {
|
||||||
|
"displaytext": "Public Template",
|
||||||
|
"name": "Public template",
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"isfeatured": True,
|
||||||
|
"ispublic": True,
|
||||||
|
"isextractable": True,
|
||||||
|
"mode": "HTTP_DOWNLOAD",
|
||||||
|
},
|
||||||
|
"templatefilter": 'self',
|
||||||
|
"destzoneid": 5,
|
||||||
|
# For Copy template (Destination zone)
|
||||||
|
"isfeatured": True,
|
||||||
|
"ispublic": True,
|
||||||
|
"isextractable": False,
|
||||||
|
"bootable": True,
|
||||||
|
"passwordenabled": True,
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"mode": 'advanced',
|
||||||
|
# Networking mode: Advanced, basic
|
||||||
|
"sleep": 30,
|
||||||
|
"timeout": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateTemplate(cloudstackTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
self.apiclient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
return
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
try:
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.services = Services().services
|
||||||
|
cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient()
|
||||||
|
|
||||||
|
# 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"]
|
||||||
|
)
|
||||||
|
template = get_template(
|
||||||
|
cls.api_client,
|
||||||
|
cls.zone.id,
|
||||||
|
cls.services["ostypeid"]
|
||||||
|
)
|
||||||
|
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
||||||
|
cls.services["volume"]["diskoffering"] = cls.disk_offering.id
|
||||||
|
cls.services["volume"]["zoneid"] = cls.zone.id
|
||||||
|
cls.services["sourcezoneid"] = 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"]
|
||||||
|
)
|
||||||
|
#create virtual machine
|
||||||
|
cls.virtual_machine = VirtualMachine.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["virtual_machine"],
|
||||||
|
templateid=template.id,
|
||||||
|
accountid=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid,
|
||||||
|
serviceofferingid=cls.service_offering.id,
|
||||||
|
mode=cls.services["mode"]
|
||||||
|
)
|
||||||
|
|
||||||
|
#Stop virtual machine
|
||||||
|
cls.virtual_machine.stop(cls.api_client)
|
||||||
|
|
||||||
|
# Poll listVM to ensure VM is stopped properly
|
||||||
|
timeout = cls.services["timeout"]
|
||||||
|
while True:
|
||||||
|
time.sleep(cls.services["sleep"])
|
||||||
|
|
||||||
|
# Ensure that VM is in stopped state
|
||||||
|
list_vm_response = list_virtual_machines(
|
||||||
|
cls.api_client,
|
||||||
|
id=cls.virtual_machine.id
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(list_vm_response, list):
|
||||||
|
|
||||||
|
vm = list_vm_response[0]
|
||||||
|
if vm.state == 'Stopped':
|
||||||
|
break
|
||||||
|
|
||||||
|
if timeout == 0:
|
||||||
|
raise Exception(
|
||||||
|
"Failed to stop VM (ID: %s) in change service offering" %
|
||||||
|
vm.id)
|
||||||
|
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
list_volume = list_volumes(
|
||||||
|
cls.api_client,
|
||||||
|
virtualmachineid=cls.virtual_machine.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.volume = list_volume[0]
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.account,
|
||||||
|
cls.service_offering,
|
||||||
|
cls.disk_offering,
|
||||||
|
]
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient()
|
||||||
|
#Cleanup resources used
|
||||||
|
cleanup_resources(cls.api_client, cls._cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_01_create_template(self):
|
||||||
|
"""Test create public & private template
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. database (vm_template table) should be updated
|
||||||
|
# with newly created template
|
||||||
|
# 2. UI should show the newly added template
|
||||||
|
# 3. ListTemplates API should show the newly added template
|
||||||
|
|
||||||
|
#Create template from Virtual machine and Volume ID
|
||||||
|
template = Template.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["template_1"],
|
||||||
|
self.volume.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.cleanup.append(template)
|
||||||
|
|
||||||
|
self.debug("Created template with ID: %s" % template.id)
|
||||||
|
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templatefilter"],
|
||||||
|
id=template.id
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
#Verify template response to check whether template added successfully
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List Templates"
|
||||||
|
)
|
||||||
|
template_response = list_template_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.displaytext,
|
||||||
|
self.services["template_1"]["displaytext"],
|
||||||
|
"Check display text of newly created template"
|
||||||
|
)
|
||||||
|
name = template_response.name
|
||||||
|
self.assertEqual(
|
||||||
|
name.count(self.services["template_1"]["name"]),
|
||||||
|
1,
|
||||||
|
"Check name of newly created template"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.ostypeid,
|
||||||
|
self.services["template_1"]["ostypeid"],
|
||||||
|
"Check osTypeID of newly created template"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class TestTemplates(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
|
||||||
|
cls.services = Services().services
|
||||||
|
cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient()
|
||||||
|
|
||||||
|
# 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"]
|
||||||
|
)
|
||||||
|
template = get_template(
|
||||||
|
cls.api_client,
|
||||||
|
cls.zone.id,
|
||||||
|
cls.services["ostypeid"]
|
||||||
|
)
|
||||||
|
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
||||||
|
cls.services["volume"]["diskoffering"] = cls.disk_offering.id
|
||||||
|
cls.services["volume"]["zoneid"] = cls.zone.id
|
||||||
|
cls.services["template_2"]["zoneid"] = cls.zone.id
|
||||||
|
cls.services["sourcezoneid"] = cls.zone.id
|
||||||
|
|
||||||
|
cls.account = Account.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["account"],
|
||||||
|
admin=True,
|
||||||
|
domainid=cls.domain.id
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.user = 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"]
|
||||||
|
)
|
||||||
|
#create virtual machine
|
||||||
|
cls.virtual_machine = VirtualMachine.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["virtual_machine"],
|
||||||
|
templateid=template.id,
|
||||||
|
accountid=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid,
|
||||||
|
serviceofferingid=cls.service_offering.id,
|
||||||
|
mode=cls.services["mode"]
|
||||||
|
)
|
||||||
|
#Stop virtual machine
|
||||||
|
cls.virtual_machine.stop(cls.api_client)
|
||||||
|
|
||||||
|
# Poll listVM to ensure VM is stopped properly
|
||||||
|
timeout = cls.services["timeout"]
|
||||||
|
while True:
|
||||||
|
time.sleep(cls.services["sleep"])
|
||||||
|
|
||||||
|
# Ensure that VM is in stopped state
|
||||||
|
list_vm_response = list_virtual_machines(
|
||||||
|
cls.api_client,
|
||||||
|
id=cls.virtual_machine.id
|
||||||
|
)
|
||||||
|
|
||||||
|
if isinstance(list_vm_response, list):
|
||||||
|
|
||||||
|
vm = list_vm_response[0]
|
||||||
|
if vm.state == 'Stopped':
|
||||||
|
break
|
||||||
|
|
||||||
|
if timeout == 0:
|
||||||
|
raise Exception(
|
||||||
|
"Failed to stop VM (ID: %s) in change service offering" %
|
||||||
|
vm.id)
|
||||||
|
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
list_volume = list_volumes(
|
||||||
|
cls.api_client,
|
||||||
|
virtualmachineid=cls.virtual_machine.id,
|
||||||
|
type='ROOT',
|
||||||
|
listall=True
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
cls.volume = list_volume[0]
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception(
|
||||||
|
"Exception: Unable to find root volume foe VM: %s" %
|
||||||
|
cls.virtual_machine.id)
|
||||||
|
|
||||||
|
#Create templates for Edit, Delete & update permissions testcases
|
||||||
|
cls.template_1 = Template.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["template_1"],
|
||||||
|
cls.volume.id,
|
||||||
|
account=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid
|
||||||
|
)
|
||||||
|
cls.template_2 = Template.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["template_2"],
|
||||||
|
cls.volume.id,
|
||||||
|
account=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid
|
||||||
|
)
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.service_offering,
|
||||||
|
cls.disk_offering,
|
||||||
|
cls.account,
|
||||||
|
cls.user
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient()
|
||||||
|
#Cleanup created resources such as templates and VMs
|
||||||
|
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:
|
||||||
|
|
||||||
|
self.dbclient.close()
|
||||||
|
#Clean up, terminate the created templates
|
||||||
|
cleanup_resources(self.apiclient, self.cleanup)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_02_edit_template(self):
|
||||||
|
"""Test Edit template
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. UI should show the edited values for template
|
||||||
|
# 2. database (vm_template table) should have updated values
|
||||||
|
|
||||||
|
new_displayText = random_gen()
|
||||||
|
new_name = random_gen()
|
||||||
|
|
||||||
|
cmd = updateTemplate.updateTemplateCmd()
|
||||||
|
# Update template attributes
|
||||||
|
cmd.id = self.template_1.id
|
||||||
|
cmd.displaytext = new_displayText
|
||||||
|
cmd.name = new_name
|
||||||
|
cmd.bootable = self.services["bootable"]
|
||||||
|
cmd.passwordenabled = self.services["passwordenabled"]
|
||||||
|
|
||||||
|
self.apiclient.updateTemplate(cmd)
|
||||||
|
|
||||||
|
self.debug("Edited template with new name: %s" % new_name)
|
||||||
|
|
||||||
|
# Sleep to ensure update reflected across all the calls
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
|
||||||
|
timeout = self.services["timeout"]
|
||||||
|
while True:
|
||||||
|
# Verify template response for updated attributes
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templatefilter"],
|
||||||
|
id=self.template_1.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
if isinstance(list_template_response, list):
|
||||||
|
break
|
||||||
|
elif timeout == 0:
|
||||||
|
raise Exception("List Template failed!")
|
||||||
|
|
||||||
|
time.sleep(10)
|
||||||
|
timeout = timeout -1
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List Templates"
|
||||||
|
)
|
||||||
|
template_response = list_template_response[0]
|
||||||
|
|
||||||
|
self.debug("New Name: %s" % new_displayText)
|
||||||
|
self.debug("Name in Template response: %s"
|
||||||
|
% template_response.displaytext)
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.displaytext,
|
||||||
|
new_displayText,
|
||||||
|
"Check display text of updated template"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.name,
|
||||||
|
new_name,
|
||||||
|
"Check name of updated template"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
str(template_response.passwordenabled).lower(),
|
||||||
|
str(self.services["passwordenabled"]).lower(),
|
||||||
|
"Check passwordenabled field of updated template"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.ostypeid,
|
||||||
|
self.services["ostypeid"],
|
||||||
|
"Check OSTypeID of updated template"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_delete_template(self):
|
||||||
|
"""Test delete template
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following:
|
||||||
|
# 1. UI should not show the deleted template
|
||||||
|
# 2. database (vm_template table) should not contain deleted template
|
||||||
|
|
||||||
|
self.debug("Deleting Template ID: %s" % self.template_1.id)
|
||||||
|
|
||||||
|
self.template_1.delete(self.apiclient)
|
||||||
|
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templatefilter"],
|
||||||
|
id=self.template_1.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
# Verify template is deleted properly using ListTemplates
|
||||||
|
self.assertEqual(
|
||||||
|
list_template_response,
|
||||||
|
None,
|
||||||
|
"Check if template exists in List Templates"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_04_extract_template(self):
|
||||||
|
"Test for extract template"
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Admin should able extract and download the templates
|
||||||
|
# 2. ListTemplates should display all the public templates
|
||||||
|
# for all kind of users
|
||||||
|
# 3 .ListTemplates should not display the system templates
|
||||||
|
|
||||||
|
self.debug("Extracting template with ID: %s" % self.template_2.id)
|
||||||
|
|
||||||
|
cmd = extractTemplate.extractTemplateCmd()
|
||||||
|
cmd.id = self.template_2.id
|
||||||
|
cmd.mode = self.services["template_2"]["mode"]
|
||||||
|
cmd.zoneid = self.zone.id
|
||||||
|
list_extract_response = self.apiclient.extractTemplate(cmd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Format URL to ASCII to retrieve response code
|
||||||
|
formatted_url = urllib.unquote_plus(list_extract_response.url)
|
||||||
|
url_response = urllib.urlopen(formatted_url)
|
||||||
|
response_code = url_response.getcode()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
self.fail(
|
||||||
|
"Extract Template Failed with invalid URL %s (template id: %s)" \
|
||||||
|
% (formatted_url, self.template_2.id)
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_extract_response.id,
|
||||||
|
self.template_2.id,
|
||||||
|
"Check ID of the extracted template"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_extract_response.extractMode,
|
||||||
|
self.services["template_2"]["mode"],
|
||||||
|
"Check mode of extraction"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_extract_response.zoneid,
|
||||||
|
self.services["template_2"]["zoneid"],
|
||||||
|
"Check zone ID of extraction"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
response_code,
|
||||||
|
200,
|
||||||
|
"Check for a valid response download URL"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_05_template_permissions(self):
|
||||||
|
"""Update & Test for template permissions"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. listTemplatePermissions returns valid
|
||||||
|
# permissions set for template
|
||||||
|
# 2. permission changes should be reflected in vm_template
|
||||||
|
# table in database
|
||||||
|
|
||||||
|
self.debug("Updating Template permissions ID:%s" % self.template_2.id)
|
||||||
|
|
||||||
|
cmd = updateTemplatePermissions.updateTemplatePermissionsCmd()
|
||||||
|
# Update template permissions
|
||||||
|
cmd.id = self.template_2.id
|
||||||
|
cmd.isfeatured = self.services["isfeatured"]
|
||||||
|
cmd.ispublic = self.services["ispublic"]
|
||||||
|
cmd.isextractable = self.services["isextractable"]
|
||||||
|
self.apiclient.updateTemplatePermissions(cmd)
|
||||||
|
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter='featured',
|
||||||
|
id=self.template_2.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
# Verify template response for updated permissions for normal user
|
||||||
|
template_response = list_template_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.id,
|
||||||
|
self.template_2.id,
|
||||||
|
"Check template ID"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.ispublic,
|
||||||
|
int(True),
|
||||||
|
"Check ispublic permission of template"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
template_response.templatetype,
|
||||||
|
'SYSTEM',
|
||||||
|
"ListTemplates should not list any system templates"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_06_copy_template(self):
|
||||||
|
"""Test for copy template from one zone to another"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. copy template should be successful and
|
||||||
|
# secondary storage should contain new copied template.
|
||||||
|
|
||||||
|
self.debug("Copy template from Zone: %s to %s" % (
|
||||||
|
self.services["sourcezoneid"],
|
||||||
|
self.services["destzoneid"]
|
||||||
|
))
|
||||||
|
cmd = copyTemplate.copyTemplateCmd()
|
||||||
|
cmd.id = self.template_2.id
|
||||||
|
cmd.destzoneid = self.services["destzoneid"]
|
||||||
|
cmd.sourcezoneid = self.services["sourcezoneid"]
|
||||||
|
self.apiclient.copyTemplate(cmd)
|
||||||
|
|
||||||
|
# Verify template is copied to another zone using ListTemplates
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter=\
|
||||||
|
self.services["templatefilter"],
|
||||||
|
id=self.template_2.id,
|
||||||
|
zoneid=self.services["destzoneid"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template extracted in List Templates"
|
||||||
|
)
|
||||||
|
|
||||||
|
template_response = list_template_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.id,
|
||||||
|
self.template_2.id,
|
||||||
|
"Check ID of the downloaded template"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
template_response.zoneid,
|
||||||
|
self.services["destzoneid"],
|
||||||
|
"Check zone ID of the copied template"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Cleanup- Delete the copied template
|
||||||
|
cmd = deleteTemplate.deleteTemplateCmd()
|
||||||
|
cmd.id = template_response.id
|
||||||
|
cmd.zoneid = self.services["destzoneid"]
|
||||||
|
self.apiclient.deleteTemplate(cmd)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_07_list_public_templates(self):
|
||||||
|
"""Test only public templates are visible to normal user"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. ListTemplates should show only 'public' templates for normal user
|
||||||
|
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter='featured',
|
||||||
|
account=self.user.account.name,
|
||||||
|
domainid=self.user.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List Templates"
|
||||||
|
)
|
||||||
|
#Template response should list all 'public' templates
|
||||||
|
for template in list_template_response:
|
||||||
|
self.assertEqual(
|
||||||
|
template.ispublic,
|
||||||
|
True,
|
||||||
|
"ListTemplates should list only public templates"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_08_list_system_templates(self):
|
||||||
|
"""Test System templates are not visible to normal user"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. ListTemplates should not show 'SYSTEM' templates for normal user
|
||||||
|
|
||||||
|
list_template_response = list_templates(
|
||||||
|
self.apiclient,
|
||||||
|
templatefilter='featured',
|
||||||
|
account=self.user.account.name,
|
||||||
|
domainid=self.user.account.domainid
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_template_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
len(list_template_response),
|
||||||
|
0,
|
||||||
|
"Check template available in List Templates"
|
||||||
|
)
|
||||||
|
|
||||||
|
for template in list_template_response:
|
||||||
|
self.assertNotEqual(
|
||||||
|
template.templatetype,
|
||||||
|
'SYSTEM',
|
||||||
|
"ListTemplates should not list any system templates"
|
||||||
|
)
|
||||||
|
return
|
||||||
947
test/integration/smoke/test_vm_life_cycle.py
Normal file
947
test/integration/smoke/test_vm_life_cycle.py
Normal file
@ -0,0 +1,947 @@
|
|||||||
|
# -*- 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 integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.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": "fr3sca",
|
||||||
|
},
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"iso": # ISO settings for Attach/Detach ISO tests
|
||||||
|
{
|
||||||
|
"displaytext": "Test ISO",
|
||||||
|
"name": "testISO",
|
||||||
|
"url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso",
|
||||||
|
# Source URL where ISO is located
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"mode": 'HTTP_DOWNLOAD', # Downloading existing ISO
|
||||||
|
},
|
||||||
|
"diskdevice": '/dev/xvdd',
|
||||||
|
# Disk device where ISO is attached to instance
|
||||||
|
"mount_dir": "/mnt/tmp",
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 10,
|
||||||
|
#Migrate VM to hostid
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
# 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
|
||||||
|
self.services["iso"]["zoneid"] = zone.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
|
||||||
|
cls.services["iso"]["zoneid"] = zone.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_03_reboot_vm(self):
|
||||||
|
"""Test Reboot Virtual Machine
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Should be able to login to the VM.
|
||||||
|
# 2. listVM command should return the deployed VM.
|
||||||
|
# State of this VM should be "Running"
|
||||||
|
|
||||||
|
self.debug("Rebooting VM - ID: %s" % self.virtual_machine.id)
|
||||||
|
self.small_virtual_machine.reboot(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,
|
||||||
|
"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
|
||||||
|
|
||||||
|
try:
|
||||||
|
ssh = self.medium_virtual_machine.get_ssh_client()
|
||||||
|
except Exception as e:
|
||||||
|
self.fail(
|
||||||
|
"SSH Access failed for %s: %s" % \
|
||||||
|
(self.medium_virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
|
||||||
|
cpuinfo = ssh.execute("cat /proc/cpuinfo")
|
||||||
|
|
||||||
|
cpu_cnt = len([i for i in cpuinfo if "processor" in i])
|
||||||
|
#'cpu MHz\t\t: 2660.499'
|
||||||
|
cpu_speed = [i for i in cpuinfo if "cpu MHz" in i ][0].split()[3]
|
||||||
|
|
||||||
|
meminfo = ssh.execute("cat /proc/meminfo")
|
||||||
|
#MemTotal: 1017464 kB
|
||||||
|
total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1]
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"CPU count: %s, CPU Speed: %s, Mem Info: %s" % (
|
||||||
|
cpu_cnt,
|
||||||
|
cpu_speed,
|
||||||
|
total_mem
|
||||||
|
))
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
int(cpu_cnt),
|
||||||
|
self.small_offering.cpunumber,
|
||||||
|
"Check CPU Count for small offering"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
list_vm_response[0].cpuspeed,
|
||||||
|
self.small_offering.cpuspeed,
|
||||||
|
"Check CPU Speed for small offering"
|
||||||
|
)
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
int(total_mem) / 1024, # In MBs
|
||||||
|
self.small_offering.memory,
|
||||||
|
"Check Memory(kb) for small offering"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_05_change_offering_medium(self):
|
||||||
|
"""Change Offering to a medium 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 "Medium" service offering.
|
||||||
|
# 2. Using listVM command verify that this Vm
|
||||||
|
# has Medium service offering Id.
|
||||||
|
|
||||||
|
self.debug("Stopping VM - ID: %s" % self.small_virtual_machine.id)
|
||||||
|
self.small_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.small_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.small_virtual_machine.id)
|
||||||
|
|
||||||
|
cmd = changeServiceForVirtualMachine.changeServiceForVirtualMachineCmd()
|
||||||
|
cmd.id = self.small_virtual_machine.id
|
||||||
|
cmd.serviceofferingid = self.medium_offering.id
|
||||||
|
self.apiclient.changeServiceForVirtualMachine(cmd)
|
||||||
|
|
||||||
|
self.debug("Starting VM - ID: %s" % self.small_virtual_machine.id)
|
||||||
|
self.small_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.small_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
|
||||||
|
|
||||||
|
list_vm_response = list_virtual_machines(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.small_virtual_machine.id
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ssh_client = self.small_virtual_machine.get_ssh_client()
|
||||||
|
except Exception as e:
|
||||||
|
self.fail(
|
||||||
|
"SSH Access failed for %s: %s" % \
|
||||||
|
(self.small_virtual_machine.ipaddress, e)
|
||||||
|
)
|
||||||
|
|
||||||
|
cpuinfo = ssh_client.execute("cat /proc/cpuinfo")
|
||||||
|
|
||||||
|
cpu_cnt = len([i for i in cpuinfo if "processor" in i])
|
||||||
|
#'cpu MHz\t\t: 2660.499'
|
||||||
|
cpu_speed = [i for i in cpuinfo if "cpu MHz" in i][0].split()[3]
|
||||||
|
|
||||||
|
meminfo = ssh_client.execute("cat /proc/meminfo")
|
||||||
|
#MemTotal: 1017464 kB
|
||||||
|
total_mem = [i for i in meminfo if "MemTotal" in i][0].split()[1]
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"CPU count: %s, CPU Speed: %s, Mem Info: %s" % (
|
||||||
|
cpu_cnt,
|
||||||
|
cpu_speed,
|
||||||
|
total_mem
|
||||||
|
))
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
int(cpu_cnt),
|
||||||
|
self.medium_offering.cpunumber,
|
||||||
|
"Check CPU Count for medium offering"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
list_vm_response[0].cpuspeed,
|
||||||
|
self.medium_offering.cpuspeed,
|
||||||
|
"Check CPU Speed for medium offering"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertAlmostEqual(
|
||||||
|
int(total_mem) / 1024, # In MBs
|
||||||
|
self.medium_offering.memory,
|
||||||
|
"Check Memory(kb) for medium offering"
|
||||||
|
)
|
||||||
|
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
|
||||||
|
|
||||||
|
def test_08_migrate_vm(self):
|
||||||
|
"""Test migrate VM
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. Should be able to login to the VM.
|
||||||
|
# 2. listVM command should return this VM.State of this VM
|
||||||
|
# should be "Running" and the host should be the host
|
||||||
|
# to which the VM was migrated to
|
||||||
|
|
||||||
|
hosts = Host.list(
|
||||||
|
self.apiclient,
|
||||||
|
zoneid=self.medium_virtual_machine.zoneid,
|
||||||
|
type='Routing'
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(hosts, list),
|
||||||
|
True,
|
||||||
|
"Check the number of hosts in the zone"
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
len(hosts),
|
||||||
|
2,
|
||||||
|
"Atleast 2 hosts should be present in a zone for VM migration"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Find the host of VM and also the new host to migrate VM.
|
||||||
|
if self.medium_virtual_machine.hostid == hosts[0].id:
|
||||||
|
host = hosts[1]
|
||||||
|
else:
|
||||||
|
host = hosts[0]
|
||||||
|
|
||||||
|
self.debug("Migrating VM-ID: %s to Host: %s" % (
|
||||||
|
self.medium_virtual_machine.id,
|
||||||
|
host.id
|
||||||
|
))
|
||||||
|
|
||||||
|
cmd = migrateVirtualMachine.migrateVirtualMachineCmd()
|
||||||
|
cmd.hostid = host.id
|
||||||
|
cmd.virtualmachineid = self.medium_virtual_machine.id
|
||||||
|
self.apiclient.migrateVirtualMachine(cmd)
|
||||||
|
|
||||||
|
list_vm_response = list_virtual_machines(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.medium_virtual_machine.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_vm_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
list_vm_response,
|
||||||
|
None,
|
||||||
|
"Check virtual machine is listVirtualMachines"
|
||||||
|
)
|
||||||
|
|
||||||
|
vm_response = list_vm_response[0]
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
vm_response.id,
|
||||||
|
self.medium_virtual_machine.id,
|
||||||
|
"Check virtual machine ID of migrated VM"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
vm_response.hostid,
|
||||||
|
host.id,
|
||||||
|
"Check destination hostID of migrated VM"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_09_expunge_vm(self):
|
||||||
|
"""Test destroy(expunge) Virtual Machine
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. listVM command should NOT return this VM any more.
|
||||||
|
|
||||||
|
self.debug("Expunge VM-ID: %s" % self.small_virtual_machine.id)
|
||||||
|
|
||||||
|
cmd = destroyVirtualMachine.destroyVirtualMachineCmd()
|
||||||
|
cmd.id = self.small_virtual_machine.id
|
||||||
|
self.apiclient.destroyVirtualMachine(cmd)
|
||||||
|
|
||||||
|
config = list_configurations(
|
||||||
|
self.apiclient,
|
||||||
|
name='expunge.delay'
|
||||||
|
)
|
||||||
|
|
||||||
|
response = config[0]
|
||||||
|
# Wait for some time more than expunge.delay
|
||||||
|
time.sleep(int(response.value) * 2)
|
||||||
|
|
||||||
|
list_vm_response = list_virtual_machines(
|
||||||
|
self.apiclient,
|
||||||
|
id=self.small_virtual_machine.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_vm_response,
|
||||||
|
None,
|
||||||
|
"Check Expunged virtual machine is listVirtualMachines"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_10_attachAndDetach_iso(self):
|
||||||
|
"""Test for detach ISO to virtual machine"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Create ISO
|
||||||
|
# 2. Attach ISO to VM
|
||||||
|
# 3. Log in to the VM.
|
||||||
|
# 4. The device should be available for use
|
||||||
|
# 5. Detach ISO
|
||||||
|
# 6. Check the device is properly detached by logging into VM
|
||||||
|
|
||||||
|
iso = Iso.create(
|
||||||
|
self.apiclient,
|
||||||
|
self.services["iso"],
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid
|
||||||
|
)
|
||||||
|
|
||||||
|
self.debug("Successfully created ISO with ID: %s" % iso.id)
|
||||||
|
try:
|
||||||
|
iso.download(self.apiclient)
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("Exception while downloading ISO %s: %s"\
|
||||||
|
% (iso.id, e))
|
||||||
|
|
||||||
|
self.debug("Attach ISO with ID: %s to VM ID: %s" % (
|
||||||
|
iso.id,
|
||||||
|
self.virtual_machine.id
|
||||||
|
))
|
||||||
|
#Attach ISO to virtual machine
|
||||||
|
cmd = attachIso.attachIsoCmd()
|
||||||
|
cmd.id = iso.id
|
||||||
|
cmd.virtualmachineid = self.virtual_machine.id
|
||||||
|
self.apiclient.attachIso(cmd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ssh_client = self.virtual_machine.get_ssh_client()
|
||||||
|
|
||||||
|
cmds = [
|
||||||
|
"mkdir -p %s" % self.services["mount_dir"],
|
||||||
|
"mount -rt iso9660 %s %s" \
|
||||||
|
% (
|
||||||
|
self.services["diskdevice"],
|
||||||
|
self.services["mount_dir"]
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
for c in cmds:
|
||||||
|
res = ssh_client.execute(c)
|
||||||
|
|
||||||
|
self.assertEqual(res, [], "Check mount is successful or not")
|
||||||
|
|
||||||
|
c = "fdisk -l|grep %s|head -1" % self.services["diskdevice"]
|
||||||
|
res = ssh_client.execute(c)
|
||||||
|
#Disk /dev/xvdd: 4393 MB, 4393723904 bytes
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH failed for virtual machine: %s - %s" %
|
||||||
|
(self.virtual_machine.ipaddress, e))
|
||||||
|
|
||||||
|
# Res may contain more than one strings depending on environment
|
||||||
|
# Split strings to form new list which is used for assertion on ISO size
|
||||||
|
result = []
|
||||||
|
for i in res:
|
||||||
|
for k in i.split():
|
||||||
|
result.append(k)
|
||||||
|
|
||||||
|
# Get ISO size
|
||||||
|
iso_response = list_isos(
|
||||||
|
self.apiclient,
|
||||||
|
id=iso.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(iso_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
iso_size = iso_response[0].size
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
str(iso_size) in result,
|
||||||
|
True,
|
||||||
|
"Check size of the attached ISO"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
#Unmount ISO
|
||||||
|
command = "umount %s" % self.services["mount_dir"]
|
||||||
|
ssh_client.execute(command)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH failed for virtual machine: %s - %s" %
|
||||||
|
(self.virtual_machine.ipaddress, e))
|
||||||
|
|
||||||
|
#Detach from VM
|
||||||
|
cmd = detachIso.detachIsoCmd()
|
||||||
|
cmd.virtualmachineid = self.virtual_machine.id
|
||||||
|
self.apiclient.detachIso(cmd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
res = ssh_client.execute(c)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH failed for virtual machine: %s - %s" %
|
||||||
|
(self.virtual_machine.ipaddress, e))
|
||||||
|
|
||||||
|
# Check if ISO is properly detached from VM (using fdisk)
|
||||||
|
result = self.services["diskdevice"] in str(res)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
result,
|
||||||
|
False,
|
||||||
|
"Check if ISO is detached from virtual machine"
|
||||||
|
)
|
||||||
|
return
|
||||||
517
test/integration/smoke/test_volumes.py
Normal file
517
test/integration/smoke/test_volumes.py
Normal file
@ -0,0 +1,517 @@
|
|||||||
|
# -*- 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 Volumes
|
||||||
|
"""
|
||||||
|
#Import Local Modules
|
||||||
|
import marvin
|
||||||
|
from marvin.cloudstackTestCase import *
|
||||||
|
from marvin.cloudstackAPI import *
|
||||||
|
from integration.lib.utils import *
|
||||||
|
from integration.lib.base import *
|
||||||
|
from integration.lib.common import *
|
||||||
|
from marvin.remoteSSHClient import remoteSSHClient
|
||||||
|
#Import System modules
|
||||||
|
import os
|
||||||
|
import urllib
|
||||||
|
import time
|
||||||
|
import tempfile
|
||||||
|
|
||||||
|
|
||||||
|
class Services:
|
||||||
|
"""Test Volume Services
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.services = {
|
||||||
|
"account": {
|
||||||
|
"email": "test@test.com",
|
||||||
|
"firstname": "Test",
|
||||||
|
"lastname": "User",
|
||||||
|
"username": "test",
|
||||||
|
# Random characters are appended for unique
|
||||||
|
# username
|
||||||
|
"password": "fr3sca",
|
||||||
|
},
|
||||||
|
"service_offering": {
|
||||||
|
"name": "Tiny Instance",
|
||||||
|
"displaytext": "Tiny Instance",
|
||||||
|
"cpunumber": 1,
|
||||||
|
"cpuspeed": 100, # in MHz
|
||||||
|
"memory": 64, # In MBs
|
||||||
|
},
|
||||||
|
"disk_offering": {
|
||||||
|
"displaytext": "Small",
|
||||||
|
"name": "Small",
|
||||||
|
"disksize": 1
|
||||||
|
},
|
||||||
|
"volume_offerings": {
|
||||||
|
0: {
|
||||||
|
"diskname": "TestDiskServ",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"customdisksize": 1, # GBs
|
||||||
|
"username": "root", # Creds for SSH to VM
|
||||||
|
"password": "password",
|
||||||
|
"ssh_port": 22,
|
||||||
|
"diskname": "TestDiskServ",
|
||||||
|
"hypervisor": 'XenServer',
|
||||||
|
"privateport": 22,
|
||||||
|
"publicport": 22,
|
||||||
|
"protocol": 'TCP',
|
||||||
|
"diskdevice": "/dev/xvdb",
|
||||||
|
"ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9',
|
||||||
|
"mode": 'advanced',
|
||||||
|
"sleep": 60,
|
||||||
|
"timeout": 10,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateVolume(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.api_client = super(TestCreateVolume, 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.custom_disk_offering = DiskOffering.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services["disk_offering"],
|
||||||
|
custom=True
|
||||||
|
)
|
||||||
|
template = get_template(
|
||||||
|
cls.api_client,
|
||||||
|
cls.zone.id,
|
||||||
|
cls.services["ostypeid"]
|
||||||
|
)
|
||||||
|
cls.services["domainid"] = cls.domain.id
|
||||||
|
cls.services["zoneid"] = cls.zone.id
|
||||||
|
cls.services["template"] = template.id
|
||||||
|
cls.services["customdiskofferingid"] = cls.custom_disk_offering.id
|
||||||
|
|
||||||
|
# Create VMs, NAT Rules etc
|
||||||
|
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.virtual_machine = VirtualMachine.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services,
|
||||||
|
accountid=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid,
|
||||||
|
serviceofferingid=cls.service_offering.id,
|
||||||
|
mode=cls.services["mode"]
|
||||||
|
)
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.service_offering,
|
||||||
|
cls.disk_offering,
|
||||||
|
cls.custom_disk_offering,
|
||||||
|
cls.account
|
||||||
|
]
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
|
||||||
|
self.apiClient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
self.cleanup = []
|
||||||
|
|
||||||
|
def test_01_create_volume(self):
|
||||||
|
"""Test Volume creation for all Disk Offerings (incl. custom)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. Create volumes from the different sizes
|
||||||
|
# 2. Verify the size of volume with actual size allocated
|
||||||
|
|
||||||
|
self.volumes = []
|
||||||
|
for k, v in self.services["volume_offerings"].items():
|
||||||
|
volume = Volume.create(
|
||||||
|
self.apiClient,
|
||||||
|
v,
|
||||||
|
zoneid=self.zone.id,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
diskofferingid=self.disk_offering.id
|
||||||
|
)
|
||||||
|
self.debug("Created a volume with ID: %s" % volume.id)
|
||||||
|
self.volumes.append(volume)
|
||||||
|
|
||||||
|
volume = Volume.create_custom_disk(
|
||||||
|
self.apiClient,
|
||||||
|
self.services,
|
||||||
|
account=self.account.account.name,
|
||||||
|
domainid=self.account.account.domainid,
|
||||||
|
)
|
||||||
|
self.debug("Created a volume with custom offering: %s" % volume.id)
|
||||||
|
self.volumes.append(volume)
|
||||||
|
|
||||||
|
#Attach a volume with different disk offerings
|
||||||
|
#and check the memory allocated to each of them
|
||||||
|
for volume in self.volumes:
|
||||||
|
list_volume_response = list_volumes(
|
||||||
|
self.apiClient,
|
||||||
|
id=volume.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_volume_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
list_volume_response,
|
||||||
|
None,
|
||||||
|
"Check if volume exists in ListVolumes"
|
||||||
|
)
|
||||||
|
self.debug(
|
||||||
|
"Attaching volume (ID: %s) to VM (ID: %s)" % (
|
||||||
|
volume.id,
|
||||||
|
self.virtual_machine.id
|
||||||
|
))
|
||||||
|
self.virtual_machine.attach_volume(
|
||||||
|
self.apiClient,
|
||||||
|
volume
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
ssh = self.virtual_machine.get_ssh_client()
|
||||||
|
ssh.execute("reboot")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH access failed for VM %s - %s" %
|
||||||
|
(self.virtual_machine.ipaddress, e))
|
||||||
|
|
||||||
|
# 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.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) " % vm.id)
|
||||||
|
|
||||||
|
timeout = timeout - 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
ssh = self.virtual_machine.get_ssh_client(
|
||||||
|
reconnect=True
|
||||||
|
)
|
||||||
|
c = "fdisk -l"
|
||||||
|
res = ssh.execute(c)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.fail("SSH access failed for VM: %s - %s" %
|
||||||
|
(self.virtual_machine.ipaddress, e))
|
||||||
|
|
||||||
|
# Disk /dev/sda doesn't contain a valid partition table
|
||||||
|
# Disk /dev/sda: 21.5 GB, 21474836480 bytes
|
||||||
|
result = str(res)
|
||||||
|
self.debug("fdisk result: %s" % result)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
str(list_volume_response[0].size) in result,
|
||||||
|
True,
|
||||||
|
"Check if promised disk size actually available"
|
||||||
|
)
|
||||||
|
self.virtual_machine.detach_volume(self.apiClient, volume)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
#Clean up, terminate the created volumes
|
||||||
|
cleanup_resources(self.apiClient, self.cleanup)
|
||||||
|
return
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cls.api_client = super(TestCreateVolume, cls).getClsTestClient().getApiClient()
|
||||||
|
cleanup_resources(cls.api_client, cls._cleanup)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
|
||||||
|
class TestVolumes(cloudstackTestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpClass(cls):
|
||||||
|
cls.api_client = super(TestVolumes, 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"]
|
||||||
|
)
|
||||||
|
template = get_template(
|
||||||
|
cls.api_client,
|
||||||
|
cls.zone.id,
|
||||||
|
cls.services["ostypeid"]
|
||||||
|
)
|
||||||
|
cls.services["domainid"] = cls.domain.id
|
||||||
|
cls.services["zoneid"] = cls.zone.id
|
||||||
|
cls.services["template"] = template.id
|
||||||
|
cls.services["diskofferingid"] = cls.disk_offering.id
|
||||||
|
|
||||||
|
# Create VMs, VMs etc
|
||||||
|
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.virtual_machine = VirtualMachine.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services,
|
||||||
|
accountid=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid,
|
||||||
|
serviceofferingid=cls.service_offering.id,
|
||||||
|
mode=cls.services["mode"]
|
||||||
|
)
|
||||||
|
|
||||||
|
cls.volume = Volume.create(
|
||||||
|
cls.api_client,
|
||||||
|
cls.services,
|
||||||
|
account=cls.account.account.name,
|
||||||
|
domainid=cls.account.account.domainid
|
||||||
|
)
|
||||||
|
cls._cleanup = [
|
||||||
|
cls.service_offering,
|
||||||
|
cls.disk_offering,
|
||||||
|
cls.account
|
||||||
|
]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def tearDownClass(cls):
|
||||||
|
try:
|
||||||
|
cleanup_resources(cls.api_client, cls._cleanup)
|
||||||
|
except Exception as e:
|
||||||
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.apiClient = self.testClient.getApiClient()
|
||||||
|
self.dbclient = self.testClient.getDbConnection()
|
||||||
|
|
||||||
|
def test_02_attach_volume(self):
|
||||||
|
"""Attach a created Volume to a Running VM
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. shows list of volumes
|
||||||
|
# 2. "Attach Disk" pop-up box will display with list of instances
|
||||||
|
# 3. disk should be attached to instance successfully
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Attaching volume (ID: %s) to VM (ID: %s)" % (
|
||||||
|
self.volume.id,
|
||||||
|
self.virtual_machine.id
|
||||||
|
))
|
||||||
|
self.virtual_machine.attach_volume(self.apiClient, self.volume)
|
||||||
|
|
||||||
|
list_volume_response = list_volumes(
|
||||||
|
self.apiClient,
|
||||||
|
id=self.volume.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_volume_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
self.assertNotEqual(
|
||||||
|
list_volume_response,
|
||||||
|
None,
|
||||||
|
"Check if volume exists in ListVolumes"
|
||||||
|
)
|
||||||
|
volume = list_volume_response[0]
|
||||||
|
self.assertNotEqual(
|
||||||
|
volume.virtualmachineid,
|
||||||
|
None,
|
||||||
|
"Check if volume state (attached) is reflected"
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
#Format the attached volume to a known fs
|
||||||
|
format_volume_to_ext3(self.virtual_machine.get_ssh_client())
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
|
||||||
|
self.fail("SSH failed for VM: %s - %s" %
|
||||||
|
(self.virtual_machine.ipaddress, e))
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_03_download_attached_volume(self):
|
||||||
|
"""Download a Volume attached to a VM
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. download volume will fail with proper error message
|
||||||
|
# "Failed - Invalid state of the volume with ID:
|
||||||
|
# It should be either detached or the VM should be in stopped state
|
||||||
|
|
||||||
|
self.debug("Extract attached Volume ID: %s" % self.volume.id)
|
||||||
|
|
||||||
|
cmd = extractVolume.extractVolumeCmd()
|
||||||
|
cmd.id = self.volume.id
|
||||||
|
cmd.mode = "HTTP_DOWNLOAD"
|
||||||
|
cmd.zoneid = self.services["zoneid"]
|
||||||
|
# A proper exception should be raised;
|
||||||
|
# downloading attach VM is not allowed
|
||||||
|
with self.assertRaises(Exception):
|
||||||
|
self.apiClient.extractVolume(cmd)
|
||||||
|
|
||||||
|
def test_04_delete_attached_volume(self):
|
||||||
|
"""Delete a Volume attached to a VM
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# 1. delete volume will fail with proper error message
|
||||||
|
# "Failed - Invalid state of the volume with ID:
|
||||||
|
# It should be either detached or the VM should be in stopped state
|
||||||
|
|
||||||
|
self.debug("Trying to delete attached Volume ID: %s" %
|
||||||
|
self.volume.id)
|
||||||
|
|
||||||
|
cmd = deleteVolume.deleteVolumeCmd()
|
||||||
|
cmd.id = self.volume.id
|
||||||
|
#Proper exception should be raised; deleting attach VM is not allowed
|
||||||
|
#with self.assertRaises(Exception):
|
||||||
|
result = self.apiClient.deleteVolume(cmd)
|
||||||
|
self.assertEqual(
|
||||||
|
result,
|
||||||
|
None,
|
||||||
|
"Check for delete download error while volume is attached"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_05_detach_volume(self):
|
||||||
|
"""Detach a Volume attached to a VM
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Validate the following
|
||||||
|
# Data disk should be detached from instance and detached data disk
|
||||||
|
# details should be updated properly
|
||||||
|
|
||||||
|
self.debug(
|
||||||
|
"Detaching volume (ID: %s) from VM (ID: %s)" % (
|
||||||
|
self.volume.id,
|
||||||
|
self.virtual_machine.id
|
||||||
|
))
|
||||||
|
|
||||||
|
self.virtual_machine.detach_volume(self.apiClient, self.volume)
|
||||||
|
#Sleep to ensure the current state will reflected in other calls
|
||||||
|
time.sleep(self.services["sleep"])
|
||||||
|
list_volume_response = list_volumes(
|
||||||
|
self.apiClient,
|
||||||
|
id=self.volume.id
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
isinstance(list_volume_response, list),
|
||||||
|
True,
|
||||||
|
"Check list response returns a valid list"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertNotEqual(
|
||||||
|
list_volume_response,
|
||||||
|
None,
|
||||||
|
"Check if volume exists in ListVolumes"
|
||||||
|
)
|
||||||
|
volume = list_volume_response[0]
|
||||||
|
self.assertEqual(
|
||||||
|
volume.virtualmachineid,
|
||||||
|
None,
|
||||||
|
"Check if volume state (detached) is reflected"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def test_06_download_detached_volume(self):
|
||||||
|
"""Download a Volume unattached to an VM
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. able to download the volume when its not attached to instance
|
||||||
|
|
||||||
|
self.debug("Extract detached Volume ID: %s" % self.volume.id)
|
||||||
|
|
||||||
|
cmd = extractVolume.extractVolumeCmd()
|
||||||
|
cmd.id = self.volume.id
|
||||||
|
cmd.mode = "HTTP_DOWNLOAD"
|
||||||
|
cmd.zoneid = self.services["zoneid"]
|
||||||
|
extract_vol = self.apiClient.extractVolume(cmd)
|
||||||
|
|
||||||
|
#Attempt to download the volume and save contents locally
|
||||||
|
try:
|
||||||
|
formatted_url = urllib.unquote_plus(extract_vol.url)
|
||||||
|
response = urllib.urlopen(formatted_url)
|
||||||
|
fd, path = tempfile.mkstemp()
|
||||||
|
os.close(fd)
|
||||||
|
fd = open(path, 'wb')
|
||||||
|
fd.write(response.read())
|
||||||
|
fd.close()
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
self.fail(
|
||||||
|
"Extract Volume Failed with invalid URL %s (vol id: %s)" \
|
||||||
|
% (extract_vol.url, self.volume.id)
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_07_delete_detached_volume(self):
|
||||||
|
"""Delete a Volume unattached to an VM
|
||||||
|
"""
|
||||||
|
# Validate the following
|
||||||
|
# 1. volume should be deleted successfully and listVolume should not
|
||||||
|
# contain the deleted volume details.
|
||||||
|
# 2. "Delete Volume" menu item not shown under "Actions" menu.
|
||||||
|
# (UI should not allow to delete the volume when it is attached
|
||||||
|
# to instance by hiding the menu Item)
|
||||||
|
|
||||||
|
self.debug("Delete Volume ID: %s" % self.volume.id)
|
||||||
|
|
||||||
|
cmd = deleteVolume.deleteVolumeCmd()
|
||||||
|
cmd.id = self.volume.id
|
||||||
|
self.apiClient.deleteVolume(cmd)
|
||||||
|
|
||||||
|
list_volume_response = list_volumes(
|
||||||
|
self.apiClient,
|
||||||
|
id=self.volume.id,
|
||||||
|
type='DATADISK'
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
list_volume_response,
|
||||||
|
None,
|
||||||
|
"Check if volume exists in ListVolumes"
|
||||||
|
)
|
||||||
|
return
|
||||||
Loading…
x
Reference in New Issue
Block a user