From 99af149db7e2c87768b2a8a9476e18ff57db2e83 Mon Sep 17 00:00:00 2001 From: Chirag Jog Date: Sun, 18 Mar 2012 23:08:58 -0700 Subject: [PATCH] Refactored the code to fetch domainid from API calls. Changed env. setup code in test accounts. --- .../testClient/testcase/BVT-tests/test_iso.py | 22 +- .../testcase/BVT-tests/test_network.py | 62 +- .../testcase/BVT-tests/test_routers.py | 13 +- .../BVT-tests/test_secondary_storage.py | 11 +- .../testcase/BVT-tests/test_snapshots.py | 27 +- .../testcase/BVT-tests/test_ssvm.py | 3 - .../testcase/BVT-tests/test_templates.py | 25 +- .../testcase/BVT-tests/test_vm_life_cycle.py | 23 +- .../testcase/BVT-tests/test_volumes.py | 21 +- tools/testClient/testcase/P1-tests/README | 36 + .../testClient/testcase/P1-tests/__init__.py | 0 .../testcase/P1-tests/test_accounts.py | 1365 ++++++++++++++ .../testcase/P1-tests/test_blocker_bugs.py | 1264 +++++++++++++ .../testcase/P1-tests/test_resource_limits.py | 1265 +++++++++++++ .../testcase/P1-tests/test_routers.py | 1178 ++++++++++++ .../testcase/P1-tests/test_security_groups.py | 1617 +++++++++++++++++ .../testcase/P1-tests/test_snapshots.py | 1350 ++++++++++++++ .../testcase/P1-tests/test_templates.py | 602 ++++++ .../testcase/P1-tests/test_usage.py | 1564 ++++++++++++++++ .../testcase/P1-tests/test_volumes.py | 1009 ++++++++++ tools/testClient/testcase/libs/base.py | 115 +- tools/testClient/testcase/libs/common.py | 67 +- 22 files changed, 11512 insertions(+), 127 deletions(-) create mode 100644 tools/testClient/testcase/P1-tests/README create mode 100644 tools/testClient/testcase/P1-tests/__init__.py create mode 100644 tools/testClient/testcase/P1-tests/test_accounts.py create mode 100644 tools/testClient/testcase/P1-tests/test_blocker_bugs.py create mode 100644 tools/testClient/testcase/P1-tests/test_resource_limits.py create mode 100644 tools/testClient/testcase/P1-tests/test_routers.py create mode 100644 tools/testClient/testcase/P1-tests/test_security_groups.py create mode 100644 tools/testClient/testcase/P1-tests/test_snapshots.py create mode 100644 tools/testClient/testcase/P1-tests/test_templates.py create mode 100644 tools/testClient/testcase/P1-tests/test_usage.py create mode 100644 tools/testClient/testcase/P1-tests/test_volumes.py diff --git a/tools/testClient/testcase/BVT-tests/test_iso.py b/tools/testClient/testcase/BVT-tests/test_iso.py index f12a06d87af..180f3b3d992 100644 --- a/tools/testClient/testcase/BVT-tests/test_iso.py +++ b/tools/testClient/testcase/BVT-tests/test_iso.py @@ -40,7 +40,7 @@ class Services: "isextractable": True, "isfeatured": True, "ispublic": True, - "ostypeid": '5a5b5f64-de08-452d-9672-608a4946f754', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', }, "iso_2": { @@ -51,7 +51,7 @@ class Services: "isextractable": True, "isfeatured": True, "ispublic": True, - "ostypeid": '5a5b5f64-de08-452d-9672-608a4946f754', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', "mode": 'HTTP_DOWNLOAD', # Used in Extract template, value must be HTTP_DOWNLOAD }, @@ -64,12 +64,8 @@ class Services: "passwordenabled": True, "sleep": 60, "timeout": 10, - "ostypeid": '5a5b5f64-de08-452d-9672-608a4946f754', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', # CentOS 5.3 (64 bit) - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests "mode": 'advanced' # Networking mode: Basic or Advanced } @@ -82,12 +78,15 @@ class TestCreateIso(cloudstackTestCase): self.apiclient = self.testClient.getApiClient() self.dbclient = self.testClient.getDbConnection() # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) + self.services["domainid"] = self.domain.id self.services["iso_2"]["zoneid"] = self.zone.id self.account = Account.create( self.apiclient, - self.services["account"] + self.services["account"], + domainid=self.domain.id ) self.cleanup = [self.account] @@ -172,7 +171,10 @@ class TestISO(cloudstackTestCase): cls.api_client = fetch_api_client() # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) + + cls.services["domainid"] = cls.domain.id cls.services["iso_1"]["zoneid"] = cls.zone.id cls.services["iso_2"]["zoneid"] = cls.zone.id cls.services["sourcezoneid"] = cls.zone.id @@ -181,6 +183,7 @@ class TestISO(cloudstackTestCase): cls.account = Account.create( cls.api_client, cls.services["account"], + domainid=cls.domain.id ) cls.services["account"] = cls.account.account.name cls.iso_1 = Iso.create( @@ -259,7 +262,6 @@ class TestISO(cloudstackTestCase): cmd.name = new_name cmd.bootable = self.services["bootable"] cmd.passwordenabled = self.services["passwordenabled"] - cmd.ostypeid = self.services["ostypeid"] self.apiclient.updateIso(cmd) @@ -485,4 +487,4 @@ class TestISO(cloudstackTestCase): cmd.id = iso_response.id cmd.zoneid = self.services["destzoneid"] self.apiclient.deleteIso(cmd) - return \ No newline at end of file + return diff --git a/tools/testClient/testcase/BVT-tests/test_network.py b/tools/testClient/testcase/BVT-tests/test_network.py index 1218b37af27..be5ee3842c6 100644 --- a/tools/testClient/testcase/BVT-tests/test_network.py +++ b/tools/testClient/testcase/BVT-tests/test_network.py @@ -22,11 +22,8 @@ class Services: def __init__(self): self.services = { - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', # Cent OS 5.3 (64 bit) - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests "mode": 'advanced', # Networking mode: Basic or advanced "lb_switch_wait": 10, @@ -36,7 +33,7 @@ class Services: "network": { "name": "Test Network", "displaytext": "Test Network", - "networkoffering": '4c6dea7e-7aa8-4b17-bf1c-26c312586e7c', + "networkoffering": '3d4e36f1-6b5f-40fc-bb63-fe9353419e91', }, "service_offering": { "name": "Tiny Instance", @@ -60,7 +57,6 @@ class Services: "username": "root", "password": "password", "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "privateport": 22, "publicport": 22, "ssh_port": 22, @@ -94,18 +90,21 @@ class TestPublicIP(cloudstackTestCase): cls.api_client = fetch_api_client() 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) # Create Accounts & networks cls.account = Account.create( cls.api_client, cls.services["account"], - admin=True + admin=True, + domainid=cls.domain.id ) cls.user = Account.create( cls.api_client, cls.services["account"], + domainid=cls.domain.id ) cls.services["network"]["zoneid"] = cls.zone.id cls.account_network = Network.create( @@ -261,6 +260,7 @@ class TestPortForwarding(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) template = get_template( cls.api_client, @@ -271,7 +271,8 @@ class TestPortForwarding(cloudstackTestCase): cls.account = Account.create( cls.api_client, cls.services["account"], - admin=True + admin=True, + domainid=cls.domain.id ) cls.services["server"]["zoneid"] = cls.zone.id cls.service_offering = ServiceOffering.create( @@ -283,6 +284,7 @@ class TestPortForwarding(cloudstackTestCase): cls.services["server"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id ) cls._cleanup = [ @@ -537,6 +539,7 @@ class TestLoadBalancingRule(cloudstackTestCase): cls.api_client = fetch_api_client() cls.services = Services().services # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) template = get_template( cls.api_client, @@ -549,7 +552,8 @@ class TestLoadBalancingRule(cloudstackTestCase): cls.account = Account.create( cls.api_client, cls.services["account"], - admin=True + admin=True, + domainid=cls.domain.id ) cls.service_offering = ServiceOffering.create( cls.api_client, @@ -560,6 +564,7 @@ class TestLoadBalancingRule(cloudstackTestCase): cls.services["server"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id ) cls.vm_2 = VirtualMachine.create( @@ -567,6 +572,7 @@ class TestLoadBalancingRule(cloudstackTestCase): cls.services["server"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id ) cls.non_src_nat_ip = PublicIPAddress.create( @@ -689,7 +695,12 @@ class TestLoadBalancingRule(cloudstackTestCase): 0, "Check Load Balancer instances Rule in its List" ) - + 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.assertIn( lb_instance_rules[0].id, [self.vm_1.id, self.vm_2.id], @@ -744,6 +755,7 @@ class TestLoadBalancingRule(cloudstackTestCase): self.fail("%s: SSH failed for VM with IP Address: %s" % (e, src_nat_ip_addr.ipaddress)) + self.debug("Hostnames: %s" % str(hostnames)) self.assertIn( self.vm_1.name, hostnames, @@ -795,7 +807,7 @@ class TestLoadBalancingRule(cloudstackTestCase): ) ssh_1.execute("hostname")[0] return - + def test_02_create_lb_rule_non_nat(self): """Test to create Load balancing rule with source NAT""" @@ -924,7 +936,7 @@ class TestLoadBalancingRule(cloudstackTestCase): ) hostnames.append(ssh_2.execute("hostname")[0]) - + self.debug("Hostnames after adding 2 VMs to LB rule: %s" % str(hostnames)) self.assertIn( self.vm_1.name, hostnames, @@ -952,7 +964,7 @@ class TestLoadBalancingRule(cloudstackTestCase): ) 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" % (e, self.non_src_nat_ip.ipaddress.ipaddress)) @@ -988,6 +1000,7 @@ class TestRebootRouter(cloudstackTestCase): self.services = Services().services # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) template = get_template( self.apiclient, @@ -1000,7 +1013,8 @@ class TestRebootRouter(cloudstackTestCase): self.account = Account.create( self.apiclient, self.services["account"], - admin=True + admin=True, + domainid=self.domain.id ) self.service_offering = ServiceOffering.create( self.apiclient, @@ -1011,6 +1025,7 @@ class TestRebootRouter(cloudstackTestCase): self.services["server"], templateid=template.id, accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) @@ -1135,6 +1150,7 @@ class TestAssignRemoveLB(cloudstackTestCase): self.apiclient = self.testClient.getApiClient() self.services = Services().services # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) template = get_template( self.apiclient, @@ -1147,7 +1163,8 @@ class TestAssignRemoveLB(cloudstackTestCase): self.account = Account.create( self.apiclient, self.services["account"], - admin=True + admin=True, + domainid=self.domain.id ) self.service_offering = ServiceOffering.create( self.apiclient, @@ -1159,6 +1176,7 @@ class TestAssignRemoveLB(cloudstackTestCase): self.services["server"], templateid=template.id, accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) @@ -1167,6 +1185,7 @@ class TestAssignRemoveLB(cloudstackTestCase): self.services["server"], templateid=template.id, accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) @@ -1175,6 +1194,7 @@ class TestAssignRemoveLB(cloudstackTestCase): self.services["server"], templateid=template.id, accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) @@ -1378,6 +1398,7 @@ class TestReleaseIP(cloudstackTestCase): self.services = Services().services # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) template = get_template( self.apiclient, @@ -1390,7 +1411,8 @@ class TestReleaseIP(cloudstackTestCase): self.account = Account.create( self.apiclient, self.services["account"], - admin=True + admin=True, + domainid=self.domain.id ) self.service_offering = ServiceOffering.create( @@ -1403,6 +1425,7 @@ class TestReleaseIP(cloudstackTestCase): self.services["server"], templateid=template.id, accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) @@ -1514,6 +1537,7 @@ class TestDeleteAccount(cloudstackTestCase): self.services = Services().services # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) template = get_template( self.apiclient, @@ -1526,7 +1550,8 @@ class TestDeleteAccount(cloudstackTestCase): self.account = Account.create( self.apiclient, self.services["account"], - admin=True + admin=True, + domainid=self.domain.id ) self.service_offering = ServiceOffering.create( self.apiclient, @@ -1537,6 +1562,7 @@ class TestDeleteAccount(cloudstackTestCase): self.services["server"], templateid=template.id, accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) @@ -1651,4 +1677,4 @@ class TestDeleteAccount(cloudstackTestCase): def tearDown(self): cleanup_resources(self.apiclient, self.cleanup) - return \ No newline at end of file + return diff --git a/tools/testClient/testcase/BVT-tests/test_routers.py b/tools/testClient/testcase/BVT-tests/test_routers.py index de9e9f6d7c6..255f77e0768 100644 --- a/tools/testClient/testcase/BVT-tests/test_routers.py +++ b/tools/testClient/testcase/BVT-tests/test_routers.py @@ -36,7 +36,6 @@ class Services: "password": "fr3sca", "ssh_port": 22, "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "privateport": 22, "publicport": 22, "protocol": 'TCP', @@ -48,12 +47,9 @@ class Services: "username": "testuser", "password": "fr3sca", }, - "ostypeid":'0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid":'144f66aa-7f74-4cfe-9799-80cc21439cb3', "sleep": 60, "timeout": 10, - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests "mode": 'advanced', #Networking mode: Basic, Advanced } @@ -66,6 +62,7 @@ class TestRouterServices(cloudstackTestCase): cls.api_client = fetch_api_client() cls.services = Services().services # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) template = get_template( cls.api_client, @@ -77,7 +74,8 @@ class TestRouterServices(cloudstackTestCase): #Create an account, network, VM and IP addresses cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=cls.domain.id ) cls.service_offering = ServiceOffering.create( cls.api_client, @@ -88,6 +86,7 @@ class TestRouterServices(cloudstackTestCase): cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id ) cls.cleanup = [ @@ -754,7 +753,7 @@ class TestRouterServices(cloudstackTestCase): ) response = config[0] - # Wait for network.gc.interval * 3 time + # Wait for network.gc.interval * 3 time to cleanup all the resources time.sleep(int(response.value) * 3) timeout = self.services["timeout"] diff --git a/tools/testClient/testcase/BVT-tests/test_secondary_storage.py b/tools/testClient/testcase/BVT-tests/test_secondary_storage.py index 76719ad87fa..635914e5c58 100644 --- a/tools/testClient/testcase/BVT-tests/test_secondary_storage.py +++ b/tools/testClient/testcase/BVT-tests/test_secondary_storage.py @@ -40,10 +40,6 @@ class Services: }, "sleep": 60, "timeout": 5, - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', } class TestSecStorageServices(cloudstackTestCase): @@ -70,6 +66,7 @@ class TestSecStorageServices(cloudstackTestCase): self.cleanup = [] self.services = Services().services # Get Zone and pod + self.domain = get_domain(self.apiclient, self.services) self.zone = get_zone(self.apiclient, self.services) self.pod = get_pod(self.apiclient, self.zone.id) return @@ -286,7 +283,7 @@ class TestSecStorageServices(cloudstackTestCase): templatefilter=v["templatefilter"], listall=True, account='system', - domainid=self.services["domainid"] + domainid=self.domain.id ) # Ensure all BUILTIN templates are downloaded @@ -309,7 +306,7 @@ class TestSecStorageServices(cloudstackTestCase): templatefilter=v["templatefilter"], listall=True, account='system', - domainid=self.services["domainid"] + domainid=self.domain.id ) if isinstance(template_response, list): @@ -345,7 +342,7 @@ class TestSecStorageServices(cloudstackTestCase): templatefilter=v["templatefilter"], listall=True, account='system', - domainid=self.services["domainid"] + domainid=self.domain.id ) if isinstance(template_response, list): diff --git a/tools/testClient/testcase/BVT-tests/test_snapshots.py b/tools/testClient/testcase/BVT-tests/test_snapshots.py index e8ee666205a..5a162708a7d 100644 --- a/tools/testClient/testcase/BVT-tests/test_snapshots.py +++ b/tools/testClient/testcase/BVT-tests/test_snapshots.py @@ -47,7 +47,6 @@ class Services: "password": "password", "ssh_port": 22, "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "privateport": 22, "publicport": 22, "protocol": 'TCP', @@ -60,7 +59,6 @@ class Services: "password": "password", "ssh_port": 22, "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "privateport": 22, # For NAT rule creation "publicport": 22, @@ -81,17 +79,16 @@ class Services: { "displaytext": 'Template from snapshot', "name": 'Template from snapshot', - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', "templatefilter": 'self', }, - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', # Cent OS 5.3 (64 bit) "diskdevice": "/dev/xvdb", # Data Disk "rootdisk": "/dev/xvda", # Root Disk "diskname": "Test Disk", "size": 1, # GBs - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "mount_dir": "/mnt/tmp", "sub_dir": "test", @@ -102,9 +99,6 @@ class Services: "username": "root", "password": "password", "ssh_port": 22, - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests "sleep": 60, "timeout": 10, "mode": 'advanced', @@ -119,6 +113,7 @@ class TestSnapshotRootDisk(cloudstackTestCase): cls.api_client = fetch_api_client() cls.services = Services().services # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) template = get_template( @@ -126,6 +121,7 @@ class TestSnapshotRootDisk(cloudstackTestCase): cls.zone.id, cls.services["ostypeid"] ) + cls.services["domainid"] = cls.domain.id cls.services["server_without_disk"]["zoneid"] = cls.zone.id cls.services["template"] = template.id cls.services["zoneid"] = cls.zone.id @@ -133,7 +129,8 @@ class TestSnapshotRootDisk(cloudstackTestCase): # Create VMs, NAT Rules etc cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=cls.domain.id ) cls.services["account"] = cls.account.account.name @@ -148,6 +145,7 @@ class TestSnapshotRootDisk(cloudstackTestCase): cls.services["server_without_disk"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) @@ -329,6 +327,7 @@ class TestSnapshots(cloudstackTestCase): cls.api_client = fetch_api_client() cls.services = Services().services # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) cls.disk_offering = DiskOffering.create( cls.api_client, @@ -339,6 +338,8 @@ class TestSnapshots(cloudstackTestCase): cls.zone.id, cls.services["ostypeid"] ) + + cls.services["domainid"] = cls.domain.id cls.services["server_with_disk"]["zoneid"] = cls.zone.id cls.services["server_with_disk"]["diskoffering"] = cls.disk_offering.id @@ -351,7 +352,8 @@ class TestSnapshots(cloudstackTestCase): # Create VMs, NAT Rules etc cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=cls.domain.id ) cls.services["account"] = cls.account.account.name @@ -366,6 +368,7 @@ class TestSnapshots(cloudstackTestCase): cls.services["server_with_disk"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) @@ -375,6 +378,7 @@ class TestSnapshots(cloudstackTestCase): cls.services["server_without_disk"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) @@ -519,7 +523,7 @@ class TestSnapshots(cloudstackTestCase): self.debug(c) result = ssh_client.execute(c) self.debug(result) - + except Exception as e: self.fail("SSH failed for VM with IP: %s" % self.virtual_machine_with_disk.ipaddress) @@ -1062,6 +1066,7 @@ class TestSnapshots(cloudstackTestCase): self.services["server_without_disk"], templateid=template.id, accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id, mode=self.services["mode"] ) diff --git a/tools/testClient/testcase/BVT-tests/test_ssvm.py b/tools/testClient/testcase/BVT-tests/test_ssvm.py index 5e0d9b01fc1..ce034cb0b95 100644 --- a/tools/testClient/testcase/BVT-tests/test_ssvm.py +++ b/tools/testClient/testcase/BVT-tests/test_ssvm.py @@ -27,9 +27,6 @@ class Services: "password": 'fr3sca', "publicport": 22, }, - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests "sleep": 60, "timeout": 10, } diff --git a/tools/testClient/testcase/BVT-tests/test_templates.py b/tools/testClient/testcase/BVT-tests/test_templates.py index 59d2e1f1150..c7e1393aa99 100644 --- a/tools/testClient/testcase/BVT-tests/test_templates.py +++ b/tools/testClient/testcase/BVT-tests/test_templates.py @@ -46,7 +46,6 @@ class Services: "virtual_machine": { "displayname": "testVM", "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "protocol": 'TCP', "ssh_port": 22, "username": "root", @@ -60,12 +59,12 @@ class Services: "template_1": { "displaytext": "Cent OS Template", "name": "Cent OS Template", - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', }, "template_2": { "displaytext": "Public Template", "name": "Public template", - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', "isfeatured": True, "ispublic": True, "isextractable": True, @@ -79,10 +78,7 @@ class Services: "isextractable": False, "bootable": True, "passwordenabled": True, - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', "mode": 'advanced', # Networking mode: Advanced, basic "sleep": 30, @@ -115,6 +111,7 @@ class TestCreateTemplate(cloudstackTestCase): cls.api_client = fetch_api_client() # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) cls.disk_offering = DiskOffering.create( cls.api_client, @@ -132,7 +129,8 @@ class TestCreateTemplate(cloudstackTestCase): cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=cls.domain.id ) cls.services["account"] = cls.account.account.name @@ -146,6 +144,7 @@ class TestCreateTemplate(cloudstackTestCase): cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) @@ -274,6 +273,7 @@ class TestTemplates(cloudstackTestCase): cls.api_client = fetch_api_client() # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) cls.disk_offering = DiskOffering.create( cls.api_client, @@ -292,12 +292,15 @@ class TestTemplates(cloudstackTestCase): cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + admin=True, + domainid=cls.domain.id ) cls.user = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=cls.domain.id ) cls.services["account"] = cls.account.account.name @@ -312,6 +315,7 @@ class TestTemplates(cloudstackTestCase): cls.services["virtual_machine"], templateid=template.id, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) @@ -426,7 +430,6 @@ class TestTemplates(cloudstackTestCase): cmd.name = new_name cmd.bootable = self.services["bootable"] cmd.passwordenabled = self.services["passwordenabled"] - cmd.ostypeid = self.services["ostypeid"] self.apiclient.updateTemplate(cmd) diff --git a/tools/testClient/testcase/BVT-tests/test_vm_life_cycle.py b/tools/testClient/testcase/BVT-tests/test_vm_life_cycle.py index c7f5f316f0b..db287d395ec 100644 --- a/tools/testClient/testcase/BVT-tests/test_vm_life_cycle.py +++ b/tools/testClient/testcase/BVT-tests/test_vm_life_cycle.py @@ -43,7 +43,6 @@ class Services: "password": "password", "ssh_port": 22, "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "privateport": 22, "publicport": 22, "protocol": 'TCP', @@ -55,7 +54,6 @@ class Services: "password": "password", "ssh_port": 22, "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "privateport": 22, "publicport": 22, "protocol": 'TCP', @@ -97,7 +95,7 @@ class Services: "name": "testISO", "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", # Source URL where ISO is located - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO }, "diskdevice": '/dev/xvdd', @@ -107,11 +105,8 @@ class Services: "timeout": 10, "hostid": 5, #Migrate VM to hostid - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', # CentOS 5.3 (64-bit) - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests "mode":'advanced', # Networking mode: Basic or Advanced } @@ -125,6 +120,7 @@ class TestDeployVM(cloudstackTestCase): self.dbclient = self.testClient.getDbConnection() self.services = Services().services # Get Zone, Domain and templates + domain = get_domain(self.apiclient, self.services) zone = get_zone(self.apiclient, self.services) template = get_template( @@ -143,7 +139,8 @@ class TestDeployVM(cloudstackTestCase): # Create Account, VMs, NAT Rules etc self.account = Account.create( self.apiclient, - self.services["account"] + self.services["account"], + domainid=domain.id ) self.service_offering = ServiceOffering.create( @@ -169,6 +166,7 @@ class TestDeployVM(cloudstackTestCase): self.apiclient, self.services["small"], accountid=self.account.account.name, + domainid=self.account.account.domainid, serviceofferingid=self.service_offering.id ) @@ -224,6 +222,7 @@ class TestVMLifeCycle(cloudstackTestCase): 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, @@ -241,7 +240,8 @@ class TestVMLifeCycle(cloudstackTestCase): # Create VMs, NAT Rules etc cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=domain.id ) cls.small_offering = ServiceOffering.create( @@ -258,6 +258,7 @@ class TestVMLifeCycle(cloudstackTestCase): 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"] ) @@ -265,6 +266,7 @@ class TestVMLifeCycle(cloudstackTestCase): cls.api_client, cls.services["medium"], accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.medium_offering.id, mode=cls.services["mode"] ) @@ -272,6 +274,7 @@ class TestVMLifeCycle(cloudstackTestCase): 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"] ) @@ -322,7 +325,7 @@ class TestVMLifeCycle(cloudstackTestCase): self.assertNotEqual( len(list_vm_response), 0, - "Check VM avaliable in List Virtual Machines" + "Check VM available in List Virtual Machines" ) self.assertEqual( diff --git a/tools/testClient/testcase/BVT-tests/test_volumes.py b/tools/testClient/testcase/BVT-tests/test_volumes.py index 589367bffcd..463ed7163c5 100644 --- a/tools/testClient/testcase/BVT-tests/test_volumes.py +++ b/tools/testClient/testcase/BVT-tests/test_volumes.py @@ -48,7 +48,6 @@ class Services: "volume_offerings": { 0: { "diskname": "TestDiskServ", - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', }, }, "customdisksize": 1, # GBs @@ -57,15 +56,11 @@ class Services: "ssh_port": 22, "diskname": "TestDiskServ", "hypervisor": 'XenServer', - "domainid": '9ee36d2e-8b8f-432e-a927-a678ebec1d6b', "privateport": 22, "publicport": 22, "protocol": 'TCP', "diskdevice": "/dev/xvdb", - "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', - "zoneid": '4a6c0290-e64d-40fc-afbb-4a05cab6fa4b', - # Optional, if specified the mentioned zone will be - # used for tests + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', "mode": 'advanced', "sleep": 60, "timeout": 10, @@ -80,6 +75,7 @@ class TestCreateVolume(cloudstackTestCase): cls.services = Services().services # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) cls.disk_offering = DiskOffering.create( cls.api_client, @@ -95,6 +91,7 @@ class TestCreateVolume(cloudstackTestCase): cls.zone.id, cls.services["ostypeid"] ) + cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id cls.services["template"] = template.id cls.services["customdiskofferingid"] = cls.custom_disk_offering.id @@ -102,7 +99,8 @@ class TestCreateVolume(cloudstackTestCase): # Create VMs, NAT Rules etc cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=cls.domain.id ) cls.services["account"] = cls.account.account.name @@ -114,6 +112,7 @@ class TestCreateVolume(cloudstackTestCase): cls.api_client, cls.services, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) @@ -263,6 +262,7 @@ class TestVolumes(cloudstackTestCase): cls.api_client = fetch_api_client() cls.services = Services().services # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) cls.zone = get_zone(cls.api_client, cls.services) cls.disk_offering = DiskOffering.create( cls.api_client, @@ -273,6 +273,7 @@ class TestVolumes(cloudstackTestCase): cls.zone.id, cls.services["ostypeid"] ) + cls.services["domainid"] = cls.domain.id cls.services["zoneid"] = cls.zone.id cls.services["template"] = template.id cls.services["diskofferingid"] = cls.disk_offering.id @@ -280,7 +281,8 @@ class TestVolumes(cloudstackTestCase): # Create VMs, VMs etc cls.account = Account.create( cls.api_client, - cls.services["account"] + cls.services["account"], + domainid=cls.domain.id ) cls.services["account"] = cls.account.account.name @@ -292,6 +294,7 @@ class TestVolumes(cloudstackTestCase): cls.api_client, cls.services, accountid=cls.account.account.name, + domainid=cls.account.account.domainid, serviceofferingid=cls.service_offering.id, mode=cls.services["mode"] ) @@ -502,4 +505,4 @@ class TestVolumes(cloudstackTestCase): None, "Check if volume exists in ListVolumes" ) - return + return \ No newline at end of file diff --git a/tools/testClient/testcase/P1-tests/README b/tools/testClient/testcase/P1-tests/README new file mode 100644 index 00000000000..ba0a04c6714 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/README @@ -0,0 +1,36 @@ +P1 Cases +-------------------------------------- +These test cases are the core functionality tests that ensure the application is stable and can be tested thoroughly. +These P1 cases definitions are located at : https://docs.google.com/a/clogeny.com/spreadsheet/ccc?key=0Aq5M2ldK6eyedDJBa0EzM0RPNmdVNVZOWnFnOVJJcHc&hl=en_US + + +Guidelines +---------- +P1 test cases are being developed using Python's unittests2. Following are certain guidelines being followed + 1. Tests exercised for the same resource should ideally be present under a single suite or file. + + 2. Time-consuming operations that create new cloud resources like server creation, volume creation etc + should not necessarily be exercised per unit test. The resources can be shared by creating them at + the class-level using setUpClass and shared across all instances during a single run. + + 3. Certain tests pertaining to NAT, Firewall and Load Balancing warrant fresh resources per test. Hence a call should be + taken by the stakeholders regarding sharing resources. + + 4. Ensure that the tearDown/tearDownClass functions clean up all the resources created during the test run. + +For more information about unittests: http://docs.python.org/library/unittest.html + + +P1 Tests +---------- +The following files contain these P1 cases: + +1. test_snapshots.py - Snapshots related tests +2. test_routers.py - Router related tests +3. test_usage.py - Usage realted tests +4. test_account.py - Account related tests +5. test_resource_limits.py - Resource limits tests +6. test_security_groups.py - Security groups related tests +7. test_templates - templates related tests +8. test_volumes - Volumes related tests +9. test_blocker_bugs - Blocker bugs tests diff --git a/tools/testClient/testcase/P1-tests/__init__.py b/tools/testClient/testcase/P1-tests/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tools/testClient/testcase/P1-tests/test_accounts.py b/tools/testClient/testcase/P1-tests/test_accounts.py new file mode 100644 index 00000000000..70358ac9643 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_accounts.py @@ -0,0 +1,1365 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Account +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import remoteSSHClient +import datetime + + +class Services: + """Test Account Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "zone": { + "dns1": '121.242.190.180', + "internaldns1": '192.168.100.1', + "name" : "Basic test", + "networktype" : "Basic", + "dns2": '121.242.190.211', + }, + "pod": { + "name": "Test Pod", + "gateway": '192.168.100.1', + "netmask": '255.255.255.0', + "startip": '192.168.100.132', + "endip": '192.168.100.140', + }, + "physical_network": { + "name" : "Physical network 1", + }, + "network": { + "name": 'guestNetworkForBasicZone', + "displaytext": 'guestNetworkForBasicZone', + }, + "public_ip": { + "gateway": '192.168.100.1', + "netmask": '255.255.255.0', + "forvirtualnetwork": False, + "startip": '192.168.100.142', + "endip": '192.168.100.149', + "vlan": "untagged", + }, + "cluster": { + "clustername": "Xen Cluster", + "clustertype": "CloudManaged", + # CloudManaged or ExternalManaged" + "hypervisor": "XenServer", + # Hypervisor type + }, + "host": { + "hypervisor": 'XenServer', + # Hypervisor type + "clustertype": 'CloudManaged', + # CloudManaged or ExternalManaged" + "url": 'http://192.168.100.211', + "username": "root", + "password": "fr3sca", + "port": 22, + "ipaddress": '192.168.100.211' + }, + + "primary_storage": { + "name": "Test Primary", + "url": "nfs://192.168.100.150/mnt/DroboFS/Shares/nfsclo3", + # Format: File_System_Type/Location/Path + }, + "sec_storage": { + "url": "nfs://192.168.100.150/mnt/DroboFS/Shares/nfsclo4" + # Format: File_System_Type/Location/Path + + + }, + "mgmt_server": { + "ipaddress": '192.168.100.21', + "port": 22, + "username": 'root', + "password": 'fr3sca', + }, + "sysVM": { + "mnt_dir": '/mnt/test', + "sec_storage": '192.168.100.150', + "path": 'TestSec', + "command": '/usr/lib64/cloud/agent/scripts/storage/secondary/cloud-install-sys-tmplt', + "download_url": 'http://download.cloud.com/releases/2.2.0/systemvm.vhd.bz2', + "hypervisor": "xenserver", + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "user": { + "email": "user@test.com", + "firstname": "User", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "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', + }, + "template": { + "displaytext": "Public Template", + "name": "Public template", + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "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, + }, + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestAccounts(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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._cleanup = [cls.service_offering] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_create_account(self): + """Test Create Account and user for that account + """ + + # Validate the following + # 1. Create an Account. Verify the account is created. + # 2. Create User associated with that account. Verify the created user + + # Create an account + account = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % account.account.name) + self.cleanup.append(account) + list_accounts_response = list_accounts( + self.apiclient, + id=account.account.id + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "Check list accounts for valid data" + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "Check List Account response" + ) + + account_response = list_accounts_response[0] + self.assertEqual( + account.account.accounttype, + account_response.accounttype, + "Check Account Type of Created account" + ) + self.assertEqual( + account.account.name, + account_response.name, + "Check Account Name of Created account" + ) + # Create an User associated with account + user = User.create( + self.apiclient, + self.services["user"], + account=account.account.name, + domainid=account.account.domainid + ) + self.debug("Created user: %s" % user.id) + list_users_response = list_users( + self.apiclient, + id=user.id + ) + self.assertEqual( + isinstance(list_users_response, list), + True, + "Check list users for valid data" + ) + + self.assertNotEqual( + len(list_users_response), + 0, + "Check List User response" + ) + + user_response = list_users_response[0] + self.assertEqual( + user.username, + user_response.username, + "Check username of Created user" + ) + self.assertEqual( + user.state, + user_response.state, + "Check state of created user" + ) + return + + +class TestRemoveUserFromAccount(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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"] + ) + # Create an account + cls.account = Account.create( + cls.api_client, + cls.services["account"] + ) + + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, users etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_user_remove_VM_running(self): + """Test Remove one user from the account + """ + + # Validate the following + # 1. Create an account with 2 users. + # 2. Start 2 VMs; one for each user of the account + # 3. Remove one user from the account. Verify that account still exists. + # 4. Verify that VM started by the removed user are still running + + # Create an User associated with account and VMs + user_1 = User.create( + self.apiclient, + self.services["user"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created user: %s" % user_1.id) + user_2 = User.create( + self.apiclient, + self.services["user"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created user: %s" % user_2.id) + self.cleanup.append(user_2) + + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM in account: %s, ID: %s" % ( + self.account.account.name, + vm_1.id + )) + self.cleanup.append(vm_1) + + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM in account: %s, ID: %s" % ( + self.account.account.name, + vm_2.id + )) + self.cleanup.append(vm_2) + + # Remove one of the user + self.debug("Deleting user: %s" % user_1.id) + user_1.delete(self.apiclient) + + # Account should exist after deleting user + accounts_response = list_accounts( + self.apiclient, + id=self.account.account.id + ) + self.assertEqual( + isinstance(accounts_response, list), + True, + "Check for valid list accounts response" + ) + + self.assertNotEqual( + len(accounts_response), + 0, + "Check List Account response" + ) + vm_response = list_virtual_machines( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(vm_response, list), + True, + "Check for valid list VM response" + ) + + self.assertNotEqual( + len(vm_response), + 0, + "Check List VM response" + ) + + # VMs associated with that account should be running + for vm in vm_response: + self.assertEqual( + vm.state, + 'Running', + "Check state of VMs associated with account" + ) + return + @unittest.skip("Open Questions") + def test_02_remove_all_users(self): + """Test Remove both users from the account + """ + + # Validate the following + # 1. Remove both the users from the account. + # 2. Verify account is removed + # 3. Verify all VMs associated with that account got removed + + # Create an User associated with account and VMs + user_1 = User.create( + self.apiclient, + self.services["user"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created user: %s" % user_1.id) + user_2 = User.create( + self.apiclient, + self.services["user"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created user: %s" % user_2.id) + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM in account: %s, ID: %s" % ( + self.account.account.name, + vm_1.id + )) + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM in account: %s, ID: %s" % ( + self.account.account.name, + vm_2.id + )) + # Get users associated with an account + # (Total 3: 2 - Created & 1 default generated while account creation) + users = list_users( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(users, list), + True, + "Check for valid list users response" + ) + for user in users: + + self.debug("Deleting user: %s" % user.id) + cmd = deleteUser.deleteUserCmd() + cmd.id = user.id + self.apiclient.deleteUser(cmd) + + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + self.assertEqual( + isinstance(interval, list), + True, + "Check for valid list configurations response" + ) + self.debug("account.cleanup.interval: %s" % interval[0].value) + + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value)) + + # Account is removed after last user is deleted + account_response = list_accounts( + self.apiclient, + id=self.account.account.id + ) + self.assertEqual( + account_response, + None, + "Check List VM response" + ) + # All VMs associated with account are removed. + vm_response = list_virtual_machines( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + vm_response, + None, + "Check List VM response" + ) + # DomR associated with account is deleted + with self.assertRaises(Exception): + list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return + + +class TestNonRootAdminsPrivileges(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone settings + cls.zone = get_zone(cls.api_client, cls.services) + + # Create an account, domain etc + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"], + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup = [ + cls.account, + cls.domain + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created accounts + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_non_root_admin_Privileges(self): + """Test to verify Non Root admin previleges""" + + # Validate the following + # 1. Create few accounts/users in ROOT domain + # 2. Verify listAccounts API gives only accounts associated with new + # domain. + + # Create accounts for ROOT domain + account_1 = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % account_1.account.name) + self.cleanup.append(account_1) + account_2 = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % account_2.account.name) + self.cleanup.append(account_2) + + accounts_response = list_accounts( + self.apiclient, + domainid=self.domain.id + ) + + self.assertEqual( + isinstance(accounts_response, list), + True, + "Check list accounts response for valid data" + ) + + self.assertEqual( + len(accounts_response), + 1, + "Check List accounts response" + ) + # Verify only account associated with domain is listed + for account in accounts_response: + self.assertEqual( + account.domainid, + self.domain.id, + "Check domain ID of account" + ) + return + + +class TestServiceOfferingSiblings(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + + # Create Domains, accounts etc + cls.domain_1 = Domain.create( + cls.api_client, + cls.services["domain"] + ) + cls.domain_2 = Domain.create( + cls.api_client, + cls.services["domain"] + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + domainid=cls.domain_1.id + ) + # Create account for doamin_1 + cls.account_1 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain_1.id + ) + + # Create an account for domain_2 + cls.account_2 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain_2.id + ) + + cls._cleanup = [ + cls.account_1, + cls.account_2, + cls.service_offering, + cls.domain_1, + cls.domain_2, + ] + 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 domains, accounts + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_service_offering_siblings(self): + """Test to verify service offerings at same level in hierarchy""" + + # Validate the following + # 1. Verify service offering is visible for domain_1 + # 2. Verify service offering is not visible for domain_2 + + service_offerings = list_service_offering( + self.apiclient, + domainid=self.domain_1.id + ) + self.assertEqual( + isinstance(service_offerings, list), + True, + "Check if valid list service offerings response" + ) + + self.assertNotEqual( + len(service_offerings), + 0, + "Check List Service Offerings response" + ) + + for service_offering in service_offerings: + self.debug("Validating service offering: %s" % service_offering.id) + self.assertEqual( + service_offering.id, + self.service_offering.id, + "Check Service offering ID for domain" + str(self.domain_1.name) + ) + # Verify private service offering is not visible to other domain + service_offerings = list_service_offering( + self.apiclient, + domainid=self.domain_2.id + ) + self.assertEqual( + service_offerings, + None, + "Check List Service Offerings response for other domain" + ) + return + +@unittest.skip("Open Questions") +class TestServiceOfferingHierarchy(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + + # Create domain, service offerings etc + cls.domain_1 = Domain.create( + cls.api_client, + cls.services["domain"] + ) + cls.domain_2 = Domain.create( + cls.api_client, + cls.services["domain"], + parentdomainid=cls.domain_1.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + domainid=cls.domain_1.id + ) + # Create account for doamin_1 + cls.account_1 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain_1.id + ) + + # Create an account for domain_2 + cls.account_2 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain_2.id + ) + + cls._cleanup = [ + cls.account_1, + cls.account_2, + cls.service_offering, + cls.domain_1, + cls.domain_2, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_service_offering_hierarchy(self): + """Test to verify service offerings at same level in hierarchy""" + + # Validate the following + # 1. Verify service offering is visible for domain_1 + # 2. Verify service offering is also visible for domain_2 + + service_offerings = list_service_offering( + self.apiclient, + domainid=self.domain_1.id + ) + self.assertEqual( + isinstance(service_offerings, list), + True, + "Check List Service Offerings for a valid response" + ) + self.assertNotEqual( + len(service_offerings), + 0, + "Check List Service Offerings response" + ) + + for service_offering in service_offerings: + self.assertEqual( + service_offering.id, + self.service_offering.id, + "Check Service offering ID for domain" + str(self.domain_1.name) + ) + + # Verify private service offering is not visible to other domain + service_offerings = list_service_offering( + self.apiclient, + domainid=self.domain_2.id + ) + self.assertEqual( + isinstance(service_offerings, list), + True, + "Check List Service Offerings for a valid response" + ) + self.assertNotEqual( + len(service_offerings), + 0, + "Check List Service Offerings response" + ) + + for service_offering in service_offerings: + self.assertEqual( + service_offering.id, + self.service_offering.id, + "Check Service offering ID for domain" + str(self.domain_2.name) + ) + return + +@unittest.skip("Open Questions") +class TesttemplateHierarchy(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone settings + cls.zone = get_zone(cls.api_client, cls.services) + cls.services["template"]["zoneid"] = cls.zone.id + + # Create domains, accounts and template + cls.domain_1 = Domain.create( + cls.api_client, + cls.services["domain"] + ) + cls.domain_2 = Domain.create( + cls.api_client, + cls.services["domain"], + parentdomainid=cls.domain_1.id + ) + + # Create account for doamin_1 + cls.account_1 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain_1.id + ) + + # Create an account for domain_2 + cls.account_2 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain_2.id + ) + + cls.template = Template.register( + cls.api_client, + cls.services["template"], + account=cls.account_1.account.name, + domainid=cls.domain_1.id + ) + cls._cleanup = [ + cls.template, + cls.account_1, + cls.account_2, + cls.domain_1, + cls.domain_2, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_template_hierarchy(self): + """Test to verify template at same level in hierarchy""" + + # Validate the following + # 1. Verify template is visible for domain_1 + # 2. Verify template is also visible for domain_2 + + # Sleep to ensure that template state is reflected across + time.sleep(self.services["sleep"]) + + templates = list_templates( + self.apiclient, + templatefilter='self', + account=self.account_1.account.name, + domainid=self.domain_1.id + ) + self.assertEqual( + isinstance(templates, list), + True, + "Check List templates for a valid response" + ) + self.assertNotEqual( + len(templates), + 0, + "Check List Template response" + ) + + for template in templates: + self.assertEqual( + template.id, + self.template.id, + "Check Template ID for domain" + str(self.domain_1.name) + ) + + # Verify private service offering is not visible to other domain + templates = list_templates( + self.apiclient, + templatefilter='self', + account=self.account_2.account.name, + domainid=self.domain_2.id + ) + self.assertEqual( + isinstance(templates, list), + True, + "Check List templates for a valid response" + ) + self.assertNotEqual( + len(templates), + 0, + "Check List Service Offerings response" + ) + + for template in templates: + self.assertEqual( + template.id, + self.template.id, + "Check Template ID for domain" + str(self.domain_2.name) + ) + return + +@unittest.skip("Open Questions") +class TestAddVmToSubDomain(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + + # Setup working Environment- Create domain, zone, pod cluster etc. + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + cls.zone = Zone.create( + cls.api_client, + cls.services["zone"], + domainid=cls.domain.id + ) + cls.services["pod"]["zoneid"] = cls.zone.id + + cls.pod = Pod.create( + cls.api_client, + cls.services["pod"] + ) + cls.services["public_ip"]["zoneid"] = cls.zone.id + cls.services["public_ip"]["podid"] = cls.pod.id + + cls.physical_network = PhysicalNetwork.create( + cls.api_client, + cls.services["physical_network"], + cls.zone.id, + cls.domain.id + ) + cls.physical_network.addTrafficType( + cls.api_client, + type='Guest' + ) + cls.physical_network.addTrafficType( + cls.api_client, + type='Management' + ) + cls.physical_network.update( + cls.api_client, + state='Enabled' + ) + nsp_list = list_nw_service_prividers( + cls.api_client, + name='VirtualRouter', + physicalNetworkId=cls.physical_network.id + ) + if isinstance(nsp_list, list): + nsp = nsp_list[0] + else: + raise Exception("List Network Service Providers call failed") + + virtual_routers = list_virtual_router_elements( + cls.api_client, + nspid=nsp.id + ) + if isinstance(virtual_routers, list): + virtual_router = virtual_routers[0] + else: + raise Exception("List virtual routers call failed") + + cmd = configureVirtualRouterElement.configureVirtualRouterElementCmd() + cmd.id = virtual_router.id + cmd.enabled = True + cls.api_client.configureVirtualRouterElement(cmd) + + cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + cmd.id = nsp.id + cmd.state = 'Enabled' + cls.api_client.updateNetworkServiceProvider(cmd) + + nsp_list = list_nw_service_prividers( + cls.api_client, + name='SecurityGroupProvider', + physicalNetworkId=cls.physical_network.id + ) + if isinstance(nsp_list, list): + nsp = nsp_list[0] + else: + raise Exception("List Network Service Providers call failed") + + cmd = updateNetworkServiceProvider.updateNetworkServiceProviderCmd() + cmd.id = nsp.id + cmd.state = 'Enabled' + cls.api_client.updateNetworkServiceProvider(cmd) + + network_offerings = list_network_offerings( + cls.api_client, + ) + if isinstance(network_offerings, list): + cls.services["network"]["networkoffering"] = network_offerings[0].id + else: + raise Exception("Invalid Network offering ID") + + cls.services["network"]["zoneid"] = cls.zone.id + cls.network = Network.create( + cls.api_client, + cls.services["network"] + ) + + cls.public_ip_range = PublicIpRange.create( + cls.api_client, + cls.services["public_ip"] + ) + + cls.services["cluster"]["zoneid"] = cls.zone.id + cls.services["cluster"]["podid"] = cls.pod.id + + cls.cluster = Cluster.create( + cls.api_client, + cls.services["cluster"] + ) + + cls.services["host"]["zoneid"] = cls.zone.id + cls.services["host"]["podid"] = cls.pod.id + + cls.host = Host.create( + cls.api_client, + cls.cluster, + cls.services["host"] + ) + + cls.services["primary_storage"]["zoneid"] = cls.zone.id + cls.services["primary_storage"]["podid"] = cls.pod.id + + cls.primary_storage = StoragePool.create( + cls.api_client, + cls.services["primary_storage"], + cls.cluster.id + ) + + # before adding Sec Storage, First download System Templates on it + download_systemplates_sec_storage( + cls.services["mgmt_server"], + cls.services["sysVM"] + ) + + cls.services["sec_storage"]["zoneid"] = cls.zone.id + cls.services["sec_storage"]["podid"] = cls.pod.id + + cls.secondary_storage = SecondaryStorage.create( + cls.api_client, + cls.services["sec_storage"] + ) + + # Enable the zone + + cls.zone.update( + cls.api_client, + allocationstate='Enabled' + ) + # After adding Host, Clusters wait for SSVMs to come up + wait_for_ssvms( + cls.api_client, + cls.zone.id, + cls.pod.id + ) + + ssvm_response = list_ssvms( + cls.api_client, + systemvmtype='secondarystoragevm', + hostid=cls.host.id, + sleep=cls.services["sleep"] + ) + if isinstance(ssvm_response, list): + ssvm = ssvm_response[0] + else: + raise Exception("List SSVM failed") + + # Download BUILTIN templates + download_builtin_templates( + cls.api_client, + cls.zone.id, + cls.services["cluster"]["hypervisor"], + cls.services["host"], + ssvm.linklocalip + ) + cls.sub_domain = Domain.create( + cls.api_client, + cls.services["domain"], + parentdomainid=cls.domain.id + ) + + # Create account for doamin_1 + cls.account_1 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Create an account for domain_2 + cls.account_2 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.sub_domain.id + ) + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + domainid=cls.domain.id + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=cls.template.id, + accountid=cls.account_1.account.name, + domainid=cls.account_1.account.domainid, + serviceofferingid=cls.service_offering.id + ) + + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=cls.template.id, + accountid=cls.account_2.account.name, + domainid=cls.account_2.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup the accounts + cls.account_1.delete(cls.api_client) + cls.account_2.delete(cls.api_client) + + cleanup_wait = list_configurations( + cls.api_client, + name='account.cleanup.interval' + ) + + # Sleep for account.cleanup.interval * 2 to wait for expunge of + # resources associated with that account + if isinstance(cleanup_wait, list): + sleep_time = int(cleanup_wait[0].value) * 2 + + time.sleep(sleep_time) + + # Delete Service offerings and sub-domains + cls.service_offering.delete(cls.api_client) + cls.sub_domain.delete(cls.api_client) + + # Enable maintenance mode of + cls.host.enableMaintenance(cls.api_client) + cls.primary_storage.enableMaintenance(cls.api_client) + + # Destroy SSVMs and wait for volumes to cleanup + ssvms = list_ssvms( + cls.api_client, + zoneid=cls.zone.id + ) + + if isinstance(ssvms, list): + for ssvm in ssvms: + cmd = destroySystemVm.destroySystemVmCmd() + cmd.id = ssvm.id + cls.api_client.destroySystemVm(cmd) + + # Sleep for account.cleanup.interval*2 to wait for SSVM volume + # to cleanup + time.sleep(sleep_time) + + # Cleanup Primary, secondary storage, hosts, zones etc. + cls.secondary_storage.delete(cls.api_client) + + cls.host.delete(cls.api_client) + cls.primary_storage.delete(cls.api_client) + + cls.network.delete(cls.api_client) + cls.cluster.delete(cls.api_client) + + cls.physical_network.delete(cls.api_client) + cls.pod.delete(cls.api_client) + cls.zone.delete(cls.api_client) + + 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 resources + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + + def test_01_add_vm_to_subdomain(self): + """ Test Sub domain allowed to launch VM when a Domain level zone is + created""" + + # Validate the following + # 1. Verify VM created by Account_1 is in Running state + # 2. Verify VM created by Account_2 is in Running state + + vm_response = list_virtual_machines( + self.apiclient, + id=self.vm_1.id + ) + self.assertEqual( + isinstance(vm_response, list), + True, + "Check List VM for a valid response" + ) + self.assertNotEqual( + len(vm_response), + 0, + "Check List Template response" + ) + + for vm in vm_response: + self.debug("VM ID: %s and state: %s" % (vm.id, vm.state)) + self.assertEqual( + vm.state, + 'Running', + "Check State of Virtual machine" + ) + + vm_response = list_virtual_machines( + self.apiclient, + id=self.vm_2.id + ) + self.assertNotEqual( + len(vm_response), + 0, + "Check List Template response" + ) + + for vm in vm_response: + self.debug("VM ID: %s and state: %s" % (vm.id, vm.state)) + self.assertEqual( + vm.state, + 'Running', + "Check State of Virtual machine" + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_blocker_bugs.py b/tools/testClient/testcase/P1-tests/test_blocker_bugs.py new file mode 100644 index 00000000000..b5c1e03ab65 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_blocker_bugs.py @@ -0,0 +1,1264 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# + +""" Tests for Blocker bugs +""" +from testcase.libs.base import * +from testcase.libs.utils import * +from testcase.libs.common import * + +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +import remoteSSHClient + +class Services: + """Test Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "disk_offering": { + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "volume": { + "diskname": "APP Data Volume", + "size": 1, # in GBs + "diskdevice": "/dev/xvdb", # Data Disk + }, + "templates": { + "displaytext": 'Template from snapshot', + "name": 'Template from snapshot', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "templatefilter": 'self', + "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, + "passwordenabled":True, + }, + "paths": { + "mount_dir": "/mnt/tmp", + "sub_dir": "test", + "sub_lvl_dir1": "test1", + "sub_lvl_dir2": "test2", + "random_data": "random.data", + }, + "static_nat": { + "startport": 22, + "endport": 22, + "protocol": "TCP" + }, + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + # Cent OS 5.3 (64 bit) + "sleep":60, + "mode": 'advanced', + # Networking mode, Advanced, Basic + } + + +class TestSnapshots(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["volume"]["zoneid"] = cls.zone.id + + cls.services["template"] = cls.template.id + cls.services["zoneid"] = cls.zone.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=cls.template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_volume_from_snapshot(self): + """TS_BUG_001-Test Creating snapshot from volume having spaces in name(KVM) + """ + + # Validate the following + #1. Create a virtual machine and data volume + #2. Attach data volume to VM + #3. Login to machine; create temp/test directories on data volume + #4. Snapshot the Volume + #5. Create another Volume from snapshot + #6. Mount/Attach volume to another server + #7. Compare data + + random_data_0 = random_gen(100) + random_data_1 = random_gen(100) + + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume with ID: %s" % volume.id) + self.virtual_machine.attach_volume( + self.apiclient, + volume + ) + self.debug("Attach volume: %s to VM: %s" % + (volume.id, self.virtual_machine.id)) + try: + ssh_client = self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH failed for VM: %s" % + self.virtual_machine.ipaddress) + + self.debug("Formatting volume: %s to ext3" % volume.id) + #Format partition using ext3 + format_volume_to_ext3( + ssh_client, + self.services["volume"]["diskdevice"] + ) + cmds = [ + "mkdir -p %s" % self.services["paths"]["mount_dir"], + "mount %s1 %s" % ( + self.services["volume"]["diskdevice"], + self.services["paths"]["mount_dir"] + ), + "mkdir -p %s/%s/{%s,%s} " % ( + self.services["paths"]["mount_dir"], + self.services["paths"]["sub_dir"], + self.services["paths"]["sub_lvl_dir1"], + self.services["paths"]["sub_lvl_dir2"] + ), + "echo %s > %s/%s/%s/%s" % ( + random_data_0, + self.services["paths"]["mount_dir"], + self.services["paths"]["sub_dir"], + self.services["paths"]["sub_lvl_dir1"], + self.services["paths"]["random_data"] + ), + "echo %s > %s/%s/%s/%s" % ( + random_data_1, + self.services["paths"]["mount_dir"], + self.services["paths"]["sub_dir"], + self.services["paths"]["sub_lvl_dir2"], + self.services["paths"]["random_data"] + ), + ] + for c in cmds: + self.debug("Command: %s" % c) + ssh_client.execute(c) + + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["paths"]["mount_dir"]), + ] + for c in cmds: + self.debug("Command: %s" % c) + ssh_client.execute(c) + + list_volume_response = Volume.list( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volume response for valid data" + ) + volume_response = list_volume_response[0] + #Create snapshot from attached volume + snapshot = Snapshot.create( + self.apiclient, + volume_response.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created snapshot: %s" % snapshot.id) + #Create volume from snapshot + volume_from_snapshot = Volume.create_from_snapshot( + self.apiclient, + snapshot.id, + self.services["volume"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created Volume: %s from Snapshot: %s" % ( + volume_from_snapshot.id, + snapshot.id)) + volumes = Volume.list( + self.apiclient, + id=volume_from_snapshot.id + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + len(volumes), + None, + "Check Volume list Length" + ) + self.assertEqual ( + volumes[0].id, + volume_from_snapshot.id, + "Check Volume in the List Volumes" + ) + #Attaching volume to new VM + new_virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + mode=self.services["mode"] + ) + self.debug("Deployed new VM for account: %s" % self.account.account.name) + self.cleanup.append(new_virtual_machine) + + self.debug("Attaching volume: %s to VM: %s" % ( + volume_from_snapshot.id, + new_virtual_machine.id + )) + + cmd = attachVolume.attachVolumeCmd() + cmd.id = volume_from_snapshot.id + cmd.virtualmachineid = new_virtual_machine.id + self.apiclient.attachVolume(cmd) + + try: + #Login to VM to verify test directories and files + ssh = new_virtual_machine.get_ssh_client() + + cmds = [ + "mkdir -p %s" % self.services["paths"]["mount_dir"], + "mount %s1 %s" % ( + self.services["volume"]["diskdevice"], + self.services["paths"]["mount_dir"] + ), + ] + + for c in cmds: + self.debug("Command: %s" % c) + ssh.execute(c) + + returned_data_0 = ssh.execute( + "cat %s/%s/%s/%s" % ( + self.services["paths"]["mount_dir"], + self.services["paths"]["sub_dir"], + self.services["paths"]["sub_lvl_dir1"], + self.services["paths"]["random_data"] + )) + returned_data_1 = ssh.execute( + "cat %s/%s/%s/%s" % ( + self.services["paths"]["mount_dir"], + self.services["paths"]["sub_dir"], + self.services["paths"]["sub_lvl_dir2"], + self.services["paths"]["random_data"] + )) + except Exception as e: + self.fail("SSH access failed for VM: %s" % + new_virtual_machine.ipaddress) + #Verify returned data + self.assertEqual( + random_data_0, + returned_data_0[0], + "Verify newly attached volume contents with existing one" + ) + self.assertEqual( + random_data_1, + returned_data_1[0], + "Verify newly attached volume contents with existing one" + ) + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["paths"]["mount_dir"]), + ] + for c in cmds: + self.debug("Command: %s" % c) + ssh_client.execute(c) + return + + +class TestTemplate(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["templates"]["zoneid"] = cls.zone.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_create_template(self): + """TS_BUG_002-Test to create and deploy VM using password enabled template + """ + + # Validate the following: + #1. Create a password enabled template + #2. Deploy VM using this template + #3. Deploy VM should return password set in template. + + self.debug("Registering a new template") + # Register new template + template = Template.register( + self.apiclient, + self.services["templates"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Registering template with ID: %s" % template.id) + try: + # Wait for template to download + template.download(self.apiclient) + except Exception as e: + self.fail("Exception while downloading template %s: %s"\ + % (template.id, e)) + + self.cleanup.append(template) + + # Wait for template status to be changed across + time.sleep(self.services["sleep"]) + + list_template_response = Template.list( + self.apiclient, + templatefilter=\ + self.services["templatefilter"], + id=template.id, + zoneid=self.zone.id + ) + + self.assertEqual( + isinstance(list_template_response, list), + True, + "Check list response returns a valid list" + ) + #Verify template response to check whether template added successfully + self.assertNotEqual( + len(list_template_response), + 0, + "Check template available in List Templates" + ) + template_response = list_template_response[0] + + self.assertEqual( + template_response.isready, + True, + "Check display text of newly created template" + ) + + # Deploy new virtual machine using template + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.debug("Deployed VM with ID: %s " % virtual_machine.id) + self.assertEqual( + hasattr(virtual_machine,"password"), + True, + "Check if the deployed VM returned a password" + ) + return + + +class TestNATRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = fetch_api_client() + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + #Create an account, network, VM and IP addresses + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + services=cls.services["virtual_machine"] + ) + cls._cleanup = [ + cls.virtual_machine, + cls.account, + cls.service_offering + ] + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def tearDown(self): + cleanup_resources(self.apiclient, self.cleanup) + return + + def test_01_firewall_rules_port_fw(self): + """"Checking firewall rules deletion after static NAT disable""" + + # Validate the following: + #1. Enable static NAT for a VM + #2. Open up some ports. At this point there will be new rows in the + # firewall_rules table. + #3. Disable static NAT for the VM. + #4. Check fire wall rules are deleted from firewall_rules table. + + public_ip = self.public_ip.ipaddress + + # Enable Static NAT for VM + StaticNATRule.enable( + self.apiclient, + public_ip.id, + self.virtual_machine.id + ) + self.debug("Enabled static NAT for public IP ID: %s" % + public_ip.id) + #Create Static NAT rule + nat_rule = StaticNATRule.create( + self.apiclient, + self.services["static_nat"], + public_ip.id + ) + self.debug("Created Static NAT rule for public IP ID: %s" % + public_ip.id) + list_rules_repsonse = StaticNATRule.list( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(list_rules_repsonse, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(list_rules_repsonse), + 0, + "Check IP Forwarding Rule is created" + ) + self.assertEqual( + list_rules_repsonse[0].id, + nat_rule.id, + "Check Correct IP forwarding Rule is returned" + ) + # Verify the entries made in firewall_rules tables + self.debug( + "select id from user_ip_address where uuid = '%s';" \ + % public_ip.id + ) + qresultset = self.dbclient.execute( + "select id from user_ip_address where uuid = '%s';" \ + % public_ip.id + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check database query returns a valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + qresult = qresultset[0] + public_ip_id = qresult[0] + # Verify the entries made in firewall_rules tables + self.debug( + "select id, state from firewall_rules where ip_address_id = '%s';" \ + % public_ip_id + ) + qresultset = self.dbclient.execute( + "select id, state from firewall_rules where ip_address_id = '%s';" \ + % public_ip_id + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check database query returns a valid data for firewall rules" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + + for qresult in qresultset: + self.assertEqual( + qresult[1], + 'Active', + "Check state of the static NAT rule in database" + ) + + nat_rule.delete(self.apiclient) + + list_rules_repsonse = StaticNATRule.list( + self.apiclient, + id=nat_rule.id + ) + + self.assertEqual( + list_rules_repsonse, + None, + "Check Port Forwarding Rule is deleted" + ) + + # Verify the entries made in firewall_rules tables + self.debug( + "select id, state from firewall_rules where ip_address_id = '%s';" \ + % public_ip.id + ) + qresultset = self.dbclient.execute( + "select id, state from firewall_rules where ip_address_id = '%s';" \ + % public_ip.id + ) + + self.assertEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + return + + +class TestRouters(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + # Create an account, domain etc + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"], + ) + cls.admin_account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.user_account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + 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._cleanup = [ + cls.service_offering, + cls.admin_account, + cls.user_account, + cls.domain + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, users etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_list_routers_admin(self): + """TS_BUG_007-Check listRouters() using Admin User + """ + + # Validate the following + # 1. PreReq: have rounters that are owned by other account + # 2. Create domain and create accounts in that domain + # 3. Create one VM for each account + # 4. Using Admin , run listRouters. It should return all the routers + + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM with ID: %s" % vm_1.id) + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.user_account.account.name, + domainid=self.user_account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM with ID: %s" % vm_2.id) + routers = list_routers( + self.apiclient, + account=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + # ListRouter Should return 2 records + self.assertEqual( + len(routers), + 1, + "Check list router response" + ) + for router in routers: + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + return + + +class TestRouterRestart(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + #Create an account, network, VM and IP addresses + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.cleanup = [ + cls.vm_1, + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Clean up, terminate the created templates + cleanup_resources(cls.api_client, cls.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + return + + + def test_01_restart_network_cleanup(self): + """TS_BUG_008-Test restart network + """ + + # Validate the following + # 1. When cleanup = true, router is destroyed and a new one created + # 2. New router will have new publicIp and linkLocalIp and + # all it's services should resume + + # Find router associated with user account + list_router_response = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(list_router_response, list), + True, + "Check list response returns a valid list" + ) + router = list_router_response[0] + + #Store old values before restart + old_linklocalip = router.linklocalip + + timeout = 10 + # Network should be in Implemented or Setup stage before restart + while True: + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + network = networks[0] + if network.state in ["Implemented", "Setup"]: + break + elif timeout == 0: + break + else: + time.sleep(60) + timeout = timeout - 1 + + self.debug("Restarting network: %s" % network.id) + cmd = restartNetwork.restartNetworkCmd() + cmd.id = network.id + cmd.cleanup = True + self.apiclient.restartNetwork(cmd) + + # Get router details after restart + list_router_response = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(list_router_response, list), + True, + "Check list response returns a valid list" + ) + router = list_router_response[0] + + self.assertNotEqual( + router.linklocalip, + old_linklocalip, + "Check link-local IP after restart" + ) + return + + +class TestTemplates(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, templates etc + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # create virtual machine + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) + + #Wait before server has be successfully stopped + time.sleep(30) + list_volume = Volume.list( + cls.api_client, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True + ) + try: + if isinstance(list_volume, list): + cls.volume = list_volume[0] + except Exception as e: + raise Exception("Warning: Exception during setup : %s" % e) + + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup created resources such as templates and VMs + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_check_template_size(self): + """TS_BUG_009-Test the size of template created from root disk + """ + + # Validate the following: + # 1. Deploy new VM using the template created from Volume + # 2. VM should be in Up and Running state + + #Create template from volume + template = Template.create( + self.apiclient, + self.services["templates"], + self.volume.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Creating template with ID: %s" % template.id) + # Volume and Template Size should be same + self.assertEqual( + template.size, + self.volume.size, + "Check if size of template and volume are same" + ) + return + + def test_02_check_size_snapshotTemplate(self): + """TS_BUG_010-Test check size of snapshot and template + """ + + # Validate the following + # 1. Deploy VM using default template, small service offering + # and small data disk offering. + # 2. Perform snapshot on the root disk of this VM. + # 3. Create a template from snapshot. + # 4. Check the size of snapshot and template + + # Create a snapshot from the ROOTDISK + snapshot = Snapshot.create( + self.apiclient, + self.volume.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created snapshot with ID: %s" % snapshot.id) + snapshots = Snapshot.list( + self.apiclient, + id=snapshot.id + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + + # Generate template from the snapshot + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"] + ) + self.cleanup.append(template) + + self.debug("Created template from snapshot with ID: %s" % template.id) + templates = Template.list( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + self.assertEqual( + isinstance(templates, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + templates, + None, + "Check if result exists in list item call" + ) + + self.assertEqual( + templates[0].isready, + True, + "Check new template state in list templates call" + ) + # check size of template with that of snapshot + self.assertEqual( + templates[0].size, + self.volume.size, + "Check if size of snapshot and template matches" + ) + return + + def test_03_resuse_template_name(self): + """TS_BUG_011-Test Reusing deleted template name + """ + + # Validate the following + # 1. Deploy VM using default template, small service offering + # and small data disk offering. + # 2. Perform snapshot on the root disk of this VM. + # 3. Create a template from snapshot. + # 4. Delete the template and create a new template with same name + # 5. Template should be created succesfully + + # Create a snapshot from the ROOTDISK + snapshot = Snapshot.create( + self.apiclient, + self.volume.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created snapshot with ID: %s" % snapshot.id) + snapshots = Snapshot.list( + self.apiclient, + id=snapshot.id + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + + # Generate template from the snapshot + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"], + random_name=False + ) + self.debug("Created template from snapshot: %s" % template.id) + templates = Template.list( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + self.assertEqual( + isinstance(templates, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + templates, + None, + "Check if result exists in list item call" + ) + + self.assertEqual( + templates[0].isready, + True, + "Check new template state in list templates call" + ) + + self.debug("Deleting template: %s" % template.id) + template.delete(self.apiclient) + + # Wait for some time to ensure template state is reflected in other calls + time.sleep(self.services["sleep"]) + + # Generate template from the snapshot + self.debug("Creating template from snapshot: %s with same name" % + template.id) + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"], + random_name=False + ) + + templates = Template.list( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + self.assertEqual( + isinstance(templates, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + templates, + None, + "Check if result exists in list item call" + ) + + self.assertEqual( + templates[0].name, + self.services["templates"]["name"], + "Check the name of the template" + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_resource_limits.py b/tools/testClient/testcase/P1-tests/test_resource_limits.py new file mode 100644 index 00000000000..edcc557b721 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_resource_limits.py @@ -0,0 +1,1265 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Resource limits +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import datetime + +class Services: + """Test Resource Limits Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "disk_offering": { + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "volume": { + "diskname": "TestDiskServ", + }, + "server": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "templatefilter": 'self', + }, + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced', + } + +class TestResourceLimitsAccount(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + 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["server"]["zoneid"] = cls.zone.id + + # Create Account, VMs etc + cls.account_1 = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Create Account, VMs etc + cls.account_2 = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls._cleanup = [ + cls.disk_offering, + cls.service_offering, + cls.account_1, + cls.account_2 + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_vm_per_account(self): + """Test VM limit per account + """ + + # Validate the following + # 1. Set user_vm=1 limit for account 1. + # 2. Try to start 2 VMs account 1. Verify start of second VM is denied + # for this account. + # 3. Try to start 2 VMs account 2. Verify 2 SM are started properly + + self.debug( + "Updating instance resource limit for account: %s" % + self.account_1.account.name) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 0, # Instance + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + max=1 + ) + self.debug( + "Deploying VM instance in account: %s" % + self.account_1.account.name) + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine) + + # Verify VM state + self.assertEqual( + virtual_machine.state, + 'Running', + "Check VM state is Running or not" + ) + + # Exception should be raised for second instance (account_1) + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug( + "Deploying VM instance in account: %s" % + self.account_2.account.name) + # Start 2 instances for account_2 + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + self.debug( + "Deploying VM instance in account: %s" % + self.account_2.account.name) + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + return + + def test_02_publicip_per_account(self): + """Test Public IP limit per account + """ + + # Validate the following + # 1. Set Public_IP= 2 limit for account 1. + # 2. start 1 VMs account 1 + # 3. start 1 VMs account 2 + # 4. Acquire 2 IP in account 1. Verify account with limit should be + # denied to acquire more than one IP. + # 5. Acquire 2 IP in account 2. Verify account 2 should be able to + # Acquire IP without any warning + + self.debug( + "Updating public IP resource limit for account: %s" % + self.account_1.account.name) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 1, # Public Ip + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + max=2 + ) + + self.debug( + "Deploying VM instance in account: %s" % + self.account_1.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + self.debug( + "Deploying VM instance in account: %s" % + self.account_2.account.name) + # Create VM for second account + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + self.debug( + "Associating public IP for account: %s" % + virtual_machine_1.account) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + virtual_machine_1.account, + virtual_machine_1.zoneid, + virtual_machine_1.domainid, + self.services["server"] + ) + self.cleanup.append(public_ip_1) + + # Sleep to ensure that state is reflected across all the calls + time.sleep(self.services["sleep"]) + + # Verify Public IP state + self.assertEqual( + public_ip_1.ipaddress.state in [ + 'Allocated', + 'Allocating' + ], + True, + "Check Public IP state is allocated or not" + ) + + # Exception should be raised for second instance (account_1) + with self.assertRaises(Exception): + public_ip_2 = PublicIPAddress.create( + self.apiclient, + virtual_machine_1.account, + virtual_machine_1.zoneid, + virtual_machine_1.domainid, + self.services["server"] + ) + + self.debug( + "Associating public IP for account: %s" % + virtual_machine_2.account) + # Assign Public IP for account 2 + public_ip_3 = PublicIPAddress.create( + self.apiclient, + virtual_machine_2.account, + virtual_machine_2.zoneid, + virtual_machine_2.domainid, + self.services["server"] + ) + self.cleanup.append(public_ip_3) + + # Verify Public IP state + self.assertEqual( + public_ip_3.ipaddress.state in [ + 'Allocated', + 'Allocating' + ], + True, + "Check Public IP state is allocated or not" + ) + self.debug( + "Associating public IP for account: %s" % + virtual_machine_2.account) + public_ip_4 = PublicIPAddress.create( + self.apiclient, + virtual_machine_2.account, + virtual_machine_2.zoneid, + virtual_machine_2.domainid, + self.services["server"] + ) + self.cleanup.append(public_ip_4) + # Verify Public IP state + self.assertEqual( + public_ip_4.ipaddress.state in [ + 'Allocated', + 'Allocating' + ], + True, + "Check Public IP state is allocated or not" + ) + return + + def test_03_snapshots_per_account(self): + """Test Snapshot limit per account + """ + + # Validate the following + # 1. Set snapshot= 2 limit for account 1. + # 2. start 1 VMs account 1 + # 3. start 1 VMs account 2 + # 4. Create 2 snapshot in account 1. Verify account with limit should + # be denied to create more than one snapshot. + # 5. Create 2 snapshot in account 2. Verify account 2 should be able to + # create snapshots without any warning + + self.debug( + "Updating public IP resource limit for account: %s" % + self.account_1.account.name) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 3, # Snapshot + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + max=1 + ) + + self.debug( + "Deploying VM instance in account: %s" % + self.account_1.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + self.debug( + "Deploying VM instance in account: %s" % + self.account_1.account.name) + # Create VM for second account + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_1.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating snapshot from volume: %s" % volumes[0].id) + # Create a snapshot from the ROOTDISK (Account 1) + snapshot_1 = Snapshot.create(self.apiclient, + volumes[0].id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + ) + self.cleanup.append(snapshot_1) + # Verify Snapshot state + self.assertEqual( + snapshot_1.state in [ + 'BackedUp', + 'CreatedOnPrimary' + ], + True, + "Check Snapshot state is Running or not" + ) + + # Exception should be raised for second snapshot (account_1) + with self.assertRaises(Exception): + Snapshot.create(self.apiclient, + volumes[0].id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + ) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_2.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating snapshot from volume: %s" % volumes[0].id) + # Create a snapshot from the ROOTDISK (Account 2) + snapshot_2 = Snapshot.create(self.apiclient, + volumes[0].id, + account=self.account_2.account.name, + domainid=self.account_2.account.domainid, + ) + self.cleanup.append(snapshot_2) + # Verify Snapshot state + self.assertEqual( + snapshot_2.state in [ + 'BackedUp', + 'CreatedOnPrimary' + ], + True, + "Check Snapshot state is Running or not" + ) + + self.debug("Creating snapshot from volume: %s" % volumes[0].id) + # Create a second snapshot from the ROOTDISK (Account 2) + snapshot_3 = Snapshot.create(self.apiclient, + volumes[0].id, + account=self.account_2.account.name, + domainid=self.account_2.account.domainid, + ) + self.cleanup.append(snapshot_3) + # Verify Snapshot state + self.assertEqual( + snapshot_3.state in [ + 'BackedUp', + 'CreatedOnPrimary' + ], + True, + "Check Snapshot state is Running or not" + ) + return + + def test_04_volumes_per_account(self): + """Test Volumes limit per account + """ + + # Validate the following + # 1. Set volumes=2 limit for account 1. + # 2. Start 1 VMs account 1 + # 3. Start 1 VMs account 2 + # 4. Create 2 volumes in account 1. Verify account with limit should be + # denied to create more than one volume. + # 5. Create 2 volumes in account 2. Verify account 2 should be able to + # create Volume without any warning + + self.debug( + "Updating volume resource limit for account: %s" % + self.account_1.account.name) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 2, # Volume + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + max=2 + ) + + self.debug( + "Deploying VM for account: %s" % self.account_1.account.name) + + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + self.debug( + "Deploying VM for account: %s" % self.account_2.account.name) + + # Create VM for second account + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + + self.debug( + "Create a data volume for account: %s" % self.account_1.account.name) + volume_1 = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.cleanup.append(volume_1) + # Verify Volume state + self.assertEqual( + volume_1.state in [ + 'Allocated', + 'Ready' + ], + True, + "Check Volume state is Ready or not" + ) + + # Exception should be raised for second snapshot (account_1) + with self.assertRaises(Exception): + Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + diskofferingid=self.disk_offering.id + ) + + self.debug( + "Create a data volume for account: %s" % self.account_2.account.name) + # Create volume for Account 2 + volume_2 = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account_2.account.name, + domainid=self.account_2.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.cleanup.append(volume_2) + # Verify Volume state + self.assertEqual( + volume_2.state in [ + 'Allocated', + 'Ready' + ], + True, + "Check Volume state is Ready or not" + ) + + self.debug( + "Create a data volume for account: %s" % self.account_2.account.name) + # Create a second volume from the ROOTDISK (Account 2) + volume_3 = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account_2.account.name, + domainid=self.account_2.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.cleanup.append(volume_3) + # Verify Volume state + self.assertEqual( + volume_3.state in [ + 'Allocated', + 'Ready' + ], + True, + "Check Volume state is Ready or not" + ) + return + + def test_05_templates_per_account(self): + """Test Templates limit per account + """ + + # Validate the following + # 1. Set templates=1 limit for account 1. + # 2. Try to create 2 templates in account 1. Verify account with limit + # should be denied to create more than 1 template. + # 3. Try to create 2 templates in account 2. Verify account 2 should be + # able to create template without any error + + self.debug( + "Updating template resource limit for account: %s" % + self.account_1.account.name) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 4, # Template + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + max=1 + ) + + self.debug( + "Updating volume resource limit for account: %s" % + self.account_1.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + self.debug( + "Deploying virtual machine for account: %s" % + self.account_2.account.name) + # Create VM for second account + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_1.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug( + "Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK (Account 1) + template_1 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + ) + + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( + template_1.isready, + True, + "Check Template is in ready state or not" + ) + + # Exception should be raised for second snapshot (account_1) + with self.assertRaises(Exception): + Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + ) + virtual_machine_2.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_2.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug( + "Creating template from volume: %s" % volume.id) + # Create a snapshot from the ROOTDISK (Account 1) + template_2 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + account=self.account_2.account.name, + domainid=self.account_2.account.domainid, + ) + + self.cleanup.append(template_2) + # Verify Template state + self.assertEqual( + template_2.isready, + True, + "Check Template is in ready state or not" + ) + self.debug( + "Creating template from volume: %s" % volume.id) + # Create a second volume from the ROOTDISK (Account 2) + template_3 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + account=self.account_2.account.name, + domainid=self.account_2.account.domainid, + ) + + self.cleanup.append(template_3) + # Verify Template state + self.assertEqual( + template_3.isready, + True, + "Check Template is in ready state or not" + ) + return + + +class TestResourceLimitsDomain(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + # Create Domains, Account etc + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + # Create Service offering and disk offerings etc + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account, + cls.domain + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_vm_per_domain(self): + """Test VM limit per domain + """ + + # Validate the following + # 1. Set max VM per domain to 2 + # 2. Create account and start 2 VMs. Verify VM state is Up and Running + # 3. Try to create 3rd VM instance. The appropriate error or alert + # should be raised + + self.debug( + "Updating instance resource limits for domain: %s" % + self.account.account.domainid) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 0, # Instance + domainid=self.account.account.domainid, + max=2 + ) + + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + # Exception should be raised for second instance + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + return + + def test_01_publicip_per_domain(self): + """Test Public IP limit per domain + """ + + # Validate the following + # 1. set max no of IPs per domain to 2. + # 2. Create an account in this domain + # 3. Create 1 VM in this domain + # 4. Acquire 1 IP in the domain. IP should be successfully acquired + # 5. Try to acquire 3rd IP in this domain. It should give the user an + # appropriate error and an alert should be generated. + + self.debug( + "Updating public IP resource limits for domain: %s" % + self.account.account.domainid) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 1, # Public Ip + domainid=self.account.account.domainid, + max=2 + ) + + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + self.debug("Associating public IP for account: %s" % self.account.account.name) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + virtual_machine_1.account, + virtual_machine_1.zoneid, + virtual_machine_1.domainid, + self.services["server"] + ) + self.cleanup.append(public_ip_1) + # Verify Public IP state + self.assertEqual( + public_ip_1.ipaddress.state in [ + 'Allocated', + 'Allocating' + ], + True, + "Check Public IP state is allocated or not" + ) + + # Exception should be raised for second Public IP + with self.assertRaises(Exception): + public_ip_2 = PublicIPAddress.create( + self.apiclient, + virtual_machine_1.account, + virtual_machine_1.zoneid, + virtual_machine_1.domainid, + self.services["server"] + ) + return + + def test_03_snapshots_per_domain(self): + """Test Snapshot limit per domain + """ + + # Validate the following + # 1. set max no of snapshots per domain to 1. + # 2. Create an account in this domain + # 3. Create 1 VM in this domain + # 4. Create one snapshot in the domain. Snapshot should be successfully + # created + # 5. Try to create another snapshot in this domain. It should give the + # user an appropriate error and an alert should be generated. + + self.debug( + "Updating snapshot resource limits for domain: %s" % + self.account.account.domainid) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 3, # Snapshot + domainid=self.account.account.domainid, + max=1 + ) + + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_1.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating snapshot from volume: %s" % volumes[0].id) + # Create a snapshot from the ROOTDISK + snapshot_1 = Snapshot.create(self.apiclient, + volumes[0].id, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.cleanup.append(snapshot_1) + # Verify Snapshot state + self.assertEqual( + snapshot_1.state in [ + 'BackedUp', + 'CreatedOnPrimary' + ], + True, + "Check Snapshot state is Running or not" + ) + + # Exception should be raised for second snapshot + with self.assertRaises(Exception): + Snapshot.create(self.apiclient, + volumes[0].id, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + return + + def test_04_volumes_per_domain(self): + """Test Volumes limit per domain + """ + + # Validate the following + # 1. set max no of volume per domain to 1. + # 2. Create an account in this domain + # 3. Create 1 VM in this domain + # 4. Try to Create another VM in the domain. It should give the user an + # appropriate error that Volume limit is exhausted and an alert + # should be generated. + + self.debug( + "Updating volume resource limits for domain: %s" % + self.account.account.domainid) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 2, # Volume + domainid=self.account.account.domainid, + max=1 + ) + + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + # Exception should be raised for second volume + with self.assertRaises(Exception): + Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + return + + def test_05_templates_per_domain(self): + """Test Templates limit per domain + """ + + # Validate the following + # 1. set max no of templates per domain to 2. + # 2. Create an account in this domain + # 3. Create 2 templates in this domain. Both template should be in + # ready state + # 4. Try create 3rd template in the domain. It should give the user an + # appropriate error and an alert should be generated. + + self.debug( + "Updating template resource limits for domain: %s" % + self.account.account.domainid) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 4, # Template + domainid=self.account.account.domainid, + max=2 + ) + + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_1.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_1 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( + template_1.isready, + True, + "Check Template is in ready state or not" + ) + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_2 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.cleanup.append(template_2) + # Verify Template state + self.assertEqual( + template_2.isready, + True, + "Check Template is in ready state or not" + ) + + # Exception should be raised for second template + with self.assertRaises(Exception): + Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_routers.py b/tools/testClient/testcase/P1-tests/test_routers.py new file mode 100644 index 00000000000..05dfc99e7fd --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_routers.py @@ -0,0 +1,1178 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for routers +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +import remoteSSHClient +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * + +#Import System modules +import time + + +class Services: + """Test router Services + """ + + def __init__(self): + self.services = { + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "virtual_machine": + { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "host": { + "username": "root", + "password": "fr3sca", + "publicport": 22, + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "testuser", + "password": "password", + }, + "natrule": + { + "privateport": 22, + "publicport": 222, + "protocol": "TCP" + }, + "lbrule": + { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + }, + "fw_rule":{ + "startport": 1, + "endport": 6000, + "cidr": '55.55.0.0/11', + # Any network (For creating FW rule + }, + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + # Used for Get_Template : CentOS 5.3 (64 bit) + "mode": 'advanced', # Networking mode: Advanced, basic + } + + +class TestRouterServices(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = fetch_api_client() + 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 + + #Create an account, network, VM and IP addresses + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=cls.template.id, + 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"], + templateid=cls.template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Clean up, terminate the created templates + cleanup_resources(cls.api_client, cls.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self._cleanup = [] + return + + def test_01_AdvancedZoneRouterServices(self): + """Test advanced zone router services + """ + + # Validate the following: + # 1. Verify that list of services provided by this network are running + # a. DNS + # b. DHCP + # c. Gateway + # d. Firewall + # e. LB + # f. VPN + # g. userdata + # 2. wait for router to start and guest network to be created + # a. listRouters account=user, domainid=1 (router state=Running) + # b. listNetworks account=user domainid=1 (network state=Implemented) + # c. listVirtualMachines account=user domainid=1 (VM state=Running) + # 3. listNetwork + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + self.assertNotEqual( + len(routers), + 0, + "Check list router response" + ) + for router in routers: + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + self.debug("Router ID: %s & Router state: %s" % ( + router.id, + router.state + )) + # Network state associated with account should be 'Implemented' + networks = list_networks( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(networks, list), + True, + "Check for list networks response return valid data" + ) + + self.assertNotEqual( + len(networks), + 0, + "Check list networks response" + ) + for network in networks: + self.assertIn( + network.state, + ['Implemented','Allocated'], + "Check list network response for network state" + ) + self.debug("Network ID: %s & Network state: %s" % ( + network.id, + network.state + )) + # VM state associated with account should be 'Running' + virtual_machines = list_virtual_machines( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(virtual_machines, list), + True, + "Check for list virtual machines response return valid data" + ) + self.assertNotEqual( + len(virtual_machines), + 0, + "Check list virtual machines response" + ) + for virtual_machine in virtual_machines: + self.assertEqual( + virtual_machine.state, + 'Running', + "Check list VM response for Running state" + ) + self.debug("VM ID: %s & VM state: %s" % ( + virtual_machine.id, + virtual_machine.state + )) + + # Check status of DNS, DHCP, FIrewall, LB VPN processes + networks = list_networks( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(networks, list), + True, + "Check for list networks response return valid data" + ) + self.assertNotEqual( + len(networks), + 0, + "Check list networks response" + ) + # Load Balancer, Userdata, VPN, Firewall, Gateway, DNS processes should + # be running + for network in networks: + self.assertEqual( + 'Lb' in str(network.service), + True, + "Check Load balancing process in list networks" + ) + self.assertEqual( + 'UserData' in str(network.service), + True, + "Check UserData service in list networks" + ) + self.assertEqual( + 'Vpn' in str(network.service), + True, + "Check Vpn service in list networks" + ) + self.assertEqual( + 'Firewall' in str(network.service), + True, + "Check Firewall service in list networks" + ) + self.assertEqual( + 'Dns' in str(network.service), + True, + "Check Dns service in list networks" + ) + return + + def test_02_NetworkGarbageCollection(self): + """Test network garbage collection + """ + + # Validate the following + # 1. wait for router to start and guest network to be created + # a.listRouters account=user, domainid=1 (router state=Running) + # b.listNetworks account=user domainid=1 (network state=Implemented) + # c.listVirtualMachines account=user domainid=1 (VM states=Running) + # 4. stopVirtualMachines (stop all VMs in this account) + # 5. wait for VMs to stop-listVirtualMachines account=user, domainid=1 + # (Both VM states = Stopped) + # 6. wait for network.gc.interval*2 seconds (600s) + # 7. listRouters account=user, domainid=1 + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + self.assertNotEqual( + len(routers), + 0, + "Check list router response" + ) + # Router associated with account should be in running state + for router in routers: + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + self.debug("Router ID: %s & Router state: %s" % ( + router.id, + router.state + )) + # Network state associated with account should be 'Implemented' + networks = list_networks( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(networks, list), + True, + "Check for list networks response return valid data" + ) + self.assertNotEqual( + len(networks), + 0, + "Check list networks response" + ) + # Check if network in 'Implemented' state + for network in networks: + self.assertIn( + network.state, + ['Implemented','Allocated'], + "Check list network response for network state" + ) + self.debug("Network ID: %s & Network state: %s" % ( + network.id, + network.state + )) + # VM state associated with account should be 'Running' + virtual_machines = list_virtual_machines( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(virtual_machines, list), + True, + "Check for list virtual machines response return valid data" + ) + self.assertNotEqual( + len(virtual_machines), + 0, + "Check list virtual machines response" + ) + for virtual_machine in virtual_machines: + self.assertEqual( + virtual_machine.state, + 'Running', + "Check list VM response for Running state" + ) + self.debug("VM ID: %s & VM state: %s" % ( + virtual_machine.id, + virtual_machine.state + )) + # Stop virtual machine + cmd = stopVirtualMachine.stopVirtualMachineCmd() + cmd.id = virtual_machine.id + self.apiclient.stopVirtualMachine(cmd) + + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + self.assertEqual( + isinstance(interval, list), + True, + "Check for list intervals response return valid data" + ) + self.debug("network.gc.interval: %s" % interval[0].value) + # Router is stopped after (network.gc.interval *2) time. Wait for + # (network.gc.interval *4) for moving router to 'Stopped' + time.sleep(int(interval[0].value) * 4) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + self.assertNotEqual( + len(routers), + 0, + "Check list router response" + ) + for router in routers: + self.assertEqual( + router.state, + 'Stopped', + "Check list router response for router state" + ) + self.debug("Router ID: %s & Router state: %s" % ( + router.id, + router.state + )) + # Cleanup Vm_2 - Not required for further tests + self._cleanup.append(self.vm_2) + return + + def test_03_RouterStartOnVmDeploy(self): + """Test router start on VM deploy + """ + # Validate the following + # 1. deployVirtualMachine in the account + # 2. listVirtualMachines account=user, domainid=1 + # 3. when listVirtualMachines reports the userVM to be in state=Running + # 4. listRouters should report router to have come back to "Running" state + # 5. All other VMs in the account should remain in "Stopped" state + + vm = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed a VM with ID: %s" % vm.id) + + virtual_machines = list_virtual_machines( + self.apiclient, + id=vm.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(virtual_machines, list), + True, + "Check for list virtual machines response return valid data" + ) + + self.assertNotEqual( + len(virtual_machines), + 0, + "Check list virtual machines response" + ) + # VM state should be 'Running' + for virtual_machine in virtual_machines: + self.assertEqual( + virtual_machine.state, + 'Running', + "Check list VM response for Running state" + ) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + + self.assertNotEqual( + len(routers), + 0, + "Check list router response" + ) + # Routers associated with account should be 'Running' after deployment + # of VM + for router in routers: + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + self.debug("Router ID: %s & Router state: %s" % ( + router.id, + router.state + )) + + # All other VMs (VM_1) should be in 'Stopped' + virtual_machines = list_virtual_machines( + self.apiclient, + id=self.vm_1.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(virtual_machines, list), + True, + "Check for list VMs response return valid data" + ) + + self.assertNotEqual( + len(virtual_machines), + 0, + "Check list virtual machines response" + ) + for virtual_machine in virtual_machines: + self.assertEqual( + virtual_machine.state, + 'Stopped', + "Check list VM response for Stopped state" + ) + self.debug("VM ID: %s & VM state: %s" % ( + virtual_machine.id, + virtual_machine.state + )) + return + + + +class TestRouterStopCreatePF(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + #Create an account, network, VM and IP addresses + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + # Clean up, terminate the created resources + cleanup_resources(cls.api_client, cls.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def tearDown(self): + try: + # Clean up, terminate the created resources + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self._cleanup = [] + return + + def test_01_RouterStopCreatePF(self): + """Test router stop create port forwarding + """ + + # validate the following + # 1. wait for router to start, guest network to be implemented and + # VM to report Running + # 2. stopRouter for this account + # 3. wait for listRouters to report Router as 'Stopped' + # 4. listPublicIpAddresses account=user, domainid=1 - pick ipaddressid + # 5. createPortForwardingRule (ipaddressid from step 5.) + # a. for port 22 (ssh) for user VM deployed in step 1. + # b. public port 222 , private port 22 + # 6. startRouter stopped for this account + # 7. wait for listRouters to show router as Running + + # Get router details associated for that account + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + self.assertNotEqual( + len(routers), + 0, + "Check list router response" + ) + router = routers[0] + + self.debug("Stopping router ID: %s" % router.id) + + #Stop the router + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + + self.assertEqual( + router.state, + 'Stopped', + "Check list router response for router state" + ) + + public_ips = list_publicIP( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "Check for list public IPs response return valid data" + ) + public_ip = public_ips[0] + + self.debug("Creating NAT rule for VM ID: %s" % self.vm_1.id) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + self.vm_1, + self.services["natrule"], + public_ip.id + ) + + self.debug("Starting router ID: %s" % router.id) + #Start the router + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + # NAT Rule should be in Active state after router start + nat_rules = list_nat_rules( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "Check for list NAT rules response return valid data" + ) + self.assertEqual( + nat_rules[0].state, + 'Active', + "Check list port forwarding rules" + ) + 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: + self.fail( + "SSH Access failed for %s: %s" % \ + (self.vm_1.ipaddress, e) + ) + return + +class TestRouterStopCreateLB(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + #Create an account, network, VM and IP addresses + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Clean up, terminate the created resources + cleanup_resources(cls.api_client, cls.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self._cleanup = [] + return + + def test_01_RouterStopCreateLB(self): + """Test router stop create Load balancing + """ + + # validate the following + # 1. listLoadBalancerRules (publicipid=ipaddressid of source NAT) + # 2. rule should be for port 2222 as applied and + # should be in state=Active + # 3. ssh access should be allowed to the userVMs over the source NAT IP + # and port 2222 + + # Get router details associated for that account + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + + self.assertNotEqual( + len(routers), + 0, + "Check list router response" + ) + + router = routers[0] + + self.debug("Stopping router with ID: %s" % router.id) + #Stop the router + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + + self.assertEqual( + router.state, + 'Stopped', + "Check list router response for router state" + ) + + public_ips = list_publicIP( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "Check for list public IPs response return valid data" + ) + public_ip = public_ips[0] + 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( + self.apiclient, + self.services["lbrule"], + public_ip.id, + accountid=self.account.account.name + ) + self.debug("Assigning VM %s to LB rule: %s" % ( + self.vm_1.id, + lb_rule.id + )) + lb_rule.assign(self.apiclient, [self.vm_1]) + + #Start the router + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + # After router start, LB RUle should be in Active state + lb_rules = list_lb_rules( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "Check for list LB rules response return valid data" + ) + self.assertEqual( + lb_rules[0].state, + 'Active', + "Check list load balancing rules" + ) + self.assertEqual( + lb_rules[0].publicport, + str(self.services["lbrule"]["publicport"]), + "Check list load balancing rules" + ) + + try: + self.debug("SSH into VM with IP: %s" % public_ip.ipaddress) + self.vm_1.ssh_port = self.services["lbrule"]["publicport"] + self.vm_1.get_ssh_client(public_ip.ipaddress) + except Exception as e: + self.fail( + "SSH Access failed for %s: %s" % \ + (self.vm_1.ipaddress, e) + ) + return + + +class TestRouterStopCreateFW(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + #Create an account, network, VM and IP addresses + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Clean up, terminate the created templates + cleanup_resources(cls.api_client, cls.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self._cleanup = [] + return + + def test_01_RouterStopCreateFW(self): + """Test router stop create Firewall rule + """ + + # validate the following + # 1. 1. listFirewallRules (filter by ipaddressid of sourcenat) + # 2. rule should be for ports 1-600 and in state=Active + # (optional backend) + # 3. verify on router using iptables -t nat -nvx if rules are applied + + # Get the router details associated with account + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + + self.assertNotEqual( + len(routers), + 0, + "Check list router response" + ) + + router = routers[0] + + self.debug("Stopping the router: %s" % router.id) + #Stop the router + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + + self.assertEqual( + router.state, + 'Stopped', + "Check list router response for router state" + ) + + public_ips = list_publicIP( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "Check for list public IP response return valid data" + ) + public_ip = public_ips[0] + + #Create Firewall rule with configurations from settings file + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=public_ip.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + self.debug("Created firewall rule: %s" % fw_rule.id) + + self.debug("Starting the router: %s" % router.id) + #Start the router + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + routers = list_routers( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + + router = routers[0] + + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + # After Router start, FW rule should be in Active state + fw_rules = list_firewall_rules( + self.apiclient, + id=fw_rule.id, + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "Check for list FW rules response return valid data" + ) + + self.assertEqual( + fw_rules[0].state, + 'Active', + "Check list load balancing rules" + ) + self.assertEqual( + fw_rules[0].startport, + str(self.services["fw_rule"]["startport"]), + "Check start port of firewall rule" + ) + + self.assertEqual( + fw_rules[0].endport, + str(self.services["fw_rule"]["endport"]), + "Check end port of firewall rule" + ) + hosts = list_hosts( + self.apiclient, + id=router.hostid, + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check for list hosts response return valid data" + ) + host = hosts[0] + # For DNS and DHCP check 'dnsmasq' process status + result = get_process_status( + host.ipaddress, + self.services['host']["publicport"], + self.services['host']["username"], + self.services['host']["password"], + router.linklocalip, + 'iptables -t nat -L' + ) + self.debug("iptables -t nat -L: %s" % result) + self.debug("Public IP: %s" % public_ip.ipaddress) + res = str(result) + self.assertEqual( + res.count(str(public_ip.ipaddress)), + 1, + "Check public IP address" + ) + return + diff --git a/tools/testClient/testcase/P1-tests/test_security_groups.py b/tools/testClient/testcase/P1-tests/test_security_groups.py new file mode 100644 index 00000000000..d096ad4daa2 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_security_groups.py @@ -0,0 +1,1617 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# + +""" P1 for Security groups +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +import remoteSSHClient +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * + +#Import System modules +import time +import subprocess + + +class Services: + """Test Security groups Services + """ + + def __init__(self): + self.services = { + "disk_offering":{ + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "fr3sca", + }, + "virtual_machine": { + # Create a small virtual machine instance with disk offering + "displayname": "Test VM", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + "userdata": 'This is sample data', + }, + "host": { + "publicport": 22, + "username": "root", # Host creds for SSH + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "security_group": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '0.0.0.0/0', + }, + "security_group_2": { + "name": 'ICMP', + "protocol": 'ICMP', + "startport": -1, + "endport": -1, + "cidrlist": '0.0.0.0/0', + }, + "ostypeid": '0c2c5d19-525b-41be-a8c3-c6607412f82b', + # CentOS 5.3 (64-bit) + "sleep": 60, + "timeout": 10, + "mode":'basic', + # Networking mode: Basic or Advanced + } + + +class TestDefaultSecurityGroup(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = 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 + ) + cls.services["account"] = cls.account.account.name + + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_deployVM_InDefaultSecurityGroup(self): + """Test deploy VM in default security group + """ + + # Validate the following: + # 1. deploy Virtual machine using admin user + # 2. listVM should show a VM in Running state + # 3. listRouters should show one router running + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM with ID: %s" % self.virtual_machine.id) + self.cleanup.append(self.virtual_machine) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check for list VM response" + ) + vm_response = list_vm_response[0] + self.assertNotEqual( + len(list_vm_response), + 0, + "Check VM available in List Virtual Machines" + ) + + self.assertEqual( + + vm_response.id, + self.virtual_machine.id, + "Check virtual machine id in listVirtualMachines" + ) + + self.assertEqual( + vm_response.displayname, + self.virtual_machine.displayname, + "Check virtual machine displayname in listVirtualMachines" + ) + + # Verify List Routers response for account + self.debug( + "Verify list routers response for account: %s" \ + % self.account.account.name + ) + routers = list_routers( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check for list Routers response" + ) + + self.debug("Router Response: %s" % routers) + self.assertEqual( + len(routers), + 1, + "Check virtual router is created for account or not" + ) + return + + def test_02_listSecurityGroups(self): + """Test list security groups for admin account + """ + + # Validate the following: + # 1. listSecurityGroups in admin account + # 2. There should be one security group (default) listed for the admin account + # 3. No Ingress Rules should be part of the default security group + + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + self.assertNotEqual( + len(sercurity_groups), + 0, + "Check List Security groups response" + ) + self.debug("List Security groups response: %s" % + str(sercurity_groups)) + self.assertEqual( + hasattr(sercurity_groups, 'ingressrule'), + False, + "Check ingress rule attribute for default security group" + ) + return + + def test_03_accessInDefaultSecurityGroup(self): + """Test access in default security group + """ + + # Validate the following: + # 1. deploy Virtual machine using admin user + # 2. listVM should show a VM in Running state + # 3. listRouters should show one router running + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Deployed VM with ID: %s" % self.virtual_machine.id) + self.cleanup.append(self.virtual_machine) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check for list VM response" + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + vm_response = list_vm_response[0] + self.assertNotEqual( + len(list_vm_response), + 0, + "Check VM available in List Virtual Machines" + ) + + self.assertEqual( + + vm_response.id, + self.virtual_machine.id, + "Check virtual machine id in listVirtualMachines" + ) + + self.assertEqual( + vm_response.displayname, + self.virtual_machine.displayname, + "Check virtual machine displayname in listVirtualMachines" + ) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.debug("List Security groups response: %s" % + str(sercurity_groups)) + self.assertNotEqual( + len(sercurity_groups), + 0, + "Check List Security groups response" + ) + self.assertEqual( + hasattr(sercurity_groups, 'ingressrule'), + False, + "Check ingress rule attribute for default security group" + ) + + # SSH Attempt to VM should fail + with self.assertRaises(Exception): + self.debug("SSH into VM: %s" % self.virtual_machine.ssh_ip) + ssh = remoteSSHClient.remoteSSHClient( + self.virtual_machine.ssh_ip, + self.virtual_machine.ssh_port, + self.virtual_machine.username, + self.virtual_machine.password + ) + return + + +class TestAuthorizeIngressRule(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_authorizeIngressRule(self): + """Test authorize ingress rule + """ + + # Validate the following: + #1. Create Security group for the account. + #2. Createsecuritygroup (ssh-incoming) for this account + #3. authorizeSecurityGroupIngress to allow ssh access to the VM + #4. deployVirtualMachine into this security group (ssh-incoming) + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + self.debug("Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.id) + self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + return + + +class TestRevokeIngressRule(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_revokeIngressRule(self): + """Test revoke ingress rule + """ + + # Validate the following: + #1. Create Security group for the account. + #2. Createsecuritygroup (ssh-incoming) for this account + #3. authorizeSecurityGroupIngress to allow ssh access to the VM + #4. deployVirtualMachine into this security group (ssh-incoming) + #5. Revoke the ingress rule, SSH access should fail + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + self.debug("Authorizing ingress rule for sec group ID: %s for ssh access" + % security_group.id) + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.virtual_machine.id) + self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + + self.debug("Revoking ingress rule for sec group ID: %s for ssh access" + % security_group.id) + # Revoke Security group to SSH to VM + result = security_group.revoke( + self.apiclient, + id=ssh_rule["ruleid"] + ) + + # SSH Attempt to VM should fail + with self.assertRaises(Exception): + self.debug("SSH into VM: %s" % self.virtual_machine.id) + remoteSSHClient.remoteSSHClient( + self.virtual_machine.ssh_ip, + self.virtual_machine.ssh_port, + self.virtual_machine.username, + self.virtual_machine.password + ) + return + + +class TestDhcpOnlyRouter(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls.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 + ) + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_dhcpOnlyRouter(self): + """Test router services for user account + """ + # Validate the following + #1. List routers for any user account + #2. The only service supported by this router should be dhcp + + # Find router associated with user account + list_router_response = list_routers( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(list_router_response, list), + True, + "Check list response returns a valid list" + ) + router = list_router_response[0] + + hosts = list_hosts( + self.apiclient, + zoneid=router.zoneid, + type='Routing', + state='Up' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list host returns a valid list" + ) + host = hosts[0] + + self.debug("Router ID: %s, state: %s" % (router.id, router.state)) + + self.assertEqual( + router.state, + 'Running', + "Check list router response for router state" + ) + + result = get_process_status( + host.ipaddress, + self.services['host']["publicport"], + self.services['host']["username"], + self.services['host']["password"], + router.linklocalip, + "service dnsmasq status" + ) + res = str(result) + self.debug("Dnsmasq process status: %s" % res) + + self.assertEqual( + res.count("running"), + 1, + "Check dnsmasq service is running or not" + ) + return + + +class TestdeployVMWithUserData(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.services["domainid"] = cls.domain.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_deployVMWithUserData(self): + """Test Deploy VM with User data""" + + # Validate the following + # 1. CreateAccount of type user + # 2. CreateSecurityGroup ssh-incoming + # 3. authorizeIngressRule to allow ssh-access + # 4. deployVirtualMachine into this group with some base64 encoded user-data + # 5. wget http://10.1.1.1/latest/user-data to get the latest userdata from the + # router for this VM + + # Find router associated with user account + list_router_response = list_routers( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(list_router_response, list), + True, + "Check list response returns a valid list" + ) + router = list_router_response[0] + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Should be able to SSH VM + try: + self.debug( + "SSH to VM with IP Address: %s"\ + % self.virtual_machine.ssh_ip + ) + + ssh = self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.virtual_machine.ipaddress, e) + ) + + cmds = [ + "wget http://%s/latest/user-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + + res = str(result) + self.assertEqual( + res.count(self.services["virtual_machine"]["userdata"]), + 1, + "Verify user data" + ) + return + + +class TestDeleteSecurityGroup(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + + self.services = Services().services + + # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient, self.services) + self.zone = get_zone(self.apiclient, self.services) + + template = get_template( + self.apiclient, + self.zone.id, + self.services["ostypeid"] + ) + + self.services["domainid"] = self.domain.id + self.services["virtual_machine"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["template"] = template.id + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"] + ) + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.services["account"] = self.account.account.name + self.cleanup = [ + self.account, + self.service_offering + ] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_delete_security_grp_running_vm(self): + """Test delete security group with running VM""" + + # Validate the following + # 1. createsecuritygroup (ssh-incoming) for this account + # 2. authorizeSecurityGroupIngress to allow ssh access to the VM + # 3. deployVirtualMachine into this security group (ssh-incoming) + # 4. deleteSecurityGroup created in step 1. Deletion should fail + # complaining there are running VMs in this group + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Deleting Security group should raise exception + security_group.delete(self.apiclient) + + #sleep to ensure that Security group is deleted properly + time.sleep(self.services["sleep"]) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + id=security_group.id + ) + self.assertNotEqual( + sercurity_groups, + None, + "Check List Security groups response" + ) + return + + def test_02_delete_security_grp_withoout_running_vm(self): + """Test delete security group without running VM""" + + # Validate the following + # 1. createsecuritygroup (ssh-incoming) for this account + # 2. authorizeSecurityGroupIngress to allow ssh access to the VM + # 3. deployVirtualMachine into this security group (ssh-incoming) + # 4. deleteSecurityGroup created in step 1. Deletion should fail + # complaining there are running VMs in this group + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Destroy the VM + self.virtual_machine.delete(self.apiclient) + + config = list_configurations( + self.apiclient, + name='expunge.delay' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list configurations response" + ) + response = config[0] + self.debug("expunge.delay: %s" % response.value) + # Wait for some time more than expunge.delay + time.sleep(int(response.value) * 2) + + # Deleting Security group should raise exception + try: + self.debug("Deleting Security Group: %s" % security_group.id) + security_group.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete security group - ID: %s" \ + % security_group.id + ) + return + + +class TestIngressRule(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + self.services = Services().services + + # Get Zone, Domain and templates + self.domain = get_domain(self.apiclient, self.services) + self.zone = get_zone(self.apiclient, self.services) + + template = get_template( + self.apiclient, + self.zone.id, + self.services["ostypeid"] + ) + + self.services["domainid"] = self.domain.id + self.services["virtual_machine"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["template"] = template.id + + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"] + ) + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.services["account"] = self.account.account.name + self.cleanup = [ + self.account, + self.service_offering + ] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_authorizeIngressRule_AfterDeployVM(self): + """Test delete security group with running VM""" + + # Validate the following + # 1. createsecuritygroup (ssh-incoming, 22via22) for this account + # 2. authorizeSecurityGroupIngress to allow ssh access to the VM + # 3. deployVirtualMachine into this security group (ssh-incoming) + # 4. authorizeSecurityGroupIngress to allow ssh access (startport:222 to + # endport:22) to the VM + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + # Authorize Security group to SSH to VM + ingress_rule_1 = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule_1, dict), + True, + "Check ingress rule created properly" + ) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + # Authorize Security group to SSH to VM + ingress_rule_2 = security_group.authorize( + self.apiclient, + self.services["security_group_2"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule_2, dict), + True, + "Check ingress rule created properly" + ) + # SSH should be allowed on 22 & 2222 ports + try: + self.debug("Trying to SSH into VM %s on port %s" % ( + self.virtual_machine.ssh_ip, + self.services["security_group"]["endport"] + )) + self.virtual_machine.get_ssh_client() + + except Exception as e: + self.fail("SSH access failed for ingress rule ID: %s, %s" \ + % (ingress_rule_1["id"], e)) + + # User should be able to ping VM + try: + self.debug("Trying to ping VM %s" % self.virtual_machine.ssh_ip) + result = subprocess.call(['ping', '-c 1', self.virtual_machine.ssh_ip]) + + self.debug("Ping result: %s" % result) + # if ping successful, then result should be 0 + self.assertEqual( + result, + 0, + "Check if ping is successful or not" + ) + + except Exception as e: + self.fail("Ping failed for ingress rule ID: %s, %s" \ + % (ingress_rule_2["id"], e)) + return + + def test_02_revokeIngressRule_AfterDeployVM(self): + """Test Revoke ingress rule after deploy VM""" + + # Validate the following + # 1. createsecuritygroup (ssh-incoming, 22via22) for this account + # 2. authorizeSecurityGroupIngress to allow ssh access to the VM + # 3. deployVirtualMachine into this security group (ssh-incoming) + # 4. authorizeSecurityGroupIngress to allow ssh access (startport:222 + # to endport:22) to the VM + # 5. check ssh access via port 222 + # 6. revokeSecurityGroupIngress to revoke rule added in step 5. verify + # that ssh-access into the VM is now NOT allowed through ports 222 + # but allowed through port 22 + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + # Authorize Security group to SSH to VM + ingress_rule_2 = security_group.authorize( + self.apiclient, + self.services["security_group_2"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule_2, dict), + True, + "Check ingress rule created properly" + ) + + ssh_rule = (ingress_rule["ingressrule"][0]).__dict__ + icmp_rule = (ingress_rule_2["ingressrule"][0]).__dict__ + + # SSH should be allowed on 22 + try: + self.debug("Trying to SSH into VM %s on port %s" % ( + self.virtual_machine.ssh_ip, + self.services["security_group"]["endport"] + )) + self.virtual_machine.get_ssh_client() + + except Exception as e: + self.fail("SSH access failed for ingress rule ID: %s, %s" \ + % (ssh_rule["ruleid"], e)) + + # User should be able to ping VM + try: + self.debug("Trying to ping VM %s" % self.virtual_machine.ssh_ip) + result = subprocess.call(['ping', '-c 1', self.virtual_machine.ssh_ip]) + + self.debug("Ping result: %s" % result) + # if ping successful, then result should be 0 + self.assertEqual( + result, + 0, + "Check if ping is successful or not" + ) + + except Exception as e: + self.fail("Ping failed for ingress rule ID: %s, %s" \ + % (icmp_rule["ruleid"], e)) + + self.debug( + "Revoke Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + result = security_group.revoke( + self.apiclient, + id = icmp_rule["ruleid"] + ) + self.debug("Revoke ingress rule result: %s" % result) + + time.sleep(self.services["sleep"]) + # User should not be able to ping VM + try: + self.debug("Trying to ping VM %s" % self.virtual_machine.ssh_ip) + result = subprocess.call(['ping', '-c 1', self.virtual_machine.ssh_ip]) + + self.debug("Ping result: %s" % result) + # if ping successful, then result should be 0 + self.assertNotEqual( + result, + 0, + "Check if ping is successful or not" + ) + + except Exception as e: + self.fail("Ping failed for ingress rule ID: %s, %s" \ + % (icmp_rule["ruleid"], e)) + return + + def test_03_stopStartVM_verifyIngressAccess(self): + """Test Start/Stop VM and Verify ingress rule""" + + # Validate the following + # 1. createsecuritygroup (ssh-incoming, 22via22) for this account + # 2. authorizeSecurityGroupIngress to allow ssh access to the VM + # 3. deployVirtualMachine into this security group (ssh-incoming) + # 4. once the VM is running and ssh-access is available, + # stopVirtualMachine + # 5. startVirtualMachine. After stop start of the VM is complete + # verify that ssh-access to the VM is allowed + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Created security group with ID: %s" % security_group.id) + # Default Security group should not have any ingress rule + sercurity_groups = SecurityGroup.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertEqual( + len(sercurity_groups), + 2, + "Check List Security groups response" + ) + + self.debug( + "Authorize Ingress Rule for Security Group %s for account: %s" \ + % ( + security_group.id, + self.account.account.name + )) + + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(ingress_rule, dict), + True, + "Check ingress rule created properly" + ) + + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id] + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # SSH should be allowed on 22 port + try: + self.debug("Trying to SSH into VM %s" % self.virtual_machine.ssh_ip) + self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH access failed for ingress rule ID: %s" \ + % ingress_rule["id"] + ) + + self.virtual_machine.stop(self.apiclient) + + # Sleep to ensure that VM is in stopped state + time.sleep(self.services["sleep"]) + + self.virtual_machine.start(self.apiclient) + + # Sleep to ensure that VM is in running state + time.sleep(self.services["sleep"]) + + # SSH should be allowed on 22 port after restart + try: + self.debug("Trying to SSH into VM %s" % self.virtual_machine.ssh_ip) + self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH access failed for ingress rule ID: %s" \ + % ingress_rule["id"] + ) + return \ No newline at end of file diff --git a/tools/testClient/testcase/P1-tests/test_snapshots.py b/tools/testClient/testcase/P1-tests/test_snapshots.py new file mode 100644 index 00000000000..dad9d60f050 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_snapshots.py @@ -0,0 +1,1350 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Snapshots +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import remoteSSHClient + +class Services: + """Test Snapshots Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 200, # in MHz + "memory": 256, # In MBs + }, + "disk_offering": { + "displaytext": "Small Disk", + "name": "Small Disk", + "disksize": 1 + }, + "server": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "mgmt_server": { + "ipaddress": '192.168.100.21', + "username": "root", + "password": "fr3sca", + "port": 22, + }, + "recurring_snapshot": { + "intervaltype": 'HOURLY', + # Frequency of snapshots + "maxsnaps": 1, # Should be min 2 + "schedule": 1, + "timezone": 'US/Arizona', + # Timezone Formats - http://cloud.mindtouch.us/CloudStack_Documentation/Developer's_Guide%3A_CloudStack + }, + "templates": { + "displaytext": 'Template', + "name": 'Template', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "templatefilter": 'self', + }, + "diskdevice": "/dev/xvda", + "diskname": "TestDiskServ", + "size": 1, # GBs + + "mount_dir": "/mnt/tmp", + "sub_dir": "test", + "sub_lvl_dir1": "test1", + "sub_lvl_dir2": "test2", + "random_data": "random.data", + + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode" : 'advanced', # Networking mode: Advanced, Basic + } + + +class TestCreateVMsnapshotTemplate(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + 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["domainid"] = cls.domain.id + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = cls.template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_createVM_snapshotTemplate(self): + """Test create VM, Snapshot and Template + """ + + # Validate the following + # 1. Deploy VM using default template, small service offering + # and small data disk offering. + # 2. Perform snapshot on the root disk of this VM. + # 3. Create a template from snapshot. + # 4. Create a instance from above created template. + # 5. listSnapshots should list the snapshot that was created. + # 6. verify that secondary storage NFS share contains the reqd + # volume under /secondary/snapshots/$accountid/$volumeid/$snapshot_uuid + # 7. verify backup_snap_id was non null in the `snapshots` table + # 8. listTemplates() should return the newly created Template, + # and check for template state as READY" + # 9. listVirtualMachines() command should return the deployed VM. + # State of this VM should be Running. + + #Create Virtual Machine + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Created VM with ID: %s" % self.virtual_machine.id) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + + # Create a snapshot from the ROOTDISK + snapshot = Snapshot.create(self.apiclient, volumes[0].id) + self.debug("Snapshot created: ID - %s" % snapshot.id) + self.cleanup.append(snapshot) + + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + self.debug("select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \ + % snapshot.id) + # Verify backup_snap_id is not NULL + qresultset = self.dbclient.execute( + "select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \ + % snapshot.id + ) + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + + qresult = qresultset[0] + + snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID + account_id = qresult[1] + volume_id = qresult[2] + + # Generate template from the snapshot + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"] + ) + self.debug("Created template from snapshot: %s" % template.id) + self.cleanup.append(template) + + templates = list_templates( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + + self.assertNotEqual( + templates, + None, + "Check if result exists in list item call" + ) + + self.assertEqual( + templates[0].isready, + True, + "Check new template state in list templates call" + ) + + # Deploy new virtual machine using template + new_virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + self.debug("Created VM with ID: %s from template: %s" % ( + new_virtual_machine.id, + template.id + )) + self.cleanup.append(new_virtual_machine) + + # Newly deployed VM should be 'Running' + virtual_machines = list_virtual_machines( + self.apiclient, + id=new_virtual_machine.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(virtual_machines, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(virtual_machines), + 0, + "Check list virtual machines response" + ) + for virtual_machine in virtual_machines: + self.assertEqual( + virtual_machine.state, + 'Running', + "Check list VM response for Running state" + ) + # Get the Secondary Storage details from list Hosts + hosts = list_hosts( + self.apiclient, + type='SecondaryStorage', + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (hosts[0].name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] + + # Split IP address and export path from name + sec_storage_ip = parse_url[2] + # Sec Storage IP: 192.168.100.21 + + export_path = '/'.join(parse_url[3:]) + # Export path: export/test + + # Sleep to ensure that snapshot is reflected in sec storage + time.sleep(self.services["sleep"]) + try: + # Login to VM to check snapshot present on sec disk + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["mgmt_server"]["ipaddress"], + self.services["mgmt_server"]["port"], + self.services["mgmt_server"]["username"], + self.services["mgmt_server"]["password"], + ) + + cmds = [ + "mkdir -p %s" % self.services["mount_dir"], + "mount %s:/%s %s" % ( + sec_storage_ip, + export_path, + self.services["mount_dir"] + ), + "ls %s/snapshots/%s/%s" % ( + self.services["mount_dir"], + account_id, + volume_id + ), + ] + for c in cmds: + self.debug("command: %s" % c) + result = ssh_client.execute(c) + self.debug("Result: %s" % result) + + except Exception as e: + self.fail("SSH failed for Management server: %s" % + self.services["mgmt_server"]["ipaddress"]) + + res = str(result) + self.assertEqual( + res.count(snapshot_uuid), + 1, + "Check snapshot UUID in secondary storage and database" + ) + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["mount_dir"]), + ] + try: + for c in cmds: + self.debug("command: %s" % c) + result = ssh_client.execute(c) + self.debug("Result: %s" % result) + + except Exception as e: + self.fail("SSH failed for Management server: %s" % + self.services["mgmt_server"]["ipaddress"]) + return + + +class TestAccountSnapshotClean(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + # Get the Root disk of VM + volumes = list_volumes( + cls.api_client, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + + # Create a snapshot from the ROOTDISK + cls.snapshot = Snapshot.create(cls.api_client, volumes[0].id) + + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_02_accountSnapshotClean(self): + """Test snapshot cleanup after account deletion + """ + + # Validate the following + # 1. listAccounts API should list out the newly created account + # 2. listVirtualMachines() command should return the deployed VM. + # State of this VM should be "Running" + # 3. a)listSnapshots should list the snapshot that was created. + # b)verify that secondary storage NFS share contains the reqd volume + # under /secondary/snapshots/$accountid/$volumeid/$snapshot_uuid + # 4. a)listAccounts should not list account that is deleted + # b) snapshot image($snapshot_uuid) should be deleted from the + # /secondary/snapshots/$accountid/$volumeid/ + + accounts = list_accounts( + self.apiclient, + id=self.account.account.id + ) + self.assertEqual( + isinstance(accounts, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(accounts), + 0, + "Check list Accounts response" + ) + + # VM should be in 'Running' state + virtual_machines = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + self.assertEqual( + isinstance(virtual_machines, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(virtual_machines), + 0, + "Check list virtual machines response" + ) + for virtual_machine in virtual_machines: + self.debug("VM ID: %s, VM state: %s" % ( + virtual_machine.id, + virtual_machine.state + )) + self.assertEqual( + virtual_machine.state, + 'Running', + "Check list VM response for Running state" + ) + + # Verify the snapshot was created or not + snapshots = list_snapshots( + self.apiclient, + id=self.snapshot.id + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + self.snapshot.id, + "Check snapshot id in list resources call" + ) + + # Fetch values from database + qresultset = self.dbclient.execute( + "select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \ + % self.snapshot.id + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB response returns a valid list" + ) + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + + qresult = qresultset[0] + snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID + account_id = qresult[1] + volume_id = qresult[2] + + # Get the Secondary Storage details from list Hosts + hosts = list_hosts( + self.apiclient, + type='SecondaryStorage', + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (hosts[0].name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] + + # Split IP address and export path from name + sec_storage_ip = parse_url[2] + # Sec Storage IP: 192.168.100.21 + + export_path = '/'.join(parse_url[3:]) + # Export path: export/test + + # Sleep to ensure that snapshot is reflected in sec storage + time.sleep(self.services["sleep"]) + try: + # Login to Secondary storage VM to check snapshot present on sec disk + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["mgmt_server"]["ipaddress"], + self.services["mgmt_server"]["port"], + self.services["mgmt_server"]["username"], + self.services["mgmt_server"]["password"], + ) + + cmds = [ + "mkdir -p %s" % self.services["mount_dir"], + "mount %s:/%s %s" % ( + sec_storage_ip, + export_path, + self.services["mount_dir"] + ), + "ls %s/snapshots/%s/%s" % ( + self.services["mount_dir"], + account_id, + volume_id + ), + ] + + for c in cmds: + self.debug("command: %s" % c) + result = ssh_client.execute(c) + self.debug("Result: %s" % result) + + res = str(result) + self.assertEqual( + res.count(snapshot_uuid), + 1, + "Check snapshot UUID in secondary storage and database" + ) + + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["mount_dir"]), + ] + for c in cmds: + result = ssh_client.execute(c) + except Exception: + self.fail("SSH failed for management server: %s" % + self.services["mgmt_server"]["ipaddress"]) + + self.debug("Deleting account: %s" % self.account.account.name) + # Delete account + self.account.delete(self.apiclient) + + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + self.assertEqual( + isinstance(interval, list), + True, + "Check list response returns a valid list" + ) + self.debug("account.cleanup.interval: %s" % interval[0].value) + + # Wait for account cleanup interval + time.sleep(int(interval[0].value) * 2) + + with self.assertRaises(Exception): + accounts = list_accounts( + self.apiclient, + id=self.account.account.id + ) + try: + cmds = [ + "mount %s:/%s %s" % ( + sec_storage_ip, + export_path, + self.services["mount_dir"] + ), + "ls %s/snapshots/%s/%s" % ( + self.services["mount_dir"], + account_id, + volume_id + ), + ] + + for c in cmds: + self.debug("command: %s" % c) + result = ssh_client.execute(c) + self.debug("Result: %s" % result) + + res = str(result) + + self.assertNotEqual( + res.count(snapshot_uuid), + 1, + "Check snapshot UUID in secondary storage and database" + ) + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["mount_dir"]), + ] + for c in cmds: + self.debug("command: %s" % c) + result = ssh_client.execute(c) + self.debug("Result: %s" % result) + + except Exception: + self.fail("SSH failed for management server: %s" % + self.services["mgmt_server"]["ipaddress"]) + return + + +class TestSnapshotDetachedDisk(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + cls.services["server"]["diskoffering"] = cls.disk_offering.id + + cls.services["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_03_snapshot_detachedDisk(self): + """Test snapshot from detached disk + """ + + # Validate the following + # 1. login in VM and write some data on data disk(use fdisk to + # partition datadisk,fdisk /dev/sdb, and make filesystem using + # mkfs.ext3) + # 2. Detach the data disk and write some data on data disk + # 3. perform the snapshot on the detached volume + # 4. listvolumes with VM id shouldn't show the detached volume + # 5. listSnapshots should list the snapshot that was created + # 6. verify that secondary storage NFS share contains the reqd volume + # under /secondary/snapshots/$accountid/$volumeid/$snapshot_uuid + # 7. verify backup_snap_id was non null in the `snapshots` table + + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check list response returns a valid list" + ) + volume = volumes[0] + random_data_0 = random_gen(100) + random_data_1 = random_gen(100) + try: + ssh_client = self.virtual_machine.get_ssh_client() + + #Format partition using ext3 + format_volume_to_ext3( + ssh_client, + self.services["diskdevice"] + ) + cmds = [ + "mkdir -p %s" % self.services["mount_dir"], + "mount %s1 %s" % ( + self.services["diskdevice"], + self.services["mount_dir"] + ), + "pushd %s" % self.services["mount_dir"], + "mkdir -p %s/{%s,%s} " % ( + self.services["sub_dir"], + self.services["sub_lvl_dir1"], + self.services["sub_lvl_dir2"] + ), + "echo %s > %s/%s/%s" % ( + random_data_0, + self.services["sub_dir"], + self.services["sub_lvl_dir1"], + self.services["random_data"] + ), + "echo %s > %s/%s/%s" % ( + random_data_1, + self.services["sub_dir"], + self.services["sub_lvl_dir2"], + self.services["random_data"] + ) + ] + for c in cmds: + self.debug(ssh_client.execute(c)) + + #detach volume from VM + cmd = detachVolume.detachVolumeCmd() + cmd.id = volume.id + self.apiclient.detachVolume(cmd) + + #Create snapshot from detached volume + snapshot = Snapshot.create(self.apiclient, volume.id) + self.cleanup.append(snapshot) + + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + + self.assertEqual( + volumes, + None, + "Check Volume is detached" + ) + + # Verify the snapshot was created or not + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + except Exception as e: + self.fail("SSH failed for VM with IP: %s" % + self.virtual_machine.ipaddress) + + # Fetch values from database + qresultset = self.dbclient.execute( + "select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \ + % snapshot.id + ) + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + + qresult = qresultset[0] + snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID + account_id = qresult[1] + volume_id = qresult[2] + + self.assertNotEqual( + str(qresult[0]), + 'NULL', + "Check if backup_snap_id is not null" + ) + + # Get the Secondary Storage details from list Hosts + hosts = list_hosts( + self.apiclient, + type='SecondaryStorage', + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (hosts[0].name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] + + # Split IP address and export path from name + sec_storage_ip = parse_url[2] + # Sec Storage IP: 192.168.100.21 + + export_path = '/'.join(parse_url[3:]) + # Export path: export/test + + # Sleep to ensure that snapshot is reflected in sec storage + time.sleep(self.services["sleep"]) + try: + # Login to Management server to check snapshot present on sec disk + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["mgmt_server"]["ipaddress"], + self.services["mgmt_server"]["port"], + self.services["mgmt_server"]["username"], + self.services["mgmt_server"]["password"], + ) + + cmds = [ + "mkdir -p %s" % self.services["mount_dir"], + "mount %s:/%s %s" % ( + sec_storage_ip, + export_path, + self.services["mount_dir"] + ), + "ls %s/snapshots/%s/%s" % ( + self.services["mount_dir"], + account_id, + volume_id + ), + ] + + for c in cmds: + result = ssh_client.execute(c) + res = str(result) + self.assertEqual( + res.count(snapshot_uuid), + 1, + "Check snapshot UUID in secondary storage and database" + ) + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["mount_dir"]), + ] + for c in cmds: + result = ssh_client.execute(c) + except Exception as e: + self.fail("SSH failed for management server: %s" % + self.services["mgmt_server"]["ipaddress"]) + + return + + +class TestSnapshotLimit(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_04_snapshot_limit(self): + """Test snapshot limit in snapshot policies + """ + + # Validate the following + # 1. Perform hourly recurring snapshot on the root disk of VM and keep + # the maxsnapshots as 1 + # 2. listSnapshots should list the snapshot that was created + # snapshot folder in secondary storage should contain only one + # snapshot image(/secondary/snapshots/$accountid/$volumeid/) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check list response returns a valid list" + ) + volume = volumes[0] + + # Create a snapshot policy + recurring_snapshot = SnapshotPolicy.create( + self.apiclient, + volume.id, + self.services["recurring_snapshot"] + ) + self.cleanup.append(recurring_snapshot) + + snapshot_policy = list_snapshot_policy( + self.apiclient, + id=recurring_snapshot.id, + volumeid=volume.id + ) + self.assertEqual( + isinstance(snapshot_policy, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + snapshot_policy, + None, + "Check if result exists in list item call" + ) + + self.assertEqual( + snapshot_policy[0].id, + recurring_snapshot.id, + "Check recurring snapshot id in list resources call" + ) + self.assertEqual( + snapshot_policy[0].maxsnaps, + self.services["recurring_snapshot"]["maxsnaps"], + "Check interval type in list resources call" + ) + # Sleep for (maxsnaps+1) hours to verify + # only maxsnaps snapshots are retained + time.sleep( + (self.services["recurring_snapshot"]["maxsnaps"]) * 3600 + ) + + # Verify the snapshot was created or not + snapshots = list_snapshots( + self.apiclient, + volumeid=volume.id, + intervaltype=\ + self.services["recurring_snapshot"]["intervaltype"], + snapshottype='RECURRING', + listall=True + ) + + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(snapshots), + self.services["recurring_snapshot"]["maxsnaps"], + "Check maximum number of recurring snapshots retained" + ) + # Sleep to ensure that snapshot is reflected in sec storage + time.sleep(self.services["sleep"]) + + # Fetch values from database + qresultset = self.dbclient.execute( + "select backup_snap_id, account_id, volume_id from snapshots where uuid = '%s';" \ + % self.snapshot.id + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DBQuery returns a valid list" + ) + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + + qresult = qresultset[0] + snapshot_uuid = qresult[0] # backup_snap_id = snapshot UUID + account_id = qresult[1] + volume_id = qresult[2] + + # Get the Secondary Storage details from list Hosts + hosts = list_hosts( + self.apiclient, + type='SecondaryStorage', + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (hosts[0].name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] + + # Split IP address and export path from name + sec_storage_ip = parse_url[2] + # Sec Storage IP: 192.168.100.21 + + export_path = '/'.join(parse_url[3:]) + # Export path: export/test + try: + # Login to VM to check snapshot present on sec disk + ssh_client = remoteSSHClient.remoteSSHClient( + self.services["mgmt_server"]["ipaddress"], + self.services["mgmt_server"]["port"], + self.services["mgmt_server"]["username"], + self.services["mgmt_server"]["password"], + ) + + cmds = [ + "mkdir -p %s" % self.services["mount_dir"], + "mount %s:/%s %s" % ( + sec_storage_ip, + export_path, + self.services["mount_dir"] + ), + "ls %s/snapshots/%s/%s" % ( + self.services["mount_dir"], + account_id, + volume_id + ), + ] + + for c in cmds: + result = ssh_client.execute(c) + + res = str(result) + self.assertEqual( + res.count(snapshot_uuid), + 1, + "Check snapshot UUID in secondary storage and database" + ) + + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["mount_dir"]), + ] + for c in cmds: + result = ssh_client.execute(c) + except Exception as e: + raise Exception("SSH access failed for management server: %s" % + self.services["mgmt_server"]["ipaddress"]) + return + + +class TestSnapshotEvents(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_05_snapshot_events(self): + """Test snapshot events + """ + + # Validate the following + # 1. Perform snapshot on the root disk of this VM and check the events/alerts. + # 2. delete the snapshots and check the events/alerts + # 3. listEvents() shows created/deleted snapshot events + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check list response returns a valid list" + ) + volume = volumes[0] + + # Create a snapshot from the ROOTDISK + snapshot = Snapshot.create(self.apiclient, volumes[0].id) + self.debug("Snapshot created with ID: %s" % snapshot.id) + + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + snapshot.delete(self.apiclient) + + # Sleep to ensure that snapshot is deleted properly + time.sleep(self.services["sleep"]) + events = list_events( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + type='SNAPSHOT.DELETE' + ) + self.assertEqual( + isinstance(events, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + events, + None, + "Check if event exists in list events call" + ) + self.assertIn( + events[0].state, + ['Completed', 'Scheduled'], + "Check events state in list events call" + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_templates.py b/tools/testClient/testcase/P1-tests/test_templates.py new file mode 100644 index 00000000000..bfccf54061b --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_templates.py @@ -0,0 +1,602 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Templates +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import urllib +from random import random +#Import System modules +import time + + +class Services: + """Test Templates Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "disk_offering": { + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "virtual_machine": { + "displayname": "testVM", + "hypervisor": 'XenServer', + "protocol": 'TCP', + "ssh_port": 22, + "username": "root", + "password": "password", + "privateport": 22, + "publicport": 22, + }, + "volume": { + "diskname": "Test Volume", + }, + "templates": { + # Configs for different Template formats + # For Eg. raw image, zip etc + 0:{ + "displaytext": "Public Template", + "name": "Public template", + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2", + "hypervisor": 'XenServer', + "format" : 'VHD', + "isfeatured": True, + "ispublic": True, + "isextractable": True, + }, + }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "templatefilter": 'self', + }, + "templatefilter": 'self', + "destzoneid": 2, # For Copy template (Destination zone) + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "sleep": 60, + "timeout": 10, + "mode": 'advanced', # Networking mode: Advanced, basic + } + + +@unittest.skip("Open questions") +class TestCreateTemplate(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_create_template(self): + """Test create public & private template + """ + + # Validate the following: + # 1. Upload a templates in raw img format. Create a Vm instances from + # raw img template. + # 2. Upload a templates in zip file format. Create a Vm instances from + # zip template. + # 3. Upload a templates in tar format.Create a Vm instances from tar + # template. + # 4. Upload a templates in tar gzip format.Create a Vm instances from + # tar gzip template. + # 5. Upload a templates in tar bzip format. Create a Vm instances from + # tar bzip template. + # 6. Verify VMs & Templates is up and in ready state + + for k, v in self.services["templates"].items(): + + # Register new template + template = Template.register( + self.apiclient, + v, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug( + "Registered a template of format: %s with ID: %s" % ( + v["format"], + template.id + )) + # Wait for template to download + template.download(self.apiclient) + self.cleanup.append(template) + + # Wait for template status to be changed across + time.sleep(self.services["sleep"]) + timeout = self.services["timeout"] + while True: + list_template_response = list_templates( + self.apiclient, + templatefilter=\ + self.services["templatefilter"], + id=template.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + if isinstance(list_template_response, list): + break + elif timeout == 0: + raise Exception("List template failed!") + + time.sleep(5) + timeout = timeout - 1 + #Verify template response to check whether template added successfully + self.assertEqual( + isinstance(list_template_response, list), + True, + "Check for list template response return valid data" + ) + + self.assertNotEqual( + len(list_template_response), + 0, + "Check template available in List Templates" + ) + + template_response = list_template_response[0] + self.assertEqual( + template_response.isready, + True, + "Check display text of newly created template" + ) + + # Deploy new virtual machine using template + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + mode=self.services["mode"] + ) + self.debug("creating an instance with template ID: %s" % template.id) + vm_response = list_virtual_machines( + self.apiclient, + id=virtual_machine.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(vm_response, list), + True, + "Check for list VMs response after VM deployment" + ) + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Running', + "Check the state of VM created from Template" + ) + return + + +class TestTemplates(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.services = Services().services + cls.api_client = fetch_api_client() + + # Get Zone, templates etc + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # create virtual machine + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) + + timeout = cls.services["timeout"] + #Wait before server has be successfully stopped + time.sleep(cls.services["sleep"]) + + while True: + list_volume = list_volumes( + cls.api_client, + virtualmachineid=cls.virtual_machine.id, + type='ROOT', + listall=True + ) + if isinstance(list_volume, list): + break + elif timeout == 0: + raise Exception("List volumes failed.") + + time.sleep(5) + timeout = timeout -1 + + cls.volume = list_volume[0] + + #Create template from volume + cls.template = Template.create( + cls.api_client, + cls.services["template"], + cls.volume.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + #Cleanup created resources such as templates and VMs + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_01_create_template_volume(self): + """Test Create template from volume + """ + + # Validate the following: + # 1. Deploy new VM using the template created from Volume + # 2. VM should be in Up and Running state + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + ) + + self.debug("creating an instance with template ID: %s" % self.template.id) + self.cleanup.append(virtual_machine) + vm_response = list_virtual_machines( + self.apiclient, + id=virtual_machine.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Running', + "Check the state of VM created from Template" + ) + return + + def test_02_copy_template(self): + """Test for copy template from one zone to another""" + + # Validate the following + # 1. copy template should be successful and + # secondary storage should contain new copied template. + + self.debug( + "Copying template from zone: %s to %s" % ( + self.template.id, + self.services["destzoneid"] + )) + cmd = copyTemplate.copyTemplateCmd() + cmd.id = self.template.id + cmd.destzoneid = self.services["destzoneid"] + cmd.sourcezoneid = self.zone.id + self.apiclient.copyTemplate(cmd) + + # Verify template is copied to another zone using ListTemplates + list_template_response = list_templates( + self.apiclient, + templatefilter=\ + self.services["templatefilter"], + id=self.template.id, + zoneid=self.services["destzoneid"] + ) + self.assertEqual( + isinstance(list_template_response, list), + True, + "Check for list template response return valid list" + ) + + self.assertNotEqual( + len(list_template_response), + 0, + "Check template extracted in List Templates" + ) + + template_response = list_template_response[0] + self.assertEqual( + template_response.id, + self.template.id, + "Check ID of the downloaded template" + ) + self.assertEqual( + template_response.zoneid, + self.services["destzoneid"], + "Check zone ID of the copied template" + ) + + # Cleanup- Delete the copied template + cmd = deleteTemplate.deleteTemplateCmd() + cmd.id = self.template.id + cmd.zoneid = self.services["destzoneid"] + self.apiclient.deleteTemplate(cmd) + return + + def test_03_delete_template(self): + """Test Delete template + """ + + # Validate the following: + # 1. Create a template and verify it is shown in list templates response + # 2. Delete the created template and again verify list template response + + # Verify template response for updated attributes + list_template_response = list_templates( + self.apiclient, + templatefilter=\ + self.services["template"]["templatefilter"], + id=self.template.id, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_template_response, list), + True, + "Check for list template response return valid list" + ) + + self.assertNotEqual( + len(list_template_response), + 0, + "Check template available in List Templates" + ) + template_response = list_template_response[0] + + self.assertEqual( + template_response.id, + self.template.id, + "Check display text of updated template" + ) + + self.debug("Deleting template: %s" % self.template) + # Delete the template + self.template.delete(self.apiclient) + self.debug("Delete template: %s successful" % self.template) + + list_template_response = list_templates( + self.apiclient, + templatefilter=\ + self.services["template"]["templatefilter"], + id=self.template.id, + zoneid=self.zone.id + ) + self.assertEqual( + list_template_response, + None, + "Check template available in List Templates" + ) + return + + def test_04_template_from_snapshot(self): + """Create Template from snapshot + """ + + # Validate the following + # 2. Snapshot the Root disk + # 3. Create Template from snapshot + # 4. Deploy Virtual machine using this template + # 5. VM should be in running state + + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + + self.debug("Creating a snapshot from volume: %s" % volume.id) + #Create a snapshot of volume + snapshot = Snapshot.create( + self.apiclient, + volume.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Creating a template from snapshot: %s" % snapshot.id) + # Generate template from the snapshot + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["template"] + ) + self.cleanup.append(template) + # Verify created template + templates = list_templates( + self.apiclient, + templatefilter=\ + self.services["template"]["templatefilter"], + id=template.id + ) + self.assertNotEqual( + templates, + None, + "Check if result exists in list item call" + ) + + self.assertEqual( + templates[0].id, + template.id, + "Check new template id in list resources call" + ) + self.debug("Deploying a VM from template: %s" % template.id) + # Deploy new virtual machine using template + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + ) + self.cleanup.append(virtual_machine) + + vm_response = list_virtual_machines( + self.apiclient, + id=virtual_machine.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(vm_response, list), + True, + "Check for list VM response return valid list" + ) + + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Running', + "Check the state of VM created from Template" + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_usage.py b/tools/testClient/testcase/P1-tests/test_usage.py new file mode 100644 index 00000000000..d43e43131f7 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_usage.py @@ -0,0 +1,1564 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Snapshots +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import remoteSSHClient +import datetime + +class Services: + """Test Snapshots Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "disk_offering": { + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "volume": { + "diskname": "TestDiskServ", + }, + "server": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "templates": { + "displaytext": 'Template', + "name": 'Template', + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "templatefilter": 'self', + "url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.qcow2.bz2" + }, + "iso": { + "displaytext": "Test ISO", + "name": "Test ISO", + "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + # Source URL where ISO is located + "isextractable": True, + "isfeatured": True, + "ispublic": True, + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "vpn_user": { + "username": "test", + "password": "test", + }, + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestVmUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create Account, VMs etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_vm_usage(self): + """Test Create/Destroy VM and verify usage calculation + """ + + # Validate the following + # 1. Create a VM. Verify usage_events table contains VM .create, + # VM.start , Network.offering.assign , Volume.create events + # 2. Stop the VM. Verify usage_events table contains + # network.offerings.remove ,VM .stop Events for the created account. + # 3. Destroy the VM after some time. Verify usage_events table contains + # VM.Destroy and volume .delete Event for the created account + # 4. Delete the account + + self.debug("Stopping the VM: %s" % self.virtual_machine.id) + # Stop the VM + self.virtual_machine.stop(self.apiclient) + + time.sleep(self.services["sleep"]) + # Destroy the VM + self.debug("Destroying the VM: %s" % self.virtual_machine.id) + self.virtual_machine.delete(self.apiclient) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + 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 = str(qresultset) + self.debug("Query result: %s" % qresult) + # Check if VM.CREATE, VM.DESTROY events present in usage_event table + self.assertEqual( + qresult.count('VM.START'), + 1, + "Check VM.START event in events table" + ) + + self.assertEqual( + qresult.count('NETWORK.OFFERING.ASSIGN'), + 1, + "Check NETWORK.OFFERING.ASSIGN in events table" + ) + self.assertEqual( + qresult.count('VM.CREATE'), + 1, + "Check VM.CREATE in list events" + ) + + self.assertEqual( + qresult.count('VOLUME.CREATE'), + 1, + "Check VOLUME.CREATE in events table" + ) + + self.assertEqual( + qresult.count('VM.STOP'), + 1, + "Check VM.STOP in events table" + ) + + self.assertEqual( + qresult.count('NETWORK.OFFERING.REMOVE'), + 1, + "Check NETWORK.OFFERING.REMOVE in list events" + ) + + self.assertEqual( + qresult.count('VM.DESTROY'), + 1, + "Check VM.DESTROY in events table" + ) + + self.assertEqual( + qresult.count('VOLUME.DELETE'), + 1, + "Check VOLUME.DELETE in events table" + ) + return + + +class TestPublicIPUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create VMs, Assign Public IP etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + + cls.public_ip = PublicIPAddress.create( + cls.api_client, + cls.virtual_machine.account, + cls.virtual_machine.zoneid, + cls.virtual_machine.domainid, + cls.services["server"] + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_public_ip_usage(self): + """Test Assign new IP and verify usage calculation + """ + + # Validate the following + # 1. Aquire a IP for the network of this account. Verify usage_event + # table has Acquire IP event for the IP for this account + # 2. Release one of the IP of this account. Verify usage_event table + # has IP.Release event for released IP for this account + # 3. Delete the newly created account + + self.debug("Deleting public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + # Release one of the IP + self.public_ip.delete(self.apiclient) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + 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 = str(qresultset) + # Check if NET.IPASSIGN, NET.IPRELEASE events present in usage_event + # table + self.assertEqual( + qresult.count('NET.IPASSIGN') > 0, + True, + "Check NET.IPASSIGN event in events table" + ) + + self.assertEqual( + qresult.count('NET.IPRELEASE') > 0, + True, + "Check NET.IPRELEASE in events table" + ) + return + + +class TestVolumeUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + cls.services["server"]["diskoffering"] = cls.disk_offering.id + cls.services["template"] = template.id + + # Create Account, VMs etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_volume_usage(self): + """Test Create/delete a volume and verify correct usage is recorded + """ + + # Validate the following + # 1. Volume.create event for both root and data disk is there for the + # created account in cloud.usage_event table + # 2. Stop the VM + # 3. Detach the data disk from this VM + # 4. Destroy the Data disk. Volume.delete event is generated for data + # disk of the destroyed VM + + # Stop VM + self.debug("Stopping VM with ID: %s" % self.virtual_machine.id) + self.virtual_machine.stop(self.apiclient) + + volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + self.assertEqual( + isinstance(volume_response, list), + True, + "Check for valid list volumes response" + ) + data_volume = volume_response[0] + + # Detach data Disk + self.debug("Detaching volume ID: %s VM with ID: %s" % ( + data_volume.id, + self.virtual_machine.id + )) + self.virtual_machine.detach_volume(self.apiclient, data_volume) + + # Delete Data disk + self.debug("Delete volume ID: %s" % data_volume.id) + cmd = deleteVolume.deleteVolumeCmd() + cmd.id = data_volume.id + self.apiclient.deleteVolume(cmd) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + self.assertEqual( + isinstance(qresultset, list), + True, + "Check DB query result set for valid data" + ) + + qresult = str(qresultset) + self.debug("Query result: %s" % qresult) + # Check VOLUME.CREATE, VOLUME.DESTROY events in cloud.usage_event table + self.assertEqual( + qresult.count('VOLUME.CREATE'), + 2, + "Check VOLUME.CREATE event in events table" + ) + + self.assertEqual( + qresult.count('VOLUME.DELETE'), + 1, + "Check VOLUME.DELETE in events table" + ) + return + + +class TestTemplateUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + 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.services["server"]["zoneid"] = cls.zone.id + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + #create virtual machine + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.services["mode"] + ) + + #Stop virtual machine + cls.virtual_machine.stop(cls.api_client) + + #Wait before server has be successfully stopped + time.sleep(30) + 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("List Volumes failed!") + cls._cleanup = [ + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, templates + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_template_usage(self): + """Test Upload/ delete a template and verify correct usage is generated + for the template uploaded + """ + + # Validate the following + # 1. Create a account + # 2. Upload a template from this account. template.create event is + # recorded in cloud.usage_event table for this account + # 3. Delete the template. template.delete event is recorded in + # cloud.usage_event tables for this account + # 4. Destroy the account + + #Create template from Virtual machine and Volume ID + self.template = Template.create( + self.apiclient, + self.services["templates"], + self.volume.id + ) + self.debug("Created template with ID: %s" % self.template.id) + # Delete template + self.template.delete(self.apiclient) + self.debug("Deleted template with ID: %s" % self.template.id) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + 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 = str(qresultset) + self.debug("Query result: %s" % qresult) + + # Check for TEMPLATE.CREATE, TEMPLATE.DELETE in cloud.usage_event table + self.assertEqual( + qresult.count('TEMPLATE.CREATE'), + 1, + "Check TEMPLATE.CREATE event in events table" + ) + + self.assertEqual( + qresult.count('TEMPLATE.DELETE'), + 1, + "Check TEMPLATE.DELETE in events table" + ) + return + + +class TestISOUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + 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.services["server"]["zoneid"] = cls.zone.id + cls.services["iso"]["zoneid"] = cls.zone.id + # Create Account, ISO image etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.services["account"] = cls.account.account.name + cls.iso = Iso.create( + cls.api_client, + cls.services["iso"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + try: + # Wait till ISO gets downloaded + cls.iso.download(cls.api_client) + except Exception as e: + raise Exception("%s: Failed to download ISO: %s" % ( + e, + cls.iso.id + )) + cls._cleanup = [ + cls.account, + ] + 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 ISO images + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_ISO_usage(self): + """Test Create/Delete a ISO and verify its usage is generated correctly + """ + + # Validate the following + # 1. Create a account + # 2. Upload a ISO from this account. ISO.create event is recorded in + # cloud.usage_event table for this account + # 3. Delete the ISO. ISO.delete event is recorded in cloud.usage_event + # tables for this account + # 4. Destroy the account + + # Delete the ISO + self.debug("Deleting ISO with ID: %s" % self.iso.id) + self.iso.delete(self.apiclient) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + 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 = str(qresultset) + self.debug("Query result: %s" % qresult) + + # Check for ISO.CREATE, ISO.DELETE events in cloud.usage_event table + self.assertEqual( + qresult.count('ISO.CREATE'), + 1, + "Check ISO.CREATE event in events table" + ) + + self.assertEqual( + qresult.count('ISO.DELETE'), + 1, + "Check ISO.DELETE in events table" + ) + return + + +class TestLBRuleUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create VMs, LB Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + cls.virtual_machine.account, + cls.virtual_machine.zoneid, + cls.virtual_machine.domainid, + cls.services["server"] + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, LB rules + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_lb_usage(self): + """Test Create/Delete a LB rule and verify correct usage is recorded + """ + + # Validate the following + # 1. Acquire a IP for this account. lb.rule.create event is registered + # for this account in cloud.usage_event table + # 2. Create a LB rule on the IP associated with this account + # 3. Delete the created LB rule from the account. lb.rule.delete event + # is registered for this account in cloud.usage_event table + # 4. Delete this account. + + self.debug( + "Creating load balancer rule for public IP: %s" % + self.public_ip_1.ipaddress.id) + #Create Load Balancer rule and assign VMs to rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + self.public_ip_1.ipaddress.id, + accountid=self.account.account.name + ) + # Delete LB Rule + self.debug("Deleting LB rule with ID: %s" % lb_rule.id) + lb_rule.delete(self.apiclient) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + 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 = str(qresultset) + self.debug("Query result: %s" % qresult) + + # Check for LB.CREATE, LB.DELETE in cloud.usage_event table + self.assertEqual( + qresult.count('LB.CREATE'), + 1, + "Check LB.CREATE event in events table" + ) + + self.assertEqual( + qresult.count('LB.DELETE'), + 1, + "Check LB.DELETE in events table" + ) + return + + +class TestSnapshotUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create Account, VMs etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_snapshot_usage(self): + """Test Create/Delete a manual snap shot and verify + correct usage is recorded + """ + + # Validate the following + # 1. Create snapshot of the root disk for this account.Snapshot.create + # event is there for the created account in cloud.usage_event table + # 2. Destroy the snapshot after some time. Snapshot.delete event is + # generated for the destroyed Snapshot + # 3. Delete the account + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check if list volumes return a valid data" + ) + + volume = volumes[0] + + # Create a snapshot from the ROOTDISK + self.debug("Creating snapshot from volume: %s" % volumes[0].id) + snapshot = Snapshot.create(self.apiclient, volumes[0].id) + + # Delete snapshot Rule + self.debug("Deleting snapshot: %s" % snapshot.id) + snapshot.delete(self.apiclient) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + self.assertEqual( + isinstance(qresultset, list), + True, + "Check if database query returns a valid data" + ) + + self.assertNotEqual( + len(qresultset), + 0, + "Check DB Query result set" + ) + + qresult = str(qresultset) + self.debug("Query Result: %s" % qresult) + + # Check for SNAPSHOT.CREATE, SNAPSHOT.DELETE events in cloud.usage_event + # table + self.assertEqual( + qresult.count('SNAPSHOT.CREATE'), + 1, + "Check SNAPSHOT.CREATE event in events table" + ) + + self.assertEqual( + qresult.count('SNAPSHOT.DELETE'), + 1, + "Check SNAPSHOT.DELETE in events table" + ) + return + + +class TestNatRuleUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + cls.virtual_machine.account, + cls.virtual_machine.zoneid, + cls.virtual_machine.domainid, + cls.services["server"] + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, NAT rules + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_nat_usage(self): + """Test Create/Delete a PF rule and verify correct usage is recorded + """ + + # Validate the following + # 1. Acquire a IP for this account + # 2. Create a PF rule on the IP associated with this account. + # NET.RULEADD event is registered for this account in + # cloud.usage_event table + # 3. Delete the created PF rule from the account. NET.RULEDelete event + # is registered for this account in cloud.usage_event table + # 4. Delete this account. + + self.debug("Creating NAT rule with public IP: %s" % + self.public_ip_1.ipaddress.id) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + self.virtual_machine, + self.services["natrule"], + self.public_ip_1.ipaddress.id + ) + + # Delete NAT Rule + self.debug("Deleting NAT rule: %s" % nat_rule.id) + nat_rule.delete(self.apiclient) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + 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 = str(qresultset) + self.debug("Query result: %s" % qresult) + + # Check for NET.RULEADD, NET.RULEDELETE in cloud.usage_event table + self.assertEqual( + qresult.count('NET.RULEADD'), + 1, + "Check NET.RULEADD event in events table" + ) + + self.assertEqual( + qresult.count('NET.RULEDELETE'), + 1, + "Check NET.RULEDELETE in events table" + ) + return + + +class TestVpnUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = template.id + + # Create Service offerings, VMs etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=template.id, + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + cls.virtual_machine.account, + cls.virtual_machine.zoneid, + cls.virtual_machine.domainid, + cls.services["server"] + ) + cls._cleanup = [ + cls.service_offering, + cls.account, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, VPN users + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_vpn_usage(self): + """Test Create/Delete a VPN and verify correct usage is recorded + """ + + # Validate the following + # 1. Enable VPN for this IP. vpn.add.user event is registered for this + # account in cloud.usage_event table + # 2. Add user to this vpn + # 3. Delete user for this VPN. vpn.user.delete event is registered for + # this account in cloud.usage_event table + # 4. Delete this account. + + self.debug("Created VPN with public IP: %s" % + self.public_ip.ipaddress.id) + #Assign VPN to Public IP + vpn = Vpn.create( + self.apiclient, + self.public_ip.ipaddress.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.debug("Created VPN user for account: %s" % + self.account.account.name) + + vpnuser = VpnUser.create( + self.apiclient, + self.services["vpn_user"]["username"], + self.services["vpn_user"]["password"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + # Remove VPN user + self.debug("Deleting VPN user: %s" % vpnuser.id) + vpnuser.delete(self.apiclient) + + # Delete VPN access + self.debug("Deleting VPN: %s" % vpn.publicipid) + vpn.delete(self.apiclient) + + # Fetch account ID from account_uuid + self.debug("select id from account where uuid = '%s';" \ + % self.account.account.id) + + qresultset = self.dbclient.execute( + "select id from account where uuid = '%s';" \ + % self.account.account.id + ) + 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] + + account_id = qresult[0] + self.debug("select type from usage_event where account_id = '%s';" \ + % account_id) + + qresultset = self.dbclient.execute( + "select type from usage_event where account_id = '%s';" \ + % account_id + ) + + 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 = str(qresultset) + self.debug("Query result: %s" % qresult) + + # Check for VPN user related events + self.assertEqual( + qresult.count('VPN.USER.ADD'), + 1, + "Check VPN.USER.ADD event in events table" + ) + + self.assertEqual( + qresult.count('VPN.USER.ADD'), + 1, + "Check VPN.USER.ADD in events table" + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_volumes.py b/tools/testClient/testcase/P1-tests/test_volumes.py new file mode 100644 index 00000000000..4c45bdad4e3 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_volumes.py @@ -0,0 +1,1009 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Volumes +""" +#Import Local Modules +from cloudstackTestCase import * +from cloudstackAPI import * +from testcase.libs.utils import * +from testcase.libs.base import * +from testcase.libs.common import * +import remoteSSHClient +#Import System modules +import os +import urllib +import time +import tempfile + + +class Services: + """Test Volume Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "disk_offering": { + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "volume": { + "diskname": "TestDiskServ", + "max": 6, + }, + "virtual_machine": { + "displayname": "testVM", + "hypervisor": 'XenServer', + "protocol": 'TCP', + "ssh_port": 22, + "username": "root", + "password": "password", + "privateport": 22, + "publicport": 22, + }, + "iso": # ISO settings for Attach/Detach ISO tests + { + "displaytext": "Test ISO", + "name": "testISO", + "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + # Source URL where ISO is located + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + }, + "sleep": 50, + "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "mode": 'advanced', + } + + +class TestAttachVolume(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account + ] + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def test_01_volume_attach(self): + """Test Attach volumes (max capacity) + """ + + # Validate the following + # 1. Deploy a vm and create 5 data disk + # 2. Attach all the created Volume to the vm. + # 3. Reboot the VM. VM should be successfully rebooted + # 4. Stop the VM. Stop VM should be successful + # 5. Start The VM. Start VM should be successful + + # Create 5 volumes and attach to VM + for i in range(self.services["volume"]["max"]): + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume: %s for account: %s" % ( + volume.id, + self.account.account.name + )) + # Check List Volume response for newly created volume + list_volume_response = list_volumes( + self.apiclient, + id=volume.id + ) + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + # Attach volume to VM + self.virtual_machine.attach_volume( + self.apiclient, + volume + ) + self.debug("Attach volume: %s to VM: %s" % ( + volume.id, + self.virtual_machine.id + )) + # Check all volumes attached to same VM + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + self.assertEqual( + len(list_volume_response), + self.services["volume"]["max"], + "Check number of data volumes attached to VM" + ) + self.debug("Rebooting the VM: %s" % self.virtual_machine.id) + # Reboot VM + self.virtual_machine.reboot(self.apiclient) + + vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id, + ) + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM response for valid list" + ) + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Running', + "Check the state of VM" + ) + + self.debug("Stopping the VM: %s" % self.virtual_machine.id) + # Stop VM + self.virtual_machine.stop(self.apiclient) + + vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id, + ) + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM response for valid list" + ) + + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Stopped', + "Check the state of VM" + ) + + self.debug("Starting the VM: %s" % self.virtual_machine.id) + # Start VM + self.virtual_machine.start(self.apiclient) + # Sleep to ensure that VM is in ready state + time.sleep(self.services["sleep"]) + + vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id, + ) + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM response for valid list" + ) + + #Verify VM response to check whether VM deployment was successful + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Running', + "Check the state of VM" + ) + return + + def test_02_volume_attach_max(self): + """Test attach volumes (more than max) to an instance + """ + + # Validate the following + # 1. Attach one more data volume to VM (Already 5 attached) + # 2. Attach volume should fail + + # Create a volume and attach to VM + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume: %s for account: %s" % ( + volume.id, + self.account.account.name + )) + # Check List Volume response for newly created volume + list_volume_response = list_volumes( + self.apiclient, + id=volume.id + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + # Attach volume to VM + with self.assertRaises(Exception): + self.debug("Trying to Attach volume: %s to VM: %s" % ( + volume.id, + self.virtual_machine.id + )) + self.virtual_machine.attach_volume( + self.apiclient, + volume + ) + return + + def tearDown(self): + #Clean up, terminate the created volumes + cleanup_resources(self.apiclient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + +class TestAttachDetachVolume(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account + ] + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created volumes + cleanup_resources(self.apiclient, self.cleanup) + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = fetch_api_client() + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def test_01_volume_attach_detach(self): + """Test Volume attach/detach to VM (5 data volumes) + """ + + # Validate the following + # 1. Deploy a vm and create 5 data disk + # 2. Attach all the created Volume to the vm. + # 3. Detach all the volumes attached. + # 4. Reboot the VM. VM should be successfully rebooted + # 5. Stop the VM. Stop VM should be successful + # 6. Start The VM. Start VM should be successful + + volumes = [] + # Create 5 volumes and attach to VM + for i in range(self.services["volume"]["max"]): + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume: %s for account: %s" % ( + volume.id, + self.account.account.name + )) + self.cleanup.append(volume) + volumes.append(volume) + + # Check List Volume response for newly created volume + list_volume_response = list_volumes( + self.apiclient, + id=volume.id + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + self.debug("Attach volume: %s to VM: %s" % ( + volume.id, + self.virtual_machine.id + )) + # Attach volume to VM + self.virtual_machine.attach_volume( + self.apiclient, + volume + ) + + # Check all volumes attached to same VM + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + self.assertEqual( + len(list_volume_response), + self.services["volume"]["max"], + "Check number of data volumes attached to VM" + ) + + # Detach all volumes from VM + for volume in volumes: + self.debug("Detach volume: %s to VM: %s" % ( + volume.id, + self.virtual_machine.id + )) + self.virtual_machine.detach_volume( + self.apiclient, + volume + ) + # Reboot VM + self.debug("Rebooting the VM: %s" % self.virtual_machine.id) + self.virtual_machine.reboot(self.apiclient) + # Sleep to ensure that VM is in ready state + time.sleep(self.services["sleep"]) + + vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id, + ) + #Verify VM response to check whether VM deployment was successful + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM response for valid list" + ) + + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Running', + "Check the state of VM" + ) + + # Stop VM + self.debug("Stopping the VM: %s" % self.virtual_machine.id) + self.virtual_machine.stop(self.apiclient) + # Sleep to ensure that VM is in ready state + time.sleep(self.services["sleep"]) + + vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id, + ) + #Verify VM response to check whether VM deployment was successful + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM response for valid list" + ) + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Stopped', + "Check the state of VM" + ) + + # Start VM + self.debug("Starting the VM: %s" % self.virtual_machine.id) + self.virtual_machine.start(self.apiclient) + # Sleep to ensure that VM is in ready state + time.sleep(self.services["sleep"]) + + vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id, + ) + #Verify VM response to check whether VM deployment was successful + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM response for valid list" + ) + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + vm = vm_response[0] + self.assertEqual( + vm.state, + 'Running', + "Check the state of VM" + ) + return + + +class TestAttachVolumeISO(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["iso"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account + ] + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_volume_iso_attach(self): + """Test Volumes and ISO attach + """ + + # Validate the following + # 1. Create and attach 5 data volumes to VM + # 2. Create an ISO. Attach it to VM instance + # 3. Verify that attach ISO is successful + + # Create 5 volumes and attach to VM + for i in range(self.services["volume"]["max"]): + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume: %s for account: %s" % ( + volume.id, + self.account.account.name + )) + # Check List Volume response for newly created volume + list_volume_response = list_volumes( + self.apiclient, + id=volume.id + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + # Attach volume to VM + self.virtual_machine.attach_volume( + self.apiclient, + volume + ) + + # Check all volumes attached to same VM + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + self.assertEqual( + len(list_volume_response), + self.services["volume"]["max"], + "Check number of data volumes attached to VM" + ) + # Create an ISO and attach it to VM + iso = Iso.create( + self.apiclient, + self.services["iso"], + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.debug("Created ISO with ID: %s for account: %s" % ( + iso.id, + self.account.account.name + )) + self.cleanup.append(iso) + try: + self.debug("Downloading ISO with ID: %s" % iso.id) + iso.download(self.apiclient) + except Exception as e: + self.fail("Exception while downloading ISO %s: %s"\ + % (iso.id, e)) + + #Attach ISO to virtual machine + self.debug("Attach ISO ID: %s to VM: %s" % ( + iso.id, + self.virtual_machine.id + )) + cmd = attachIso.attachIsoCmd() + cmd.id = iso.id + cmd.virtualmachineid = self.virtual_machine.id + self.apiclient.attachIso(cmd) + + # Verify ISO is attached to VM + vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id, + ) + #Verify VM response to check whether VM deployment was successful + self.assertEqual( + isinstance(vm_response, list), + True, + "Check list VM response for valid list" + ) + + self.assertNotEqual( + len(vm_response), + 0, + "Check VMs available in List VMs response" + ) + vm = vm_response[0] + self.assertEqual( + vm.isoid, + iso.id, + "Check ISO is attached to VM or not" + ) + return + + +class TestVolumes(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = fetch_api_client() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + cls.services["virtual_machine"]["diskofferingid"] = cls.disk_offering.id + + # Create VMs, VMs etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + ) + + cls.volume = Volume.create( + cls.api_client, + cls.services["volume"], + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid, + diskofferingid=cls.disk_offering.id + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account + ] + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + def tearDown(self): + #Clean up, terminate the created volumes + cleanup_resources(self.apiclient, self.cleanup) + return + + def test_01_attach_volume(self): + """Attach a created Volume to a Running VM + """ + # Validate the following + # 1. Create a data volume. + # 2. List Volumes should not have vmname and virtualmachineid fields in + # response before volume attach (to VM) + # 3. Attch volume to VM. Attach volume should be successful. + # 4. List Volumes should have vmname and virtualmachineid fields in + # response before volume attach (to VM) + + # Check the list volumes response for vmname and virtualmachineid + list_volume_response = list_volumes( + self.apiclient, + id=self.volume.id + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + + volume = list_volume_response[0] + + self.assertEqual( + volume.type, + 'DATADISK', + "Check volume type from list volume response" + ) + + self.assertEqual( + hasattr(volume, 'vmname'), + True, + "Check whether volume has vmname field" + ) + self.assertEqual( + hasattr(volume, 'virtualmachineid'), + True, + "Check whether volume has virtualmachineid field" + ) + + # Attach volume to VM + self.debug("Attach volume: %s to VM: %s" % ( + self.volume.id, + self.virtual_machine.id + )) + self.virtual_machine.attach_volume(self.apiclient, self.volume) + + # Check all volumes attached to same VM + list_volume_response = list_volumes( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + listall=True + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + volume = list_volume_response[0] + self.assertEqual( + volume.vmname, + self.virtual_machine.name, + "Check virtual machine name in list volumes response" + ) + self.assertEqual( + volume.virtualmachineid, + self.virtual_machine.id, + "Check VM ID in list Volume response" + ) + return + + def test_02_detach_volume(self): + """Detach a Volume attached to a VM + """ + + # Validate the following + # 1. Data disk should be detached from instance + # 2. Listvolumes should not have vmname and virtualmachineid fields for + # that volume. + + self.debug("Detach volume: %s to VM: %s" % ( + self.volume.id, + self.virtual_machine.id + )) + self.virtual_machine.detach_volume(self.apiclient, self.volume) + + #Sleep to ensure the current state will reflected in other calls + time.sleep(self.services["sleep"]) + + list_volume_response = list_volumes( + self.apiclient, + id=self.volume.id + ) + self.assertEqual( + isinstance(list_volume_response, list), + True, + "Check list volumes response for valid list" + ) + + self.assertNotEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + volume = list_volume_response[0] + self.assertEqual( + volume.virtualmachineid, + None, + "Check if volume state (detached) is reflected" + ) + + self.assertEqual( + volume.vmname, + None, + "Check if volume state (detached) is reflected" + ) + return + + def test_03_delete_detached_volume(self): + """Delete a Volume unattached to an VM + """ + # Validate the following + # 1. volume should be deleted successfully and listVolume should not + # contain the deleted volume details. + + self.debug("Deleting volume: %s" % self.volume.id) + cmd = deleteVolume.deleteVolumeCmd() + cmd.id = self.volume.id + self.apiclient.deleteVolume(cmd) + + #Sleep to ensure the current state will reflected in other calls + time.sleep(self.services["sleep"]) + + list_volume_response = list_volumes( + self.apiclient, + id=self.volume.id, + type='DATADISK' + ) + self.assertEqual( + list_volume_response, + None, + "Check if volume exists in ListVolumes" + ) + return diff --git a/tools/testClient/testcase/libs/base.py b/tools/testClient/testcase/libs/base.py index 65f3c1ecf4d..1647a7f3b90 100644 --- a/tools/testClient/testcase/libs/base.py +++ b/tools/testClient/testcase/libs/base.py @@ -185,20 +185,10 @@ class VirtualMachine: elif "domainid" in services: cmd.domainid = services["domainid"] - # List Networks for that user - command = listNetworks.listNetworksCmd() - command.zoneid = services["zoneid"] - command.account = accountid or services["account"] - command.domainid = domainid or services["domainid"] - network = apiclient.listNetworks(command) - if networkids: cmd.networkids = networkids elif "networkids" in services: cmd.networkids = services["networkids"] -# elif network: #If user already has source NAT created, then use that -# if hasattr(network[0], "account"): -# cmd.networkids = str(network[0].id) if templateid: cmd.templateid = templateid @@ -274,13 +264,16 @@ class VirtualMachine: cmd.id = self.id apiclient.rebootVirtualMachine(cmd) - def get_ssh_client(self, ipaddress=None, reconnect=False): + def get_ssh_client(self, ipaddress=None, reconnect=False, port=None): """Get SSH object of VM""" # If NAT Rules are not created while VM deployment in Advanced mode # then, IP address must be passed if ipaddress != None: self.ssh_ip = ipaddress + if port: + self.ssh_port = port + if reconnect: self.ssh_client = is_server_ssh_ready( self.ssh_ip, @@ -479,7 +472,7 @@ class Template: return Template(apiclient.createTemplate(cmd).__dict__) @classmethod - def register(cls, apiclient, services, 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 @@ -490,7 +483,11 @@ class Template: cmd.hypervisor = services["hypervisor"] cmd.ostypeid = services["ostypeid"] cmd.url = services["url"] - cmd.zoneid = services["zoneid"] + + if zoneid: + cmd.zoneid = zoneid + else: + cmd.zoneid = services["zoneid"] cmd.isfeatured = services["isfeatured"] if "isfeatured" in services else False cmd.ispublic = services["ispublic"] if "ispublic" in services else False @@ -529,10 +526,10 @@ class Template: cmd.id = self.id apiclient.deleteTemplate(cmd) - def download(self, apiclient, timeout=5): + def download(self, apiclient, timeout=5, interval=60): """Download Template""" #Sleep to ensure template is in proper state before download - time.sleep(30) + time.sleep(interval) while True: template_response = Template.list( @@ -548,22 +545,20 @@ class Template: # template.status = Download Complete # Downloading - x% Downloaded # Error - Any other string - - if template.status == 'Download Complete' : + if template.status == 'Download Complete': break - elif 'Downloaded' not in template.status.split() or \ - 'Installing' not in template.status.split(): + elif 'Downloaded' in template.status: + time.sleep(interval) + + elif 'Installing' not in template.status: raise Exception("ErrorInDownload") - - elif 'Downloaded' in template.status.split(): - time.sleep(10) - + elif timeout == 0: break else: - time.sleep(10) + time.sleep(interval) timeout = timeout - 1 return @@ -617,11 +612,11 @@ class Iso: apiclient.deleteIso(cmd) return - def download(self, apiclient, timeout=5): + def download(self, apiclient, timeout=5, interval=60): """Download an ISO""" #Ensuring ISO is successfully downloaded while True: - time.sleep(60) + time.sleep(interval) cmd = listIsos.listIsosCmd() cmd.id = self.id @@ -636,8 +631,9 @@ class Iso: # or ISO is 'Successfully Installed' if response.status == 'Successfully Installed': return - elif 'Downloaded' not in response.status.split(): + elif 'Downloaded' not in response.status: raise Exception("ErrorInDownload") + elif timeout == 0: raise Exception("TimeoutException") else: @@ -1083,6 +1079,13 @@ class Host: apiclient.deleteHost(cmd) return + def enableMaintenance(self, apiclient): + """enables maintainance mode Host""" + + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = self.id + return apiclient.prepareHostForMaintenance(cmd) + @classmethod def list(cls, apiclient, **kwargs): """List all Hosts matching criteria""" @@ -1136,6 +1139,13 @@ class StoragePool: apiclient.deleteStoragePool(cmd) return + def enableMaintenance(self, apiclient): + """enables maintainance mode Storage pool""" + + cmd = enableStorageMaintenance.enableStorageMaintenanceCmd() + cmd.id = self.id + return apiclient.enableStorageMaintenance(cmd) + @classmethod def list(cls, apiclient, **kwargs): """List all storage pools matching criteria""" @@ -1233,6 +1243,8 @@ class VpnUser: cmd = removeVpnUser.removeVpnUserCmd() cmd.username = self.username + cmd.account = self.account + cmd.domainid = self.domainid apiclient.removeVpnUser(cmd) @@ -1267,6 +1279,15 @@ class Zone: cmd.id = self.id apiclient.deleteZone(cmd) + 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""" @@ -1373,6 +1394,46 @@ class SecondaryStorage: apiclient.deleteHost(cmd) +class PhysicalNetwork: + """Manage physical network storage""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, zoneid, domainid=None): + """Create physical network""" + cmd = createPhysicalNetwork.createPhysicalNetworkCmd() + + cmd.name = services["name"] + cmd.zoneid = zoneid + if domainid: + cmd.domainid = domainid + return PhysicalNetwork(apiclient.createPhysicalNetwork(cmd).__dict__) + + def delete(self, apiclient): + """Delete Physical Network""" + + cmd = deletePhysicalNetwork.deletePhysicalNetworkCmd() + cmd.id = self.id + apiclient.deletePhysicalNetwork(cmd) + + 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) + class SecurityGroup: """Manage Security Groups""" diff --git a/tools/testClient/testcase/libs/common.py b/tools/testClient/testcase/libs/common.py index be0385e047a..9ed527a8353 100644 --- a/tools/testClient/testcase/libs/common.py +++ b/tools/testClient/testcase/libs/common.py @@ -16,6 +16,21 @@ from base import * #Import System modules import time +def get_domain(apiclient, services=None): + "Returns a default domain" + + cmd = listDomains.listDomainsCmd() + if services: + if "domainid" in services: + cmd.id = services["domainid"] + + domains = apiclient.listDomains(cmd) + + if isinstance(domains, list): + return domains[0] + else: + raise Exception("Failed to find specified domain.") + def get_zone(apiclient, services=None): "Returns a default zone" @@ -112,10 +127,10 @@ 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): +def wait_for_ssvms(apiclient, zoneid, podid, interval=60): """After setup wait for SSVMs to come Up""" - time.sleep(30) + time.sleep(interval) timeout = 40 while True: list_ssvm_response = list_ssvms( @@ -127,15 +142,15 @@ def wait_for_ssvms(apiclient, zoneid, podid): ssvm = list_ssvm_response[0] if ssvm.state != 'Running': # Sleep to ensure SSVMs are Up and Running - time.sleep(30) + time.sleep(interval) timeout = timeout - 1 elif ssvm.state == 'Running': break elif timeout == 0: - raise Exception("SSVM failled to come up") + raise Exception("SSVM failed to come up") break - timeout = 20 + timeout = 40 while True: list_ssvm_response = list_ssvms( apiclient, @@ -146,16 +161,16 @@ def wait_for_ssvms(apiclient, zoneid, podid): cpvm = list_ssvm_response[0] if cpvm.state != 'Running': # Sleep to ensure SSVMs are Up and Running - time.sleep(30) + time.sleep(interval) timeout = timeout - 1 elif cpvm.state == 'Running': break elif timeout == 0: - raise Exception("SSVM failled to come up") + raise Exception("CPVM failed to come up") break return -def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip): +def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip, interval=60): """After setup wait till builtin templates are downloaded""" # Change IPTABLES Rules @@ -167,7 +182,7 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip) linklocalip, "iptables -P INPUT ACCEPT" ) - + time.sleep(interval) # Find the BUILTIN Templates for given Zone, Hypervisor list_template_response = list_templates( apiclient, @@ -187,7 +202,7 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip) # Sleep to ensure that template is in downloading state after adding # Sec storage - time.sleep(30) + time.sleep(interval) while True: template_response = list_templates( apiclient, @@ -200,12 +215,15 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip) # template.status = Download Complete # Downloading - x% Downloaded # Error - Any other string - if template.status == 'Download Complete' : + if template.status == 'Download Complete': break - elif 'Downloaded' not in template.status.split(): + + elif 'Downloaded' in template.status: + time.sleep(interval) + + elif 'Installing' not in template.status: raise Exception("ErrorInDownload") - elif 'Downloaded' in template.status.split(): - time.sleep(30) + return def update_resource_limit(apiclient, resourcetype, account=None, domainid=None, @@ -413,3 +431,24 @@ def list_usage_records(apiclient, **kwargs): cmd = listUsageRecords.listUsageRecordsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listUsageRecords(cmd)) + +def list_nw_service_prividers(apiclient, **kwargs): + """Lists Network service providers""" + + cmd = listNetworkServiceProviders.listNetworkServiceProvidersCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listNetworkServiceProviders(cmd)) + +def list_virtual_router_elements(apiclient, **kwargs): + """Lists Virtual Router elements""" + + cmd = listVirtualRouterElements.listVirtualRouterElementsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listVirtualRouterElements(cmd)) + +def list_network_offerings(apiclient, **kwargs): + """Lists network offerings""" + + cmd = listNetworkOfferings.listNetworkOfferingsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listNetworkOfferings(cmd)) \ No newline at end of file