From 6cfa5629652102e475e1ec43561bb1b6dcad2b07 Mon Sep 17 00:00:00 2001 From: Chirag Jog Date: Mon, 2 Apr 2012 10:08:59 -0700 Subject: [PATCH] 1. Add support for project related tests. 2. Fix the classes to fetch HTTP COnnection from the Parent class 3. Minor fixes --- .../testcase/BVT-tests/test_disk_offerings.py | 4 +- .../testcase/BVT-tests/test_hosts.py | 3 - .../testClient/testcase/BVT-tests/test_iso.py | 10 +- .../testcase/BVT-tests/test_network.py | 35 +- .../BVT-tests/test_primary_storage.py | 3 - .../testcase/BVT-tests/test_routers.py | 41 +- .../BVT-tests/test_secondary_storage.py | 2 +- .../BVT-tests/test_service_offerings.py | 4 +- .../testcase/BVT-tests/test_snapshots.py | 166 +- .../testcase/BVT-tests/test_ssvm.py | 203 +- .../testcase/BVT-tests/test_templates.py | 14 +- .../testcase/BVT-tests/test_vm_life_cycle.py | 40 +- .../testcase/BVT-tests/test_volumes.py | 9 +- tools/testClient/testcase/P1-tests/README | 11 +- .../testcase/P1-tests/test_accounts.py | 14 +- .../testcase/P1-tests/test_blocker_bugs.py | 20 +- .../testcase/P1-tests/test_project_configs.py | 1222 ++++++++++++ .../testcase/P1-tests/test_project_limits.py | 860 +++++++++ .../P1-tests/test_project_resources.py | 1304 +++++++++++++ .../testcase/P1-tests/test_project_usage.py | 1701 +++++++++++++++++ .../testcase/P1-tests/test_projects.py | 1630 ++++++++++++++++ .../testcase/P1-tests/test_resource_limits.py | 4 +- .../testcase/P1-tests/test_routers.py | 18 +- .../testcase/P1-tests/test_security_groups.py | 31 +- .../testcase/P1-tests/test_snapshots.py | 338 ++-- .../testcase/P1-tests/test_templates.py | 14 +- .../testcase/P1-tests/test_usage.py | 18 +- .../testcase/P1-tests/test_volumes.py | 16 +- tools/testClient/testcase/libs/base.py | 338 +++- tools/testClient/testcase/libs/common.py | 13 +- tools/testClient/testcase/libs/utils.py | 66 + 31 files changed, 7680 insertions(+), 472 deletions(-) create mode 100644 tools/testClient/testcase/P1-tests/test_project_configs.py create mode 100644 tools/testClient/testcase/P1-tests/test_project_limits.py create mode 100644 tools/testClient/testcase/P1-tests/test_project_resources.py create mode 100644 tools/testClient/testcase/P1-tests/test_project_usage.py create mode 100644 tools/testClient/testcase/P1-tests/test_projects.py diff --git a/tools/testClient/testcase/BVT-tests/test_disk_offerings.py b/tools/testClient/testcase/BVT-tests/test_disk_offerings.py index 217c9f07325..cd75812561a 100644 --- a/tools/testClient/testcase/BVT-tests/test_disk_offerings.py +++ b/tools/testClient/testcase/BVT-tests/test_disk_offerings.py @@ -109,7 +109,7 @@ class TestDiskOfferings(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestDiskOfferings, cls).getClsTestClient().getApiClient() cls.disk_offering_1 = DiskOffering.create( cls.api_client, cls.services["off"] @@ -124,7 +124,7 @@ class TestDiskOfferings(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestDiskOfferings, cls).getClsTestClient().getApiClient() cleanup_resources(cls.api_client, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) diff --git a/tools/testClient/testcase/BVT-tests/test_hosts.py b/tools/testClient/testcase/BVT-tests/test_hosts.py index 45a7db7f19d..b875d6c8036 100644 --- a/tools/testClient/testcase/BVT-tests/test_hosts.py +++ b/tools/testClient/testcase/BVT-tests/test_hosts.py @@ -78,9 +78,6 @@ class Services: "password": "fr3sca", }, }, - "zoneid": '5894a264-12b0-4257-a316-06c831bcf8e2', - # Optional, if specified the mentioned zone will be - # used for tests } class TestHosts(cloudstackTestCase): diff --git a/tools/testClient/testcase/BVT-tests/test_iso.py b/tools/testClient/testcase/BVT-tests/test_iso.py index 180f3b3d992..236931bf4dc 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": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', }, "iso_2": { @@ -51,7 +51,7 @@ class Services: "isextractable": True, "isfeatured": True, "ispublic": True, - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "mode": 'HTTP_DOWNLOAD', # Used in Extract template, value must be HTTP_DOWNLOAD }, @@ -64,7 +64,7 @@ class Services: "passwordenabled": True, "sleep": 60, "timeout": 10, - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', # CentOS 5.3 (64 bit) "mode": 'advanced' # Networking mode: Basic or Advanced @@ -168,7 +168,7 @@ class TestISO(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestISO, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -216,7 +216,7 @@ class TestISO(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestISO, cls).getClsTestClient().getApiClient() #Clean up, terminate the created templates cleanup_resources(cls.api_client, cls._cleanup) diff --git a/tools/testClient/testcase/BVT-tests/test_network.py b/tools/testClient/testcase/BVT-tests/test_network.py index be5ee3842c6..a165b4cc5b9 100644 --- a/tools/testClient/testcase/BVT-tests/test_network.py +++ b/tools/testClient/testcase/BVT-tests/test_network.py @@ -22,7 +22,7 @@ class Services: def __init__(self): self.services = { - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', # Cent OS 5.3 (64 bit) "mode": 'advanced', # Networking mode: Basic or advanced @@ -30,10 +30,23 @@ class Services: # Time interval after which LB switches the requests "sleep": 60, "timeout":10, + "network_offering": { + "name": 'Test Network offering', + "displaytext": 'Test Network offering', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + }, + }, "network": { "name": "Test Network", "displaytext": "Test Network", - "networkoffering": '3d4e36f1-6b5f-40fc-bb63-fe9353419e91', }, "service_offering": { "name": "Tiny Instance", @@ -87,7 +100,7 @@ class TestPublicIP(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestPublicIP, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -107,6 +120,15 @@ class TestPublicIP(cloudstackTestCase): domainid=cls.domain.id ) cls.services["network"]["zoneid"] = cls.zone.id + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + + cls.services["network"]["networkoffering"] = cls.network_offering.id cls.account_network = Network.create( cls.api_client, cls.services["network"], @@ -138,6 +160,7 @@ class TestPublicIP(cloudstackTestCase): cls.user_network, cls.account, cls.user, + cls.network_offering ] return @@ -256,7 +279,7 @@ class TestPortForwarding(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestPortForwarding, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates @@ -301,7 +324,7 @@ class TestPortForwarding(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestPortForwarding, cls).getClsTestClient().getApiClient() cleanup_resources(cls.api_client, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -536,7 +559,7 @@ class TestLoadBalancingRule(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestLoadBalancingRule, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) diff --git a/tools/testClient/testcase/BVT-tests/test_primary_storage.py b/tools/testClient/testcase/BVT-tests/test_primary_storage.py index 4c9e5bc18fd..0838e89f3bf 100644 --- a/tools/testClient/testcase/BVT-tests/test_primary_storage.py +++ b/tools/testClient/testcase/BVT-tests/test_primary_storage.py @@ -46,9 +46,6 @@ class Services: "hypervisor": 'XEN', }, }, - "zoneid": '5894a264-12b0-4257-a316-06c831bcf8e2', - # Optional, if specified the mentioned zone will be - # used for tests } class TestPrimaryStorageServices(cloudstackTestCase): diff --git a/tools/testClient/testcase/BVT-tests/test_routers.py b/tools/testClient/testcase/BVT-tests/test_routers.py index 255f77e0768..e380506e7c7 100644 --- a/tools/testClient/testcase/BVT-tests/test_routers.py +++ b/tools/testClient/testcase/BVT-tests/test_routers.py @@ -47,7 +47,7 @@ class Services: "username": "testuser", "password": "fr3sca", }, - "ostypeid":'144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid":'5776c0d2-f331-42db-ba3a-29f1f8319bc9', "sleep": 60, "timeout": 10, "mode": 'advanced', #Networking mode: Basic, Advanced @@ -59,7 +59,10 @@ class TestRouterServices(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super( + TestRouterServices, + cls + ).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -99,7 +102,10 @@ class TestRouterServices(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super( + TestRouterServices, + cls + ).getClsTestClient().getApiClient() #Clean up, terminate the created templates cleanup_resources(cls.api_client, cls.cleanup) @@ -136,7 +142,8 @@ class TestRouterServices(cloudstackTestCase): self.apiclient, zoneid=router.zoneid, type='Routing', - state='Up' + state='Up', + virtualmachineid=self.vm_1.id ) self.assertEqual( isinstance(hosts, list), @@ -197,7 +204,8 @@ class TestRouterServices(cloudstackTestCase): self.apiclient, zoneid=router.zoneid, type='Routing', - state='Up' + state='Up', + virtualmachineid=self.vm_1.id ) self.assertEqual( isinstance(hosts, list), @@ -382,7 +390,8 @@ class TestRouterServices(cloudstackTestCase): self.apiclient, zoneid=router.zoneid, type='Routing', - state='Up' + state='Up', + virtualmachineid=self.vm_1.id ) self.assertEqual( isinstance(hosts, list), @@ -742,6 +751,7 @@ class TestRouterServices(cloudstackTestCase): cmd.id = vm.id self.apiclient.stopVirtualMachine(cmd) + # Get network.gc.interval config value config = list_configurations( self.apiclient, name='network.gc.interval' @@ -751,10 +761,23 @@ class TestRouterServices(cloudstackTestCase): True, "Check list response returns a valid list" ) - response = config[0] + gcinterval = config[0] - # Wait for network.gc.interval * 3 time to cleanup all the resources - time.sleep(int(response.value) * 3) + # Get network.gc.wait config value + config = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + self.assertEqual( + isinstance(config, list), + True, + "Check list response returns a valid list" + ) + gcwait = config[0] + + total_wait = int(gcinterval.value) + int(gcwait.value) + # Wait for wait_time * 2 time to cleanup all the resources + time.sleep(total_wait * 2) timeout = self.services["timeout"] while True: diff --git a/tools/testClient/testcase/BVT-tests/test_secondary_storage.py b/tools/testClient/testcase/BVT-tests/test_secondary_storage.py index 635914e5c58..e94996e566d 100644 --- a/tools/testClient/testcase/BVT-tests/test_secondary_storage.py +++ b/tools/testClient/testcase/BVT-tests/test_secondary_storage.py @@ -46,7 +46,7 @@ class TestSecStorageServices(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSecStorageServices, cls).getClsTestClient().getApiClient() cls.services = Services().services cls._cleanup = [] return diff --git a/tools/testClient/testcase/BVT-tests/test_service_offerings.py b/tools/testClient/testcase/BVT-tests/test_service_offerings.py index c9590393f0d..15298ca06d2 100644 --- a/tools/testClient/testcase/BVT-tests/test_service_offerings.py +++ b/tools/testClient/testcase/BVT-tests/test_service_offerings.py @@ -130,7 +130,7 @@ class TestServiceOfferings(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestServiceOfferings, cls).getClsTestClient().getApiClient() cls.service_offering_1 = ServiceOffering.create( cls.api_client, cls.services["off"] @@ -145,7 +145,7 @@ class TestServiceOfferings(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestServiceOfferings, cls).getClsTestClient().getApiClient() #Clean up, terminate the created templates cleanup_resources(cls.api_client, cls._cleanup) diff --git a/tools/testClient/testcase/BVT-tests/test_snapshots.py b/tools/testClient/testcase/BVT-tests/test_snapshots.py index 5a162708a7d..faea273ae3b 100644 --- a/tools/testClient/testcase/BVT-tests/test_snapshots.py +++ b/tools/testClient/testcase/BVT-tests/test_snapshots.py @@ -79,10 +79,10 @@ class Services: { "displaytext": 'Template from snapshot', "name": 'Template from snapshot', - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "templatefilter": 'self', }, - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', # Cent OS 5.3 (64 bit) "diskdevice": "/dev/xvdb", # Data Disk "rootdisk": "/dev/xvda", # Root Disk @@ -110,7 +110,7 @@ class TestSnapshotRootDisk(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSnapshotRootDisk, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -261,25 +261,26 @@ class TestSnapshotRootDisk(cloudstackTestCase): True, "Check list response returns a valid list" ) + uuids = [] + for host in hosts: + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (host.name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] - # 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 - # 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 - export_path = '/'.join(parse_url[3:]) - # Export path: export/test + try: + # Login to VM to check snapshot present on sec disk + ssh_client = self.virtual_machine_with_disk.get_ssh_client() - try: - # Login to VM to check snapshot present on sec disk - ssh_client = self.virtual_machine_with_disk.get_ssh_client() - - cmds = [ + cmds = [ "mkdir -p %s" % self.services["mount_dir"], - "mount %s:/%s %s" % ( + "mount %s/%s %s" % ( sec_storage_ip, export_path, self.services["mount_dir"] @@ -291,32 +292,37 @@ class TestSnapshotRootDisk(cloudstackTestCase): ), ] - for c in cmds: - result = ssh_client.execute(c) + for c in cmds: + self.debug(c) + result = ssh_client.execute(c) + self.debug(result) - except Exception: - self.fail("SSH failed for Virtual machine: %s" % + except Exception: + self.fail("SSH failed for Virtual machine: %s" % self.virtual_machine_with_disk.ipaddress) - res = str(result) + uuids.append(result) + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["mount_dir"]), + ] + try: + for c in cmds: + self.debug(c) + result = ssh_client.execute(c) + self.debug(result) + + except Exception as e: + self.fail("SSH failed for Virtual machine: %s" % + self.virtual_machine_with_disk.ipaddress) + + res = str(uuids) # Check snapshot UUID in secondary storage and database 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: - result = ssh_client.execute(c) - - except Exception as e: - self.fail("SSH failed for Virtual machine: %s" % - self.virtual_machine_with_disk.ipaddress) - return @@ -324,7 +330,7 @@ class TestSnapshots(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSnapshots, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -490,25 +496,26 @@ class TestSnapshots(cloudstackTestCase): True, "Check list response returns a valid list" ) + uuids = [] + for host in hosts: + # hosts[0].name = "nfs://192.168.100.21/export" + parse_url = (host.name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export'] - # hosts[0].name = "nfs://192.168.100.21/export" - parse_url = (hosts[0].name).split('/') - # parse_url = ['nfs:', '', '192.168.100.21', 'export'] + # Split IP address and export path from name + sec_storage_ip = parse_url[2] + # Sec Storage IP: 192.168.100.21 - # 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 - export_path = '/'.join(parse_url[3:]) - # Export path: export + try: + # Login to VM to check snapshot present on sec disk + ssh_client = self.virtual_machine_with_disk.get_ssh_client() - try: - # Login to VM to check snapshot present on sec disk - ssh_client = self.virtual_machine_with_disk.get_ssh_client() - - cmds = [ + cmds = [ "mkdir -p %s" % self.services["mount_dir"], - "mount %s:/%s %s" % ( + "mount %s/%s %s" % ( sec_storage_ip, export_path, self.services["mount_dir"] @@ -519,34 +526,36 @@ class TestSnapshots(cloudstackTestCase): volume_id ), ] - for c in cmds: - self.debug(c) - result = ssh_client.execute(c) - self.debug(result) + for c in cmds: + self.debug(c) + result = ssh_client.execute(c) + self.debug(result) - except Exception as e: - self.fail("SSH failed for VM with IP: %s" % + except Exception as e: + self.fail("SSH failed for VM with IP: %s" % self.virtual_machine_with_disk.ipaddress) - res = str(result) + uuids.append(result) + # Unmount the Sec Storage + cmds = [ + "umount %s" % (self.services["mount_dir"]), + ] + try: + for c in cmds: + self.debug(c) + ssh_client.execute(c) + + except Exception as e: + self.fail("SSH failed for VM with IP: %s" % + self.virtual_machine_with_disk.ipaddress) + + res = str(uuids) # Check snapshot UUID in secondary storage and database 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: - ssh_client.execute(c) - - except Exception as e: - self.fail("SSH failed for VM with IP: %s" % - self.virtual_machine_with_disk.ipaddress) - return def test_03_volume_from_snapshot(self): @@ -596,6 +605,7 @@ class TestSnapshots(cloudstackTestCase): ), ] for c in cmds: + self.debug(c) ssh_client.execute(c) except Exception as e: @@ -608,6 +618,7 @@ class TestSnapshots(cloudstackTestCase): try: for c in cmds: + self.debug(c) ssh_client.execute(c) except Exception as e: @@ -683,7 +694,9 @@ class TestSnapshots(cloudstackTestCase): ] for c in cmds: - ssh.execute(c) + self.debug(c) + result = ssh.execute(c) + self.debug(result) returned_data_0 = ssh.execute("cat %s/%s/%s/%s" % ( self.services["mount_dir"], @@ -830,7 +843,8 @@ class TestSnapshots(cloudstackTestCase): volumeid=volume[0].id, intervaltype=\ self.services["recurring_snapshot"]["intervaltype"], - snapshottype='RECURRING' + snapshottype='RECURRING', + listall=True ) if isinstance(snapshots, list): @@ -924,7 +938,8 @@ class TestSnapshots(cloudstackTestCase): volumeid=volume[0].id, intervaltype=\ self.services["recurring_snapshot"]["intervaltype"], - snapshottype='RECURRING' + snapshottype='RECURRING', + listall=True ) if isinstance(snapshots, list): @@ -995,7 +1010,9 @@ class TestSnapshots(cloudstackTestCase): ] for c in cmds: - ssh_client.execute(c) + self.debug(c) + result = ssh_client.execute(c) + self.debug(result) except Exception as e: self.fail("SSH failed for VM with IP address: %s" % @@ -1006,6 +1023,7 @@ class TestSnapshots(cloudstackTestCase): "umount %s" % (self.services["mount_dir"]), ] for c in cmds: + self.debug(c) ssh_client.execute(c) volumes = list_volumes( @@ -1093,13 +1111,14 @@ class TestSnapshots(cloudstackTestCase): self.services["sub_lvl_dir1"], self.services["random_data"] )) + self.debug(returned_data_0) returned_data_1 = ssh.execute("cat %s/%s/%s/%s" % ( self.services["mount_dir"], self.services["sub_dir"], self.services["sub_lvl_dir2"], self.services["random_data"] )) - + self.debug(returned_data_1) except Exception as e: self.fail("SSH failed for VM with IP address: %s" % new_virtual_machine.ipaddress) @@ -1120,6 +1139,7 @@ class TestSnapshots(cloudstackTestCase): ] try: for c in cmds: + self.debug(c) ssh_client.execute(c) except Exception as e: diff --git a/tools/testClient/testcase/BVT-tests/test_ssvm.py b/tools/testClient/testcase/BVT-tests/test_ssvm.py index ce034cb0b95..ed9ece0a437 100644 --- a/tools/testClient/testcase/BVT-tests/test_ssvm.py +++ b/tools/testClient/testcase/BVT-tests/test_ssvm.py @@ -66,7 +66,9 @@ class TestSSVMs(cloudstackTestCase): list_ssvm_response = list_ssvms( self.apiclient, - systemvmtype='secondarystoragevm' + systemvmtype='secondarystoragevm', + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_ssvm_response, list), @@ -87,6 +89,9 @@ class TestSSVMs(cloudstackTestCase): True, "Check list response returns a valid list" ) + + self.debug("Number of zones: %s" % len(list_zones_response)) + self.debug("Number of SSVMs: %s" % len(list_ssvm_response)) # Number of Sec storage VMs = No of Zones self.assertEqual( len(list_ssvm_response), @@ -97,6 +102,7 @@ class TestSSVMs(cloudstackTestCase): #public IP, link local IP and DNS for ssvm in list_ssvm_response: + self.debug("SSVM state: %s" % ssvm.state) self.assertEqual( ssvm.state, 'Running', @@ -178,7 +184,9 @@ class TestSSVMs(cloudstackTestCase): list_cpvm_response = list_ssvms( self.apiclient, - systemvmtype='consoleproxy' + systemvmtype='consoleproxy', + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_cpvm_response, list), @@ -200,6 +208,9 @@ class TestSSVMs(cloudstackTestCase): "Check list response returns a valid list" ) + self.debug("Number of zones: %s" % len(list_zones_response)) + self.debug("Number of CPVMs: %s" % len(list_cpvm_response)) + self.assertEqual( len(list_cpvm_response), len(list_zones_response), @@ -208,6 +219,7 @@ class TestSSVMs(cloudstackTestCase): #For each CPVM check private IP, public IP, link local IP and DNS for cpvm in list_cpvm_response: + self.debug("CPVM state: %s" % cpvm.state) self.assertEqual( cpvm.state, 'Running', @@ -280,23 +292,11 @@ class TestSSVMs(cloudstackTestCase): # 4. If no process is running/multiple process are running # then the test is a failure - hosts = list_hosts( - self.apiclient, - zoneid=self.zone.id, - type='Routing', - state='Up' - ) - self.assertEqual( - isinstance(hosts, list), - True, - "Check list response returns a valid list" - ) - host = hosts[0] - list_ssvm_response = list_ssvms( self.apiclient, systemvmtype='secondarystoragevm', - hostid=host.id + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_ssvm_response, list), @@ -305,7 +305,18 @@ class TestSSVMs(cloudstackTestCase): ) ssvm = list_ssvm_response[0] - self.debug("Checking cloud process status") + hosts = list_hosts( + self.apiclient, + id=ssvm.hostid + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + host = hosts[0] + + self.debug("Running SSVM check script") result = get_process_status( host.ipaddress, @@ -316,6 +327,8 @@ class TestSSVMs(cloudstackTestCase): "/usr/local/cloud/systemvm/ssvm-check.sh |grep -e ERROR -e WARNING -e FAIL" ) res = str(result) + self.debug("SSVM script output: %s" % res) + self.assertEqual( res.count("ERROR"), 1, @@ -338,6 +351,7 @@ class TestSSVMs(cloudstackTestCase): "service cloud status" ) res = str(result) + self.debug("Cloud Process status: %s" % res) # cloud.com service (type=secstorage) is running: process id: 2346 self.assertEqual( res.count("is running"), @@ -356,23 +370,11 @@ class TestSSVMs(cloudstackTestCase): # 3. Service cloud status should report cloud agent status to be # running - hosts = list_hosts( - self.apiclient, - zoneid=self.zone.id, - type='Routing', - state='Up' - ) - self.assertEqual( - isinstance(hosts, list), - True, - "Check list response returns a valid list" - ) - host = hosts[0] - list_cpvm_response = list_ssvms( self.apiclient, systemvmtype='consoleproxy', - hostid=host.id + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_cpvm_response, list), @@ -381,11 +383,24 @@ class TestSSVMs(cloudstackTestCase): ) cpvm = list_cpvm_response[0] + hosts = list_hosts( + self.apiclient, + id=cpvm.hostid + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + host = hosts[0] + try: telnet = telnetlib.Telnet( str(self.apiclient.connection.mgtSvr), '8250' ) + self.debug("Telnet management server (IP: %s)" % + self.apiclient.connection.mgtSvr) except Exception as e: self.fail( "Telnet Access failed for %s: %s" % \ @@ -403,6 +418,7 @@ class TestSSVMs(cloudstackTestCase): "service cloud status" ) res = str(result) + self.debug("Cloud Process status: %s" % res) self.assertEqual( res.count("is running"), 1, @@ -421,23 +437,11 @@ class TestSSVMs(cloudstackTestCase): # test cases still passing # 3. If either of the two above steps fail the test is a failure - hosts = list_hosts( - self.apiclient, - zoneid=self.zone.id, - type='Routing', - state='Up' - ) - self.assertEqual( - isinstance(hosts, list), - True, - "Check list response returns a valid list" - ) - host = hosts[0] - list_ssvm_response = list_ssvms( self.apiclient, systemvmtype='secondarystoragevm', - hostid=host.id + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_ssvm_response, list), @@ -446,6 +450,18 @@ class TestSSVMs(cloudstackTestCase): ) ssvm = list_ssvm_response[0] + hosts = list_hosts( + self.apiclient, + id=ssvm.hostid + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + host = hosts[0] + + self.debug("Stopping SSVM: %s" % ssvm.id) cmd = stopSystemVm.stopSystemVmCmd() cmd.id = ssvm.id self.apiclient.stopSystemVm(cmd) @@ -474,6 +490,7 @@ class TestSSVMs(cloudstackTestCase): "Check list response returns a valid list" ) ssvm_response = list_ssvm_response[0] + self.debug("SSVM state after debug: %s" % ssvm_response.state) self.assertEqual( ssvm_response.state, 'Running', @@ -495,23 +512,11 @@ class TestSSVMs(cloudstackTestCase): # two test cases still passing # 3. If either of the two above steps fail the test is a failure - hosts = list_hosts( - self.apiclient, - zoneid=self.zone.id, - type='Routing', - state='Up' - ) - self.assertEqual( - isinstance(hosts, list), - True, - "Check list response returns a valid list" - ) - host = hosts[0] - list_cpvm_response = list_ssvms( self.apiclient, systemvmtype='consoleproxy', - hostid=host.id + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_cpvm_response, list), @@ -520,6 +525,18 @@ class TestSSVMs(cloudstackTestCase): ) cpvm = list_cpvm_response[0] + hosts = list_hosts( + self.apiclient, + id=cpvm.hostid + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + host = hosts[0] + + self.debug("Stopping CPVM: %s" % cpvm.id) cmd = stopSystemVm.stopSystemVmCmd() cmd.id = cpvm.id self.apiclient.stopSystemVm(cmd) @@ -544,6 +561,8 @@ class TestSSVMs(cloudstackTestCase): cpvm_response = list_cpvm_response[0] + self.debug("CPVM state after debug: %s" % cpvm_response.state) + self.assertEqual( cpvm_response.state, 'Running', @@ -563,23 +582,11 @@ class TestSSVMs(cloudstackTestCase): # before and after reboot # 3. The cloud process should still be running within the SSVM - hosts = list_hosts( - self.apiclient, - zoneid=self.zone.id, - type='Routing', - state='Up' - ) - self.assertEqual( - isinstance(hosts, list), - True, - "Check list response returns a valid list" - ) - host = hosts[0] - list_ssvm_response = list_ssvms( self.apiclient, systemvmtype='secondarystoragevm', - hostid=host.id + state='Running', + zoneid=self.zone.id ) self.assertEqual( @@ -590,10 +597,22 @@ class TestSSVMs(cloudstackTestCase): ssvm_response = list_ssvm_response[0] + hosts = list_hosts( + self.apiclient, + id=ssvm_response.hostid + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + host = hosts[0] + #Store the public & private IP values before reboot old_public_ip = ssvm_response.publicip old_private_ip = ssvm_response.privateip + self.debug("Rebooting SSVM: %s" % ssvm_response.id) cmd = rebootSystemVm.rebootSystemVmCmd() cmd.id = ssvm_response.id self.apiclient.rebootSystemVm(cmd) @@ -617,7 +636,7 @@ class TestSSVMs(cloudstackTestCase): timeout = timeout - 1 ssvm_response = list_ssvm_response[0] - + self.debug("SSVM State: %s" % ssvm_response.state) self.assertEqual( 'Running', str(ssvm_response.state), @@ -648,23 +667,12 @@ class TestSSVMs(cloudstackTestCase): # the same before and after reboot # 3. the cloud process should still be running within the CPVM - hosts = list_hosts( - self.apiclient, - zoneid=self.zone.id, - type='Routing', - state='Up' - ) - self.assertEqual( - isinstance(hosts, list), - True, - "Check list response returns a valid list" - ) - host = hosts[0] list_cpvm_response = list_ssvms( self.apiclient, systemvmtype='consoleproxy', - hostid=host.id + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_cpvm_response, list), @@ -673,10 +681,23 @@ class TestSSVMs(cloudstackTestCase): ) cpvm_response = list_cpvm_response[0] + hosts = list_hosts( + self.apiclient, + id=cpvm_response.hostid + ) + self.assertEqual( + isinstance(hosts, list), + True, + "Check list response returns a valid list" + ) + host = hosts[0] + #Store the public & private IP values before reboot old_public_ip = cpvm_response.publicip old_private_ip = cpvm_response.privateip + self.debug("Rebooting CPVM: %s" % cpvm_response.id) + cmd = rebootSystemVm.rebootSystemVmCmd() cmd.id = cpvm_response.id self.apiclient.rebootSystemVm(cmd) @@ -701,6 +722,7 @@ class TestSSVMs(cloudstackTestCase): cpvm_response = list_cpvm_response[0] + self.debug("CPVM state: %s" % cpvm_response.state) self.assertEqual( 'Running', str(cpvm_response.state), @@ -735,8 +757,9 @@ class TestSSVMs(cloudstackTestCase): list_ssvm_response = list_ssvms( self.apiclient, - zoneid=self.zone.id, - systemvmtype='secondarystoragevm' + systemvmtype='secondarystoragevm', + state='Running', + zoneid=self.zone.id ) self.assertEqual( isinstance(list_ssvm_response, list), @@ -747,6 +770,7 @@ class TestSSVMs(cloudstackTestCase): old_name = ssvm_response.name + self.debug("Destroying SSVM: %s" % ssvm_response.id) cmd = destroySystemVm.destroySystemVmCmd() cmd.id = ssvm_response.id self.apiclient.destroySystemVm(cmd) @@ -826,6 +850,7 @@ class TestSSVMs(cloudstackTestCase): old_name = cpvm_response.name + self.debug("Destroying CPVM: %s" % cpvm_response.id) cmd = destroySystemVm.destroySystemVmCmd() cmd.id = cpvm_response.id self.apiclient.destroySystemVm(cmd) diff --git a/tools/testClient/testcase/BVT-tests/test_templates.py b/tools/testClient/testcase/BVT-tests/test_templates.py index c7e1393aa99..ea650aa1531 100644 --- a/tools/testClient/testcase/BVT-tests/test_templates.py +++ b/tools/testClient/testcase/BVT-tests/test_templates.py @@ -59,12 +59,12 @@ class Services: "template_1": { "displaytext": "Cent OS Template", "name": "Cent OS Template", - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', }, "template_2": { "displaytext": "Public Template", "name": "Public template", - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "isfeatured": True, "ispublic": True, "isextractable": True, @@ -78,7 +78,7 @@ class Services: "isextractable": False, "bootable": True, "passwordenabled": True, - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "mode": 'advanced', # Networking mode: Advanced, basic "sleep": 30, @@ -108,7 +108,7 @@ class TestCreateTemplate(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -194,7 +194,7 @@ class TestCreateTemplate(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -270,7 +270,7 @@ class TestTemplates(cloudstackTestCase): def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -384,7 +384,7 @@ class TestTemplates(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() #Cleanup created resources such as templates and VMs cleanup_resources(cls.api_client, cls._cleanup) 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 db287d395ec..64b43a0b0c5 100644 --- a/tools/testClient/testcase/BVT-tests/test_vm_life_cycle.py +++ b/tools/testClient/testcase/BVT-tests/test_vm_life_cycle.py @@ -95,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": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO }, "diskdevice": '/dev/xvdd', @@ -103,12 +103,10 @@ class Services: "mount_dir": "/mnt/tmp", "sleep": 60, "timeout": 10, - "hostid": 5, #Migrate VM to hostid - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', # CentOS 5.3 (64-bit) "mode":'advanced', - # Networking mode: Basic or Advanced } @@ -218,7 +216,7 @@ class TestVMLifeCycle(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates @@ -286,7 +284,7 @@ class TestVMLifeCycle(cloudstackTestCase): @classmethod def tearDownClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestVMLifeCycle, cls).getClsTestClient().getApiClient() cleanup_resources(cls.api_client, cls._cleanup) return @@ -680,7 +678,6 @@ class TestVMLifeCycle(cloudstackTestCase): ) return - def test_07_restore_vm(self): """Test recover Virtual Machine """ @@ -729,13 +726,36 @@ class TestVMLifeCycle(cloudstackTestCase): # should be "Running" and the host should be the host # to which the VM was migrated to + hosts = Host.list( + self.apiclient, + zoneid=self.medium_virtual_machine.zoneid, + type='Routing' + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "Check the number of hosts in the zone" + ) + self.assertEqual( + len(hosts), + 2, + "Atleast 2 hosts should be present in a zone for VM migration" + ) + + # Find the host of VM and also the new host to migrate VM. + if self.medium_virtual_machine.hostid == hosts[0].id: + host = hosts[1] + else: + host = hosts[0] + self.debug("Migrating VM-ID: %s to Host: %s" % ( self.medium_virtual_machine.id, - self.services["hostid"] + host.id )) cmd = migrateVirtualMachine.migrateVirtualMachineCmd() - cmd.hostid = self.services["hostid"] + cmd.hostid = host.id cmd.virtualmachineid = self.medium_virtual_machine.id self.apiclient.migrateVirtualMachine(cmd) @@ -765,7 +785,7 @@ class TestVMLifeCycle(cloudstackTestCase): self.assertEqual( vm_response.hostid, - self.services["hostid"], + host.id, "Check destination hostID of migrated VM" ) return diff --git a/tools/testClient/testcase/BVT-tests/test_volumes.py b/tools/testClient/testcase/BVT-tests/test_volumes.py index 463ed7163c5..9fc8f4d0e01 100644 --- a/tools/testClient/testcase/BVT-tests/test_volumes.py +++ b/tools/testClient/testcase/BVT-tests/test_volumes.py @@ -60,7 +60,7 @@ class Services: "publicport": 22, "protocol": 'TCP', "diskdevice": "/dev/xvdb", - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "mode": 'advanced', "sleep": 60, "timeout": 10, @@ -71,7 +71,7 @@ class TestCreateVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestCreateVolume, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates @@ -187,7 +187,6 @@ class TestCreateVolume(cloudstackTestCase): ) try: ssh = self.virtual_machine.get_ssh_client() - ssh.execute("reboot") except Exception as e: @@ -249,7 +248,7 @@ class TestCreateVolume(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestCreateVolume, cls).getClsTestClient().getApiClient() cleanup_resources(cls.api_client, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -259,7 +258,7 @@ class TestVolumes(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestVolumes, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) diff --git a/tools/testClient/testcase/P1-tests/README b/tools/testClient/testcase/P1-tests/README index ba0a04c6714..2fd8d4be795 100644 --- a/tools/testClient/testcase/P1-tests/README +++ b/tools/testClient/testcase/P1-tests/README @@ -31,6 +31,11 @@ The following files contain these P1 cases: 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 +7. test_templates.py - templates related tests +8. test_volumes.py - Volumes related tests +9. test_blocker_bugs.py - Blocker bugs tests +10. test_project_configs.py - Project global configuration related tests +11. test_project_limits.py - Project resource limits related tests +12. test_project_resources.py - Project resource creation related tests +13. test_project_usage.py - Project usage related tests +14. test_projects - Projects functionality tests diff --git a/tools/testClient/testcase/P1-tests/test_accounts.py b/tools/testClient/testcase/P1-tests/test_accounts.py index 70358ac9643..f463d61e881 100644 --- a/tools/testClient/testcase/P1-tests/test_accounts.py +++ b/tools/testClient/testcase/P1-tests/test_accounts.py @@ -156,7 +156,7 @@ class TestAccounts(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestAccounts, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) @@ -281,7 +281,7 @@ class TestRemoveUserFromAccount(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestRemoveUserFromAccount, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) @@ -542,7 +542,7 @@ class TestNonRootAdminsPrivileges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestNonRootAdminsPrivileges, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone settings cls.zone = get_zone(cls.api_client, cls.services) @@ -639,7 +639,7 @@ class TestServiceOfferingSiblings(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestServiceOfferingSiblings, cls).getClsTestClient().getApiClient() cls.services = Services().services # Create Domains, accounts etc @@ -751,7 +751,7 @@ class TestServiceOfferingHierarchy(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestServiceOfferingHierarchy, cls).getClsTestClient().getApiClient() cls.services = Services().services # Create domain, service offerings etc @@ -875,7 +875,7 @@ class TesttemplateHierarchy(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TesttemplateHierarchy, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone settings cls.zone = get_zone(cls.api_client, cls.services) @@ -1011,7 +1011,7 @@ class TestAddVmToSubDomain(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestAddVmToSubDomain, cls).getClsTestClient().getApiClient() cls.services = Services().services # Setup working Environment- Create domain, zone, pod cluster etc. diff --git a/tools/testClient/testcase/P1-tests/test_blocker_bugs.py b/tools/testClient/testcase/P1-tests/test_blocker_bugs.py index b5c1e03ab65..f616e9f0bdd 100644 --- a/tools/testClient/testcase/P1-tests/test_blocker_bugs.py +++ b/tools/testClient/testcase/P1-tests/test_blocker_bugs.py @@ -96,7 +96,7 @@ class TestSnapshots(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSnapshots, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -402,7 +402,7 @@ class TestTemplate(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplate, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -430,7 +430,7 @@ class TestTemplate(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplate, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -520,7 +520,7 @@ class TestNATRules(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestNATRules, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates @@ -573,7 +573,7 @@ class TestNATRules(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestNATRules, cls).getClsTestClient().getApiClient() cleanup_resources(cls.api_client, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -714,7 +714,7 @@ class TestRouters(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouters, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) @@ -837,7 +837,7 @@ class TestRouterRestart(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterRestart, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -877,7 +877,7 @@ class TestRouterRestart(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterRestart, cls).getClsTestClient().getApiClient() #Clean up, terminate the created templates cleanup_resources(cls.api_client, cls.cleanup) @@ -965,7 +965,7 @@ class TestTemplates(cloudstackTestCase): def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() # Get Zone, templates etc cls.domain = get_domain(cls.api_client, cls.services) @@ -1023,7 +1023,7 @@ class TestTemplates(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() #Cleanup created resources such as templates and VMs cleanup_resources(cls.api_client, cls._cleanup) diff --git a/tools/testClient/testcase/P1-tests/test_project_configs.py b/tools/testClient/testcase/P1-tests/test_project_configs.py new file mode 100644 index 00000000000..c938d67425a --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_project_configs.py @@ -0,0 +1,1222 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Project +""" +#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 Project Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "mgmt_server": { + "ipaddress": '192.168.100.21', + "username": 'root', + "password": 'fr3sca', + "port": 22, + }, + "account": { + "email": "administrator@clogeny.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "user": { + "email": "mayur.dhande@clogeny.com", + "firstname": "User", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "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": 'f9b709f2-e0fc-4c0f-80f1-b0494168f58d', + "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, + }, + "configs": { + "project.invite.timeout": 300, + }, + "mail_account": { + "server": 'imap.gmail.com', + "email": 'administrator@clogeny.com', + "password": 'fr3sca21!', + "folder": 'inbox', + }, + "ostypeid": 'f9b709f2-e0fc-4c0f-80f1-b0494168f58d', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestUserProjectCreation(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestUserProjectCreation, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + + # Create domains, account etc. + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.user = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls._cleanup = [cls.account, cls.user, cls.domain] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + + def test_01_admin_project_creation(self): + """Test create project as a domain admin and domain user + """ + + # Validate the following + # 1. Check if 'allow.user.create.projects' configuration is true + # 2. Create a Project as domain admin + # 3. Create a Project as domain user + # 4. In both 2 and 3 project creation should be successful + + configs = Configurations.list( + self.apiclient, + name='allow.user.create.projects' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'true', + "'allow.user.create.projects' should be true" + ) + + list_project = list_projects_reponse[0] + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.user.account.name, + domainid=self.user.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain user with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + return + @unittest.skip("Known bug-able to create project as a domain user") + def test_02_user_project_creation(self): + """Test create project as a domain admin and domain user + """ + + # Validate the following + # 1. Check if 'allow.user.create.projects' configuration is false + # 2. Create a Project as domain admin. Project creation should be + # successful. + # 3. Create a Project as domain user. Project creation should fail + + configs = Configurations.list( + self.apiclient, + name='allow.user.create.projects' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'allow.user.create.projects' should be true" + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + with self.assertRaises(Exception): + project = Project.create( + self.apiclient, + self.services["project"], + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.debug("Project creation with domain user: %s failed" % + self.user.account.name) + return + + +class TestProjectInviteRequired(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestProjectInviteRequired, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + + # Create domains, account etc. + cls.domain = get_domain(cls.api_client, cls.services) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.user = Account.create( + cls.api_client, + cls.services["user"], + admin=True, + domainid=cls.domain.id + ) + + cls._cleanup = [cls.account, cls.user] + 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_03_add_user_to_project(self): + """Add user to project when 'project.invite.required' is false""" + + # Validate the following: + # 1. Create a Project + # 2. Add users to the project. Verify user is added to project + # as regular user + + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'false', + "'project.invite.required' should be true" + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.user.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + + return + + def test_04_add_user_to_project(self): + """Add user to project when 'project.invite.required' is true""" + + # Validate the following: + # 1. Create a Project + # 2. Add users to the project. verify user is shown in pending state + + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.required' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + (config.value).lower(), + 'true', + "'project.invite.required' should be true" + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = ProjectInvitation.list( + self.apiclient, + state='Pending', + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.state, + 'Pending', + "Newly added user is not added as a regular user" + ) + return + + def test_05_invitation_timeout(self): + """Test global config project invitation timeout""" + + # Validate the following: + # 1. Set configuration to 5 mins + # 2. Create a Project + # 3. Add users to the project + # 4. As a user accept invitation within 5 mins. Verify invitation is + # accepted and user become regular user of project + + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.timeout' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + int(config.value), + self.services["configs"]["project.invite.timeout"], + "'project.invite.timeout' should be %s" % + self.services["configs"]["project.invite.timeout"] + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = ProjectInvitation.list( + self.apiclient, + state='Pending', + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.state, + 'Pending', + "Newly added user is not added as a regular user" + ) + + # Accept the invite + ProjectInvitation.update( + self.apiclient, + projectid=project.id, + accept=True, + account=self.user.account.name + ) + self.debug( + "Accepting project invitation for project: %s user: %s" % ( + project.name, + self.user.account.name + )) + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.user.account.name, + ) + + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + return + + def test_06_invitation_timeout_after_expiry(self): + """Test global config project invitation timeout""" + + # Validate the following: + # 1. Set configuration to 5 mins + # 2. Create a Project + # 3. Add users to the project + # 4. As a user accept invitation after 5 mins. Verify invitation is + # not accepted and is shown as expired + + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.timeout' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + int(config.value), + self.services["configs"]["project.invite.timeout"], + "'project.invite.timeout' should be %s" % + self.services["configs"]["project.invite.timeout"] + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = ProjectInvitation.list( + self.apiclient, + state='Pending', + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.state, + 'Pending', + "Newly added user is not added as a regular user" + ) + + # sleep for 'project.invite.timeout' * 2 interval to wait for invite + # to expire + time.sleep(int(config.value) * 2) + + with self.assertRaises(Exception): + # Accept the invite + ProjectInvitation.update( + self.apiclient, + projectid=project.id, + accept=True, + account=self.user.account.name + ) + self.debug( + "Accepting invitation after expiry project: %s user: %s" % ( + project.name, + self.user.account.name + )) + # listProjectAccount to verify the user is added to project or not + accounts_reponse = ProjectInvitation.list( + self.apiclient, + account=self.user.account.name, + domainid=self.user.account.domainid + ) + + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.state, + 'Expired', + "Newly added user is not added as a regular user" + ) + return + + def test_07_invite_after_expiry(self): + """Test global config project invitation timeout""" + + # Validate the following: + # 1. Set configuration to 5 mins + # 2. Create a Project + # 3. Add users to the project + # 4. As a user accept invitation after 5 mins. + # 5. Resend the invitation + # 6. Verify invitation is sent again + + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.timeout' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + int(config.value), + self.services["configs"]["project.invite.timeout"], + "'project.invite.timeout' should be %s" % + self.services["configs"]["project.invite.timeout"] + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = ProjectInvitation.list( + self.apiclient, + state='Pending', + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.state, + 'Pending', + "Newly added user is not added as a regular user" + ) + + # sleep for 'project.invite.timeout' * 2 interval to wait for invite + # to expire + time.sleep(int(config.value) * 2) + + self.debug("Adding %s user again to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = ProjectInvitation.list( + self.apiclient, + state='Pending', + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.state, + 'Pending', + "Newly added user is not added as a regular user" + ) + return + + def test_08_decline_invitation(self): + """Test decline invitation""" + + # Validate the following: + # 1. Set configuration to 5 mins + # 2. Create a Project + # 3. Add users to the project + # 4. As a user decline invitation within 5 mins. + # 5. Verify invitation is rejected and user doesn't become regular + # user. + + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.timeout' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + int(config.value), + self.services["configs"]["project.invite.timeout"], + "'project.invite.timeout' should be %s" % + self.services["configs"]["project.invite.timeout"] + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = ProjectInvitation.list( + self.apiclient, + state='Pending', + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.state, + 'Pending', + "Newly added user is not added as a regular user" + ) + # Accept the invite + ProjectInvitation.update( + self.apiclient, + projectid=project.id, + accept=False, + account=self.user.account.name + ) + self.debug( + "Declining invitation for project: %s user: %s" % ( + project.name, + self.user.account.name + )) + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.user.account.name, + ) + self.assertEqual( + accounts_reponse, + None, + "Check for a valid list accounts response" + ) + return + @unittest.skip("Requires SMPT configs") + def test_09_invite_to_project_by_email(self): + """Test invite user to project by email""" + + # Validate the following: + # 1. Set configuration to 5 mins + # 2. Create a Project + # 3. Add users to the project + # 4. As a user decline invitation within 5 mins. + # 5. Verify invitation is rejected and user doesn't become regular + # user. + + # Verify 'project.invite.required' is set to false + configs = Configurations.list( + self.apiclient, + name='project.invite.timeout' + ) + self.assertEqual( + isinstance(configs, list), + True, + "Check for a valid list configurations response" + ) + config = configs[0] + self.assertEqual( + int(config.value), + self.services["configs"]["project.invite.timeout"], + "'project.invite.timeout' should be %s" % + self.services["configs"]["project.invite.timeout"] + ) + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding user with email: %s to project: %s" % ( + self.user.account.email, + project.name + )) + + # Add user to the project + project.addAccount( + self.apiclient, + email=self.user.account.user[0].email + ) + + # Fetch the latest mail sent to user + mail_content = fetch_latest_mail( + self.services["mail_account"], + from_mail=self.user.account.user[0].email + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_project_limits.py b/tools/testClient/testcase/P1-tests/test_project_limits.py new file mode 100644 index 00000000000..4f8be3c88dd --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_project_limits.py @@ -0,0 +1,860 @@ +# -*- 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", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "account": { + "email": "administrator@clogeny.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "user": { + "email": "administrator@clogeny.com", + "firstname": "User", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "disk_offering": { + "displaytext": "Tiny Disk Offering", + "name": "Tiny Disk Offering", + "disksize": 1 + }, + "volume": { + "diskname": "Test Volume", + }, + "server": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "ostypeid": '471a4b5b-5523-448f-9608-7d6218995733', + "templatefilter": 'self', + }, + "ostypeid": '471a4b5b-5523-448f-9608-7d6218995733', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced', + } + + +class TestProjectLimits(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestProjectLimits, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + + # Create domains, account etc. + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + + cls.admin = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.user = Account.create( + cls.api_client, + cls.services["user"], + domainid=cls.domain.id + ) + cls._cleanup = [cls.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 accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_01_project_limits(self): + """ Test project limits + """ + + # Validate the following + # 1. Create a Project. Verify once projects are created, they inherit + # a default set of resource limits as configured by the Cloud Stack + # ROOT admin. + # 2. Reduce Project resources limits. Verify limits can be reduced by + # the Project Owner of each project and project limit applies to + # number of virtual instances, disk volumes, snapshots, IP address. + # Also, verify resource limits for the project are independent of + # account resource limits + # 3. Increase Projects Resources limits above domains limit. Verify + # project can’t have more resources than domain level limit allows. + # 4. Create Resource more than its set limit for a project. Verify + # resource allocation should fail giving proper message + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.admin.account.name, + domainid=self.admin.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + # Get the resource limits for ROOT domain + resource_limits = list_resource_limits(self.apiclient) + + self.assertEqual( + isinstance(resource_limits, list), + True, + "List resource API should return a valid list" + ) + self.assertNotEqual( + len(resource_limits), + 0, + "List resource API response should not be empty" + ) + + # Reduce resource limits for project + # Resource: 0 - Instance. Number of instances a user can create. + # Resource: 1 - IP. Number of public IP addresses a user can own. + # Resource: 2 - Volume. Number of disk volumes a user can create. + # Resource: 3 - Snapshot. Number of snapshots a user can create. + # Resource: 4 - Template. Number of templates that a user can + # register/create + for resource in resource_limits: + update_resource_limit( + self.apiclient, + resource.resourcetype, + max=1, + projectid=project.id + ) + self.debug( + "Updating resource (ID: %s) limit for project: %s" % ( + resource, + project.id + )) + resource_limits = list_resource_limits( + self.apiclient, + projectid=project.id + ) + self.assertEqual( + isinstance(resource_limits, list), + True, + "List resource API should return a valid list" + ) + self.assertNotEqual( + len(resource_limits), + 0, + "List resource API response should not be empty" + ) + for resource in resource_limits: + self.assertEqual( + resource.max, + 1, + "Resource limit should be updated to 1" + ) + + # Get the resource limits for domain + resource_limits = list_resource_limits( + self.apiclient, + domainid=self.domain.id + ) + self.assertEqual( + isinstance(resource_limits, list), + True, + "List resource API should return a valid list" + ) + self.assertNotEqual( + len(resource_limits), + 0, + "List resource API response should not be empty" + ) + + for resource in resource_limits: + # Update domain resource limits to 2 + update_resource_limit( + self.apiclient, + resource.resourcetype, + domainid=self.domain.id, + max=2 + ) + with self.assertRaises(Exception): + self.debug( + "Attempting to update project: %s resource limit to: %s" % ( + project.id, + max_value + )) + # Update project resource limits to 3 + update_resource_limit( + self.apiclient, + resource.resourcetype, + max=3, + projectid=project.id + ) + return + @unittest.skip("No provision for updating resource limits from account through API") + def test_02_project_limits_normal_user(self): + """ Test project limits + """ + + # Validate the following + # 1. Create a Project + # 2. Reduce the projects limits as a domain admin. Verify resource + # count is updated + # 3. Reduce the projects limits as a project user owner who is not a + # domain admin. Resource count should fail + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.admin.account.name, + domainid=self.admin.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + # Get the resource limits for ROOT domain + resource_limits = list_resource_limits(self.apiclient) + + self.assertEqual( + isinstance(resource_limits, list), + True, + "List resource API should return a valid list" + ) + self.assertNotEqual( + len(resource_limits), + 0, + "List resource API response should not be empty" + ) + + # Reduce resource limits for project + # Resource: 0 - Instance. Number of instances a user can create. + # Resource: 1 - IP. Number of public IP addresses a user can own. + # Resource: 2 - Volume. Number of disk volumes a user can create. + # Resource: 3 - Snapshot. Number of snapshots a user can create. + # Resource: 4 - Template. Number of templates that a user can + # register/create + for resource in resource_limits: + update_resource_limit( + self.apiclient, + resource.resourcetype, + max=1, + projectid=project.id + ) + self.debug( + "Updating resource (ID: %s) limit for project: %s" % ( + resource, + project.id + )) + resource_limits = list_resource_limits( + self.apiclient, + projectid=project.id + ) + self.assertEqual( + isinstance(resource_limits, list), + True, + "List resource API should return a valid list" + ) + self.assertNotEqual( + len(resource_limits), + 0, + "List resource API response should not be empty" + ) + for resource in resource_limits: + self.assertEqual( + resource.max, + 1, + "Resource limit should be updated to 1" + ) + + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + ) + + # Get the resource limits for domain + resource_limits = list_resource_limits( + self.apiclient, + domainid=self.domain.id + ) + self.assertEqual( + isinstance(resource_limits, list), + True, + "List resource API should return a valid list" + ) + self.assertNotEqual( + len(resource_limits), + 0, + "List resource API response should not be empty" + ) + + for resource in resource_limits: + #with self.assertRaises(Exception): + self.debug( + "Attempting to update resource limit by user: %s" % ( + self.user.account.name + )) + # Update project resource limits to 3 + update_resource_limit( + self.apiclient, + resource.resourcetype, + account=self.user.account.name, + domainid=self.user.account.domainid, + max=3, + projectid=project.id + ) + return + + +class TestResourceLimitsDomain(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super(TestResourceLimitsDomain, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + # Create Domains, Account etc + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Create project as a domain admin + cls.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + cls.services["account"] = cls.account.account.name + + # Create Service offering and disk offerings etc + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls._cleanup = [ + cls.project, + cls.service_offering, + cls.disk_offering, + cls.account, + cls.domain + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_03_vm_per_project(self): + """Test VM limit per project + """ + + # Validate the following + # 1. Set max VM per project to 2 + # 2. Create account and start 2 VMs. Verify VM state is Up and Running + # 3. Try to create 3rd VM instance. The appropriate error or alert + # should be raised + + self.debug( + "Updating instance resource limits for project: %s" % + self.project.id) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 0, # Instance + max=2, + projectid=self.project.id + ) + + self.debug("Deploying VM for project: %s" % self.project.id) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + self.debug("Deploying VM for project: %s" % self.project.id) + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + # Exception should be raised for second instance + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + return + + def test_04_publicip_per_project(self): + """Test Public IP limit per project + """ + + # Validate the following + # 1. set max no of IPs per project to 2. + # 2. Create an account in this domain + # 3. Create 1 VM in this domain + # 4. Acquire 1 IP in the domain. IP should be successfully acquired + # 5. Try to acquire 3rd IP in this domain. It should give the user an + # appropriate error and an alert should be generated. + + self.debug( + "Updating public IP resource limits for project: %s" % + self.project.id) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 1, # Public Ip + max=2, + projectid=self.project.id + ) + + self.debug("Deploying VM for Project: %s" % self.project.id) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + networks = Network.list( + self.apiclient, + projectid=self.project.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "Check list networks response returns a valid response" + ) + self.assertNotEqual( + len(networks), + 0, + "Check list networks response returns a valid network" + ) + network = networks[0] + self.debug("Associating public IP for project: %s" % + self.project.id) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + zoneid=virtual_machine_1.zoneid, + services=self.services["server"], + networkid=network.id, + projectid=self.project.id + ) + self.cleanup.append(public_ip_1) + # Verify Public IP state + self.assertEqual( + public_ip_1.ipaddress.state in [ + 'Allocated', + 'Allocating' + ], + True, + "Check Public IP state is allocated or not" + ) + + # Exception should be raised for second Public IP + with self.assertRaises(Exception): + public_ip_2 = PublicIPAddress.create( + self.apiclient, + zoneid=virtual_machine_1.zoneid, + services=self.services["server"], + networkid=network.id, + projectid=self.project.id + ) + return + + def test_05_snapshots_per_project(self): + """Test Snapshot limit per project + """ + + # Validate the following + # 1. set max no of snapshots per project to 1. + # 2. Create one snapshot in the project. Snapshot should be + # successfully created + # 5. Try to create another snapshot in this project. It should give + # user an appropriate error and an alert should be generated. + + self.debug( + "Updating snapshot resource limits for project: %s" % + self.project.id) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 3, # Snapshot + max=1, + projectid=self.project.id + ) + + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + projectid=self.project.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating snapshot from volume: %s" % volumes[0].id) + # Create a snapshot from the ROOTDISK + snapshot_1 = Snapshot.create(self.apiclient, + volumes[0].id, + projectid=self.project.id + ) + self.cleanup.append(snapshot_1) + # Verify Snapshot state + self.assertEqual( + snapshot_1.state in [ + 'BackedUp', + 'CreatedOnPrimary' + ], + True, + "Check Snapshot state is Running or not" + ) + + # Exception should be raised for second snapshot + with self.assertRaises(Exception): + Snapshot.create(self.apiclient, + volumes[0].id, + projectid=self.project.id + ) + return + + def test_06_volumes_per_project(self): + """Test Volumes limit per project + """ + + # Validate the following + # 1. set max no of volume per project to 1. + # 2. Create 1 VM in this project + # 4. Try to Create another VM in the project. It should give the user + # an appropriate error that Volume limit is exhausted and an alert + # should be generated. + + self.debug( + "Updating volume resource limits for project: %s" % + self.project.id) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 2, # Volume + max=1, + projectid=self.project.id + ) + + self.debug("Deploying VM for project: %s" % self.project.id) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + # Exception should be raised for second volume + with self.assertRaises(Exception): + Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id, + projectid=self.project.id + ) + return + + def test_07_templates_per_project(self): + """Test Templates limit per project + """ + + # Validate the following + # 1. set max no of templates per project to 1. + # 2. Create a template in this project. Both template should be in + # ready state + # 3. Try create 2nd template in the project. It should give the user + # appropriate error and an alert should be generated. + + self.debug( + "Updating template resource limits for domain: %s" % + self.account.account.domainid) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 4, # Template + max=1, + projectid=self.project.id + ) + + self.debug("Deploying VM for account: %s" % self.account.account.name) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + projectid=self.project.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_1 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + projectid=self.project.id + ) + + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( + template_1.isready, + True, + "Check Template is in ready state or not" + ) + + # Exception should be raised for second template + with self.assertRaises(Exception): + Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + projectid=self.project.id + ) + return diff --git a/tools/testClient/testcase/P1-tests/test_project_resources.py b/tools/testClient/testcase/P1-tests/test_project_resources.py new file mode 100644 index 00000000000..cc9907e4080 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_project_resources.py @@ -0,0 +1,1304 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Resource creation +""" +#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 creation Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "account": { + "email": "administrator@clogeny.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "user": { + "email": "administrator@clogeny.com", + "firstname": "User", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs + }, + "disk_offering": { + "displaytext": "Tiny Disk Offering", + "name": "Tiny Disk Offering", + "disksize": 1 + }, + "volume": { + "diskname": "Test Volume", + }, + "server": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "template": { + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + "templatefilter": 'self', + "ispublic": False, + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + }, + "domain_network": { + "name": "Domainwide Network", + "displaytext": "Domainwide Network", + "gateway": '192.168.100.1', + "netmask": '255.255.255.0', + "startip": '192.168.100.200', + "endip": '192.168.100.201', + "vlan": 4001, + "acltype": 'domain' + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "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) + }, + "security_group": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '0.0.0.0/0', + }, + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced', + } + + +class TestOfferings(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestOfferings, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone and template + 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"], + admin=True, + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + domainid=cls.domain.id + ) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls._cleanup = [ + cls.account, + cls.service_offering, + cls.disk_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_service_offerings(self): + """ Test service offerings in a project + """ + + # Validate the following + # 1. Create a project. + # 2. List service offerings for the project. All SO available in the + # domain can be used for project resource creation. + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + self.debug( + "Deploying VM instance for project: %s & service offering: %s" % ( + project.id, + self.service_offering.id + )) + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=project.id + ) + # Verify VM state + self.assertEqual( + virtual_machine.state, + 'Running', + "Check VM state is Running or not" + ) + + return + + def test_02_project_disk_offerings(self): + """ Test project disk offerings + """ + + # Validate the following + # 1. Create a project. + # 2. List service offerings for the project. All disk offerings + # available in the domain can be used for project resource creation + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug( + "Create a data volume for project: %s" % project.id) + # Create a volume for project + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id, + projectid=project.id + ) + self.cleanup.append(volume) + # Verify Volume state + self.assertEqual( + volume.state in [ + 'Allocated', + 'Ready' + ], + True, + "Check Volume state is Ready or not" + ) + return + + +class TestNetwork(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetwork, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone and template + 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"], + admin=True, + domainid=cls.domain.id + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + domainid=cls.domain.id + ) + cls._cleanup = [ + cls.account, + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_03_network_create(self): + """ Test create network in project + """ + + # Validate the following + # 1. Create a project. + # 2. Add virtual/direct network resource to the project. User shared + # network resource for the project + # 3. Verify any number of Project level Virtual/Direct networks can be + # created and used for vm deployment within the project. + # 4. Verify shared networks (zone and domain wide) from outside the + # project can also be used in a project. + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + network_offerings = list_network_offerings( + self.apiclient, + projectid=project.id, + supportedServices='SourceNat', + type='isolated', + state='Enabled' + ) + self.assertEqual( + isinstance(network_offerings, list), + True, + "Check for the valid network offerings" + ) + network_offering = network_offerings[0] + + self.debug("creating a network with network offering ID: %s" % + network_offering.id) + self.services["network"]["zoneid"] = self.zone.id + network = Network.create( + self.apiclient, + self.services["network"], + networkofferingid=network_offering.id, + projectid=project.id + ) + self.debug("Created network with ID: %s" % network.id) + networks= Network.list( + self.apiclient, + projectid=project.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "Check for the valid network list response" + ) + network_response = networks[0] + + self.debug("Deploying VM with network: %s" % network.id) + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + networkids=[str(network.id)], + serviceofferingid=self.service_offering.id, + projectid=project.id + ) + self.debug("Deployed VM with ID: %s" % virtual_machine.id) + # Verify VM state + self.assertEqual( + virtual_machine.state, + 'Running', + "Check VM state is Running or not" + ) + + network_offerings = list_network_offerings( + self.apiclient, + state='Enabled', + guestiptype='Shared', + name='DefaultSharedNetworkOffering', + displaytext='Offering for Shared networks' + ) + self.assertEqual( + isinstance(network_offerings, list), + True, + "Check for the valid network offerings" + ) + network_offering = network_offerings[0] + + self.debug("creating a shared network in domain: %s" % + self.domain.id) + domain_network = Network.create( + self.apiclient, + self.services["domain_network"], + domainid=self.domain.id, + networkofferingid=network_offering.id, + zoneid=self.zone.id + ) + self._cleanup.append(domain_network) + self.debug("Created network with ID: %s" % domain_network.id) + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + networkids=[str(domain_network.id)], + serviceofferingid=self.service_offering.id, + projectid=project.id + ) + self.debug("Deployed VM with ID: %s" % virtual_machine.id) + # Verify VM state + self.assertEqual( + virtual_machine.state, + 'Running', + "Check VM state is Running or not" + ) + return + + +class TestTemplates(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestTemplates, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + # Create Domains, Account etc + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + cls.user = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Create project as a domain admin + cls.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + cls.services["account"] = cls.account.account.name + + # Create Service offering and disk offerings etc + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.project, + cls.service_offering, + cls.account, + cls.user, + cls.domain + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created 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_public_template_use_in_project(self): + """Test Templates creation in projects + """ + + # Validate the following + # 1. Create a project + # 2. Verify Public templates can be used without any restriction + # 3. Verify that template created in project can be used in project + # without any restrictions + + self.debug("Deploying VM for with public template: %s" % + self.template.id) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + projectid=self.project.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_1 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + projectid=self.project.id + ) + + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( + template_1.isready, + True, + "Check Template is in ready state or not" + ) + return + + def test_05_use_private_template_in_project(self): + """Test use of private template in a project + """ + + # Validate the following + # 1. Create a project + # 2. Verify that in order to use somebody’s Private template for vm + # creation in the project, permission to use the template has to + # be granted to the Project (use API “updateTemplatePermissions” + # with project id to achieve that). + + self.debug("Deploying VM for with public template: %s" % + self.template.id) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + self.debug("Stopping the VM: %s" % virtual_machine_1.id) + virtual_machine_1.stop(self.apiclient) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + projectid=self.project.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating template from volume: %s" % volume.id) + # Create a template from the ROOTDISK + template_1 = Template.create( + self.apiclient, + self.services["template"], + volumeid=volume.id, + projectid=self.project.id + ) + + self.cleanup.append(template_1) + # Verify Template state + self.assertEqual( + template_1.isready, + True, + "Check Template is in ready state or not" + ) + + # Update template permissions to grant permission to project + self.debug( + "Updating template permissions:%s to grant access to project: %s" % ( + template_1.id, + self.project.id + )) + + template_1.updatePermissions( + self.apiclient, + op='add', + projectids=self.project.id + ) + self.debug("Deploying VM for with privileged template: %s" % + self.template.id) + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=template_1.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_2) + # Verify VM state + self.assertEqual( + virtual_machine_2.state, + 'Running', + "Check VM state is Running or not" + ) + return + + +class TestSnapshots(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestSnapshots, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + # Create Domains, Account etc + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Create project as a domain admin + cls.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + cls.services["account"] = cls.account.account.name + + # Create Service offering and disk offerings etc + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.project, + cls.service_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_06_create_snapshots_in_project(self): + """Test create snapshots in project + """ + + # Validate the following + # 1. Create a project + # 2. Add some snapshots to the project + # 3. Verify snapshot created inside project can only be used in inside + # the project + + self.debug("Deploying VM for Project: %s" % self.project.id) + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["server"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.cleanup.append(virtual_machine_1) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + projectid=self.project.id, + type='ROOT', + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "Check for list volume response return valid data" + ) + volume = volumes[0] + + self.debug("Creating snapshot from volume: %s" % volumes[0].id) + # Create a snapshot from the ROOTDISK + snapshot = Snapshot.create(self.apiclient, + volumes[0].id, + projectid=self.project.id + ) + self.cleanup.append(snapshot) + # Verify Snapshot state + self.assertEqual( + snapshot.state in [ + 'BackedUp', + 'CreatedOnPrimary' + ], + True, + "Check Snapshot state is Running or not" + ) + + snapshots = Snapshot.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + snapshots, + None, + "Snapshots should not be available outside the project" + ) + return + + +class TestPublicIpAddress(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestPublicIpAddress, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.zone = get_zone(cls.api_client, cls.services) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + # Create Domains, Account etc + cls.domain = Domain.create( + cls.api_client, + cls.services["domain"] + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + # Create project as a domain admin + cls.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + cls.services["account"] = cls.account.account.name + + # Create Service offering and disk offerings etc + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=cls.template.id, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + + cls._cleanup = [ + cls.project, + cls.service_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_07_associate_public_ip(self): + """Test associate public IP within the project + """ + + # Validate the following + # 1. Create a project + # 2. Add some public Ips to the project + # 3. Verify public IP assigned can only used to create PF/LB rules + # inside project + + networks = Network.list( + self.apiclient, + projectid=self.project.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "Check list networks response returns a valid response" + ) + self.assertNotEqual( + len(networks), + 0, + "Check list networks response returns a valid network" + ) + network = networks[0] + self.debug("Associating public IP for project: %s" % self.project.id) + public_ip = PublicIPAddress.create( + self.apiclient, + zoneid=self.virtual_machine.zoneid, + services=self.services["server"], + networkid=network.id, + projectid=self.project.id + ) + self.cleanup.append(public_ip) + + #Create NAT rule + self.debug( + "Creating a NAT rule within project, VM ID: %s" % + self.virtual_machine.id) + nat_rule = NATRule.create( + self.apiclient, + self.virtual_machine, + self.services["natrule"], + public_ip.ipaddress.id, + projectid=self.project.id + ) + self.debug("created a NAT rule with ID: %s" % nat_rule.id) + nat_rule_response = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(nat_rule_response, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + len(nat_rule_response), + 0, + "Check Port Forwarding Rule is created" + ) + self.assertEqual( + nat_rule_response[0].id, + nat_rule.id, + "Check Correct Port forwarding Rule is returned" + ) + + #Create Load Balancer rule and assign VMs to rule + self.debug("Created LB rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + public_ip.ipaddress.id, + projectid=self.project.id + ) + self.cleanup.append(lb_rule) + self.debug("Assigning VM: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.id + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + + lb_rules = list_lb_rules( + self.apiclient, + id=lb_rule.id + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "Check list response returns a valid list" + ) + #verify listLoadBalancerRules lists the added load balancing rule + self.assertNotEqual( + len(lb_rules), + 0, + "Check Load Balancer Rule in its List" + ) + self.assertEqual( + lb_rules[0].id, + lb_rule.id, + "Check List Load Balancer Rules returns valid Rule" + ) + + #Create Firewall rule with configurations from settings file + fw_rule = FireWallRule.create( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"], + projectid=self.project.id + ) + self.debug("Created firewall rule: %s" % fw_rule.id) + + # After Router start, FW rule should be in Active state + fw_rules = FireWallRule.list( + 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" + ) + + 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) + + self.debug("VM state after deploy: %s" % virtual_machine_1.state) + # Verify VM state + self.assertEqual( + virtual_machine_1.state, + 'Running', + "Check VM state is Running or not" + ) + + self.debug("Creating NAT rule for VM (ID: %s) outside project" % + virtual_machine_1.id) + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine_1, + self.services["natrule"], + public_ip.ipaddress.id, + ) + + self.debug("Creating LB rule for public IP: %s outside project" % + public_ip.ipaddress.ipaddress) + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + public_ip.ipaddress.id, + accountid=self.account.account.name + ) + self.debug( + "Creating firewall rule for public IP: %s outside project" % + public_ip.ipaddress.ipaddress) + with self.assertRaises(Exception): + FireWallRule.create( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"], + ) + return + + +class TestSecurityGroup(cloudstackTestCase): + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.dbclient.close() + #Clean up, terminate the created templates + cleanup_resources(self.apiclient, self.cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @classmethod + def setUpClass(cls): + cls.services = Services().services + cls.api_client = super( + TestSecurityGroup, + cls + ).getClsTestClient().getApiClient() + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + 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["server"]["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 + ) + # Create project as a domain admin + cls.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + cls.services["account"] = cls.account.account.name + + cls._cleanup = [ + cls.project, + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.api_client = super(TestSecurityGroup, cls).getClsTestClient().getApiClient() + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def test_08_security_group(self): + """Test security groups in project + """ + + # Validate the following: + # 1. Create a project + # 2. Assign some security groups to that project + # 3. Verify the security groups can only be assigned to VM belonging + # to that project. + + security_group = SecurityGroup.create( + self.apiclient, + self.services["security_group"], + projectid=self.project.id + ) + 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, + projectid=self.project.id + ) + self.assertEqual( + isinstance(sercurity_groups, list), + True, + "Check for list security groups response" + ) + + self.assertNotEqual( + len(sercurity_groups), + 0, + "Check List Security groups response" + ) + # Authorize Security group to SSH to VM + ingress_rule = security_group.authorize( + self.apiclient, + self.services["security_group"], + projectid=self.project.id + ) + 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["server"], + serviceofferingid=self.service_offering.id, + securitygroupids=[security_group.id], + projectid=self.project.id + ) + self.debug("Deployed VM (ID: %s) in project: %s" % ( + self.virtual_machine.id, + self.project.id + )) + self.assertEqual( + self.virtual_machine.state, + 'Running', + "VM state should be running after deployment" + ) + # Deploy another VM with same security group outside the project + self.debug( + "Deploying VM with security group: %s outside project:%s" % ( + security_group.id, + self.project.id + )) + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["server"], + serviceofferingid=self.service_offering.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + securitygroupids=[security_group.id], + ) + return \ No newline at end of file diff --git a/tools/testClient/testcase/P1-tests/test_project_usage.py b/tools/testClient/testcase/P1-tests/test_project_usage.py new file mode 100644 index 00000000000..c986ae5f2c5 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_project_usage.py @@ -0,0 +1,1701 @@ +# -*- 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", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "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": '471a4b5b-5523-448f-9608-7d6218995733', + "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": '471a4b5b-5523-448f-9608-7d6218995733', + }, + "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": '471a4b5b-5523-448f-9608-7d6218995733', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestVmUsage(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVmUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + 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, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + cls._cleanup = [ + cls.project, + 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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super( + TestPublicIPUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["server"]["zoneid"] = cls.zone.id + + cls.services["template"] = cls.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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["server"], + templateid=cls.template.id, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + networks = Network.list( + cls.api_client, + projectid=cls.project.id, + listall=True + ) + if isinstance(networks, list): + network = networks[0] + else: + raise Exception("List networks call failed") + + cls.public_ip = PublicIPAddress.create( + cls.api_client, + zoneid=cls.zone.zoneid, + services=cls.services["server"], + networkid=network.id, + projectid=cls.project.id + ) + cls._cleanup = [ + cls.project, + 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. Acquire 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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super( + TestVolumeUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + 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, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + cls._cleanup = [ + cls.project, + 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, + projectid=self.project.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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super( + TestTemplateUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + 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, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + + #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, + projectid=cls.project.id, + type='ROOT', + listall=True + ) + if isinstance(list_volume, list): + cls.volume = list_volume[0] + else: + raise Exception("List Volumes failed!") + cls._cleanup = [ + cls.project, + 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, + projectid=self.project.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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super(TestISOUsage, cls).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.iso = Iso.create( + cls.api_client, + cls.services["iso"], + projectid=cls.project.id + ) + 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.project, + 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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super( + TestLBRuleUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + 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, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + networks = Network.list( + cls.api_client, + projectid=cls.project.id, + listall=True + ) + if isinstance(networks, list): + network = networks[0] + else: + raise Exception("List networks call failed") + + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + zoneid=cls.zone.zoneid, + services=cls.services["server"], + networkid=network.id, + projectid=cls.project.id + ) + cls._cleanup = [ + cls.project, + 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, + projectid=self.project.id + ) + # Delete LB Rule + self.debug("Deleting LB rule with ID: %s" % lb_rule.id) + lb_rule.delete(self.apiclient) + + # Fetch project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super( + TestSnapshotUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + 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, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + cls._cleanup = [ + cls.project, + 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, + projectid=self.project.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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super( + TestNatRuleUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + 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, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + networks = Network.list( + cls.api_client, + projectid=cls.project.id, + listall=True + ) + if isinstance(networks, list): + network = networks[0] + else: + raise Exception("List networks call failed") + + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + zoneid=cls.zone.zoneid, + services=cls.services["server"], + networkid=network.id, + projectid=cls.project.id + ) + cls._cleanup = [ + cls.project, + 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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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 = super( + TestVpnUsage, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["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.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + 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, + serviceofferingid=cls.service_offering.id, + projectid=cls.project.id + ) + networks = Network.list( + cls.api_client, + projectid=cls.project.id, + listall=True + ) + if isinstance(networks, list): + network = networks[0] + else: + raise Exception("List networks call failed") + + cls.public_ip = PublicIPAddress.create( + cls.api_client, + zoneid=cls.zone.zoneid, + services=cls.services["server"], + networkid=network.id, + projectid=cls.project.id + ) + cls._cleanup = [ + cls.project, + 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, + projectid=self.project.id + ) + + 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"], + projectid=self.project.id + ) + + # 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 project account ID from project UUID + self.debug( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.id) + + qresultset = self.dbclient.execute( + "select project_account_id from projects where uuid = '%s';" \ + % self.project.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_projects.py b/tools/testClient/testcase/P1-tests/test_projects.py new file mode 100644 index 00000000000..e41b2dd87b2 --- /dev/null +++ b/tools/testClient/testcase/P1-tests/test_projects.py @@ -0,0 +1,1630 @@ +# -*- encoding: utf-8 -*- +# +# Copyright (c) 2012 Citrix. All rights reserved. +# +""" P1 tests for Project +""" +#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 Project Services + """ + + def __init__(self): + self.services = { + "domain": { + "name": "Domain", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "mgmt_server": { + "ipaddress": '192.168.100.21', + "username": 'root', + "password": 'fr3sca', + "port": 22, + }, + "account": { + "email": "administrator@clogeny.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "user": { + "email": "administrator@clogeny.com", + "firstname": "User", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "disk_offering": { + "displaytext": "Tiny Disk Offering", + "name": "Tiny Disk Offering", + "disksize": 1 + }, + "volume": { + "diskname": "Test Volume", + }, + "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', + }, + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestMultipleProjectCreation(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestMultipleProjectCreation, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + + # Create domains, account etc. + cls.domain = get_domain( + cls.api_client, + cls.services + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.user = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls._cleanup = [cls.account, cls.user] + 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_multiple_projects_by_account(self): + """ Verify an account can own multiple projects and can belong to + multiple projects + """ + + # Validate the following + # 1. Create multiple project. Verify at step 1 An account is allowed + # to create multiple projects + # 2. add one account to multiple project. Verify at step 2 an account + # is allowed to added to multiple project + + # Create project as a domain admin + project_1 = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project_1) + self.debug("Created project with domain admin with ID: %s" % + project_1.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project_1.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project_1.name, + list_project.name, + "Check project name from list response" + ) + # Create another project as a domain admin + project_2 = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project_2) + self.debug("Created project with domain user with ID: %s" % + project_2.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project_2.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + # Add user to the project + project_1.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project_1.id, + account=self.user.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + # Add user to the project + project_2.addAccount( + self.apiclient, + self.user.account.name, + self.user.account.email + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project_2.id, + account=self.user.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + return + + +class TestCrossDomainAccountAdd(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestCrossDomainAccountAdd, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain( + cls.api_client, + cls.services + ) + + # Create domains, account etc. + cls.new_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.user = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.new_domain.id + ) + + cls._cleanup = [cls.account, cls.user] + 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_02_cross_domain_account_add(self): + """ Verify No cross domain projects + """ + + # Validate the following + # 1. Create a project in a domain. + # 2. Add different domain account to the project. Add account should + # fail + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + + self.debug("Adding user: %s from domain: %s to project: %s" %( + self.user.account.name, + self.user.account.domainid, + project.id + )) + with self.assertRaises(Exception): + # Add user to the project from different domain + project.addAccount( + self.apiclient, + self.user.account.name + ) + self.debug("User add to project failed!") + return + + +class TestDeleteAccountWithProject(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeleteAccountWithProject, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain( + cls.api_client, + cls.services + ) + + # Create account + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.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 accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def test_03_delete_account_with_project(self): + """ Test As long as the project exists, its owner can't be removed + """ + + # Validate the following + # 1. Create a project. + # 2. Delete account who is owner of the project. Delete account should + # fail + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + # Deleting account who is owner of the project + with self.assertRaises(Exception): + self.account.delete(self.apiclient) + self.debug("Deleting account %s failed!" % + self.account.account.name) + return + +@unittest.skip("Deleting domain doesn't cleanup account") +class TestDeleteDomainWithProject(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeleteDomainWithProject, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + # Create account + 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 = [] + 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_04_delete_domain_with_project(self): + """ Test Verify delete domain with cleanup=true should delete projects + belonging to the domain + """ + + # Validate the following + # 1. Create a project in a domain + # 2. Delete domain forcefully. Verify that project is also deleted as + # as part of domain cleanup + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + + self.debug("Deleting domain: %s forcefully" % self.domain.name) + # Delete domain with cleanup=True + self.domain.delete(self.apiclient, cleanup=True) + self.debug("Removed domain: %s" % self.domain.name) + + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + self.assertEqual( + isinstance(interval, list), + True, + "Check if account.cleanup.interval config present" + ) + self.debug( + "Sleep for account cleanup interval: %s" % + interval[0].value) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value)) + + # Project should be deleted as part of domain cleanup + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + self.assertEqual( + list_projects_reponse, + None, + "Project should be deleted as part of domain cleanup" + ) + return + + +class TestProjectOwners(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestProjectOwners, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.domain = get_domain( + cls.api_client, + cls.services + ) + cls.zone = get_zone(cls.api_client, cls.services) + + # Create accounts + cls.admin = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.new_admin = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup = [cls.admin, cls.new_admin] + 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_05_user_project_owner_promotion(self): + """ Test Verify a project user can be later promoted to become a + owner + """ + + # Validate the following + # 1. Create a project. + # 2. Add account to the project. Edit account to make it a project + # owner. verify new user is project owner and old account is + # regular user of the project. + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.admin.account.name, + domainid=self.admin.account.domainid + ) + self.cleanup.append(project) + # Cleanup created project at end of test + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.new_admin.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.new_admin.account.name, + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.new_admin.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + + # Update the project with new admin + project.update( + self.apiclient, + account=self.new_admin.account.name + ) + + # listProjectAccount to verify the user is new admin of the project + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.new_admin.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Admin', + "Newly added user is not added as a regular user" + ) + + # listProjectAccount to verify old user becomes a regular user + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.admin.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + return + + def test_06_max_one_project_owner(self): + """ Test Verify there can only be one owner of a project at a time + """ + + # Validate the following + # 1. Create a project. + # 2. Add account to the project. Edit account to make it a project + # owner. + # 3. Update project to add another account as an owner + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.admin.account.name, + domainid=self.admin.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + self.user = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup.append(self.user) + self.debug("Created account with ID: %s" % + self.user.account.name) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.new_admin.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.new_admin.account.name, + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.new_admin.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + self.debug("Updating project with new Admin: %s" % + self.new_admin.account.name) + # Update the project with new admin + project.update( + self.apiclient, + account=self.new_admin.account.name + ) + + # listProjectAccount to verify the user is new admin of the project + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.new_admin.account.name, + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Admin', + "Newly added user is not added as a regular user" + ) + + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.user.account.name, + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + + self.debug("Updating project with new Admin: %s" % + self.user.account.name) + + # Update the project with new admin + project.update( + self.apiclient, + account=self.user.account.name + ) + + # listProjectAccount to verify the user is new admin of the project + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.user.account.name, + ) + self.debug(accounts_reponse) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Admin', + "Newly added user is not added as a regular user" + ) + + # listProjectAccount to verify old user becomes a regular user + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.new_admin.account.name, + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + return + + +class TestProjectResources(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestProjectResources, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone + cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain( + cls.api_client, + cls.services + ) + + # Create account, disk offering etc. + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.user = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup = [cls.account, cls.disk_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_07_project_resources_account_delete(self): + """ Test Verify after an account is removed from the project, all his + resources stay with the project. + """ + + # Validate the following + # 1. Create a project. + # 2. Add some accounts to project. Add resources to the project + # 3. Delete the account. Verify resources are still there after + # account deletion. + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.cleanup.append(project) + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name, + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.user.account.name, + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + # Create some resources(volumes) for the projects + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id, + projectid=project.id + ) + self.cleanup.append(volume) + + # Delete the project user + self.user.delete(self.apiclient) + + volumes = Volume.list(self.apiclient, id=volume.id) + + self.assertEqual( + isinstance(volumes, list), + True, + "Check for a valid list volumes response" + ) + + self.assertNotEqual( + len(volumes), + 0, + "Check list volumes API response returns a valid list" + ) + volume_response = volumes[0] + + self.assertEqual( + volume_response.name, + volume.name, + "Volume should exist after project user deletion." + ) + return + + def test_08_cleanup_after_project_delete(self): + """ Test accounts are unassigned from project after project deletion + """ + + # Validate the following + # 1. Create a project. + # 2. Add some accounts to project. Add resources to the project + # 3. Delete the project. Verify resources are freed after + # account deletion. + # 4. Verify all accounts are unassigned from project. + + # Create project as a domain admin + project = Project.create( + self.apiclient, + self.services["project"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + # Cleanup created project at end of test + self.debug("Created project with domain admin with ID: %s" % + project.id) + + list_projects_reponse = Project.list( + self.apiclient, + id=project.id, + listall=True + ) + + self.assertEqual( + isinstance(list_projects_reponse, list), + True, + "Check for a valid list projects response" + ) + list_project = list_projects_reponse[0] + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + + self.assertEqual( + project.name, + list_project.name, + "Check project name from list response" + ) + self.user = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup.append(self.user) + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + project.name + )) + # Add user to the project + project.addAccount( + self.apiclient, + self.user.account.name + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=project.id, + account=self.user.account.name, + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(list_projects_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + # Create some resources(volumes) for the projects + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id, + projectid=project.id + ) + self.debug("Created a volume: %s for project: %s" % ( + volume.id, + project.name + )) + # Delete the project user + self.debug("Deleting project: %s" % project.name) + project.delete(self.apiclient) + self.debug("Successfully deleted project: %s" % project.name) + + volumes = Volume.list(self.apiclient, id=volume.id) + + self.assertEqual( + volumes, + None, + "Resources (volume) should be deleted as part of cleanup" + ) + + accounts = Project.listAccounts(self.apiclient, projectid=project.id) + + self.assertEqual( + accounts, + None, + "Accounts should be un-assigned from project" + ) + return + + +class TestProjectSuspendActivate(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestProjectSuspendActivate, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, domain, template etc + cls.zone = get_zone(cls.api_client, cls.services) + cls.domain = get_domain( + cls.api_client, + cls.services + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + # Create account, service offering, disk offering etc. + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + domainid=cls.domain.id + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.user = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Create project as a domain admin + cls.project = Project.create( + cls.api_client, + cls.services["project"], + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls._cleanup = [ + cls.project, + cls.account, + cls.disk_offering, + 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_09_project_suspend(self): + """ Test Verify after an account is removed from the project, all his + resources stay with the project. + """ + + # Validate the following + # 1. Create a project. + # 2. Add some accounts to project. Add resources to the project + # 3. Delete the account. Verify resources are still there after + # account deletion. + + self.debug("Adding %s user to project: %s" % ( + self.user.account.name, + self.project.name + )) + # Add user to the project + self.project.addAccount( + self.apiclient, + self.user.account.name, + ) + + # listProjectAccount to verify the user is added to project or not + accounts_reponse = Project.listAccounts( + self.apiclient, + projectid=self.project.id, + account=self.user.account.name, + ) + self.assertEqual( + isinstance(accounts_reponse, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(accounts_reponse), + 0, + "Check list project response returns a valid project" + ) + account = accounts_reponse[0] + + self.assertEqual( + account.role, + 'Regular', + "Newly added user is not added as a regular user" + ) + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + self.debug("Created a VM: %s for project: %s" % ( + virtual_machine.id, + self.project.id + )) + self.debug("Suspending a project: %s" % self.project.name) + self.project.suspend(self.apiclient) + + # Check status of all VMs associated with project + vms = VirtualMachine.list( + self.apiclient, + projectid=self.project.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(vms), + 0, + "Check list project response returns a valid project" + ) + + for vm in vms: + self.debug("VM ID: %s state: %s" % (vm.id, vm.state)) + self.assertEqual( + vm.state, + 'Stopped', + "VM should be in stopped state after project suspension" + ) + + self.debug("Attempting to create volume in suspended project") + with self.assertRaises(Exception): + # Create some resources(volumes) for the projects + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + diskofferingid=self.disk_offering.id, + projectid=self.project.id + ) + + self.debug("Volume creation failed") + + # Start the stopped VM + self.debug("Attempting to start VM: %s in suspended project" % + virtual_machine.id) + with self.assertRaises(Exception): + virtual_machine.start(self.apiclient) + self.debug("VM start failed!") + + # Destroy Stopped VM + virtual_machine.delete(self.apiclient) + self.debug("Destroying VM: %s" % virtual_machine.id) + + # Check status of all VMs associated with project + vms = VirtualMachine.list( + self.apiclient, + projectid=self.project.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(vms), + 0, + "Check list project response returns a valid project" + ) + + for vm in vms: + self.debug("VM ID: %s state: %s" % (vm.id, vm.state)) + self.assertEqual( + vm.state, + 'Destroyed', + "VM should be in stopped state after project suspension" + ) + return + + def test_10_project_activation(self): + """ Test project activation after suspension + """ + + # Validate the following + # 1. Activate the project + # 2. Verify project is activated and we are able to add resources + + # Activating the project + self.debug("Activating project: %s" % self.project.name) + self.project.activate(self.apiclient) + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + projectid=self.project.id + ) + + self.cleanup.append(virtual_machine) + self.debug("Created a VM: %s for project: %s" % ( + virtual_machine.id, + self.project.id + )) + # Check status of all VMs associated with project + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "Check for a valid list accounts response" + ) + + self.assertNotEqual( + len(vms), + 0, + "Check list project response returns a valid project" + ) + + for vm in vms: + self.debug("VM ID: %s state: %s" % (vm.id, vm.state)) + self.assertEqual( + vm.state, + 'Running', + "VM should be in Running state after project activation" + ) + return \ No newline at end of file diff --git a/tools/testClient/testcase/P1-tests/test_resource_limits.py b/tools/testClient/testcase/P1-tests/test_resource_limits.py index edcc557b721..dd4fa423a30 100644 --- a/tools/testClient/testcase/P1-tests/test_resource_limits.py +++ b/tools/testClient/testcase/P1-tests/test_resource_limits.py @@ -72,7 +72,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestResourceLimitsAccount, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -830,7 +830,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestResourceLimitsDomain, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.zone = get_zone(cls.api_client, cls.services) diff --git a/tools/testClient/testcase/P1-tests/test_routers.py b/tools/testClient/testcase/P1-tests/test_routers.py index 05dfc99e7fd..29be4b635c7 100644 --- a/tools/testClient/testcase/P1-tests/test_routers.py +++ b/tools/testClient/testcase/P1-tests/test_routers.py @@ -74,7 +74,7 @@ class Services: "cidr": '55.55.0.0/11', # Any network (For creating FW rule }, - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', # Used for Get_Template : CentOS 5.3 (64 bit) "mode": 'advanced', # Networking mode: Advanced, basic } @@ -85,7 +85,7 @@ class TestRouterServices(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterServices, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -133,7 +133,7 @@ class TestRouterServices(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterServices, cls).getClsTestClient().getApiClient() #Clean up, terminate the created templates cleanup_resources(cls.api_client, cls.cleanup) @@ -558,7 +558,7 @@ class TestRouterStopCreatePF(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterStopCreatePF, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -598,7 +598,7 @@ class TestRouterStopCreatePF(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterStopCreatePF, cls).getClsTestClient().getApiClient() # Clean up, terminate the created resources cleanup_resources(cls.api_client, cls.cleanup) @@ -758,7 +758,7 @@ class TestRouterStopCreateLB(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterStopCreateLB, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -798,7 +798,7 @@ class TestRouterStopCreateLB(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterStopCreateLB, cls).getClsTestClient().getApiClient() #Clean up, terminate the created resources cleanup_resources(cls.api_client, cls.cleanup) @@ -959,7 +959,7 @@ class TestRouterStopCreateFW(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterStopCreateFW, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -998,7 +998,7 @@ class TestRouterStopCreateFW(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestRouterStopCreateFW, cls).getClsTestClient().getApiClient() #Clean up, terminate the created templates cleanup_resources(cls.api_client, cls.cleanup) diff --git a/tools/testClient/testcase/P1-tests/test_security_groups.py b/tools/testClient/testcase/P1-tests/test_security_groups.py index d096ad4daa2..a65b5615a9e 100644 --- a/tools/testClient/testcase/P1-tests/test_security_groups.py +++ b/tools/testClient/testcase/P1-tests/test_security_groups.py @@ -107,7 +107,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestDefaultSecurityGroup, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -143,7 +143,7 @@ class TestDefaultSecurityGroup(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestDefaultSecurityGroup, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -374,7 +374,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestAuthorizeIngressRule, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -408,7 +408,7 @@ class TestAuthorizeIngressRule(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestAuthorizeIngressRule, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -508,7 +508,7 @@ class TestRevokeIngressRule(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestRevokeIngressRule, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -542,7 +542,7 @@ class TestRevokeIngressRule(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestRevokeIngressRule, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -665,7 +665,7 @@ class TestDhcpOnlyRouter(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestDhcpOnlyRouter, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -707,7 +707,7 @@ class TestDhcpOnlyRouter(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestDhcpOnlyRouter, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -740,7 +740,8 @@ class TestDhcpOnlyRouter(cloudstackTestCase): self.apiclient, zoneid=router.zoneid, type='Routing', - state='Up' + state='Up', + virtualmachineid=self.virtual_machine.id ) self.assertEqual( isinstance(hosts, list), @@ -798,7 +799,7 @@ class TestdeployVMWithUserData(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestdeployVMWithUserData, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -833,7 +834,7 @@ class TestdeployVMWithUserData(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestdeployVMWithUserData, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -1000,14 +1001,14 @@ class TestDeleteSecurityGroup(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestDeleteSecurityGroup, cls).getClsTestClient().getApiClient() cls._cleanup = [] return @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestDeleteSecurityGroup, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -1242,14 +1243,14 @@ class TestIngressRule(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestIngressRule, cls).getClsTestClient().getApiClient() cls._cleanup = [] return @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestIngressRule, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) diff --git a/tools/testClient/testcase/P1-tests/test_snapshots.py b/tools/testClient/testcase/P1-tests/test_snapshots.py index dad9d60f050..265b84e5e00 100644 --- a/tools/testClient/testcase/P1-tests/test_snapshots.py +++ b/tools/testClient/testcase/P1-tests/test_snapshots.py @@ -91,7 +91,7 @@ class TestCreateVMsnapshotTemplate(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestCreateVMsnapshotTemplate, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -307,32 +307,33 @@ class TestCreateVMsnapshotTemplate(cloudstackTestCase): True, "Check list response returns a valid list" ) + uuids = [] + for host in hosts: + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (host.name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] - # 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 - # 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 + 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( + # 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 = [ + cmds = [ "mkdir -p %s" % self.services["mount_dir"], - "mount %s:/%s %s" % ( + "mount %s/%s %s" % ( sec_storage_ip, export_path, self.services["mount_dir"] @@ -343,34 +344,36 @@ class TestCreateVMsnapshotTemplate(cloudstackTestCase): volume_id ), ] - for c in cmds: - self.debug("command: %s" % c) - result = ssh_client.execute(c) - self.debug("Result: %s" % result) + 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" % + except Exception as e: + self.fail("SSH failed for Management server: %s" % self.services["mgmt_server"]["ipaddress"]) + uuids.append(result) + # 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) - res = str(result) + except Exception as e: + self.fail("SSH failed for Management server: %s" % + self.services["mgmt_server"]["ipaddress"]) + + res = str(uuids) 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 @@ -378,7 +381,7 @@ class TestAccountSnapshotClean(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestAccountSnapshotClean, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -563,32 +566,33 @@ class TestAccountSnapshotClean(cloudstackTestCase): True, "Check list response returns a valid list" ) + uuids = [] + for host in hosts: + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (host.name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] - # 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 - # 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 + 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( + # 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 = [ + cmds = [ "mkdir -p %s" % self.services["mount_dir"], - "mount %s:/%s %s" % ( + "mount %s/%s %s" % ( sec_storage_ip, export_path, self.services["mount_dir"] @@ -600,27 +604,29 @@ class TestAccountSnapshotClean(cloudstackTestCase): ), ] - for c in cmds: - self.debug("command: %s" % c) - result = ssh_client.execute(c) - self.debug("Result: %s" % result) + for c in cmds: + self.debug("command: %s" % c) + result = ssh_client.execute(c) + self.debug("Result: %s" % result) - res = str(result) - self.assertEqual( + uuids.append(result) + + # 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"]) + + res = str(uuids) + 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 @@ -645,44 +651,58 @@ class TestAccountSnapshotClean(cloudstackTestCase): self.apiclient, id=self.account.account.id ) - try: - cmds = [ - "mount %s:/%s %s" % ( + uuids = [] + for host in hosts: + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (host.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: + cmds = [ + "mount %s/%s %s" % ( sec_storage_ip, export_path, self.services["mount_dir"] ), - "ls %s/snapshots/%s/%s" % ( + "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) + for c in cmds: + self.debug("command: %s" % c) + result = ssh_client.execute(c) + self.debug("Result: %s" % result) - res = str(result) - - self.assertNotEqual( + uuids.append(result) + # 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"]) + + res = str(uuids) + 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 @@ -690,7 +710,7 @@ class TestSnapshotDetachedDisk(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSnapshotDetachedDisk, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -902,32 +922,34 @@ class TestSnapshotDetachedDisk(cloudstackTestCase): True, "Check list response returns a valid list" ) + uuids = [] + for host in hosts: + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (host.name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] - # 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 - # 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 + 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( + # 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 = [ + cmds = [ "mkdir -p %s" % self.services["mount_dir"], - "mount %s:/%s %s" % ( + "mount %s/%s %s" % ( sec_storage_ip, export_path, self.services["mount_dir"] @@ -937,26 +959,28 @@ class TestSnapshotDetachedDisk(cloudstackTestCase): account_id, volume_id ), - ] + ] - for c in cmds: - result = ssh_client.execute(c) - res = str(result) - self.assertEqual( + for c in cmds: + result = ssh_client.execute(c) + + uuids.append(result) + # 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"]) + + res = str(uuids) + 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 @@ -964,7 +988,7 @@ class TestSnapshotLimit(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSnapshotLimit, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -1150,29 +1174,30 @@ class TestSnapshotLimit(cloudstackTestCase): True, "Check list response returns a valid list" ) + uuids = [] + for host in hosts: + # hosts[0].name = "nfs://192.168.100.21/export/test" + parse_url = (host.name).split('/') + # parse_url = ['nfs:', '', '192.168.100.21', 'export', 'test'] - # 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 - # 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( + 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 = [ + cmds = [ "mkdir -p %s" % self.services["mount_dir"], - "mount %s:/%s %s" % ( + "mount %s/%s %s" % ( sec_storage_ip, export_path, self.services["mount_dir"] @@ -1184,25 +1209,28 @@ class TestSnapshotLimit(cloudstackTestCase): ), ] - for c in cmds: - result = ssh_client.execute(c) + for c in cmds: + result = ssh_client.execute(c) - res = str(result) - self.assertEqual( + uuids.append(result) + + # 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"]) + + res = str(uuids) + 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 @@ -1210,7 +1238,7 @@ class TestSnapshotEvents(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSnapshotEvents, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) diff --git a/tools/testClient/testcase/P1-tests/test_templates.py b/tools/testClient/testcase/P1-tests/test_templates.py index bfccf54061b..1274944ba4d 100644 --- a/tools/testClient/testcase/P1-tests/test_templates.py +++ b/tools/testClient/testcase/P1-tests/test_templates.py @@ -62,7 +62,7 @@ class Services: 0:{ "displaytext": "Public Template", "name": "Public template", - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2", "hypervisor": 'XenServer', "format" : 'VHD', @@ -74,12 +74,12 @@ class Services: "template": { "displaytext": "Cent OS Template", "name": "Cent OS Template", - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "templatefilter": 'self', }, "templatefilter": 'self', "destzoneid": 2, # For Copy template (Destination zone) - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "sleep": 60, "timeout": 10, "mode": 'advanced', # Networking mode: Advanced, basic @@ -109,7 +109,7 @@ class TestCreateTemplate(cloudstackTestCase): @classmethod def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -136,7 +136,7 @@ class TestCreateTemplate(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestCreateTemplate, cls).getClsTestClient().getApiClient() #Cleanup resources used cleanup_resources(cls.api_client, cls._cleanup) @@ -264,7 +264,7 @@ class TestTemplates(cloudstackTestCase): def setUpClass(cls): cls.services = Services().services - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() # Get Zone, templates etc cls.domain = get_domain(cls.api_client, cls.services) @@ -335,7 +335,7 @@ class TestTemplates(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplates, cls).getClsTestClient().getApiClient() #Cleanup created resources such as templates and VMs cleanup_resources(cls.api_client, cls._cleanup) diff --git a/tools/testClient/testcase/P1-tests/test_usage.py b/tools/testClient/testcase/P1-tests/test_usage.py index d43e43131f7..2db6a8d4042 100644 --- a/tools/testClient/testcase/P1-tests/test_usage.py +++ b/tools/testClient/testcase/P1-tests/test_usage.py @@ -98,7 +98,7 @@ class TestVmUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestVmUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -281,7 +281,7 @@ class TestPublicIPUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestPublicIPUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -432,7 +432,7 @@ class TestVolumeUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestVolumeUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -605,7 +605,7 @@ class TestTemplateUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestTemplateUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -769,7 +769,7 @@ class TestISOUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestISOUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -905,7 +905,7 @@ class TestLBRuleUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestLBRuleUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -1066,7 +1066,7 @@ class TestSnapshotUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestSnapshotUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -1231,7 +1231,7 @@ class TestNatRuleUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestNatRuleUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) @@ -1392,7 +1392,7 @@ class TestVpnUsage(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestVpnUsage, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) diff --git a/tools/testClient/testcase/P1-tests/test_volumes.py b/tools/testClient/testcase/P1-tests/test_volumes.py index 4c45bdad4e3..540aa5fbb44 100644 --- a/tools/testClient/testcase/P1-tests/test_volumes.py +++ b/tools/testClient/testcase/P1-tests/test_volumes.py @@ -65,10 +65,10 @@ 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": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', }, "sleep": 50, - "ostypeid": '144f66aa-7f74-4cfe-9799-80cc21439cb3', + "ostypeid": '5776c0d2-f331-42db-ba3a-29f1f8319bc9', "mode": 'advanced', } @@ -77,7 +77,7 @@ class TestAttachVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestAttachVolume, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates @@ -336,7 +336,7 @@ class TestAttachVolume(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestAttachVolume, cls).getClsTestClient().getApiClient() cleanup_resources(cls.api_client, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -346,7 +346,7 @@ class TestAttachDetachVolume(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestAttachDetachVolume, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates @@ -404,7 +404,7 @@ class TestAttachDetachVolume(cloudstackTestCase): @classmethod def tearDownClass(cls): try: - cls.api_client = fetch_api_client() + cls.api_client = super(TestAttachDetachVolume, cls).getClsTestClient().getApiClient() cleanup_resources(cls.api_client, cls._cleanup) except Exception as e: raise Exception("Warning: Exception during cleanup : %s" % e) @@ -590,7 +590,7 @@ class TestAttachVolumeISO(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestAttachVolumeISO, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates @@ -781,7 +781,7 @@ class TestVolumes(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = fetch_api_client() + cls.api_client = super(TestVolumes, cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone, Domain and templates cls.domain = get_domain(cls.api_client, cls.services) diff --git a/tools/testClient/testcase/libs/base.py b/tools/testClient/testcase/libs/base.py index 1647a7f3b90..feceec7c734 100644 --- a/tools/testClient/testcase/libs/base.py +++ b/tools/testClient/testcase/libs/base.py @@ -162,7 +162,7 @@ class VirtualMachine: @classmethod def create(cls, apiclient, services, templateid=None, accountid=None, domainid=None, networkids=None, serviceofferingid=None, - securitygroupids=None, mode='basic'): + securitygroupids=None, projectid=None, mode='basic'): """Create the instance""" cmd = deployVirtualMachine.deployVirtualMachineCmd() @@ -204,6 +204,9 @@ class VirtualMachine: if "userdata" in services: cmd.userdata = base64.b64encode(services["userdata"]) + if projectid: + cmd.projectid = projectid + virtual_machine = apiclient.deployVirtualMachine(cmd) # VM should be in Running state after deploy @@ -325,7 +328,7 @@ class Volume: @classmethod def create(cls, apiclient, services, zoneid=None, account=None, domainid=None, - diskofferingid=None): + diskofferingid=None, projectid=None): """Create Volume""" cmd = createVolume.createVolumeCmd() cmd.name = services["diskname"] @@ -350,6 +353,8 @@ class Volume: elif "domainid" in services: cmd.domainid = services["domainid"] + if projectid: + cmd.projectid = projectid return Volume(apiclient.createVolume(cmd).__dict__) @classmethod @@ -414,7 +419,7 @@ class Snapshot: self.__dict__.update(items) @classmethod - def create(cls, apiclient, volume_id, account=None, domainid=None): + def create(cls, apiclient, volume_id, account=None, domainid=None, projectid=None): """Create Snapshot""" cmd = createSnapshot.createSnapshotCmd() cmd.volumeid = volume_id @@ -422,6 +427,8 @@ class Snapshot: cmd.account = account if domainid: cmd.domainid = domainid + if projectid: + cmd.projectid = projectid return Snapshot(apiclient.createSnapshot(cmd).__dict__) def delete(self, apiclient): @@ -447,7 +454,7 @@ class Template: @classmethod def create(cls, apiclient, services, volumeid=None, - account=None, domainid=None): + account=None, domainid=None, projectid=None): """Create template from Volume""" #Create template from Virtual machine and Volume ID cmd = createTemplate.createTemplateCmd() @@ -469,6 +476,8 @@ class Template: if domainid: cmd.domainid = domainid + if projectid: + cmd.projectid = projectid return Template(apiclient.createTemplate(cmd).__dict__) @classmethod @@ -561,7 +570,15 @@ class Template: time.sleep(interval) timeout = timeout - 1 return - + + def updatePermissions(self, apiclient, **kwargs): + """Updates the template permissions""" + + cmd = updateTemplatePermissions.updateTemplatePermissionsCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.updateTemplatePermissions(cmd)) + @classmethod def list(cls, apiclient, **kwargs): """List all templates matching criteria""" @@ -578,7 +595,8 @@ class Iso: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, account=None, domainid=None): + def create(cls, apiclient, services, account=None, domainid=None, + projectid=None): """Create an ISO""" #Create ISO from URL cmd = registerIso.registerIsoCmd() @@ -599,6 +617,8 @@ class Iso: cmd.account = account if domainid: cmd.domainid = domainid + if projectid: + cmd.projectid = projectid # Register ISO iso = apiclient.registerIso(cmd) @@ -656,17 +676,29 @@ class PublicIPAddress: self.__dict__.update(items) @classmethod - def create(cls, apiclient, accountid, zoneid=None, domainid=None, - services=None, networkid=None): + def create(cls, apiclient, accountid=None, zoneid=None, domainid=None, + services=None, networkid=None, projectid=None): """Associate Public IP address""" cmd = associateIpAddress.associateIpAddressCmd() - cmd.account = accountid - cmd.zoneid = zoneid or services["zoneid"] - cmd.domainid = domainid or services["domainid"] + + if accountid: + cmd.account = accountid + + if zoneid: + cmd.zoneid = zoneid + elif "zoneid" in services: + services["zoneid"] + + if domainid: + cmd.domainid = domainid + elif "domainid" in services: + services["domainid"] if networkid: cmd.networkid = networkid - + + if projectid: + cmd.projectid = projectid return PublicIPAddress(apiclient.associateIpAddress(cmd).__dict__) def delete(self, apiclient): @@ -691,7 +723,8 @@ class NATRule: self.__dict__.update(items) @classmethod - def create(cls, apiclient, virtual_machine, services, ipaddressid=None): + def create(cls, apiclient, virtual_machine, services, ipaddressid=None, + projectid=None): """Create Port forwarding rule""" cmd = createPortForwardingRule.createPortForwardingRuleCmd() @@ -705,6 +738,9 @@ class NATRule: cmd.protocol = services["protocol"] cmd.virtualmachineid = virtual_machine.id + if projectid: + cmd.projectid = projectid + return NATRule(apiclient.createPortForwardingRule(cmd).__dict__) def delete(self, apiclient): @@ -793,7 +829,7 @@ class FireWallRule: @classmethod def create(cls, apiclient, ipaddressid, protocol, cidrlist=None, - startport=None, endport=None): + startport=None, endport=None, projectid=None): """Create Firewall Rule""" cmd = createFirewallRule.createFirewallRuleCmd() cmd.ipaddressid = ipaddressid @@ -805,7 +841,10 @@ class FireWallRule: if endport: cmd.endport = endport - return NATRule(apiclient.createFirewallRule(cmd).__dict__) + if projectid: + cmd.projectid = projectid + + return FireWallRule(apiclient.createFirewallRule(cmd).__dict__) def delete(self, apiclient): """Delete Firewall rule""" @@ -867,7 +906,7 @@ class DiskOffering: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, custom=False): + def create(cls, apiclient, services, custom=False, domainid=None): """Create Disk offering""" cmd = createDiskOffering.createDiskOfferingCmd() cmd.displaytext = services["displaytext"] @@ -876,6 +915,10 @@ class DiskOffering: cmd.customized = True else: cmd.disksize = services["disksize"] + + if domainid: + cmd.domainid = domainid + return DiskOffering(apiclient.createDiskOffering(cmd).__dict__) def delete(self, apiclient): @@ -894,6 +937,58 @@ class DiskOffering: return(apiclient.listDiskOfferings(cmd)) +class NetworkOffering: + """Manage network offerings cycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, serviceProviderList=None, **kwargs): + """Create network offering""" + + cmd = createNetworkOffering.createNetworkOfferingCmd() + cmd.displaytext = services["displaytext"] + cmd.name = services["name"] + cmd.guestiptype = services["guestiptype"] + cmd.supportedservices = services["supportedservices"] + cmd.traffictype = services["traffictype"] + + cmd.serviceProviderList = [] + for service, provider in services["serviceProviderList"].items(): + cmd.serviceProviderList.append({ + 'service' : service, + 'provider': provider + }) + + [setattr(cmd, k, v) for k, v in kwargs.items()] + + return NetworkOffering(apiclient.createNetworkOffering(cmd).__dict__) + + def delete(self, apiclient): + """Delete network offering""" + cmd = deleteNetworkOffering.deleteNetworkOfferingCmd() + cmd.id = self.id + apiclient.deleteNetworkOffering(cmd) + return + + def update(self, apiclient, **kwargs): + """Lists all available network offerings.""" + + cmd = updateNetworkOffering.updateNetworkOfferingCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.updateNetworkOffering(cmd)) + + @classmethod + def list(cls, apiclient, **kwargs): + """Lists all available network offerings.""" + + cmd = listNetworkOfferings.listNetworkOfferingsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listNetworkOfferings(cmd)) + + class SnapshotPolicy: """Manage snapshot policies""" @@ -934,16 +1029,26 @@ class LoadBalancerRule: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, ipaddressid, accountid=None): + def create(cls, apiclient, services, ipaddressid, accountid=None, + projectid=None): """Create Load balancing Rule""" cmd = createLoadBalancerRule.createLoadBalancerRuleCmd() cmd.publicipid = ipaddressid or services["ipaddressid"] - cmd.account = accountid or services["account"] + + if accountid: + cmd.account = accountid + elif "account" in services: + cmd.account = services["account"] + cmd.name = services["name"] cmd.algorithm = services["alg"] cmd.privateport = services["privateport"] cmd.publicport = services["publicport"] + + if projectid: + cmd.projectid = projectid + return LoadBalancerRule(apiclient.createLoadBalancerRule(cmd).__dict__) def delete(self, apiclient): @@ -1162,17 +1267,42 @@ class Network: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, accountid=None, domainid=None): + def create(cls, apiclient, services, accountid=None, domainid=None, + networkofferingid=None, projectid=None, zoneid=None): """Create Network for account""" cmd = createNetwork.createNetworkCmd() cmd.name = services["name"] cmd.displaytext = services["displaytext"] - cmd.networkofferingid = services["networkoffering"] - cmd.zoneid = services["zoneid"] + + if networkofferingid: + cmd.networkofferingid = networkofferingid + elif "networkoffering" in services: + cmd.networkofferingid = services["networkoffering"] + + if zoneid: + cmd.zoneid = zoneid + elif "zoneid" in services: + cmd.zoneid = services["zoneid"] + + if "gateway" in services: + cmd.gateway = services["gateway"] + if "netmask" in services: + cmd.netmask = services["netmask"] + if "startip" in services: + cmd.startip = services["startip"] + if "endip" in services: + cmd.endip = services["endip"] + if "vlan" in services: + cmd.vlan = services["vlan"] + if "acltype" in services: + cmd.acltype = services["acltype"] + if accountid: cmd.account = accountid if domainid: cmd.domainid = domainid + if projectid: + cmd.projectid = projectid return Network(apiclient.createNetwork(cmd).__dict__) @@ -1199,7 +1329,8 @@ class Vpn: self.__dict__.update(items) @classmethod - def create(cls, apiclient, publicipid, account=None, domainid=None): + def create(cls, apiclient, publicipid, account=None, domainid=None, + projectid=None): """Create VPN for Public IP address""" cmd = createRemoteAccessVpn.createRemoteAccessVpnCmd() cmd.publicipid = publicipid @@ -1207,7 +1338,8 @@ class Vpn: cmd.account = account if domainid: cmd.domainid = domainid - + if projectid: + cmd.projectid = projectid return Vpn(apiclient.createRemoteAccessVpn(cmd).__dict__) def delete(self, apiclient): @@ -1225,7 +1357,8 @@ class VpnUser: self.__dict__.update(items) @classmethod - def create(cls, apiclient, username, password, account=None, domainid=None): + def create(cls, apiclient, username, password, account=None, domainid=None, + projectid=None): """Create VPN user""" cmd = addVpnUser.addVpnUserCmd() cmd.username = username @@ -1235,7 +1368,8 @@ class VpnUser: cmd.account = account if domainid: cmd.domainid = domainid - + if projectid: + cmd.projectid = projectid return VpnUser(apiclient.addVpnUser(cmd).__dict__) def delete(self, apiclient): @@ -1442,7 +1576,7 @@ class SecurityGroup: @classmethod def create(cls, apiclient, services, account=None, domainid=None, - description=None): + description=None, projectid=None): """Create security group""" cmd = createSecurityGroup.createSecurityGroupCmd() @@ -1453,7 +1587,9 @@ class SecurityGroup: cmd.domainid=domainid if description: cmd.description=description - + if projectid: + cmd.projectid = projectid + return SecurityGroup(apiclient.createSecurityGroup(cmd).__dict__) def delete(self, apiclient): @@ -1464,7 +1600,7 @@ class SecurityGroup: apiclient.deleteSecurityGroup(cmd) def authorize(self, apiclient, services, - account=None, domainid=None): + account=None, domainid=None, projectid=None): """Authorize Ingress Rule""" cmd=authorizeSecurityGroupIngress.authorizeSecurityGroupIngressCmd() @@ -1473,7 +1609,9 @@ class SecurityGroup: cmd.domainid = domainid if account: cmd.account = account - + + if projectid: + cmd.projectid = projectid cmd.securitygroupid=self.id cmd.protocol=services["protocol"] @@ -1500,4 +1638,144 @@ class SecurityGroup: cmd = listSecurityGroups.listSecurityGroupsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return(apiclient.listSecurityGroups(cmd)) \ No newline at end of file + return(apiclient.listSecurityGroups(cmd)) + +class Project: + """Manage Project life cycle""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def create(cls, apiclient, services, account=None, domainid=None): + """Create project""" + + cmd = createProject.createProjectCmd() + cmd.displaytext = services["displaytext"] + cmd.name = "-".join([services["name"], random_gen()]) + if account: + cmd.account = account + if domainid: + cmd.domainid = domainid + + return Project(apiclient.createProject(cmd).__dict__) + + def delete(self, apiclient): + """Delete Project""" + + cmd = deleteProject.deleteProjectCmd() + cmd.id = self.id + apiclient.deleteProject(cmd) + + def update(self, apiclient, **kwargs): + """Updates the project""" + + cmd = updateProject.updateProjectCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return apiclient.updateProject(cmd) + + def activate(self, apiclient): + """Activates the suspended project""" + + cmd = activateProject.activateProjectCmd() + cmd.id = self.id + return apiclient.activateProject(cmd) + + def suspend(self, apiclient): + """Suspend the active project""" + + cmd = suspendProject.suspendProjectCmd() + cmd.id = self.id + return apiclient.suspendProject(cmd) + + def addAccount(self, apiclient, account=None, email=None): + """Add account to project""" + + cmd = addAccountToProject.addAccountToProjectCmd() + cmd.projectid = self.id + if account: + cmd.account = account + if email: + cmd.email = email + return apiclient.addAccountToProject(cmd) + + def deleteAccount(self, apiclient, account): + """Delete account from project""" + + cmd = deleteAccountFromProject.deleteAccountFromProjectCmd() + cmd.projectid = self.id + cmd.account = account + return apiclient.deleteAccountFromProject(cmd) + + @classmethod + def listAccounts(cls, apiclient, **kwargs): + """Lists all accounts associated with projects.""" + + cmd = listProjectAccounts.listProjectAccountsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listProjectAccounts(cmd)) + + @classmethod + def list(cls, apiclient, **kwargs): + """Lists all projects.""" + + cmd = listProjects.listProjectsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listProjects(cmd)) + +class ProjectInvitation: + """Manage project invitations""" + + def __init__(self, items): + self.__dict__.update(items) + + @classmethod + def update(cls, apiclient, projectid, accept, account=None, token=None): + """Updates the project invitation for that account""" + + cmd = updateProjectInvitation.updateProjectInvitationCmd() + cmd.projectid = projectid + cmd.accept = accept + if account: + cmd.account = account + if token: + cmd.token = token + + return (apiclient.updateProjectInvitation(cmd).__dict__) + + def delete(self, apiclient, id): + """Deletes the project invitation""" + + cmd = deleteProjectInvitation.deleteProjectInvitationCmd() + cmd.id = id + return apiclient.deleteProjectInvitation(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """Lists project invitations""" + + cmd = listProjectInvitations.listProjectInvitationsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listProjectInvitations(cmd)) + + +class Configurations: + """Manage Configuration""" + + @classmethod + def update(cls, apiclient, name, value=None): + """Updates the specified configuration""" + + cmd = updateConfiguration.updateConfigurationCmd() + cmd.name = name + cmd.value = value + apiclient.updateConfiguration(cmd) + + @classmethod + def list(cls, apiclient, **kwargs): + """Lists configurations""" + + cmd = listConfigurations.listConfigurationsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listConfigurations(cmd)) \ No newline at end of file diff --git a/tools/testClient/testcase/libs/common.py b/tools/testClient/testcase/libs/common.py index 9ed527a8353..1270a7c87cb 100644 --- a/tools/testClient/testcase/libs/common.py +++ b/tools/testClient/testcase/libs/common.py @@ -227,7 +227,7 @@ def download_builtin_templates(apiclient, zoneid, hypervisor, host, linklocalip, return def update_resource_limit(apiclient, resourcetype, account=None, domainid=None, - max=None): + max=None, projectid=None): """Updates the resource limit to 'max' for given account""" cmd = updateResourceLimit.updateResourceLimitCmd() @@ -238,6 +238,8 @@ def update_resource_limit(apiclient, resourcetype, account=None, domainid=None, cmd.domainid = domainid if max: cmd.max = max + if projectid: + cmd.projectid = projectid apiclient.updateResourceLimit(cmd) return @@ -451,4 +453,11 @@ def list_network_offerings(apiclient, **kwargs): cmd = listNetworkOfferings.listNetworkOfferingsCmd() [setattr(cmd, k, v) for k, v in kwargs.items()] - return(apiclient.listNetworkOfferings(cmd)) \ No newline at end of file + return(apiclient.listNetworkOfferings(cmd)) + +def list_resource_limits(apiclient, **kwargs): + """Lists resource limits""" + + cmd = listResourceLimits.listResourceLimitsCmd() + [setattr(cmd, k, v) for k, v in kwargs.items()] + return(apiclient.listResourceLimits(cmd)) \ No newline at end of file diff --git a/tools/testClient/testcase/libs/utils.py b/tools/testClient/testcase/libs/utils.py index 9b6b05e785f..c542a3e96ad 100644 --- a/tools/testClient/testcase/libs/utils.py +++ b/tools/testClient/testcase/libs/utils.py @@ -15,6 +15,72 @@ import configGenerator import logging import string import random +import imaplib +import email +import datetime + +def restart_mgmt_server(server): + """Restarts the management server""" + + try: + # Get the SSH client + ssh = is_server_ssh_ready( + server["ipaddress"], + server["port"], + server["username"], + server["password"], + ) + result = ssh.execute("/etc/init.d/cloud-management restart") + res = str(result) + # Server Stop - OK + # Server Start - OK + if res.count("OK") != 2: + raise ("ErrorInReboot!") + except Exception as e: + raise e + return + +def fetch_latest_mail(services, from_mail): + """Fetch mail""" + + # Login to mail server to verify email + mail = imaplib.IMAP4_SSL(services["server"]) + mail.login( + services["email"], + services["password"] + ) + mail.list() + mail.select(services["folder"]) + date = (datetime.date.today() - datetime.timedelta(1)).strftime("%d-%b-%Y") + + result, data = mail.uid( + 'search', + None, + '(SENTSINCE {date} HEADER FROM "{mail}")'.format( + date=date, + mail=from_mail + ) + ) + # Return False if email is not present + if data == []: + return False + + latest_email_uid = data[0].split()[-1] + result, data = mail.uid('fetch', latest_email_uid, '(RFC822)') + raw_email = data[0][1] + email_message = email.message_from_string(raw_email) + result = get_first_text_block(email_message) + return result + +def get_first_text_block(email_message_instance): + """fetches first text block from the mail""" + maintype = email_message_instance.get_content_maintype() + if maintype == 'multipart': + for part in email_message_instance.get_payload(): + if part.get_content_maintype() == 'text': + return part.get_payload() + elif maintype == 'text': + return email_message_instance.get_payload() def random_gen(size=6, chars=string.ascii_uppercase + string.digits): """Generate Random Strings of variable length"""