From cbbed24ef42535d6463727cf71c0db4623556b06 Mon Sep 17 00:00:00 2001 From: Chirag Jog Date: Tue, 22 May 2012 19:17:26 +0530 Subject: [PATCH] Adding ELP/EIP tests & firewall rule changes for SSH --- .../component/test_egress_rules.py | 34 +- test/integration/component/test_eip_elb.py | 1574 +++++++++++++++++ .../component/test_high_availability.py | 197 ++- .../component/test_network_offering.py | 56 +- .../component/test_project_resources.py | 3 +- test/integration/component/test_projects.py | 2 +- .../component/test_resource_limits.py | 1 + test/integration/component/test_routers.py | 48 +- .../component/test_security_groups.py | 4 +- test/integration/component/test_snapshots.py | 2 +- test/integration/component/test_templates.py | 1 + test/integration/component/test_volumes.py | 2 +- test/integration/lib/base.py | 473 +++-- test/integration/lib/common.py | 102 +- test/integration/lib/utils.py | 32 +- test/integration/smoke/test_network.py | 257 +-- test/integration/smoke/test_routers.py | 3 +- test/integration/smoke/test_snapshots.py | 4 +- test/integration/smoke/test_templates.py | 7 +- test/integration/smoke/test_vm_life_cycle.py | 350 +++- test/integration/smoke/test_volumes.py | 6 +- 21 files changed, 2673 insertions(+), 485 deletions(-) create mode 100644 test/integration/component/test_eip_elb.py diff --git a/test/integration/component/test_egress_rules.py b/test/integration/component/test_egress_rules.py index d0e00498ac6..aa301dad3cb 100644 --- a/test/integration/component/test_egress_rules.py +++ b/test/integration/component/test_egress_rules.py @@ -34,7 +34,7 @@ class Services: def __init__(self): self.services = { - "disk_offering": { + "disk_offering":{ "displaytext": "Small", "name": "Small", "disksize": 1 @@ -64,8 +64,8 @@ class Services: "name": "Tiny Instance", "displaytext": "Tiny Instance", "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs }, "security_group": { "name": 'SSH', @@ -107,9 +107,8 @@ class Services: "protocol": 'TCP', "startport": 22, "endport": 22, - "cidrlist": '0.0.0.0/0', }, - "mgmt_server": { + "mgmt_server": { "username": "root", "password": "fr3sca", "ipaddress": "192.168.100.21" @@ -118,7 +117,7 @@ class Services: # CentOS 5.3 (64-bit) "sleep": 60, "timeout": 10, - "mode": 'basic', + "mode":'basic', # Networking mode: Basic or Advanced } @@ -801,7 +800,7 @@ class TestDefaultGroupEgressAfterDeploy(cloudstackTestCase): # --- www.l.google.com ping statistics --- # 1 packets transmitted, 1 received, 0% packet loss, time 0ms # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms - self.debug("SSH result: %s" %str(res)) + self.debug("SSH result: %s" % str(res)) except Exception as e: self.fail("SSH Access failed for %s: %s" % \ (self.virtual_machine.ipaddress, e) @@ -985,7 +984,7 @@ class TestRevokeEgressRule(cloudstackTestCase): # --- www.l.google.com ping statistics --- # 1 packets transmitted, 1 received, 0% packet loss, time 0ms # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms - self.debug("SSH result: %s" % str(res)) + self.debug("SSH result: %s" % str(res)) except Exception as e: self.fail("SSH Access failed for %s: %s" % \ (self.virtual_machine.ipaddress, e) @@ -1026,7 +1025,7 @@ class TestRevokeEgressRule(cloudstackTestCase): result = security_group.revokeEgress( self.apiclient, - id=ssh_egress_rule["ruleid"] + id = ssh_egress_rule["ruleid"] ) self.debug("Revoke egress rule result: %s" % result) @@ -1319,14 +1318,14 @@ class TestMultipleAccountsEgressRuleNeg(cloudstackTestCase): "Authorizing egress rule for sec group ID: %s for ssh access" % security_group.id) # Authorize to only account not CIDR - user_secgrp_list = {self.accountB.account.name: 'default'} + user_secgrp_list = {self.accountB.account.name: 'default'} egress_rule = security_group.authorizeEgress( self.apiclient, self.services["sg_account"], account=self.accountA.account.name, domainid=self.accountA.account.domainid, - user_secgrp_list=user_secgrp_list + user_secgrp_list=user_secgrp_list ) self.assertEqual( @@ -1422,7 +1421,7 @@ class TestMultipleAccountsEgressRuleNeg(cloudstackTestCase): try: self.debug("SSHing into VM type B from VM A") - self.debug("VM IP: %s" % self.virtual_machineB.ssh_ip) + self.debug("VM IP: %s" % self.virtual_machineB.ssh_ip) res = ssh.execute("ssh %s@%s" % ( self.services["virtual_machine"]["username"], self.virtual_machineB.ssh_ip @@ -1592,14 +1591,14 @@ class TestMultipleAccountsEgressRule(cloudstackTestCase): "Authorizing egress rule for sec group ID: %s for ssh access" % security_groupA.id) # Authorize to only account not CIDR - user_secgrp_list = {self.accountB.account.name: security_groupB.name} + user_secgrp_list = {self.accountB.account.name: security_groupB.name} egress_rule = security_groupA.authorizeEgress( self.apiclient, self.services["sg_account"], account=self.accountA.account.name, domainid=self.accountA.account.domainid, - user_secgrp_list=user_secgrp_list + user_secgrp_list=user_secgrp_list ) self.assertEqual( @@ -1716,7 +1715,7 @@ class TestMultipleAccountsEgressRule(cloudstackTestCase): try: self.debug("SSHing into VB type B from VM A") - self.debug("VM IP: %s" % self.virtual_machineB.ssh_ip) + self.debug("VM IP: %s" % self.virtual_machineB.ssh_ip) res = ssh.execute("ssh %s@%s" % ( self.services["virtual_machine"]["username"], @@ -1945,7 +1944,6 @@ class TestStartStopVMWithEgressRule(cloudstackTestCase): ) return - @unittest.skip("Valid bug- ID: CS-12647") class TestInvalidParametersForEgress(cloudstackTestCase): @@ -2306,12 +2304,12 @@ class TestEgressAfterHostMaintainance(cloudstackTestCase): ) vm = vms[0] - self.debug("Enabling host maintainance for ID: %s" % vm.hostid) + self.debug("Enabling host maintainance for ID: %s" % host.id) cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() cmd.id = vm.hostid self.apiclient.prepareHostForMaintenance(cmd) - self.debug("Canceling host maintainance for ID: %s" % vm.hostid) + self.debug("Canceling host maintainance for ID: %s" % host.id) cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() cmd.id = vm.hostid self.apiclient.cancelHostMaintenance(cmd) diff --git a/test/integration/component/test_eip_elb.py b/test/integration/component/test_eip_elb.py new file mode 100644 index 00000000000..ac11d6dab54 --- /dev/null +++ b/test/integration/component/test_eip_elb.py @@ -0,0 +1,1574 @@ +# -*- 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 elastic load balancing and elastic IP +""" +#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 elastic load balancing and elastic IP + """ + + 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 + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test 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', + }, + "netscaler": { + "ipaddress": '192.168.100.213', + "username": 'nsroot', + "password": 'nsroot' + }, + "ostypeid": 'd73dd44c-4244-4848-b20a-906796326749', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'basic' + } + + +class TestEIP(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestEIP, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["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"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + # Spawn an instance + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + networks = Network.list( + cls.api_client, + zoneid=cls.zone.id, + listall=True + ) + if isinstance(networks, list): + # Basic zone has only one network i.e Basic network + cls.guest_network = networks[0] + else: + raise Exception( + "List networks returned empty response for zone: %s" % + cls.zone.id) + + ip_addrs = PublicIPAddress.list( + cls.api_client, + associatednetworkid=cls.guest_network.id, + isstaticnat=True, + account=cls.account.account.name, + domainid=cls.account.account.domainid, + listall=True + ) + if isinstance(ip_addrs, list): + cls.source_nat = ip_addrs[0] + else: + raise Exception( + "No Source NAT IP found for guest network: %s" % + guest_network.id) + cls._cleanup = [ + cls.account, + 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.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.dbclient.close() + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_eip_by_deploying_instance(self): + """Test EIP by deploying an instance + """ + + # Validate the following + # 1. Instance gets an IP from GUEST IP range. + # 2. One IP from EIP pool is taken and configured on NS + # commands to verify on NS: + # show ip, show inat- make sure that output says USIP : ON + # 3. After allowing ingress rule based on source CIDR to the + # respective port, verify that you are able to reach guest with EIP + # 4. user_ip_address.is_system=1, user_ip_address.one_to_one_nat=1 + + self.debug("Fetching public network IP range for public network") + ip_ranges = PublicIpRange.list( + self.apiclient, + zoneid=self.zone.id, + forvirtualnetwork=True + ) + self.assertEqual( + isinstance(ip_ranges, list), + True, + "Public IP range should return a valid range" + ) + # Guest network can have multiple IP ranges. In that case, split IP + # address and then compare the values + for ip_range in ip_ranges: + self.debug("IP range: %s - %s" % ( + ip_range.startip, + ip_range.endip + )) + + start_ip_list = ip_range.startip.split(".") + end_ip_list = ip_range.endip.split(".") + source_nat_list = self.source_nat.ipaddress.split(".") + + flag = True + for i in range(3): + if int(start_ip_list[i]) != int(source_nat_list[i]): + flag = False + + self.assertGreaterEqual( + int(source_nat_list[3]), + int(start_ip_list[3]), + "The NAT should be greater/equal to start IP of guest network" + ) + + self.assertLessEqual( + int(source_nat_list[3]), + int(end_ip_list[3]), + "The NAT should be less/equal to start IP of guest network" + ) + + # Verify listSecurity groups response + security_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(security_groups, list), + True, + "Check for list security groups response" + ) + self.assertEqual( + len(security_groups), + 1, + "Check List Security groups response" + ) + self.debug("List Security groups response: %s" % + str(security_groups)) + + security_group = security_groups[0] + + self.debug( + "Creating Ingress rule to allow SSH on default security group") + + cmd = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() + cmd.domainid = self.account.account.domainid + cmd.account = self.account.account.name + cmd.securitygroupid = security_group.id + cmd.protocol = 'TCP' + cmd.startport = 22 + cmd.endport = 22 + cmd.cidrlist = '0.0.0.0/0' + self.apiclient.authorizeSecurityGroupIngress(cmd) + + try: + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + ssh = self.virtual_machine.get_ssh_client( + ipaddress=self.source_nat.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + # Fetch details from user_ip_address table in database + self.debug( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % self.source_nat.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % self.source_nat.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 1, + "user_ip_address.is_system value should be 1 for static NAT" + ) + + self.assertEqual( + qresult[1], + 1, + "user_ip_address.one_to_one_nat value should be 1 for static NAT" + ) + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.source_nat.ipaddress), + 1, + "One IP from EIP pool should be taken and configured on NS" + ) + + self.debug("Command:show inat") + res = ssh_client.execute("show inat") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("USIP: ON"), + 2, + "User source IP should be enabled for INAT service" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_02_acquire_ip_enable_static_nat(self): + """Test associate new IP and enable static NAT for new IP and the VM + """ + + # Validate the following + # 1. user_ip_address.is_system = 0 & user_ip_address.one_to_one_nat=1 + # 2. releases default EIP whose user_ip_address.is_system=1 + # 3. After allowing ingress rule based on source CIDR to the + # respective port, verify that you are able to reach guest with EIP + # 4. check configuration changes for EIP reflects on NS + # commands to verify on NS : + # * "show ip" + # * "show inat" - make sure that output says USIP : ON + + self.debug("Acquiring new IP for network: %s" % self.guest_network.id) + + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + services=self.services["virtual_machine"] + ) + self.debug("IP address: %s is acquired by network: %s" % ( + public_ip.ipaddress.ipaddress, + self.guest_network.id)) + self.debug("Enabling static NAT for IP Address: %s" % + public_ip.ipaddress.ipaddress) + + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=self.virtual_machine.id + ) + + # Fetch details from user_ip_address table in database + self.debug( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % public_ip.ipaddress.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % public_ip.ipaddress.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 0, + "user_ip_address.is_system value should be 0 for new IP" + ) + + self.assertEqual( + qresult[1], + 1, + "user_ip_address.one_to_one_nat value should be 1 for static NAT" + ) + + self.debug( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % self.source_nat.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % self.source_nat.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 0, + "user_ip_address.is_system value should be 0 old source NAT" + ) + + try: + self.debug("SSH into VM: %s" % public_ip.ipaddress.ipaddress) + ssh = self.virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (public_ip.ipaddress.ipaddress, e) + ) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(public_ip.ipaddress.ipaddress), + 1, + "One IP from EIP pool should be taken and configured on NS" + ) + + self.debug("Command:show inat") + res = ssh_client.execute("show inat") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("USIP: ON"), + 2, + "User source IP should be enabled for INAT service" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_03_disable_static_nat(self): + """Test disable static NAT and release EIP acquired + """ + + # Validate the following + # 1. Disable static NAT. Disables one-to-one NAT and releases EIP + # whose user_ip_address.is_system=0 + # 2. Gets a new ip from EIP pool whose user_ip_address.is_system=1 + # and user_ip_address.one_to_one_nat=1 + # 3. DisassicateIP should mark this EIP whose is_system=0 as free. + # commands to verify on NS : + # * "show ip" + # * "show inat"-make sure that output says USIP : ON + + self.debug( + "Fetching static NAT for VM: %s" % self.virtual_machine.name) + ip_addrs = PublicIPAddress.list( + self.api_client, + associatednetworkid=self.guest_network.id, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "List Public IP address should return valid IP address for network" + ) + static_nat = ip_addrs[0] + self.debug("Static NAT for VM: %s is: %s" % ( + self.virtual_machine.name, + static_nat.ipaddress + )) + + # Fetch details from user_ip_address table in database + self.debug( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 0, + "user_ip_address.is_system value should be 0" + ) + + self.debug("Disassociate Static NAT: %s" % static_nat.ipaddress) + cmd = disassociateIpAddress.disassociateIpAddressCmd() + cmd.id = static_nat.id + self.apiclient.disassociateIpAddress(cmd) + + self.debug("Sleeping - after disassociating static NAT") + time.sleep(self.services["sleep"]) + + # Fetch details from user_ip_address table in database + self.debug( + "select state from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress) + + qresultset = self.dbclient.execute( + "select state from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + "Free", + "Ip should be marked as Free after disassociate IP" + ) + + self.debug( + "Fetching static NAT for VM: %s" % self.virtual_machine.name) + ip_addrs = PublicIPAddress.list( + self.api_client, + associatednetworkid=self.guest_network.id, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "List Public IP address should return valid IP address for network" + ) + static_nat = ip_addrs[0] + self.debug("Static NAT for VM: %s is: %s" % ( + self.virtual_machine.name, + static_nat.ipaddress + )) + + # Fetch details from user_ip_address table in database + self.debug( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system, one_to_one_nat from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 1, + "is_system value should be 1 for automatically assigned IP" + ) + self.assertEqual( + qresult[1], + 1, + "one_to_one_nat value should be 1 for automatically assigned IP" + ) + try: + self.debug("SSH into VM: %s" % static_nat.ipaddress) + ssh = self.virtual_machine.get_ssh_client( + ipaddress=static_nat.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (static_nat.ipaddress, e)) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(static_nat.ipaddress), + 1, + "One IP from EIP pool should be taken and configured on NS" + ) + + self.debug("Command:show inat") + res = ssh_client.execute("show inat") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("USIP: ON"), + 2, + "User source IP should be enabled for INAT service" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_04_disable_static_nat_system(self): + """Test disable static NAT with system = True + """ + + # Validate the following + # 1. Try to disassociate/disable static NAT on EIP where is_system=1 + # 2. This operation should fail with proper error message. + + self.debug( + "Fetching static NAT for VM: %s" % self.virtual_machine.name) + ip_addrs = PublicIPAddress.list( + self.api_client, + associatednetworkid=self.guest_network.id, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "List Public IP address should return valid IP address for network" + ) + static_nat = ip_addrs[0] + self.debug("Static NAT for VM: %s is: %s" % ( + self.virtual_machine.name, + static_nat.ipaddress + )) + + # Fetch details from user_ip_address table in database + self.debug( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 1, + "user_ip_address.is_system value should be 1" + ) + + self.debug("Disassociate Static NAT: %s" % static_nat.ipaddress) + + with self.assertRaises(Exception): + cmd = disassociateIpAddress.disassociateIpAddressCmd() + cmd.id = static_nat.id + apiclient.disassociateIpAddress(cmd) + + self.debug("Disassociate system IP failed") + return + + def test_05_destroy_instance(self): + """Test EIO after destroying instance + """ + + # Validate the following + # 1. Destroy instance. Destroy should result in is_system=0 for EIP + # and EIP should also be marked as free. + # 2. Commands to verify on NS : + # * "show ip" + # * "show inat" - make sure that output says USIP: ON + + self.debug( + "Fetching static NAT for VM: %s" % self.virtual_machine.name) + ip_addrs = PublicIPAddress.list( + self.api_client, + associatednetworkid=self.guest_network.id, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "List Public IP address should return valid IP address for network" + ) + static_nat = ip_addrs[0] + self.debug("Static NAT for VM: %s is: %s" % ( + self.virtual_machine.name, + static_nat.ipaddress + )) + + self.debug("Destroying an instance: %s" % self.virtual_machine.name) + self.virtual_machine.delete(self.apiclient) + self.debug("Destroy instance complete!") + + config = list_configurations( + self.apiclient, + name='expunge.delay' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list configurations response" + ) + exp_delay = config[0] + self.debug("expunge.delay: %s" % exp_delay.value) + + config = list_configurations( + self.apiclient, + name='expunge.interval' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list configurations response" + ) + exp_interval = config[0] + self.debug("expunge.interval: %s" % exp_interval.value) + + # wait for exp_delay+exp_interval - cleans up VM + total_wait = int(exp_interval.value) + int(exp_delay.value) + time.sleep(total_wait) + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id + ) + self.assertEqual( + vms, + None, + "list VM should not return anything after destroy" + ) + # Fetch details from user_ip_address table in database + self.debug( + "select is_system, state from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system, state from user_ip_address where public_ip_address='%s';" \ + % static_nat.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 0, + "user_ip_address.is_system value should be 0" + ) + + self.assertEqual( + qresult[1], + "Free", + "IP should be marked as Free after destroying VM" + ) + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(static_nat.ipaddress), + 0, + "show ip should return nothing after VM destroy" + ) + + self.debug("Command:show inat") + res = ssh_client.execute("show inat") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(static_nat.ipaddress), + 0, + "show inat should return nothing after VM destroy" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestELB(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestELB, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["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"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + # Spawn an instance + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + networks = Network.list( + cls.api_client, + zoneid=cls.zone.id, + listall=True + ) + if isinstance(networks, list): + # Basic zone has only one network i.e Basic network + cls.guest_network = networks[0] + else: + raise Exception( + "List networks returned empty response for zone: %s" % + cls.zone.id) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + accountid=cls.account.account.name, + networkid=cls.guest_network.id, + domainid=cls.account.account.domainid + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) + + cls._cleanup = [ + cls.account, + 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.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.dbclient.close() + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_elb_create(self): + """Test ELB by creating a LB rule + """ + + # Validate the following + # 1. Deploy 2 instances + # 2. Create LB rule to port 22 for the VMs and try to access VMs with + # EIP:port. Make sure that ingress rule is created to allow access + # with universal CIDR (0.0.0.0/0) + # 3. For LB rule IP user_ip_address.is_system=1 + # 4. check configuration changes for EIP reflects on NS + # commands to verify on NS : + # * "show ip" + # * "show lb vserer"-make sure that output says they are all up + # and running and USNIP : ON + + # Verify listSecurity groups response + security_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(security_groups, list), + True, + "Check for list security groups response" + ) + self.assertEqual( + len(security_groups), + 1, + "Check List Security groups response" + ) + self.debug("List Security groups response: %s" % + str(security_groups)) + + security_group = security_groups[0] + + self.debug( + "Creating Ingress rule to allow SSH on default security group") + + cmd = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() + cmd.domainid = self.account.account.domainid + cmd.account = self.account.account.name + cmd.securitygroupid = security_group.id + cmd.protocol = 'TCP' + cmd.startport = 22 + cmd.endport = 22 + cmd.cidrlist = '0.0.0.0/0' + self.apiclient.authorizeSecurityGroupIngress(cmd) + + self.debug( + "Fetching LB IP for account: %s" % self.account.account.name) + ip_addrs = PublicIPAddress.list( + self.api_client, + associatednetworkid=self.guest_network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + forloadbalancing=True, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "List Public IP address should return valid IP address for network" + ) + + lb_ip = ip_addrs[0] + self.debug("LB IP generated for account: %s is: %s" % ( + self.account.account.name, + lb_ip.ipaddress + )) + self.debug("SSHing into VMs using ELB IP: %s" % lb_ip.ipaddress) + try: + ssh_1 = self.vm_1.get_ssh_client(ipaddress=lb_ip.ipaddress) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Result: %s" % result) + + if isinstance(result, list): + res = result[0] + else: + self.fail("hostname retrieval failed!") + + self.assertIn( + res, + [self.vm_1.name, self.vm_2.name], + "SSH should return hostname of one of the VM" + ) + + ssh_2 = self.vm_2.get_ssh_client(ipaddress=lb_ip.ipaddress) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Result: %s" % result) + + if isinstance(result, list): + res = result[0] + else: + self.fail("hostname retrieval failed!") + self.assertIn( + res, + [self.vm_1.name, self.vm_2.name], + "SSH should return hostname of one of the VM" + ) + except Exception as e: + self.fail( + "SSH Access failed for %s: %s" % (self.vm_1.ipaddress, e)) + + # Fetch details from user_ip_address table in database + self.debug( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % lb_ip.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % lb_ip.ipaddress + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 1, + "is_system value should be 1 for system generated LB rule" + ) + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(lb_ip.ipaddress), + 1, + "One IP from EIP pool should be taken and configured on NS" + ) + + self.debug("Command:show lb vserver") + res = ssh_client.execute("show lb vserver") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("State: UP"), + 2, + "User subnet IP should be enabled for LB service" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_02_elb_acquire_and_create(self): + """Test ELB by acquiring IP and then creating a LB rule + """ + + # Validate the following + # 1. Deploy 2 instances + # 2. Create LB rule to port 22 for the VMs and try to access VMs with + # EIP:port. Make sure that ingress rule is created to allow access + # with universal CIDR (0.0.0.0/0) + # 3. For LB rule IP user_ip_address.is_system=0 + # 4. check configuration changes for EIP reflects on NS + # commands to verify on NS : + # * "show ip" + # * "show lb vserer" - make sure that output says they are all up + # and running and USNIP : ON + + self.debug("Acquiring new IP for network: %s" % self.guest_network.id) + + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + services=self.services["virtual_machine"] + ) + self.debug("IP address: %s is acquired by network: %s" % ( + public_ip.ipaddress.ipaddress, + self.guest_network.id)) + + self.debug("Creating LB rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + accountid=self.account.account.name, + ipaddressid=public_ip.ipaddress.id, + networkid=self.guest_network.id, + domainid=self.account.account.domaind + ) + self.debug("Assigning VMs (%s, %s) to LB rule: %s" % (self.vm_1.name, + self.vm_2.name, + lb_rule.name)) + lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) + + self.debug("SSHing into VMs using ELB IP: %s" % + public_ip.ipaddress.ipaddress) + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Result: %s" % result) + + if isinstance(result, list): + res = result[0] + else: + self.fail("hostname retrieval failed!") + self.assertIn( + res, + [self.vm_1.name, self.vm_2.name], + "SSH should return hostname of one of the VM" + ) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Result: %s" % result) + + if isinstance(result, list): + res = result[0] + else: + self.fail("hostname retrieval failed!") + self.assertIn( + res, + [self.vm_1.name, self.vm_2.name], + "SSH should return hostname of one of the VM" + ) + except Exception as e: + self.fail( + "SSH Access failed for %s: %s" % (self.vm_1.ipaddress, e)) + + # Fetch details from user_ip_address table in database + self.debug( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % public_ip.ipaddress.ipaddress) + + qresultset = self.dbclient.execute( + "select is_system from user_ip_address where public_ip_address='%s';" \ + % public_ip.ipaddress.ipaddress) + + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + + self.assertEqual( + qresult[0], + 0, + "is_system value should be 0 for non-system generated LB rule" + ) + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(public_ip.ipaddress.ipaddress), + 1, + "One IP from EIP pool should be taken and configured on NS" + ) + + self.debug("Command:show lb vserver") + res = ssh_client.execute("show lb vserver") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("State: UP"), + 4, + "User subnet IP should be enabled for LB service" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_03_elb_delete_lb_system(self): + """Test delete LB rule generated with public IP with is_system = 1 + """ + + # Validate the following + # 1. Deleting LB rule should release EIP where is_system=1 + # 2. check configuration changes for EIP reflects on NS + # commands to verify on NS: + # * "show ip" + # * "show lb vserer"-make sure that output says they are all up and + # running and USNIP : ON + + self.debug( + "Fetching LB IP for account: %s" % self.account.account.name) + ip_addrs = PublicIPAddress.list( + self.api_client, + associatednetworkid=self.guest_network.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + forloadbalancing=True, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "List Public IP address should return valid IP address for network" + ) + + lb_ip = ip_addrs[0] + self.debug("LB IP generated for account: %s is: %s" % ( + self.account.account.name, + lb_ip.ipaddress + )) + + self.debug("Deleting LB rule: %s" % self.lb_rule.id) + self.lb_rule.delete(self.apiclient) + + config = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list configurations response" + ) + gc_delay = config[0] + self.debug("network.gc.wait: %s" % gc_delay.value) + + config = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list configurations response" + ) + gc_interval = config[0] + self.debug("network.gc.intervall: %s" % gc_interval.value) + + # wait for exp_delay+exp_interval - cleans up VM + total_wait = int(gc_interval.value) + int(gc_delay.value) + time.sleep(total_wait) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(lb_ip.ipaddress), + 1, + "One IP from EIP pool should be taken and configured on NS" + ) + + self.debug("Command:show lb vserver") + res = ssh_client.execute("show lb vserver") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("State: UP"), + 2, + "User subnet IP should be enabled for LB service" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + def test_04_delete_lb_on_eip(self): + """Test delete LB rule generated on EIP + """ + + # Validate the following + # 1. Deleting LB rule won't release EIP where is_system=0 + # 2. disassociateIP must release the above IP + # 3. check configuration changes for EIP reflects on NS + # commands to verify on NS : + # * "show ip" + # * "show lb vserer"-make sure that output says they are all up and + # running and USNIP : ON + + # Fetch details from account_id table in database + self.debug( + "select id from account where account_name='%s';" \ + % self.account.account.name) + + qresultset = self.dbclient.execute( + "select id from account where account_name='%s';" \ + % self.account.account.name) + + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "DB query should return a valid public IP address" + ) + qresult = qresultset[0] + account_id = qresult[0] + # Fetch details from user_ip_address table in database + self.debug( + "select public_ip_address from user_ip_address where is_system=0 and account_id=%s;" \ + % account_id) + + qresultset = self.dbclient.execute( + "select public_ip_address from user_ip_address where is_system=0 and account_id=%s;" \ + % account_id) + + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "DB query should return a valid public IP address" + ) + qresult = qresultset[0] + public_ip = qresult[0] + + self.debug( + "Fetching public IP for account: %s" % self.account.account.name) + ip_addrs = PublicIPAddress.list( + self.api_client, + ipaddress=public_ip, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "List Public IP address should return valid IP address for network" + ) + + lb_ip = ip_addrs[0] + + lb_rules = LoadBalancerRule.list( + self.apiclient, + publicipid=lb_ip.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "Atleast one LB rule must be present for public IP address" + ) + lb_rule = lb_rules[0] + self.debug("Deleting LB rule associated with IP: %s" % public_ip) + + try: + cmd = deleteLoadBalancerRule.deleteLoadBalancerRuleCmd() + cmd.id = lb_rule.id + self.apiclient.deleteLoadBalancerRule(cmd) + except Exception as e: + self.fail("Deleting LB rule failed for IP: %s-%s" % (public_ip, e)) + + config = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list configurations response" + ) + gc_delay = config[0] + self.debug("network.gc.wait: %s" % gc_delay.value) + + config = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list configurations response" + ) + gc_interval = config[0] + self.debug("network.gc.intervall: %s" % gc_interval.value) + + # wait for exp_delay+exp_interval - cleans up VM + total_wait = int(gc_interval.value) + int(gc_delay.value) + time.sleep(total_wait) + + self.debug("LB rule deleted!") + + ip_addrs = PublicIPAddress.list( + self.api_client, + ipaddress=public_ip, + listall=True + ) + self.assertEqual( + isinstance(ip_addrs, list), + True, + "Deleting LB rule should not delete public IP" + ) + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show ip") + res = ssh_client.execute("show ip") + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(public_ip), + 1, + "One IP from EIP pool should be taken and configured on NS" + ) + + self.debug("Command:show lb vserver") + res = ssh_client.execute("show lb vserver") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count("State: UP"), + 2, + "User subnet IP should be enabled for LB service" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return diff --git a/test/integration/component/test_high_availability.py b/test/integration/component/test_high_availability.py index b4ccbafc41a..9e95df1ffc8 100644 --- a/test/integration/component/test_high_availability.py +++ b/test/integration/component/test_high_availability.py @@ -77,7 +77,19 @@ class Services: "publicport": 22, "protocol": 'TCP', }, - "ostypeid": '9958b10f-9e5d-4ef1-908d-a047372d823b', + "templates": { + "displaytext": "Public Template", + "name": "Public template", + "ostypeid": '946b031b-0e10-4f4a-a3fc-d212ae2ea07f', + "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, + "templatefilter": 'self', + }, + "ostypeid": '946b031b-0e10-4f4a-a3fc-d212ae2ea07f', # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 100, @@ -127,14 +139,14 @@ class TestHighAvailability(cloudstackTestCase): ] 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 + @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() @@ -148,15 +160,15 @@ class TestHighAvailability(cloudstackTestCase): 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 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 + @unittest.skip("skipped") def test_01_host_maintenance_mode(self): """Test host maintenance mode """ @@ -255,7 +267,7 @@ class TestHighAvailability(cloudstackTestCase): )) self.debug("Creating PF rule for IP address: %s" % public_ip.ipaddress.ipaddress) - nat_rule= NATRule.create( + nat_rule = NATRule.create( self.apiclient, virtual_machine, self.services["natrule"], @@ -265,6 +277,15 @@ class TestHighAvailability(cloudstackTestCase): self.debug("Creating LB rule on IP with NAT: %s" % public_ip.ipaddress.ipaddress) + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + protocol=self.services["natrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["natrule"]["publicport"], + endport=self.services["natrule"]["publicport"] + ) # Create Load Balancer rule on IP already having NAT rule lb_rule = LoadBalancerRule.create( self.apiclient, @@ -318,7 +339,11 @@ class TestHighAvailability(cloudstackTestCase): vm = vms[0] self.debug("VM 1 state: %s" % vm.state) - if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: if vm.state == "Running": break else: @@ -418,7 +443,53 @@ class TestHighAvailability(cloudstackTestCase): self.debug( "VM state after enabling maintenance on first host: %s" % vm.state) - if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state in [ + "Stopping", + "Stopped", + "Running", + "Starting", + "Migrating" + ]: + 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" + ) + + # 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[1] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in [ + "Stopping", + "Stopped", + "Running", + "Starting", + "Migrating" + ]: if vm.state == "Running": break else: @@ -438,6 +509,7 @@ class TestHighAvailability(cloudstackTestCase): "Running", "Deployed VM should be in Running state" ) + # Spawn an instance on other host virtual_machine_3 = VirtualMachine.create( self.apiclient, @@ -486,6 +558,7 @@ class TestHighAvailability(cloudstackTestCase): 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, @@ -596,13 +669,23 @@ class TestHighAvailability(cloudstackTestCase): )) self.debug("Creating PF rule for IP address: %s" % public_ip.ipaddress.ipaddress) - nat_rule= NATRule.create( + nat_rule = NATRule.create( self.apiclient, virtual_machine, self.services["natrule"], ipaddressid=public_ip.ipaddress.id ) + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + protocol=self.services["natrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["natrule"]["publicport"], + endport=self.services["natrule"]["publicport"] + ) + self.debug("Creating LB rule on IP with NAT: %s" % public_ip.ipaddress.ipaddress) @@ -624,7 +707,7 @@ class TestHighAvailability(cloudstackTestCase): self.fail("SSH Access failed for %s: %s" % \ (virtual_machine.ipaddress, e) ) - # Get the Root disk of VM + # Get the Root disk of VM volumes = list_volumes( self.apiclient, virtualmachineid=virtual_machine.id, @@ -662,6 +745,7 @@ class TestHighAvailability(cloudstackTestCase): 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( @@ -669,7 +753,6 @@ class TestHighAvailability(cloudstackTestCase): snapshot, self.services["templates"] ) - self.cleanup.append(template) self.debug("Created template from snapshot: %s" % template.id) templates = list_templates( @@ -725,7 +808,11 @@ class TestHighAvailability(cloudstackTestCase): vm = vms[0] self.debug("VM 1 state: %s" % vm.state) - if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: if vm.state == "Running": break else: @@ -789,7 +876,7 @@ class TestHighAvailability(cloudstackTestCase): self.apiclient.cancelHostMaintenance(cmd) self.debug("Maintenance mode canceled for host: %s" % first_host) - # Get the Root disk of VM + # Get the Root disk of VM volumes = list_volumes( self.apiclient, virtualmachineid=virtual_machine_2.id, @@ -827,6 +914,7 @@ class TestHighAvailability(cloudstackTestCase): 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( @@ -834,7 +922,6 @@ class TestHighAvailability(cloudstackTestCase): snapshot, self.services["templates"] ) - self.cleanup.append(template) self.debug("Created template from snapshot: %s" % template.id) templates = list_templates( @@ -892,7 +979,49 @@ class TestHighAvailability(cloudstackTestCase): self.debug( "VM state after enabling maintenance on first host: %s" % vm.state) - if vm.state in ["Stopping", "Stopped", "Running", "Starting"]: + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: + 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" + ) + + # 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[1] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: if vm.state == "Running": break else: @@ -912,6 +1041,7 @@ class TestHighAvailability(cloudstackTestCase): "Running", "Deployed VM should be in Running state" ) + # Spawn an instance on other host virtual_machine_3 = VirtualMachine.create( self.apiclient, @@ -945,21 +1075,12 @@ class TestHighAvailability(cloudstackTestCase): "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, diff --git a/test/integration/component/test_network_offering.py b/test/integration/component/test_network_offering.py index b536da11a2d..ddacad1f4c5 100644 --- a/test/integration/component/test_network_offering.py +++ b/test/integration/component/test_network_offering.py @@ -44,7 +44,7 @@ class Services: "name": "Tiny Instance", "displaytext": "Tiny Instance", "cpunumber": 1, - "cpuspeed": 100, # in MHz + "cpuspeed": 100, # in MHz "memory": 64, # In MBs }, "network_offering": { @@ -54,16 +54,16 @@ class Services: "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', "traffictype": 'GUEST', "availability": 'Optional', - "serviceProviderList": { + "serviceProviderList" : { "Dhcp": 'VirtualRouter', "Dns": 'VirtualRouter', "SourceNat": 'VirtualRouter', "PortForwarding": 'VirtualRouter', - "Vpn": 'VirtualRouter', - "Firewall": 'VirtualRouter', - "Lb": 'VirtualRouter', - "UserData": 'VirtualRouter', - "StaticNat": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', }, }, "network_offering_netscaler": { @@ -73,7 +73,7 @@ class Services: "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', "traffictype": 'GUEST', "availability": 'Optional', - "serviceProviderList": { + "serviceProviderList" : { "Dhcp": 'VirtualRouter', "Dns": 'VirtualRouter', "SourceNat": 'VirtualRouter', @@ -115,7 +115,7 @@ class Services: "publicport": 66, "protocol": "TCP" }, - "fw_rule": { + "fw_rule":{ "startport": 1, "endport": 6000, "cidr": '55.55.0.0/11', @@ -137,7 +137,7 @@ class Services: # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, - "mode": 'advanced' + "mode":'advanced' } @@ -240,7 +240,7 @@ class TestNOVirtualRouter(cloudstackTestCase): self.debug("Created n/w offering with ID: %s" % self.network_offering.id) - # Enable Network offering + # Enable Network offering self.network_offering.update(self.apiclient, state='Enabled') # Creating network using the network offering created @@ -252,7 +252,7 @@ class TestNOVirtualRouter(cloudstackTestCase): accountid=self.account.account.name, domainid=self.account.account.domainid, networkofferingid=self.network_offering.id, - zoneid=self.zone.id + zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network.id) @@ -268,6 +268,7 @@ class TestNOVirtualRouter(cloudstackTestCase): networkids=[str(self.network.id)] ) self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=self.network.id, @@ -286,7 +287,9 @@ class TestNOVirtualRouter(cloudstackTestCase): 0, "Length of response from listPublicIp should not be 0" ) + src_nat = src_nat_list[0] + self.debug("Trying to create LB rule on source NAT IP: %s" % src_nat.ipaddress) # Create Load Balancer rule with source NAT @@ -326,7 +329,7 @@ class TestNOVirtualRouter(cloudstackTestCase): ip_with_nat_rule.ipaddress.ipaddress) NATRule.create( self.apiclient, - virtual_machine, + virtual_machine, self.services["natrule"], ipaddressid=ip_with_nat_rule.ipaddress.id ) @@ -478,7 +481,7 @@ class TestNOVirtualRouter(cloudstackTestCase): self.debug("Created n/w offering with ID: %s" % self.network_offering.id) - # Enable Network offering + # Enable Network offering self.network_offering.update(self.apiclient, state='Enabled') # Creating network using the network offering created @@ -490,7 +493,7 @@ class TestNOVirtualRouter(cloudstackTestCase): accountid=self.account.account.name, domainid=self.account.account.domainid, networkofferingid=self.network_offering.id, - zoneid=self.zone.id + zoneid=self.zone.id ) self.debug("Created network with ID: %s" % self.network.id) @@ -506,6 +509,7 @@ class TestNOVirtualRouter(cloudstackTestCase): networkids=[str(self.network.id)] ) self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=self.network.id, @@ -694,7 +698,7 @@ class TestNOVirtualRouter(cloudstackTestCase): vpns = Vpn.list( self.apiclient, publicipid=src_nat.id, - listall=True, + listall=True, ) self.assertEqual( @@ -789,13 +793,14 @@ class TestNOWithNetscaler(cloudstackTestCase): # 5. On an ipaddress that has Lb rules , we should NOT allow firewall # rules to be programmed. # 6. On an ipaddress that has Lb rules , we should NOT allow PF rules - # to be programmed. + # to be programmed. # 7. We should be allowed to program multiple PF rules on the same Ip # address on different public ports. # 8. We should be allowed to program multiple LB rules on the same Ip - # address for different public port ranges. + # address for different public port ranges. # 9. On source NAT ipaddress, we should NOT be allowed to Enable VPN. + # Create a network offering with all virtual router services enabled self.debug( "Creating n/w offering with all services in VR & conserve mode:ON" @@ -837,6 +842,7 @@ class TestNOWithNetscaler(cloudstackTestCase): networkids=[str(self.network.id)] ) self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=self.network.id, @@ -882,7 +888,7 @@ class TestNOWithNetscaler(cloudstackTestCase): ) self.debug("Creating firewall rule on source NAT: %s" % src_nat.ipaddress) - #Create Firewall rule on source NAT + #Create Firewall rule on source NAT fw_rule = FireWallRule.create( self.apiclient, ipaddressid=src_nat.id, @@ -1056,13 +1062,14 @@ class TestNOWithNetscaler(cloudstackTestCase): # 5. On an ipaddress that has Lb rules , we should NOT allow firewall # rules to be programmed. # 6. On an ipaddress that has Lb rules , we should NOT allow PF rules - # to be programmed. + # to be programmed. # 7. We should be allowed to program multiple PF rules on the same Ip # address on different public ports. # 8. We should be allowed to program multiple LB rules on the same Ip - # address for different public port ranges. + # address for different public port ranges. # 9. On source NAT ipaddress, we should be allowed to Enable VPN. + # Create a network offering with all virtual router services enabled self.debug( "Creating n/w offering with all services in VR & conserve mode:ON" @@ -1104,6 +1111,7 @@ class TestNOWithNetscaler(cloudstackTestCase): networkids=[str(self.network.id)] ) self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=self.network.id, @@ -1452,6 +1460,7 @@ class TestNetworkUpgrade(cloudstackTestCase): networkids=[str(self.network.id)] ) self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=self.network.id, @@ -1535,6 +1544,7 @@ class TestNetworkUpgrade(cloudstackTestCase): ) self.cleanup.append(ns_lb_offering) ns_lb_offering.update(self.apiclient, state='Enabled') + #Stop all the VMs associated with network to update cidr self.debug("Stopping the VM: %s" % virtual_machine.name) virtual_machine.stop(self.apiclient) @@ -1549,6 +1559,7 @@ class TestNetworkUpgrade(cloudstackTestCase): ) self.debug("Network upgrade failed!") + self.debug("Deleting LB Rule: %s" % lb_rule.id) lb_rule.delete(self.apiclient) self.debug("LB rule deleted") @@ -1646,6 +1657,7 @@ class TestNetworkUpgrade(cloudstackTestCase): networkids=[str(self.network.id)] ) self.debug("Deployed VM in network: %s" % self.network.id) + src_nat_list = PublicIPAddress.list( self.apiclient, associatednetworkid=self.network.id, @@ -1729,6 +1741,7 @@ class TestNetworkUpgrade(cloudstackTestCase): ) self.cleanup.append(ns_lb_offering) ns_lb_offering.update(self.apiclient, state='Enabled') + #Stop all the VMs associated with network to update cidr self.debug("Stopping the VM: %s" % virtual_machine.name) virtual_machine.stop(self.apiclient) @@ -1743,6 +1756,7 @@ class TestNetworkUpgrade(cloudstackTestCase): ) self.debug("Network upgrade failed!") + self.debug("Deleting LB Rule: %s" % lb_rule.id) lb_rule.delete(self.apiclient) self.debug("LB rule deleted") diff --git a/test/integration/component/test_project_resources.py b/test/integration/component/test_project_resources.py index 624b9846a53..a98f860a67b 100644 --- a/test/integration/component/test_project_resources.py +++ b/test/integration/component/test_project_resources.py @@ -20,6 +20,7 @@ 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: @@ -1311,4 +1312,4 @@ class TestSecurityGroup(cloudstackTestCase): domainid=self.account.account.domainid, securitygroupids=[security_group.id], ) - return \ No newline at end of file + return diff --git a/test/integration/component/test_projects.py b/test/integration/component/test_projects.py index 8dd64ee8a46..fd195436905 100644 --- a/test/integration/component/test_projects.py +++ b/test/integration/component/test_projects.py @@ -1806,4 +1806,4 @@ class TestProjectSuspendActivate(cloudstackTestCase): 'Running', "VM should be in Running state after project activation" ) - return \ No newline at end of file + return diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index 9dea37f2ac0..c7a0c6c8c5b 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -15,6 +15,7 @@ """ #Import Local Modules import marvin +from marvin.cloudstackTestCase import * from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * diff --git a/test/integration/component/test_routers.py b/test/integration/component/test_routers.py index 05792336d69..a1bdb166ee8 100644 --- a/test/integration/component/test_routers.py +++ b/test/integration/component/test_routers.py @@ -17,10 +17,10 @@ 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 * +from marvin.remoteSSHClient import remoteSSHClient #Import System modules import time @@ -219,7 +219,7 @@ class TestRouterServices(cloudstackTestCase): True, "Check for list networks response return valid data" ) - + self.assertNotEqual( len(networks), 0, @@ -228,7 +228,7 @@ class TestRouterServices(cloudstackTestCase): for network in networks: self.assertIn( network.state, - ['Implemented','Allocated'], + ['Implemented', 'Allocated'], "Check list network response for network state" ) self.debug("Network ID: %s & Network state: %s" % ( @@ -371,7 +371,7 @@ class TestRouterServices(cloudstackTestCase): for network in networks: self.assertIn( network.state, - ['Implemented','Allocated'], + ['Implemented', 'Allocated'], "Check list network response for network state" ) self.debug("Network ID: %s & Network state: %s" % ( @@ -486,7 +486,7 @@ class TestRouterServices(cloudstackTestCase): serviceofferingid=self.service_offering.id ) self.debug("Deployed a VM with ID: %s" % vm.id) - + virtual_machines = list_virtual_machines( self.apiclient, id=vm.id, @@ -499,7 +499,7 @@ class TestRouterServices(cloudstackTestCase): True, "Check for list virtual machines response return valid data" ) - + self.assertNotEqual( len(virtual_machines), 0, @@ -524,7 +524,7 @@ class TestRouterServices(cloudstackTestCase): True, "Check for list routers response return valid data" ) - + self.assertNotEqual( len(routers), 0, @@ -556,7 +556,7 @@ class TestRouterServices(cloudstackTestCase): True, "Check for list VMs response return valid data" ) - + self.assertNotEqual( len(virtual_machines), 0, @@ -678,7 +678,7 @@ class TestRouterStopCreatePF(cloudstackTestCase): router = routers[0] self.debug("Stopping router ID: %s" % router.id) - + #Stop the router cmd = stopRouter.stopRouterCmd() cmd.id = router.id @@ -715,6 +715,16 @@ class TestRouterStopCreatePF(cloudstackTestCase): ) public_ip = public_ips[0] + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=public_ip.id, + protocol=self.services["natrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["natrule"]["publicport"], + endport=self.services["natrule"]["publicport"] + ) + self.debug("Creating NAT rule for VM ID: %s" % self.vm_1.id) #Create NAT rule nat_rule = NATRule.create( @@ -766,7 +776,7 @@ class TestRouterStopCreatePF(cloudstackTestCase): try: self.debug("SSH into VM with ID: %s" % nat_rule.ipaddress) - + self.vm_1.ssh_port = nat_rule.publicport self.vm_1.get_ssh_client(nat_rule.ipaddress) except Exception as e: @@ -864,7 +874,7 @@ class TestRouterStopCreateLB(cloudstackTestCase): True, "Check for list routers response return valid data" ) - + self.assertNotEqual( len(routers), 0, @@ -908,6 +918,16 @@ class TestRouterStopCreateLB(cloudstackTestCase): "Check for list public IPs response return valid data" ) public_ip = public_ips[0] + + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=public_ip.id, + protocol=self.services["lbrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["lbrule"]["publicport"], + endport=self.services["lbrule"]["publicport"] + ) self.debug("Creating LB rule for public IP: %s" % public_ip.id) #Create Load Balancer rule and assign VMs to rule lb_rule = LoadBalancerRule.create( @@ -1071,7 +1091,7 @@ class TestRouterStopCreateFW(cloudstackTestCase): ) router = routers[0] - + self.debug("Stopping the router: %s" % router.id) #Stop the router cmd = stopRouter.stopRouterCmd() @@ -1135,7 +1155,7 @@ class TestRouterStopCreateFW(cloudstackTestCase): True, "Check for list routers response return valid data" ) - + router = routers[0] self.assertEqual( @@ -1153,7 +1173,7 @@ class TestRouterStopCreateFW(cloudstackTestCase): True, "Check for list FW rules response return valid data" ) - + self.assertEqual( fw_rules[0].state, 'Active', diff --git a/test/integration/component/test_security_groups.py b/test/integration/component/test_security_groups.py index 60cab0ee947..68074536f9e 100644 --- a/test/integration/component/test_security_groups.py +++ b/test/integration/component/test_security_groups.py @@ -18,10 +18,10 @@ 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 * +from marvin.remoteSSHClient import remoteSSHClient #Import System modules import time @@ -1625,4 +1625,4 @@ class TestIngressRule(cloudstackTestCase): self.fail("SSH access failed for ingress rule ID: %s" \ % ingress_rule["id"] ) - return \ No newline at end of file + return diff --git a/test/integration/component/test_snapshots.py b/test/integration/component/test_snapshots.py index 2dd6d90b684..05585b5ae68 100644 --- a/test/integration/component/test_snapshots.py +++ b/test/integration/component/test_snapshots.py @@ -860,7 +860,7 @@ class TestSnapshotDetachedDisk(cloudstackTestCase): self.services["sub_lvl_dir2"], self.services["random_data"] ), - "sync", + "sync", ] for c in cmds: self.debug(ssh_client.execute(c)) diff --git a/test/integration/component/test_templates.py b/test/integration/component/test_templates.py index 82d85441855..afad16c04b7 100644 --- a/test/integration/component/test_templates.py +++ b/test/integration/component/test_templates.py @@ -20,6 +20,7 @@ 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 urllib from random import random #Import System modules diff --git a/test/integration/component/test_volumes.py b/test/integration/component/test_volumes.py index 33c6b1ce4c0..4caee7d170f 100644 --- a/test/integration/component/test_volumes.py +++ b/test/integration/component/test_volumes.py @@ -743,7 +743,7 @@ class TestAttachVolumeISO(cloudstackTestCase): iso.id, self.account.account.name )) - self.cleanup.append(iso) + try: self.debug("Downloading ISO with ID: %s" % iso.id) iso.download(self.apiclient) diff --git a/test/integration/lib/base.py b/test/integration/lib/base.py index 11f01d2a607..1f8a2f851c0 100644 --- a/test/integration/lib/base.py +++ b/test/integration/lib/base.py @@ -9,7 +9,7 @@ # 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 """ Base class for all Cloudstack resources @@ -23,7 +23,6 @@ from marvin.cloudstackAPI import * import time import hashlib import base64 -import types class Domain: @@ -174,9 +173,9 @@ class VirtualMachine: domainid=None, networkids=None, serviceofferingid=None, securitygroupids=None, projectid=None, mode='basic'): """Create the instance""" - + cmd = deployVirtualMachine.deployVirtualMachineCmd() - + if serviceofferingid: cmd.serviceofferingid = serviceofferingid elif "serviceoffering" in services: @@ -207,21 +206,21 @@ class VirtualMachine: if "diskoffering" in services: cmd.diskofferingid = services["diskoffering"] - + if securitygroupids: cmd.securitygroupids = [str(sg_id) for sg_id in securitygroupids] - + if "userdata" in services: cmd.userdata = base64.b64encode(services["userdata"]) - + if projectid: cmd.projectid = projectid virtual_machine = apiclient.deployVirtualMachine(cmd) - + # VM should be in Running state after deploy timeout = 10 - while True: + while True: vm_status = VirtualMachine.list( apiclient, id=virtual_machine.id @@ -231,12 +230,12 @@ class VirtualMachine: break elif timeout == 0: raise Exception( - "TimeOutException: Failed to start VM (ID: %s)" % + "TimeOutException: Failed to start VM (ID: %s)" % virtual_machine.id) - + time.sleep(10) - timeout = timeout -1 - + timeout = timeout - 1 + if mode.lower() == 'advanced': public_ip = PublicIPAddress.create( apiclient, @@ -245,6 +244,14 @@ class VirtualMachine: virtual_machine.domainid, services ) + fw_rule = FireWallRule.create( + apiclient, + ipaddressid=public_ip.ipaddress.id, + protocol='TCP', + cidrlist=['0.0.0.0/0'], + startport=22, + endport=22 + ) nat_rule = NATRule.create( apiclient, virtual_machine, @@ -329,6 +336,20 @@ class VirtualMachine: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listVirtualMachines(cmd)) + def resetPassword(self, apiclient): + """Resets VM password if VM created using password enabled template""" + + cmd = resetPasswordForVirtualMachine.resetPasswordForVirtualMachineCmd() + cmd.id = self.id + try: + response = apiclient.resetPasswordForVirtualMachine(cmd) + print response + except Exception as e: + raise Exception("Reset Password failed! - %s" % e) + print type(response) + if isinstance(response, list): + return response[0].password + class Volume: """Manage Volume Lifecycle @@ -337,8 +358,8 @@ class Volume: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, zoneid=None, account=None, domainid=None, - diskofferingid=None, projectid=None): + def create(cls, apiclient, services, zoneid=None, account=None, + domainid=None, diskofferingid=None, projectid=None): """Create Volume""" cmd = createVolume.createVolumeCmd() cmd.name = services["diskname"] @@ -368,24 +389,25 @@ class Volume: return Volume(apiclient.createVolume(cmd).__dict__) @classmethod - def create_custom_disk(cls, apiclient, services, account=None, domainid=None): + def create_custom_disk(cls, apiclient, services, + account=None, domainid=None): """Create Volume from Custom disk offering""" cmd = createVolume.createVolumeCmd() cmd.name = services["diskname"] cmd.diskofferingid = services["customdiskofferingid"] cmd.size = services["customdisksize"] cmd.zoneid = services["zoneid"] - + if account: cmd.account = account else: cmd.account = services["account"] - + if domainid: cmd.domainid = domainid else: cmd.domainid = services["domainid"] - + return Volume(apiclient.createVolume(cmd).__dict__) @classmethod @@ -429,7 +451,8 @@ class Snapshot: self.__dict__.update(items) @classmethod - def create(cls, apiclient, volume_id, account=None, domainid=None, projectid=None): + def create(cls, apiclient, volume_id, account=None, + domainid=None, projectid=None): """Create Snapshot""" cmd = createSnapshot.createSnapshotCmd() cmd.volumeid = volume_id @@ -476,7 +499,8 @@ class Template: cmd.ispublic = services["ispublic"] if "ispublic" in services else False cmd.isextractable = services["isextractable"] if "isextractable" in services else False cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False - + cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False + if volumeid: cmd.volumeid = volumeid @@ -491,9 +515,10 @@ class Template: return Template(apiclient.createTemplate(cmd).__dict__) @classmethod - def register(cls, apiclient, services, zoneid=None, account=None, domainid=None): + def register(cls, apiclient, services, zoneid=None, + account=None, domainid=None): """Create template from URL""" - + #Create template from Virtual machine and Volume ID cmd = registerTemplate.registerTemplateCmd() cmd.displaytext = services["displaytext"] @@ -502,7 +527,7 @@ class Template: cmd.hypervisor = services["hypervisor"] cmd.ostypeid = services["ostypeid"] cmd.url = services["url"] - + if zoneid: cmd.zoneid = zoneid else: @@ -511,27 +536,29 @@ class Template: cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False cmd.ispublic = services["ispublic"] if "ispublic" in services else False cmd.isextractable = services["isextractable"] if "isextractable" in services else False + cmd.passwordenabled = services["passwordenabled"] if "passwordenabled" in services else False if account: cmd.account = account if domainid: cmd.domainid = domainid - + # Register Template template = apiclient.registerTemplate(cmd) - + if isinstance(template, list): return Template(template[0].__dict__) @classmethod - def create_from_snapshot(cls, apiclient, snapshot, services, random_name=True): + def create_from_snapshot(cls, apiclient, snapshot, services, + random_name=True): """Create Template from snapshot""" #Create template from Virtual machine and Snapshot ID cmd = createTemplate.createTemplateCmd() cmd.displaytext = services["displaytext"] cmd.name = "-".join([ - services["name"], + services["name"], random_gen() ]) if random_name else services["name"] cmd.ostypeid = services["ostypeid"] @@ -540,7 +567,7 @@ class Template: def delete(self, apiclient): """Delete Template""" - + cmd = deleteTemplate.deleteTemplateCmd() cmd.id = self.id apiclient.deleteTemplate(cmd) @@ -549,7 +576,7 @@ class Template: """Download Template""" #Sleep to ensure template is in proper state before download time.sleep(interval) - + while True: template_response = Template.list( apiclient, @@ -558,15 +585,15 @@ class Template: templatefilter='self' ) if isinstance(template_response, list): - + template = template_response[0] # If template is ready, # template.status = Download Complete # Downloading - x% Downloaded - # Error - Any other string + # Error - Any other string if template.status == 'Download Complete': break - + elif 'Downloaded' in template.status: time.sleep(interval) @@ -575,7 +602,7 @@ class Template: elif timeout == 0: break - + else: time.sleep(interval) timeout = timeout - 1 @@ -583,7 +610,7 @@ class Template: def updatePermissions(self, apiclient, **kwargs): """Updates the template permissions""" - + cmd = updateTemplatePermissions.updateTemplatePermissionsCmd() cmd.id = self.id [setattr(cmd, k, v) for k, v in kwargs.items()] @@ -605,7 +632,7 @@ class Iso: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, account=None, domainid=None, + def create(cls, apiclient, services, account=None, domainid=None, projectid=None): """Create an ISO""" #Create ISO from URL @@ -615,7 +642,7 @@ class Iso: cmd.ostypeid = services["ostypeid"] cmd.url = services["url"] cmd.zoneid = services["zoneid"] - + if "isextractable" in services: cmd.isextractable = services["isextractable"] if "isfeatured" in services: @@ -631,7 +658,7 @@ class Iso: cmd.projectid = projectid # Register ISO iso = apiclient.registerIso(cmd) - + if iso: return Iso(iso[0].__dict__) @@ -651,17 +678,18 @@ class Iso: cmd = listIsos.listIsosCmd() cmd.id = self.id iso_response = apiclient.listIsos(cmd) - - if isinstance(iso_response, list): + + if isinstance(iso_response, list): response = iso_response[0] # Again initialize timeout to avoid listISO failure timeout = 5 - + print response.status # Check whether download is in progress(for Ex:10% Downloaded) # or ISO is 'Successfully Installed' if response.status == 'Successfully Installed': return - elif 'Downloaded' not in response.status: + elif 'Downloaded' not in response.status and \ + 'Installing' not in response.status: raise Exception("ErrorInDownload") elif timeout == 0: @@ -690,15 +718,15 @@ class PublicIPAddress: services=None, networkid=None, projectid=None): """Associate Public IP address""" cmd = associateIpAddress.associateIpAddressCmd() - + if accountid: cmd.account = accountid - + if zoneid: cmd.zoneid = zoneid elif "zoneid" in services: services["zoneid"] - + if domainid: cmd.domainid = domainid elif "domainid" in services: @@ -706,7 +734,7 @@ class PublicIPAddress: if networkid: cmd.networkid = networkid - + if projectid: cmd.projectid = projectid return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__) @@ -726,6 +754,7 @@ class PublicIPAddress: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listPublicIpAddresses(cmd)) + class NATRule: """Manage port forwarding rule""" @@ -747,10 +776,10 @@ class NATRule: cmd.publicport = services["publicport"] cmd.protocol = services["protocol"] cmd.virtualmachineid = virtual_machine.id - + if projectid: cmd.projectid = projectid - + return NATRule(apiclient.createPortForwardingRule(cmd).__dict__) def delete(self, apiclient): @@ -767,7 +796,7 @@ class NATRule: cmd = listPortForwardingRules.listPortForwardingRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listPortForwardingRules(cmd)) - + class StaticNATRule: """Manage Static NAT rule""" @@ -778,22 +807,22 @@ class StaticNATRule: @classmethod def create(cls, apiclient, services, ipaddressid=None): """Creates static ip forwarding rule""" - + cmd = createIpForwardingRule.createIpForwardingRuleCmd() cmd.protocol = services["protocol"] cmd.startport = services["startport"] - + if "endport" in services: cmd.endport = services["endport"] - + if "cidrlist" in services: cmd.cidrlist = services["cidrlist"] - + if ipaddressid: cmd.ipaddressid = ipaddressid elif "ipaddressid" in services: cmd.ipaddressid = services["ipaddressid"] - + return StaticNATRule(apiclient.createIpForwardingRule(cmd).__dict__) def delete(self, apiclient): @@ -810,26 +839,26 @@ class StaticNATRule: cmd = listIpForwardingRules.listIpForwardingRulesCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listIpForwardingRules(cmd)) - + @classmethod def enable(cls, apiclient, ipaddressid, virtualmachineid): """Enables Static NAT rule""" - + cmd = enableStaticNat.enableStaticNatCmd() cmd.ipaddressid = ipaddressid cmd.virtualmachineid = virtualmachineid apiclient.enableStaticNat(cmd) return - + @classmethod def disable(cls, apiclient, ipaddressid, virtualmachineid): """Disables Static NAT rule""" - + cmd = disableStaticNat.disableStaticNatCmd() cmd.ipaddressid = ipaddressid apiclient.disableStaticNat(cmd) return - + class FireWallRule: """Manage Firewall rule""" @@ -910,6 +939,7 @@ class ServiceOffering: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listServiceOfferings(cmd)) + class DiskOffering: """Manage disk offerings cycle""" @@ -957,7 +987,7 @@ class NetworkOffering: @classmethod def create(cls, apiclient, services, **kwargs): """Create network offering""" - + cmd = createNetworkOffering.createNetworkOfferingCmd() cmd.displaytext = "-".join([services["displaytext"], random_gen()]) cmd.name = "-".join([services["name"], random_gen()]) @@ -968,12 +998,25 @@ class NetworkOffering: cmd.serviceProviderList = [] for service, provider in services["serviceProviderList"].items(): cmd.serviceProviderList.append({ - 'service' : service, + 'service': service, 'provider': provider }) + if "servicecapabilitylist" in services: + cmd.servicecapabilitylist = [] + for service, capability in services["servicecapabilitylist"].items(): + for ctype, value in capability.items(): + cmd.servicecapabilitylist.append({ + 'service': service, + 'capabilitytype': ctype, + 'capabilityvalue': value + }) + if "specifyVlan" in services: + cmd.specifyVlan = services["specifyVlan"] + if "specifyIpRanges" in services: + cmd.specifyIpRanges = services["specifyIpRanges"] [setattr(cmd, k, v) for k, v in kwargs.items()] - + return NetworkOffering(apiclient.createNetworkOffering(cmd).__dict__) def delete(self, apiclient): @@ -1040,23 +1083,30 @@ class LoadBalancerRule: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, ipaddressid, accountid=None, - networkid=None, projectid=None): + def create(cls, apiclient, services, ipaddressid=None, accountid=None, + networkid=None, projectid=None, domainid=None): """Create Load balancing Rule""" cmd = createLoadBalancerRule.createLoadBalancerRuleCmd() - cmd.publicipid = ipaddressid or services["ipaddressid"] + + if ipaddressid: + cmd.publicipid = ipaddressid + elif "ipaddressid" in services: + cmd.publicipid = services["ipaddressid"] if accountid: cmd.account = accountid elif "account" in services: cmd.account = services["account"] + if domainid: + cmd.domainid = domainid + cmd.name = services["name"] cmd.algorithm = services["alg"] cmd.privateport = services["privateport"] cmd.publicport = services["publicport"] - + if "openfirewall" in services: cmd.openfirewall = services["openfirewall"] @@ -1090,6 +1140,19 @@ class LoadBalancerRule: apiclient.removeFromLoadBalancerRule(cmd) return + def update(self, apiclient, algorithm=None, description=None, name=None): + """Updates the load balancing rule""" + cmd = updateLoadBalancerRule.updateLoadBalancerRuleCmd() + cmd.id = self.id + if algorithm: + cmd.algorithm = algorithm + if description: + cmd.description = description + if name: + cmd.name = name + + return apiclient.updateLoadBalancerRule(cmd) + @classmethod def list(cls, apiclient, **kwargs): """List all Load balancing rules matching criteria""" @@ -1111,12 +1174,12 @@ class Cluster: cmd = addCluster.addClusterCmd() cmd.clustertype = services["clustertype"] cmd.hypervisor = services["hypervisor"] - + if zoneid: cmd.zoneid = zoneid else: cmd.zoneid = services["zoneid"] - + if podid: cmd.podid = podid else: @@ -1158,17 +1221,17 @@ class Host: @classmethod def create(cls, apiclient, cluster, services, zoneid=None, podid=None): """Create Host in cluster""" - + cmd = addHost.addHostCmd() cmd.hypervisor = services["hypervisor"] cmd.url = services["url"] cmd.clusterid = cluster.id - + if zoneid: cmd.zoneid = zoneid else: cmd.zoneid = services["zoneid"] - + if podid: cmd.podid = podid else: @@ -1180,10 +1243,10 @@ class Host: cmd.username = services["username"] if "password" in services: cmd.password = services["password"] - + # Add host host = apiclient.addHost(cmd) - + if isinstance(host, list): return Host(host[0].__dict__) @@ -1202,7 +1265,7 @@ class Host: def enableMaintenance(self, apiclient): """enables maintainance mode Host""" - + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() cmd.id = self.id return apiclient.prepareHostForMaintenance(cmd) @@ -1223,23 +1286,24 @@ class StoragePool: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, clusterid=None, zoneid=None, podid=None): + def create(cls, apiclient, services, clusterid=None, + zoneid=None, podid=None): """Create Storage pool (Primary Storage)""" cmd = createStoragePool.createStoragePoolCmd() cmd.name = services["name"] - + if podid: cmd.podid = podid else: cmd.podid = services["podid"] - + cmd.url = services["url"] if clusterid: cmd.clusterid = clusterid elif "clusterid" in services: cmd.clusterid = services["clusterid"] - + if zoneid: cmd.zoneid = zoneid else: @@ -1262,7 +1326,7 @@ class StoragePool: def enableMaintenance(self, apiclient): """enables maintainance mode Storage pool""" - + cmd = enableStorageMaintenance.enableStorageMaintenanceCmd() cmd.id = self.id return apiclient.enableStorageMaintenance(cmd) @@ -1283,23 +1347,23 @@ class Network: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, accountid=None, domainid=None, + def create(cls, apiclient, services, accountid=None, domainid=None, networkofferingid=None, projectid=None, zoneid=None): """Create Network for account""" cmd = createNetwork.createNetworkCmd() cmd.name = services["name"] cmd.displaytext = services["displaytext"] - + if networkofferingid: cmd.networkofferingid = networkofferingid elif "networkoffering" in services: cmd.networkofferingid = services["networkoffering"] - + if zoneid: cmd.zoneid = zoneid elif "zoneid" in services: cmd.zoneid = services["zoneid"] - + if "gateway" in services: cmd.gateway = services["gateway"] if "netmask" in services: @@ -1312,7 +1376,7 @@ class Network: cmd.vlan = services["vlan"] if "acltype" in services: cmd.acltype = services["acltype"] - + if accountid: cmd.account = accountid if domainid: @@ -1353,7 +1417,7 @@ class Vpn: self.__dict__.update(items) @classmethod - def create(cls, apiclient, publicipid, account=None, domainid=None, + def create(cls, apiclient, publicipid, account=None, domainid=None, projectid=None): """Create VPN for Public IP address""" cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd() @@ -1455,13 +1519,12 @@ class Zone: def update(self, apiclient, **kwargs): """Update the zone""" - + cmd = updateZone.updateZoneCmd() cmd.id = self.id [setattr(cmd, k, v) for k, v in kwargs.items()] return apiclient.updateZone(cmd) - - + @classmethod def list(cls, apiclient, **kwargs): """List all Zones matching criteria""" @@ -1515,7 +1578,7 @@ class PublicIpRange: @classmethod def create(cls, apiclient, services): """Create VlanIpRange""" - + cmd = createVlanIpRange.createVlanIpRangeCmd() cmd.gateway = services["gateway"] cmd.netmask = services["netmask"] @@ -1566,7 +1629,7 @@ class SecondaryStorage: cmd = deleteHost.deleteHostCmd() cmd.id = self.id apiclient.deleteHost(cmd) - + class PhysicalNetwork: """Manage physical network storage""" @@ -1594,20 +1657,28 @@ class PhysicalNetwork: def update(self, apiclient, **kwargs): """Update Physical network state""" - + cmd = updatePhysicalNetwork.updatePhysicalNetworkCmd() cmd.id = self.id [setattr(cmd, k, v) for k, v in kwargs.items()] return apiclient.updatePhysicalNetwork(cmd) - + def addTrafficType(self, apiclient, type): """Add Traffic type to Physical network""" - + cmd = addTrafficType.addTrafficTypeCmd() cmd.physicalnetworkid = self.id cmd.traffictype = type return apiclient.addTrafficType(cmd) + @classmethod + def list(cls, apiclient, **kwargs): + """Lists all physical networks""" + + cmd = listPhysicalNetworks.listPhysicalNetworksCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listPhysicalNetworks(cmd)) + class SecurityGroup: """Manage Security Groups""" @@ -1624,9 +1695,9 @@ class SecurityGroup: if account: cmd.account = account if domainid: - cmd.domainid=domainid + cmd.domainid = domainid if description: - cmd.description=description + cmd.description = description if projectid: cmd.projectid = projectid @@ -1638,79 +1709,79 @@ class SecurityGroup: cmd = deleteSecurityGroup.deleteSecurityGroupCmd() cmd.id = self.id apiclient.deleteSecurityGroup(cmd) - + def authorize(self, apiclient, services, account=None, domainid=None, projectid=None): """Authorize Ingress Rule""" - - cmd=authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() - + + cmd = authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() + if domainid: cmd.domainid = domainid if account: cmd.account = account if projectid: - cmd.projectid = projectid - cmd.securitygroupid=self.id - cmd.protocol=services["protocol"] - + cmd.projectid = projectid + cmd.securitygroupid = self.id + cmd.protocol = services["protocol"] + if services["protocol"] == 'ICMP': cmd.icmptype = -1 cmd.icmpcode = -1 else: cmd.startport = services["startport"] cmd.endport = services["endport"] - + cmd.cidrlist = services["cidrlist"] return (apiclient.authorizeSecurityGroupIngress(cmd).__dict__) - + def revoke(self, apiclient, id): """Revoke ingress rule""" - - cmd=revokeSecurityGroupIngress.revokeSecurityGroupIngressCmd() - cmd.id=id + + cmd = revokeSecurityGroupIngress.revokeSecurityGroupIngressCmd() + cmd.id = id return apiclient.revokeSecurityGroupIngress(cmd) def authorizeEgress(self, apiclient, services, account=None, domainid=None, - projectid=None, user_secgrp_list = {}): + projectid=None, user_secgrp_list={}): """Authorize Egress Rule""" - - cmd=authorizeSecurityGroupEgress.authorizeSecurityGroupEgressCmd() - + + cmd = authorizeSecurityGroupEgress.authorizeSecurityGroupEgressCmd() + if domainid: cmd.domainid = domainid if account: cmd.account = account if projectid: - cmd.projectid = projectid - cmd.securitygroupid=self.id - cmd.protocol=services["protocol"] - + cmd.projectid = projectid + cmd.securitygroupid = self.id + cmd.protocol = services["protocol"] + if services["protocol"] == 'ICMP': cmd.icmptype = -1 cmd.icmpcode = -1 else: cmd.startport = services["startport"] cmd.endport = services["endport"] - + cmd.cidrlist = services["cidrlist"] - + cmd.usersecuritygrouplist = [] for account, group in user_secgrp_list.items(): cmd.usersecuritygrouplist.append({ - 'account' : account, + 'account': account, 'group': group }) return (apiclient.authorizeSecurityGroupEgress(cmd).__dict__) - + def revokeEgress(self, apiclient, id): """Revoke Egress rule""" - - cmd=revokeSecurityGroupEgress.revokeSecurityGroupEgressCmd() - cmd.id=id + + cmd = revokeSecurityGroupEgress.revokeSecurityGroupEgressCmd() + cmd.id = id return apiclient.revokeSecurityGroupEgress(cmd) @classmethod @@ -1720,7 +1791,8 @@ class SecurityGroup: cmd = listSecurityGroups.listSecurityGroupsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listSecurityGroups(cmd)) - + + class Project: """Manage Project life cycle""" @@ -1730,7 +1802,7 @@ class Project: @classmethod def create(cls, apiclient, services, account=None, domainid=None): """Create project""" - + cmd = createProject.createProjectCmd() cmd.displaytext = services["displaytext"] cmd.name = "-".join([services["name"], random_gen()]) @@ -1740,17 +1812,17 @@ class Project: cmd.domainid = domainid return Project(apiclient.createProject(cmd).__dict__) - + def delete(self, apiclient): """Delete Project""" cmd = deleteProject.deleteProjectCmd() cmd.id = self.id apiclient.deleteProject(cmd) - + def update(self, apiclient, **kwargs): """Updates the project""" - + cmd = updateProject.updateProjectCmd() cmd.id = self.id [setattr(cmd, k, v) for k, v in kwargs.items()] @@ -1758,21 +1830,21 @@ class Project: def activate(self, apiclient): """Activates the suspended project""" - + cmd = activateProject.activateProjectCmd() cmd.id = self.id return apiclient.activateProject(cmd) - + def suspend(self, apiclient): """Suspend the active project""" - + cmd = suspendProject.suspendProjectCmd() cmd.id = self.id return apiclient.suspendProject(cmd) def addAccount(self, apiclient, account=None, email=None): """Add account to project""" - + cmd = addAccountToProject.addAccountToProjectCmd() cmd.projectid = self.id if account: @@ -1783,7 +1855,7 @@ class Project: def deleteAccount(self, apiclient, account): """Delete account from project""" - + cmd = deleteAccountFromProject.deleteAccountFromProjectCmd() cmd.projectid = self.id cmd.account = account @@ -1805,16 +1877,17 @@ class Project: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listProjects(cmd)) + class ProjectInvitation: """Manage project invitations""" def __init__(self, items): self.__dict__.update(items) - + @classmethod def update(cls, apiclient, projectid, accept, account=None, token=None): """Updates the project invitation for that account""" - + cmd = updateProjectInvitation.updateProjectInvitationCmd() cmd.projectid = projectid cmd.accept = accept @@ -1822,20 +1895,20 @@ class ProjectInvitation: cmd.account = account if token: cmd.token = token - + return (apiclient.updateProjectInvitation(cmd).__dict__) - + def delete(self, apiclient, id): """Deletes the project invitation""" - + cmd = deleteProjectInvitation.deleteProjectInvitationCmd() cmd.id = id return apiclient.deleteProjectInvitation(cmd) - + @classmethod def list(cls, apiclient, **kwargs): """Lists project invitations""" - + cmd = listProjectInvitations.listProjectInvitationsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listProjectInvitations(cmd)) @@ -1843,20 +1916,132 @@ class ProjectInvitation: class Configurations: """Manage Configuration""" - + @classmethod def update(cls, apiclient, name, value=None): """Updates the specified configuration""" - + cmd = updateConfiguration.updateConfigurationCmd() cmd.name = name cmd.value = value apiclient.updateConfiguration(cmd) - + @classmethod def list(cls, apiclient, **kwargs): """Lists configurations""" - + cmd = listConfigurations.listConfigurationsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listConfigurations(cmd)) + + +class NetScaler: + """Manage external netscaler device""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def add(cls, apiclient, services, physicalnetworkid, username=None, password=None): + """Add external netscaler device to cloudstack""" + + cmd = addNetscalerLoadBalancer.addNetscalerLoadBalancerCmd() + cmd.physicalnetworkid = physicalnetworkid + if username: + cmd.username = username + else: + cmd.username = services["username"] + + if password: + cmd.password = password + else: + cmd.password = services["password"] + + cmd.networkdevicetype = services["networkdevicetype"] + + # Generate the URL + url = 'https://' + str(services["ipaddress"]) + '?' + url = url + 'publicinterface=' + str(services["publicinterface"]) + '&' + url = url + 'privateinterface=' + str(services["privateinterface"]) + '&' + url = url + 'numretries=' + str(services["numretries"]) + '&' + + if not services["lbdevicededicated"] and "lbdevicecapacity" in services: + url = url + 'lbdevicecapacity=' + str(services["lbdevicecapacity"]) + '&' + + url = url + 'lbdevicededicated=' + str(services["lbdevicededicated"]) + + cmd.url = url + return NetScaler(apiclient.addNetscalerLoadBalancer(cmd).__dict__) + + def delete(self, apiclient): + """Deletes a netscaler device from CloudStack""" + + cmd = deleteNetscalerLoadBalancer.deleteNetscalerLoadBalancerCmd() + cmd.lbdeviceid = self.lbdeviceid + apiclient.deleteNetscalerLoadBalancer(cmd) + return + + def configure(self, apiclient, **kwargs): + """List already registered netscaler devices""" + + cmd = configureNetscalerLoadBalancer.configureNetscalerLoadBalancerCmd() + cmd.lbdeviceid = self.lbdeviceid + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.configureNetscalerLoadBalancer(cmd)) + + @classmethod + def list(cls, apiclient, **kwargs): + """List already registered netscaler devices""" + + cmd = listNetscalerLoadBalancers.listNetscalerLoadBalancersCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listNetscalerLoadBalancers(cmd)) + + +class NetworkServiceProvider: + """Manage network serivce providers for CloudStack""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def add(cls, apiclient, name, physicalnetworkid, servicelist): + """Adds network service provider""" + + cmd = addNetworkServiceProvider.addNetworkServiceProviderCmd() + cmd.name = name + cmd.physicalnetworkid = physicalnetworkid + cmd.servicelist = servicelist + return NetworkServiceProvider(apiclient.addNetworkServiceProvider(cmd).__dict__) + + def delete(self, apiclient): + """Deletes network service provider""" + + cmd = deleteNetworkServiceProvider.deleteNetworkServiceProviderCmd() + cmd.id = self.id + return apiclient.deleteNetworkServiceProvider(cmd) + + def update(self, apiclient, **kwargs): + """Updates network service provider""" + + cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return apiclient.updateNetworkServiceProvider(cmd) + + @classmethod + def update(cls, apiclient, id, **kwargs): + """Updates network service provider""" + + cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + cmd.id = id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return apiclient.updateNetworkServiceProvider(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """List network service providers""" + + cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listNetworkServiceProviders(cmd)) diff --git a/test/integration/lib/common.py b/test/integration/lib/common.py index 0c84c755b6f..17f24d74770 100644 --- a/test/integration/lib/common.py +++ b/test/integration/lib/common.py @@ -9,7 +9,7 @@ # 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 """ @@ -25,6 +25,7 @@ from base import * #Import System modules import time + def get_domain(apiclient, services=None): "Returns a default domain" @@ -32,13 +33,14 @@ def get_domain(apiclient, services=None): 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.") + raise Exception("Failed to find specified domain.") + def get_zone(apiclient, services=None): "Returns a default zone" @@ -47,13 +49,14 @@ def get_zone(apiclient, services=None): 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.") + raise Exception("Failed to find specified zone.") + def get_pod(apiclient, zoneid, services=None): "Returns a default pod for specified zone" @@ -64,13 +67,14 @@ def get_pod(apiclient, zoneid, services=None): 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.") + raise Exception("Exception: Failed to find specified pod.") + def get_template(apiclient, zoneid, ostypeid=12, services=None): "Returns a template" @@ -88,11 +92,12 @@ def get_template(apiclient, zoneid, ostypeid=12, services=None): for template in list_templates: if template.ostypeid == ostypeid: return template - + raise Exception("Exception: Failed to find template with OSTypeID: %s" % - ostypeid) + ostypeid) return + def download_systemplates_sec_storage(server, services): """Download System templates on sec storage""" @@ -104,7 +109,7 @@ def download_systemplates_sec_storage(server, services): server["username"], server["password"] ) - except Exception as e: + except Exception: raise Exception("SSH access failted for server with IP address: %s" % server["ipaddess"]) # Mount Secondary Storage on Management Server @@ -136,6 +141,7 @@ def download_systemplates_sec_storage(server, services): 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""" @@ -179,18 +185,20 @@ def wait_for_ssvms(apiclient, zoneid, podid, interval=60): break return -def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip, interval=60): + +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" - ) + 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( @@ -199,10 +207,10 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip, 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: @@ -223,20 +231,21 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip, # If template is ready, # template.status = Download Complete # Downloading - x% Downloaded - # Error - Any other string + # 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): + +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() @@ -252,6 +261,7 @@ def update_resource_limit(apiclient, resourcetype, account=None, domainid=None, apiclient.updateResourceLimit(cmd) return + def list_routers(apiclient, **kwargs): """List all Routers matching criteria""" @@ -259,6 +269,7 @@ def list_routers(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listRouters(cmd)) + def list_zones(apiclient, **kwargs): """List all Zones matching criteria""" @@ -266,6 +277,7 @@ def list_zones(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listZones(cmd)) + def list_networks(apiclient, **kwargs): """List all Networks matching criteria""" @@ -273,6 +285,7 @@ def list_networks(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listNetworks(cmd)) + def list_clusters(apiclient, **kwargs): """List all Clusters matching criteria""" @@ -280,6 +293,7 @@ def list_clusters(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listClusters(cmd)) + def list_ssvms(apiclient, **kwargs): """List all SSVMs matching criteria""" @@ -287,6 +301,7 @@ def list_ssvms(apiclient, **kwargs): [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""" @@ -294,6 +309,7 @@ def list_storage_pools(apiclient, **kwargs): [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""" @@ -301,6 +317,7 @@ def list_virtual_machines(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listVirtualMachines(cmd)) + def list_hosts(apiclient, **kwargs): """List all Hosts matching criteria""" @@ -308,6 +325,7 @@ def list_hosts(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listHosts(cmd)) + def list_configurations(apiclient, **kwargs): """List configuration with specified name""" @@ -315,6 +333,7 @@ def list_configurations(apiclient, **kwargs): [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""" @@ -322,6 +341,7 @@ def list_publicIP(apiclient, **kwargs): [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""" @@ -329,6 +349,7 @@ def list_nat_rules(apiclient, **kwargs): [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""" @@ -336,6 +357,7 @@ def list_lb_rules(apiclient, **kwargs): [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""" @@ -343,6 +365,7 @@ def list_lb_instances(apiclient, **kwargs): [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""" @@ -350,6 +373,7 @@ def list_firewall_rules(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listFirewallRules(cmd)) + def list_volumes(apiclient, **kwargs): """List all volumes matching criteria""" @@ -357,6 +381,7 @@ def list_volumes(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listVolumes(cmd)) + def list_isos(apiclient, **kwargs): """Lists all available ISO files.""" @@ -364,6 +389,7 @@ def list_isos(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listIsos(cmd)) + def list_snapshots(apiclient, **kwargs): """List all snapshots matching criteria""" @@ -371,6 +397,7 @@ def list_snapshots(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listSnapshots(cmd)) + def list_templates(apiclient, **kwargs): """List all templates matching criteria""" @@ -378,6 +405,7 @@ def list_templates(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listTemplates(cmd)) + def list_domains(apiclient, **kwargs): """Lists domains""" @@ -385,6 +413,7 @@ def list_domains(apiclient, **kwargs): [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""" @@ -393,6 +422,7 @@ def list_accounts(apiclient, **kwargs): [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""" @@ -401,6 +431,7 @@ def list_users(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listUsers(cmd)) + def list_snapshot_policy(apiclient, **kwargs): """Lists snapshot policies.""" @@ -408,6 +439,7 @@ def list_snapshot_policy(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listSnapshotPolicies(cmd)) + def list_events(apiclient, **kwargs): """Lists events""" @@ -415,6 +447,7 @@ def list_events(apiclient, **kwargs): [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.""" @@ -422,6 +455,7 @@ def list_disk_offering(apiclient, **kwargs): [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.""" @@ -429,6 +463,7 @@ def list_service_offering(apiclient, **kwargs): [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.""" @@ -436,6 +471,7 @@ def list_vlan_ipranges(apiclient, **kwargs): [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""" @@ -443,6 +479,7 @@ def list_usage_records(apiclient, **kwargs): [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""" @@ -450,6 +487,7 @@ def list_nw_service_prividers(apiclient, **kwargs): [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""" @@ -457,6 +495,7 @@ def list_virtual_router_elements(apiclient, **kwargs): [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listVirtualRouterElements(cmd)) + def list_network_offerings(apiclient, **kwargs): """Lists network offerings""" @@ -464,9 +503,10 @@ def list_network_offerings(apiclient, **kwargs): [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)) \ No newline at end of file + return(apiclient.listResourceLimits(cmd)) diff --git a/test/integration/lib/utils.py b/test/integration/lib/utils.py index 3caee9b8ae4..e4a28620c7c 100644 --- a/test/integration/lib/utils.py +++ b/test/integration/lib/utils.py @@ -9,7 +9,7 @@ # 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 """ @@ -28,11 +28,12 @@ import imaplib import email import datetime + def restart_mgmt_server(server): """Restarts the management server""" try: - # Get the SSH client + # Get the SSH client ssh = is_server_ssh_ready( server["ipaddress"], server["port"], @@ -49,9 +50,10 @@ def restart_mgmt_server(server): 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( @@ -66,21 +68,22 @@ def fetch_latest_mail(services, from_mail): 'search', None, '(SENTSINCE {date} HEADER FROM "{mail}")'.format( - date=date, + 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() @@ -91,15 +94,18 @@ def get_first_text_block(email_message_instance): 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 @@ -129,6 +135,7 @@ def format_volume_to_ext3(ssh_client, device="/dev/sda"): 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) @@ -146,6 +153,7 @@ def fetch_api_client(config_file='datacenterCfg'): ) ) + def get_process_status(hostip, port, username, password, linklocalip, process): """Double hop and returns a process status""" @@ -157,20 +165,22 @@ def get_process_status(hostip, port, username, password, linklocalip, process): password ) ssh_command = "ssh -i ~/.ssh/id_rsa.cloud -ostricthostkeychecking=no " - ssh_command = ssh_command + "-oUserKnownHostsFile=/dev/null -p 3922 %s %s" \ - % (linklocalip, process) + 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 \ No newline at end of file + return res diff --git a/test/integration/smoke/test_network.py b/test/integration/smoke/test_network.py index 7f629a6c6b0..6498b865428 100644 --- a/test/integration/smoke/test_network.py +++ b/test/integration/smoke/test_network.py @@ -97,6 +97,7 @@ class Services: # Algorithm used for load balancing "privateport": 22, "publicport": 2222, + "protocol": 'TCP' } } @@ -131,12 +132,12 @@ class TestPublicIP(cloudstackTestCase): cls.services["network"]["zoneid"] = cls.zone.id cls.network_offering = NetworkOffering.create( - cls.api_client, + cls.api_client, cls.services["network_offering"], ) # Enable Network offering cls.network_offering.update(cls.api_client, state='Enabled') - + cls.services["network"]["networkoffering"] = cls.network_offering.id cls.account_network = Network.create( cls.api_client, @@ -354,26 +355,26 @@ class TestPortForwarding(cloudstackTestCase): account=self.account.account.name, domainid=self.account.account.domainid ) - + self.assertEqual( isinstance(src_nat_ip_addrs, list), True, "Check list response returns a valid list" ) src_nat_ip_addr = src_nat_ip_addrs[0] - + # Check if VM is in Running state before creating NAT rule vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) - + self.assertEqual( isinstance(vm_response, list), True, "Check list VM returns a valid list" ) - + self.assertNotEqual( len(vm_response), 0, @@ -384,6 +385,16 @@ class TestPortForwarding(cloudstackTestCase): 'Running', "VM state should be Running before creating a NAT rule." ) + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=src_nat_ip_addr.id, + protocol=self.services["natrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["natrule"]["publicport"], + endport=self.services["natrule"]["publicport"] + ) + #Create NAT rule nat_rule = NATRule.create( self.apiclient, @@ -401,7 +412,7 @@ class TestPortForwarding(cloudstackTestCase): True, "Check list response returns a valid list" ) - + self.assertNotEqual( len(list_nat_rule_response), 0, @@ -419,9 +430,9 @@ class TestPortForwarding(cloudstackTestCase): self.virtual_machine.ipaddress, src_nat_ip_addr.ipaddress )) - + self.virtual_machine.get_ssh_client(src_nat_ip_addr.ipaddress) - + except Exception as e: self.fail( "SSH Access failed for %s: %s" % \ @@ -445,7 +456,7 @@ class TestPortForwarding(cloudstackTestCase): self.debug( "SSHing into VM with IP address %s after NAT rule deletion" % self.virtual_machine.ipaddress) - + remoteSSHClient.remoteSSHClient( src_nat_ip_addr.ipaddress, self.virtual_machine.ssh_port, @@ -469,19 +480,19 @@ class TestPortForwarding(cloudstackTestCase): self.services["server"] ) self.cleanup.append(ip_address) - + # Check if VM is in Running state before creating NAT rule vm_response = VirtualMachine.list( self.apiclient, id=self.virtual_machine.id ) - + self.assertEqual( isinstance(vm_response, list), True, "Check list VM returns a valid list" ) - + self.assertNotEqual( len(vm_response), 0, @@ -492,7 +503,15 @@ class TestPortForwarding(cloudstackTestCase): 'Running', "VM state should be Running before creating a NAT rule." ) - + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=ip_address.ipaddress.id, + protocol=self.services["natrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["natrule"]["publicport"], + endport=self.services["natrule"]["publicport"] + ) #Create NAT rule nat_rule = NATRule.create( self.apiclient, @@ -553,7 +572,7 @@ class TestPortForwarding(cloudstackTestCase): self.debug( "SSHing into VM with IP address %s after NAT rule deletion" % self.virtual_machine.ipaddress) - + remoteSSHClient.remoteSSHClient( ip_address.ipaddress.ipaddress, self.virtual_machine.ssh_port, @@ -614,6 +633,15 @@ class TestLoadBalancingRule(cloudstackTestCase): cls.account.account.domainid, cls.services["server"] ) + # Open up firewall port for SSH + cls.fw_rule = FireWallRule.create( + cls.api_client, + ipaddressid=cls.non_src_nat_ip.ipaddress.id, + protocol=cls.services["lbrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=cls.services["lbrule"]["publicport"], + endport=cls.services["lbrule"]["publicport"] + ) cls._cleanup = [ cls.account, cls.service_offering @@ -653,20 +681,20 @@ class TestLoadBalancingRule(cloudstackTestCase): "Check list response returns a valid list" ) src_nat_ip_addr = src_nat_ip_addrs[0] - + # Check if VM is in Running state before creating LB rule vm_response = VirtualMachine.list( self.apiclient, account=self.account.account.name, domainid=self.account.account.domainid ) - + self.assertEqual( isinstance(vm_response, list), True, "Check list VM returns a valid list" ) - + self.assertNotEqual( len(vm_response), 0, @@ -678,7 +706,7 @@ class TestLoadBalancingRule(cloudstackTestCase): 'Running', "VM state should be Running before creating a NAT rule." ) - + #Create Load Balancer rule and assign VMs to rule lb_rule = LoadBalancerRule.create( self.apiclient, @@ -727,12 +755,12 @@ class TestLoadBalancingRule(cloudstackTestCase): 0, "Check Load Balancer instances Rule in its List" ) - self.debug("lb_instance_rules Ids: %s, %s" % ( + self.debug("lb_instance_rules Ids: %s, %s" % ( lb_instance_rules[0].id, lb_instance_rules[1].id )) - self.debug("VM ids: %s, %s" % (self.vm_1.id, self.vm_2.id)) - + self.debug("VM ids: %s, %s" % (self.vm_1.id, self.vm_2.id)) + self.assertIn( lb_instance_rules[0].id, [self.vm_1.id, self.vm_2.id], @@ -746,35 +774,35 @@ class TestLoadBalancingRule(cloudstackTestCase): ) try: self.debug( - "SSH into VM (IPaddress: %s) & NAT Rule (Public IP: %s)"% + "SSH into VM (IPaddress: %s) & NAT Rule (Public IP: %s)" % (self.vm_1.ipaddress, src_nat_ip_addr.ipaddress) ) - + ssh_1 = remoteSSHClient.remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, self.vm_1.password ) - + # If Round Robin Algorithm is chosen, # each ssh command should alternate between VMs hostnames = [ssh_1.execute("hostname")[0]] - + except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % + self.fail("%s: SSH failed for VM with IP Address: %s" % (e, src_nat_ip_addr.ipaddress)) time.sleep(self.services["lb_switch_wait"]) - + try: - self.debug("SSHing into IP address: %s after adding VMs (ID: %s , %s)" % + self.debug("SSHing into IP address: %s after adding VMs (ID: %s , %s)" % ( src_nat_ip_addr.ipaddress, self.vm_1.id, self.vm_2.id )) - + ssh_2 = remoteSSHClient.remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], @@ -784,7 +812,7 @@ class TestLoadBalancingRule(cloudstackTestCase): hostnames.append(ssh_2.execute("hostname")[0]) except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % + self.fail("%s: SSH failed for VM with IP Address: %s" % (e, src_nat_ip_addr.ipaddress)) self.debug("Hostnames: %s" % str(hostnames)) @@ -802,23 +830,23 @@ class TestLoadBalancingRule(cloudstackTestCase): #SSH should pass till there is a last VM associated with LB rule lb_rule.remove(self.apiclient, [self.vm_2]) try: - self.debug("SSHing into IP address: %s after removing VM (ID: %s)" % + self.debug("SSHing into IP address: %s after removing VM (ID: %s)" % ( src_nat_ip_addr.ipaddress, self.vm_2.id )) - + ssh_1 = remoteSSHClient.remoteSSHClient( src_nat_ip_addr.ipaddress, self.services['lbrule']["publicport"], self.vm_1.username, self.vm_1.password ) - + hostnames.append(ssh_1.execute("hostname")[0]) - + except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % + self.fail("%s: SSH failed for VM with IP Address: %s" % (e, src_nat_ip_addr.ipaddress)) self.assertIn( @@ -828,7 +856,7 @@ class TestLoadBalancingRule(cloudstackTestCase): ) lb_rule.remove(self.apiclient, [self.vm_1]) - + with self.assertRaises(Exception): self.debug("Removed all VMs, trying to SSH") ssh_1 = remoteSSHClient.remoteSSHClient( @@ -848,20 +876,20 @@ class TestLoadBalancingRule(cloudstackTestCase): #2. attempt to ssh twice on the load balanced IP #3. verify using the hostname of the VM that # round robin is indeed happening as expected - + # Check if VM is in Running state before creating LB rule vm_response = VirtualMachine.list( self.apiclient, account=self.account.account.name, domainid=self.account.account.domainid ) - + self.assertEqual( isinstance(vm_response, list), True, "Check list VM returns a valid list" ) - + self.assertNotEqual( len(vm_response), 0, @@ -873,7 +901,7 @@ class TestLoadBalancingRule(cloudstackTestCase): 'Running', "VM state should be Running before creating a NAT rule." ) - + #Create Load Balancer rule and assign VMs to rule lb_rule = LoadBalancerRule.create( self.apiclient, @@ -889,7 +917,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.apiclient, id=lb_rule.id ) - + self.assertEqual( isinstance(lb_rules, list), True, @@ -935,7 +963,7 @@ class TestLoadBalancingRule(cloudstackTestCase): "Check List Load Balancer instances Rules returns valid VM ID" ) try: - self.debug("SSHing into IP address: %s after adding VMs (ID: %s , %s)" % + self.debug("SSHing into IP address: %s after adding VMs (ID: %s , %s)" % ( self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id, @@ -951,10 +979,10 @@ class TestLoadBalancingRule(cloudstackTestCase): # If Round Robin Algorithm is chosen, # each ssh command should alternate between VMs hostnames = [ssh_1.execute("hostname")[0]] - + time.sleep(self.services["lb_switch_wait"]) - - self.debug("SSHing again into IP address: %s with VMs (ID: %s , %s) added to LB rule" % + + self.debug("SSHing again into IP address: %s with VMs (ID: %s , %s) added to LB rule" % ( self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id, @@ -966,7 +994,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.vm_1.username, self.vm_1.password ) - + hostnames.append(ssh_2.execute("hostname")[0]) self.debug("Hostnames after adding 2 VMs to LB rule: %s" % str(hostnames)) self.assertIn( @@ -982,8 +1010,8 @@ class TestLoadBalancingRule(cloudstackTestCase): #SSH should pass till there is a last VM associated with LB rule lb_rule.remove(self.apiclient, [self.vm_2]) - - self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % + + self.debug("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % ( self.non_src_nat_ip.ipaddress.ipaddress, self.vm_2.id @@ -994,11 +1022,11 @@ class TestLoadBalancingRule(cloudstackTestCase): self.vm_1.username, self.vm_1.password ) - + hostnames.append(ssh_1.execute("hostname")[0]) self.debug("Hostnames after removing VM2: %s" % str(hostnames)) except Exception as e: - self.fail("%s: SSH failed for VM with IP Address: %s" % + self.fail("%s: SSH failed for VM with IP Address: %s" % (e, self.non_src_nat_ip.ipaddress.ipaddress)) self.assertIn( @@ -1009,7 +1037,7 @@ class TestLoadBalancingRule(cloudstackTestCase): lb_rule.remove(self.apiclient, [self.vm_1]) with self.assertRaises(Exception): - self.fail("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % + self.fail("SSHing into IP address: %s after removing VM (ID: %s) from LB rule" % ( self.non_src_nat_ip.ipaddress.ipaddress, self.vm_1.id @@ -1060,7 +1088,7 @@ class TestRebootRouter(cloudstackTestCase): domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) - + src_nat_ip_addrs = list_publicIP( self.apiclient, account=self.account.account.name, @@ -1070,7 +1098,7 @@ class TestRebootRouter(cloudstackTestCase): src_nat_ip_addr = src_nat_ip_addrs[0] except Exception as e: raise Exception("Warning: Exception during fetching source NAT: %s" % e) - + self.public_ip = PublicIPAddress.create( self.apiclient, self.vm_1.account, @@ -1078,6 +1106,15 @@ class TestRebootRouter(cloudstackTestCase): self.vm_1.domainid, self.services["server"] ) + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=self.public_ip.ipaddress.id, + protocol=self.services["lbrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["lbrule"]["publicport"], + endport=self.services["lbrule"]["publicport"] + ) lb_rule = LoadBalancerRule.create( self.apiclient, @@ -1120,44 +1157,44 @@ class TestRebootRouter(cloudstackTestCase): True, "Check list routers returns a valid list" ) - + router = routers[0] - + self.debug("Rebooting the router (ID: %s)" % router.id) - + cmd = rebootRouter.rebootRouterCmd() cmd.id = router.id self.apiclient.rebootRouter(cmd) - + # 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.vm_1.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: + + if timeout == 0: raise Exception( "Failed to start VM (ID: %s) in change service offering" % vm.id) - + timeout = timeout - 1 #we should be able to SSH after successful reboot try: self.debug("SSH into VM (ID : %s ) after reboot" % self.vm_1.id) - + remoteSSHClient.remoteSSHClient( self.nat_rule.ipaddress, self.services["natrule"]["publicport"], @@ -1258,20 +1295,30 @@ class TestAssignRemoveLB(cloudstackTestCase): "Check list response returns a valid list" ) self.non_src_nat_ip = src_nat_ip_addrs[0] - + + # Open up firewall port for SSH + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=self.non_src_nat_ip.id, + protocol=self.services["lbrule"]["protocol"], + cidrlist=['0.0.0.0/0'], + startport=self.services["lbrule"]["publicport"], + endport=self.services["lbrule"]["publicport"] + ) + # Check if VM is in Running state before creating LB rule vm_response = VirtualMachine.list( self.apiclient, account=self.account.account.name, domainid=self.account.account.domainid ) - + self.assertEqual( isinstance(vm_response, list), True, "Check list VM returns a valid list" ) - + self.assertNotEqual( len(vm_response), 0, @@ -1283,7 +1330,7 @@ class TestAssignRemoveLB(cloudstackTestCase): 'Running', "VM state should be Running before creating a NAT rule." ) - + lb_rule = LoadBalancerRule.create( self.apiclient, self.services["lbrule"], @@ -1291,9 +1338,9 @@ class TestAssignRemoveLB(cloudstackTestCase): self.account.account.name ) lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) - + try: - self.debug("SSHing into IP address: %s with VMs (ID: %s , %s) added to LB rule" % + self.debug("SSHing into IP address: %s with VMs (ID: %s , %s) added to LB rule" % ( self.non_src_nat_ip.ipaddress, self.vm_1.id, @@ -1307,11 +1354,11 @@ class TestAssignRemoveLB(cloudstackTestCase): self.vm_1.password ) except Exception as e: - self.fail("SSH failed for VM with IP: %s" % + self.fail("SSH failed for VM with IP: %s" % self.non_src_nat_ip.ipaddress) - + try: - self.debug("SSHing again into IP address: %s with VMs (ID: %s , %s) added to LB rule" % + self.debug("SSHing again into IP address: %s with VMs (ID: %s , %s) added to LB rule" % ( self.non_src_nat_ip.ipaddress, self.vm_1.id, @@ -1323,19 +1370,19 @@ class TestAssignRemoveLB(cloudstackTestCase): self.vm_2.username, self.vm_2.password ) - + # If Round Robin Algorithm is chosen, # each ssh command should alternate between VMs res_1 = ssh_1.execute("hostname")[0] self.debug(res_1) - + time.sleep(self.services["lb_switch_wait"]) - + res_2 = ssh_2.execute("hostname")[0] self.debug(res_2) except Exception as e: - self.fail("SSH failed for VM with IP: %s" % + self.fail("SSH failed for VM with IP: %s" % self.non_src_nat_ip.ipaddress) self.assertIn( @@ -1351,9 +1398,9 @@ class TestAssignRemoveLB(cloudstackTestCase): #Removing VM and assigning another VM to LB rule lb_rule.remove(self.apiclient, [self.vm_2]) - + try: - self.debug("SSHing again into IP address: %s with VM (ID: %s) added to LB rule" % + self.debug("SSHing again into IP address: %s with VM (ID: %s) added to LB rule" % ( self.non_src_nat_ip.ipaddress, self.vm_1.id, @@ -1364,14 +1411,14 @@ class TestAssignRemoveLB(cloudstackTestCase): self.services["lbrule"]["publicport"], self.vm_1.username, self.vm_1.password - ) + ) res_1 = ssh_1.execute("hostname")[0] self.debug(res_1) except Exception as e: - self.fail("SSH failed for VM with IP: %s" % + self.fail("SSH failed for VM with IP: %s" % self.non_src_nat_ip.ipaddress) - + self.assertIn( self.vm_1.name, res_1, @@ -1379,7 +1426,7 @@ class TestAssignRemoveLB(cloudstackTestCase): ) lb_rule.assign(self.apiclient, [self.vm_3]) - + try: ssh_1 = remoteSSHClient.remoteSSHClient( self.non_src_nat_ip.ipaddress, @@ -1393,19 +1440,19 @@ class TestAssignRemoveLB(cloudstackTestCase): self.vm_3.username, self.vm_3.password ) - + res_1 = ssh_1.execute("hostname")[0] self.debug(res_1) - + time.sleep(self.services["lb_switch_wait"]) - + res_3 = ssh_3.execute("hostname")[0] self.debug(res_3) except Exception as e: - self.fail("SSH failed for VM with IP: %s" % + self.fail("SSH failed for VM with IP: %s" % self.non_src_nat_ip.ipaddress) - + self.assertIn( self.vm_1.name, res_1, @@ -1478,7 +1525,7 @@ class TestReleaseIP(cloudstackTestCase): except Exception as e: raise Exception("Failed: During acquiring source NAT for account: %s" % self.account.account.name) - + self.nat_rule = NATRule.create( self.apiclient, self.virtual_machine, @@ -1502,21 +1549,21 @@ class TestReleaseIP(cloudstackTestCase): def test_releaseIP(self): """Test for Associate/Disassociate public IP address""" - + self.debug("Deleting Public IP : %s" % self.ip_addr.id) - + self.ip_address.delete(self.apiclient) - + # Sleep to ensure that deleted state is reflected in other calls time.sleep(self.services["sleep"]) - + # ListPublicIpAddresses should not list deleted Public IP address list_pub_ip_addr_resp = list_publicIP( self.apiclient, id=self.ip_addr.id ) self.debug("List Public IP response" + str(list_pub_ip_addr_resp)) - + self.assertEqual( list_pub_ip_addr_resp, None, @@ -1543,7 +1590,7 @@ class TestReleaseIP(cloudstackTestCase): id=self.lb_rule.id ) self.debug("List LB Rule response" + str(list_lb_rule)) - + self.assertEqual( list_lb_rule, None, @@ -1603,12 +1650,12 @@ class TestDeleteAccount(cloudstackTestCase): account=self.account.account.name, domainid=self.account.account.domainid ) - + try: src_nat_ip_addr = src_nat_ip_addrs[0] - + except Exception as e: - self.fail("SSH failed for VM with IP: %s" % + self.fail("SSH failed for VM with IP: %s" % src_nat_ip_addr.ipaddress) self.lb_rule = LoadBalancerRule.create( @@ -1618,7 +1665,7 @@ class TestDeleteAccount(cloudstackTestCase): self.account.account.name ) self.lb_rule.assign(self.apiclient, [self.vm_1]) - + self.nat_rule = NATRule.create( self.apiclient, self.vm_1, @@ -1666,14 +1713,14 @@ class TestDeleteAccount(cloudstackTestCase): "Check load balancing rule is properly deleted." ) except Exception as e: - + raise Exception( "Exception raised while fetching LB rules for account: %s" % self.account.account.name) # ListPortForwardingRules should not # list associated rules with deleted account try: - list_nat_reponse= list_nat_rules( + list_nat_reponse = list_nat_rules( self.apiclient, account=self.account.account.name, domainid=self.account.account.domainid @@ -1684,7 +1731,7 @@ class TestDeleteAccount(cloudstackTestCase): "Check load balancing rule is properly deleted." ) except Exception as e: - + raise Exception( "Exception raised while fetching NAT rules for account: %s" % self.account.account.name) @@ -1701,7 +1748,7 @@ class TestDeleteAccount(cloudstackTestCase): "Check routers are properly deleted." ) except Exception as e: - + raise Exception( "Exception raised while fetching routers for account: %s" % self.account.account.name) diff --git a/test/integration/smoke/test_routers.py b/test/integration/smoke/test_routers.py index 5937ddf00a3..79e6bbdb2ee 100644 --- a/test/integration/smoke/test_routers.py +++ b/test/integration/smoke/test_routers.py @@ -21,7 +21,6 @@ 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 @@ -57,7 +56,7 @@ class Services: "username": "testuser", "password": "fr3sca", }, - "ostypeid":'5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid":'946b031b-0e10-4f4a-a3fc-d212ae2ea07f', "sleep": 60, "timeout": 10, "mode": 'advanced', #Networking mode: Basic, Advanced diff --git a/test/integration/smoke/test_snapshots.py b/test/integration/smoke/test_snapshots.py index 6b3ec704ff0..91e65a41a0d 100644 --- a/test/integration/smoke/test_snapshots.py +++ b/test/integration/smoke/test_snapshots.py @@ -17,10 +17,10 @@ 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 * -from marvin.remoteSSHClient import remoteSSHClient class Services: @@ -1017,7 +1017,7 @@ class TestSnapshots(cloudstackTestCase): self.services["sub_lvl_dir2"], self.services["random_data"] ), - "sync", + "sync", ] for c in cmds: diff --git a/test/integration/smoke/test_templates.py b/test/integration/smoke/test_templates.py index 0dd873cd623..b17b93fda19 100644 --- a/test/integration/smoke/test_templates.py +++ b/test/integration/smoke/test_templates.py @@ -17,6 +17,7 @@ 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 * @@ -69,12 +70,12 @@ class Services: "template_1": { "displaytext": "Cent OS Template", "name": "Cent OS Template", - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '946b031b-0e10-4f4a-a3fc-d212ae2ea07f', }, "template_2": { "displaytext": "Public Template", "name": "Public template", - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '946b031b-0e10-4f4a-a3fc-d212ae2ea07f', "isfeatured": True, "ispublic": True, "isextractable": True, @@ -88,7 +89,7 @@ class Services: "isextractable": False, "bootable": True, "passwordenabled": True, - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '946b031b-0e10-4f4a-a3fc-d212ae2ea07f', "mode": 'advanced', # Networking mode: Advanced, basic "sleep": 30, diff --git a/test/integration/smoke/test_vm_life_cycle.py b/test/integration/smoke/test_vm_life_cycle.py index 618583fcdab..839124308e5 100644 --- a/test/integration/smoke/test_vm_life_cycle.py +++ b/test/integration/smoke/test_vm_life_cycle.py @@ -107,6 +107,11 @@ class Services: "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "passwordenabled": True, + }, "diskdevice": '/dev/xvdd', # Disk device where ISO is attached to instance "mount_dir": "/mnt/tmp", @@ -186,20 +191,20 @@ class TestDeployVM(cloudstackTestCase): "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, @@ -323,7 +328,7 @@ class TestVMLifeCycle(cloudstackTestCase): self.apiclient, id=self.small_virtual_machine.id ) - + self.assertEqual( isinstance(list_vm_response, list), True, @@ -348,7 +353,7 @@ class TestVMLifeCycle(cloudstackTestCase): # 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) @@ -361,7 +366,7 @@ class TestVMLifeCycle(cloudstackTestCase): True, "Check list response returns a valid list" ) - + self.assertNotEqual( len(list_vm_response), 0, @@ -400,7 +405,7 @@ class TestVMLifeCycle(cloudstackTestCase): True, "Check list response returns a valid list" ) - + self.assertNotEqual( len(list_vm_response), 0, @@ -423,39 +428,39 @@ class TestVMLifeCycle(cloudstackTestCase): # 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: + + 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.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 @@ -463,32 +468,32 @@ class TestVMLifeCycle(cloudstackTestCase): 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: + + 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: @@ -506,7 +511,7 @@ class TestVMLifeCycle(cloudstackTestCase): 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, @@ -539,76 +544,76 @@ class TestVMLifeCycle(cloudstackTestCase): # 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: + + 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.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: + + 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: @@ -616,7 +621,7 @@ class TestVMLifeCycle(cloudstackTestCase): "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]) @@ -626,7 +631,7 @@ class TestVMLifeCycle(cloudstackTestCase): 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, @@ -644,7 +649,7 @@ class TestVMLifeCycle(cloudstackTestCase): self.medium_offering.cpuspeed, "Check CPU Speed for medium offering" ) - + self.assertAlmostEqual( int(total_mem) / 1024, # In MBs self.medium_offering.memory, @@ -660,7 +665,7 @@ class TestVMLifeCycle(cloudstackTestCase): # 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) @@ -673,7 +678,7 @@ class TestVMLifeCycle(cloudstackTestCase): True, "Check list response returns a valid list" ) - + self.assertNotEqual( len(list_vm_response), 0, @@ -695,9 +700,9 @@ class TestVMLifeCycle(cloudstackTestCase): # 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) @@ -711,7 +716,7 @@ class TestVMLifeCycle(cloudstackTestCase): True, "Check list response returns a valid list" ) - + self.assertNotEqual( len(list_vm_response), 0, @@ -734,21 +739,21 @@ class TestVMLifeCycle(cloudstackTestCase): # 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, + self.apiclient, zoneid=self.medium_virtual_machine.zoneid, type='Routing' ) - + self.assertEqual( - isinstance(hosts, list), - True, + isinstance(hosts, list), + True, "Check the number of hosts in the zone" ) self.assertEqual( - len(hosts), - 2, + len(hosts), + 2, "Atleast 2 hosts should be present in a zone for VM migration" ) @@ -757,12 +762,12 @@ class TestVMLifeCycle(cloudstackTestCase): 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 @@ -777,7 +782,7 @@ class TestVMLifeCycle(cloudstackTestCase): True, "Check list response returns a valid list" ) - + self.assertNotEqual( list_vm_response, None, @@ -804,9 +809,9 @@ class TestVMLifeCycle(cloudstackTestCase): """ # 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) @@ -848,14 +853,14 @@ class TestVMLifeCycle(cloudstackTestCase): 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 @@ -865,10 +870,10 @@ class TestVMLifeCycle(cloudstackTestCase): 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" \ @@ -877,7 +882,7 @@ class TestVMLifeCycle(cloudstackTestCase): self.services["mount_dir"] ), ] - + for c in cmds: res = ssh_client.execute(c) @@ -888,9 +893,9 @@ class TestVMLifeCycle(cloudstackTestCase): #Disk /dev/xvdd: 4393 MB, 4393723904 bytes except Exception as e: - self.fail("SSH failed for virtual machine: %s - %s" % + 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 = [] @@ -919,23 +924,23 @@ class TestVMLifeCycle(cloudstackTestCase): #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.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.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) @@ -945,3 +950,174 @@ class TestVMLifeCycle(cloudstackTestCase): "Check if ISO is detached from virtual machine" ) return + +@unittest.skip("Additional test") +class TestVMPasswordEnabled(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMPasswordEnabled, + 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 + + # 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.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"] + ) + #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 + ) + if isinstance(list_volume, list): + cls.volume = list_volume[0] + else: + raise Exception( + "Exception: Unable to find root volume foe VM: %s" % + cls.virtual_machine.id) + + cls.services["template"]["ostypeid"] = cls.services["ostypeid"] + #Create templates for Edit, Delete & update permissions testcases + cls.pw_enabled_template = Template.create( + cls.api_client, + cls.services["template"], + cls.volume.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + # Delete the VM - No longer needed + cls.virtual_machine.delete(cls.api_client) + cls.services["small"]["template"] = cls.pw_enabled_template.id + + cls.vm = 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.pw_enabled_template, + cls.account + ] + + @classmethod + def tearDownClass(cls): + # Cleanup VMs, templates etc. + 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 instances + cleanup_resources(self.apiclient, self.cleanup) + return + + def test_11_get_vm_password(self): + """Test get VM password for password enabled template""" + + # Validate the following + # 1. Create an account + # 2. Deploy VM with default service offering and "password enabled" + # template. Vm should be in running state. + # 3. Stop VM deployed in step 2 + # 4. Reset VM password. SSH with new password should be successful + + self.debug("Stopping VM: %s" % self.vm.name) + self.vm.stop(self.apiclient) + + # Sleep to ensure VM is stopped properly + time.sleep(self.services["sleep"]) + + self.debug("Resetting VM password for VM: %s" % self.vm.name) + password = self.vm.resetPassword(self.apiclient) + self.debug("Password reset to: %s" % password) + + self.debug("Starting VM to verify new password..") + self.vm.start(self.apiclient) + self.debug("VM - %s stated!" % self.vm.name) + + vms = VirtualMachine.list(self.apiclient, id=self.vm.id, listall=True) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should retun valid response for VM: %s" % self.vm.name + ) + virtual_machine = vms[0] + + self.assertEqual( + virtual_machine.state, + "Running", + "VM state should be running" + ) + try: + self.debug("SSHing into VM: %s" % self.vm.ssh_ip) + self.vm.password = password + ssh = self.vm.get_ssh_client() + except Exception as e: + self.fail("SSH into VM: %s failed" % self.vm.ssh_ip) + return diff --git a/test/integration/smoke/test_volumes.py b/test/integration/smoke/test_volumes.py index 2b3ec594093..f6b5e79db90 100644 --- a/test/integration/smoke/test_volumes.py +++ b/test/integration/smoke/test_volumes.py @@ -17,10 +17,10 @@ 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 * -from marvin.remoteSSHClient import remoteSSHClient #Import System modules import os import urllib @@ -70,7 +70,7 @@ class Services: "publicport": 22, "protocol": 'TCP', "diskdevice": "/dev/xvdb", - "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "ostypeid": '946b031b-0e10-4f4a-a3fc-d212ae2ea07f', "mode": 'advanced', "sleep": 60, "timeout": 10, @@ -514,4 +514,4 @@ class TestVolumes(cloudstackTestCase): None, "Check if volume exists in ListVolumes" ) - return \ No newline at end of file + return