From ce59b31c8d924b74ff03ad486a5f30c9de618ee7 Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Mon, 27 Aug 2012 10:37:56 -0700 Subject: [PATCH] Additional tests in various areas --- test/integration/component/test_accounts.py | 935 +++++++++++++++++- .../component/test_network_offering.py | 131 ++- .../component/test_project_limits.py | 193 +++- .../component/test_resource_limits.py | 203 +++- test/integration/component/test_volumes.py | 144 ++- test/integration/lib/base.py | 59 +- 6 files changed, 1579 insertions(+), 86 deletions(-) diff --git a/test/integration/component/test_accounts.py b/test/integration/component/test_accounts.py index 594ac283586..641f6fd139c 100644 --- a/test/integration/component/test_accounts.py +++ b/test/integration/component/test_accounts.py @@ -22,8 +22,7 @@ from marvin.cloudstackAPI import * from integration.lib.utils import * from integration.lib.base import * from integration.lib.common import * -from marvin.remoteSSHClient import remoteSSHClient -from nose.plugins.attrib import attr +from marvin import remoteSSHClient import datetime @@ -43,7 +42,7 @@ class Services: "username": "test", # Random characters are appended for unique # username - "password": "password", + "password": "fr3sca", }, "user": { "email": "user@test.com", @@ -52,14 +51,16 @@ class Services: "username": "User", # Random characters are appended for unique # username - "password": "password", + "password": "fr3sca", }, "service_offering": { "name": "Tiny Instance", "displaytext": "Tiny Instance", "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "cpuspeed": 100, + # in MHz + "memory": 64, + # In MBs }, "virtual_machine": { "displayname": "Test VM", @@ -76,7 +77,7 @@ class Services: "template": { "displaytext": "Public Template", "name": "Public template", - "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', + "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', "url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2", "hypervisor": 'XenServer', "format": 'VHD', @@ -84,7 +85,12 @@ class Services: "ispublic": True, "isextractable": True, }, - "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', + "natrule": { + "publicport": 22, + "privateport": 22, + "protocol": 'TCP', + }, + "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, @@ -96,7 +102,10 @@ class TestAccounts(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAccounts, cls).getClsTestClient().getApiClient() + 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) @@ -138,12 +147,11 @@ class TestAccounts(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_01_create_account(self): """Test Create Account and user for that account """ - # Validate the following # 1. Create an Account. Verify the account is created. # 2. Create User associated with that account. Verify the created user @@ -223,7 +231,10 @@ class TestRemoveUserFromAccount(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestRemoveUserFromAccount, cls).getClsTestClient().getApiClient() + 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) @@ -273,12 +284,11 @@ class TestRemoveUserFromAccount(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_01_user_remove_VM_running(self): """Test Remove one user from the account """ - # Validate the following # 1. Create an account with 2 users. # 2. Start 2 VMs; one for each user of the account @@ -375,12 +385,11 @@ class TestRemoveUserFromAccount(cloudstackTestCase): return @unittest.skip("Open Questions") - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_02_remove_all_users(self): """Test Remove both users from the account """ - # Validate the following # 1. Remove both the users from the account. # 2. Verify account is removed @@ -489,7 +498,10 @@ class TestNonRootAdminsPrivileges(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestNonRootAdminsPrivileges, cls).getClsTestClient().getApiClient() + cls.api_client = super( + TestNonRootAdminsPrivileges, + cls + ).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone settings cls.zone = get_zone(cls.api_client, cls.services) @@ -534,11 +546,10 @@ class TestNonRootAdminsPrivileges(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_01_non_root_admin_Privileges(self): """Test to verify Non Root admin previleges""" - # Validate the following # 1. Create few accounts/users in ROOT domain # 2. Verify listAccounts API gives only accounts associated with new @@ -588,7 +599,10 @@ class TestServiceOfferingSiblings(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestServiceOfferingSiblings, cls).getClsTestClient().getApiClient() + cls.api_client = super( + TestServiceOfferingSiblings, + cls + ).getClsTestClient().getApiClient() cls.services = Services().services # Create Domains, accounts etc @@ -653,11 +667,10 @@ class TestServiceOfferingSiblings(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_01_service_offering_siblings(self): """Test to verify service offerings at same level in hierarchy""" - # Validate the following # 1. Verify service offering is visible for domain_1 # 2. Verify service offering is not visible for domain_2 @@ -703,7 +716,10 @@ class TestServiceOfferingHierarchy(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestServiceOfferingHierarchy, cls).getClsTestClient().getApiClient() + cls.api_client = super( + TestServiceOfferingHierarchy, + cls + ).getClsTestClient().getApiClient() cls.services = Services().services # Create domain, service offerings etc @@ -769,11 +785,10 @@ class TestServiceOfferingHierarchy(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_01_service_offering_hierarchy(self): """Test to verify service offerings at same level in hierarchy""" - # Validate the following # 1. Verify service offering is visible for domain_1 # 2. Verify service offering is also visible for domain_2 @@ -830,7 +845,9 @@ class TesttemplateHierarchy(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TesttemplateHierarchy, cls).getClsTestClient().getApiClient() + cls.api_client = super( + TesttemplateHierarchy, + cls).getClsTestClient().getApiClient() cls.services = Services().services # Get Zone settings cls.zone = get_zone(cls.api_client, cls.services) @@ -901,11 +918,10 @@ class TesttemplateHierarchy(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_01_template_hierarchy(self): """Test to verify template at same level in hierarchy""" - # Validate the following # 1. Verify template is visible for domain_1 # 2. Verify template is also visible for domain_2 @@ -968,7 +984,10 @@ class TestAddVmToSubDomain(cloudstackTestCase): @classmethod def setUpClass(cls): - cls.api_client = super(TestAddVmToSubDomain, cls).getClsTestClient().getApiClient() + cls.api_client = super( + TestAddVmToSubDomain, + cls + ).getClsTestClient().getApiClient() cls.services = Services().services # Setup working Environment- Create domain, zone, pod cluster etc. @@ -1031,11 +1050,11 @@ class TestAddVmToSubDomain(cloudstackTestCase): serviceofferingid=cls.service_offering.id ) cls._cleanup = [ - cls.account_2, - cls.account_1, - cls.sub_domain, - cls.service_offering - ] + cls.account_2, + cls.account_1, + cls.sub_domain, + cls.service_offering + ] return @classmethod @@ -1044,7 +1063,6 @@ class TestAddVmToSubDomain(cloudstackTestCase): #Clean up, terminate the created resources cleanup_resources(cls.api_client, cls._cleanup) except Exception as e: - raise Exception("Warning: Exception during cleanup : %s" % e) return @@ -1062,12 +1080,11 @@ class TestAddVmToSubDomain(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "eip", "advancedns", "sg"]) + @attr(tags=["advanced", "basic", "eip", "advancedns", "sg"]) def test_01_add_vm_to_subdomain(self): """ Test Sub domain allowed to launch VM when a Domain level zone is created""" - # Validate the following # 1. Verify VM created by Account_1 is in Running state # 2. Verify VM created by Account_2 is in Running state @@ -1113,3 +1130,847 @@ class TestAddVmToSubDomain(cloudstackTestCase): "Check State of Virtual machine" ) return + + +class TestUserDetails(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestUserDetails, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain etc + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=[ + "role", + "accounts", + "simulator", + "advanced", + "advancedns", + "basic", + "eip", + "sg" + ]) + def test_updateUserDetails(self): + """Test user update API + """ + + # Steps for test scenario + # 1. create a user account + # 2. update the user details (firstname, lastname, user) with + # updateUser API + # 3. listUsers in the account + # 4. delete the account + # Validate the following + # 1. listAccounts should show account created successfully + # 2. updateUser API should return valid response + # 3. user should be updated with new details + + self.debug("Creating an user account..") + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.cleanup.append(self.account) + + # Fetching the user details of account + self.debug( + "Fetching user details for account: %s" % + self.account.account.name) + users = User.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(users, list), + True, + "List users should return a valid list for account" + ) + user_1 = users[0] + self.debug("Updating the details of user: %s" % user_1.name) + firstname = random_gen() + lastname = random_gen() + + self.debug("New firstname: %s, lastname: %s" % (firstname, lastname)) + User.update( + self.apiclient, + user_1.id, + firstname=firstname, + lastname=lastname + ) + + # Fetching the user details of account + self.debug( + "Fetching user details for user: %s" % user_1.name) + users = User.list( + self.apiclient, + id=user_1.id, + listall=True + ) + + self.assertEqual( + isinstance(users, list), + True, + "List users should return a valid list for account" + ) + user_1 = users[0] + self.assertEqual( + user_1.firstname, + firstname, + "User's first name should be updated with new one" + ) + self.assertEqual( + user_1.lastname, + lastname, + "User's last name should be updated with new one" + ) + return + + @attr(tags=[ + "role", + "accounts", + "simulator", + "advanced", + "advancedns", + "basic", + "eip", + "sg" + ]) + def test_updateAdminDetails(self): + """Test update admin details + """ + + # Steps for test scenario + # 1. create a admin account + # 2. update the user details (firstname, lastname, user) with + # updateUser API + # 3. listUsers in the account + # 4. delete the account + # Validate the following + # 1. listAccounts should show account created successfully + # 2. updateUser API should return valid response + # 3. user should be updated with new details + + self.debug("Creating a ROOT admin account") + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + ) + self.cleanup.append(self.account) + + # Fetching the user details of account + self.debug( + "Fetching user details for account: %s" % + self.account.account.name) + users = User.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(users, list), + True, + "List users should return a valid list for account" + ) + user_1 = users[0] + self.debug("Updating the details of user: %s" % user_1.name) + firstname = random_gen() + lastname = random_gen() + + self.debug("New firstname: %s, lastname: %s" % (firstname, lastname)) + User.update( + self.apiclient, + user_1.id, + firstname=firstname, + lastname=lastname + ) + + # Fetching the user details of account + self.debug( + "Fetching user details for user: %s" % user_1.name) + users = User.list( + self.apiclient, + id=user_1.id, + listall=True + ) + + self.assertEqual( + isinstance(users, list), + True, + "List users should return a valid list for account" + ) + user_1 = users[0] + self.assertEqual( + user_1.firstname, + firstname, + "User's first name should be updated with new one" + ) + self.assertEqual( + user_1.lastname, + lastname, + "User's last name should be updated with new one" + ) + return + + @attr(tags=[ + "role", + "accounts", + "simulator", + "advanced", + "advancedns", + "basic", + "eip", + "sg" + ]) + def test_updateDomainAdminDetails(self): + """Test update domain admin details + """ + + # Steps for test scenario + # 2. update the user details (firstname, lastname, user) with + # updateUser API + # 3. listUsers in the account + # 4. delete the account + # Validate the following + # 1. listAccounts should show account created successfully + # 2. updateUser API should return valid response + # 3. user should be updated with new details + + self.debug("Creating a domain admin account") + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup.append(self.account) + + # Fetching the user details of account + self.debug( + "Fetching user details for account: %s" % + self.account.account.name) + users = User.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(users, list), + True, + "List users should return a valid list for account" + ) + user_1 = users[0] + self.debug("Updating the details of user: %s" % user_1.name) + firstname = random_gen() + lastname = random_gen() + + self.debug("New firstname: %s, lastname: %s" % (firstname, lastname)) + User.update( + self.apiclient, + user_1.id, + firstname=firstname, + lastname=lastname + ) + + # Fetching the user details of account + self.debug( + "Fetching user details for user: %s" % user_1.name) + users = User.list( + self.apiclient, + id=user_1.id, + listall=True + ) + + self.assertEqual( + isinstance(users, list), + True, + "List users should return a valid list for account" + ) + user_1 = users[0] + self.assertEqual( + user_1.firstname, + firstname, + "User's first name should be updated with new one" + ) + self.assertEqual( + user_1.lastname, + lastname, + "User's last name should be updated with new one" + ) + return + +@unittest.skip("Login API response returns nothing") +class TestUserLogin(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestUserLogin, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain etc + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["login", "accounts", "simulator", "advanced", + "advancedns", "basic", "eip", "sg"]) + def test_LoginApiUuidResponse(self): + """Test if Login API does not return UUID's + """ + + # Steps for test scenario + # 1. create a user account + # 2. login to the user account with given credentials (loginCmd) + # 3. delete the user account + # Validate the following + # 1. listAccounts should return account created + # 2. loginResponse should have UUID only is response. Assert by + # checking database id is not same as response id + # Login also succeeds with non NULL sessionId in response + + self.debug("Creating an user account..") + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.cleanup.append(self.account) + + self.debug("Logging into the cloudstack with login API") + respose = User.login( + self.apiclient, + username=self.account.account.name, + password=self.services["account"]["password"] + ) + self.assertEqual(respose, None, "Login response should not be none") + self.debug("Login API response: %s" % respose) + + self.assertNotEqual( + respose.sessionkey, + None, + "Login to the CloudStack should be successful" + + "response shall have non Null key" + ) + return + + @attr(tags=["login", "accounts", "simulator", "advanced", + "advancedns", "basic", "eip", "sg"]) + def test_LoginApiDomain(self): + """Test login API with domain + """ + + # Steps for test scenario + # 1. create a domain + # 2. create user in the domain + # 3. login to the user account above using UUID domain/user + # 4. delete the user account + # Validate the following + # 1. listDomains returns created domain + # 2. listAccounts returns created user + # 3. loginResponse should have UUID only in responses + # Login also succeeds with non NULL sessionId in response + + self.debug("Creating a domain for login with API domain test") + domain = Domain.create( + self.apiclient, + self.services["domain"], + parentdomainid=self.domain.id + ) + self.debug("Domain: %s is created succesfully." % domain.name) + self.debug( + "Checking if the created domain is listed in list domains API") + domains = Domain.list(self.apiclient, id=domain.id, listall=True) + + self.assertEqual( + isinstance(domains, list), + True, + "List domains shall return a valid response" + ) + self.debug("Creating an user account in domain: %s" % domain.name) + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=domain.id + ) + self.cleanup.append(self.account) + + accounts = Account.list( + self.apiclient, + name=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + + self.assertEqual( + isinstance(accounts, list), + True, + "List accounts should return a valid response" + ) + + self.debug("Logging into the cloudstack with login API") + respose = User.login( + self.apiclient, + username=self.account.account.name, + password=self.services["account"]["password"] + ) + self.assertEqual(respose, None, "Login response should not be none") + self.debug("Login API response: %s" % respose) + + self.assertNotEqual( + respose.sessionkey, + None, + "Login to the CloudStack should be successful" + + "response shall have non Null key" + ) + return + + +class TestDomainForceRemove(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDomainForceRemove, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + + # Setup working Environment- Create domain, zone, pod cluster etc. + cls.domain = get_domain( + cls.api_client, + cls.services + ) + cls.zone = get_zone( + cls.api_client, + cls.services, + ) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + #Clean up, terminate the created resources + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created resources + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["domains", "advanced", "advancedns", "simulator"]) + def test_forceDeleteDomain(self): + """ Test delete domain with force option""" + + # Steps for validations + # 1. create a domain DOM + # 2. create 2 users under this domain + # 3. deploy 1 VM into each of these user accounts + # 4. create PF / FW rules for port 22 on these VMs for their + # respective accounts + # 5. delete the domain with force=true option + # Validate the following + # 1. listDomains should list the created domain + # 2. listAccounts should list the created accounts + # 3. listvirtualmachines should show the Running VMs + # 4. PF and FW rules should be shown in listFirewallRules + # 5. domain should delete successfully and above three list calls + # should show all the resources now deleted. listRouters should + # not return any routers in the deleted accounts/domains + + self.debug("Creating a domain for login with API domain test") + domain = Domain.create( + self.apiclient, + self.services["domain"], + parentdomainid=self.domain.id + ) + self.debug("Domain is created succesfully.") + self.debug( + "Checking if the created domain is listed in list domains API") + domains = Domain.list(self.apiclient, id=domain.id, listall=True) + + self.assertEqual( + isinstance(domains, list), + True, + "List domains shall return a valid response" + ) + self.debug("Creating 2 user accounts in domain: %s" % domain.name) + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + domainid=domain.id + ) + + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + domainid=domain.id + ) + + self.debug("Creating a tiny service offering for VM deployment") + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"], + domainid=self.domain.id + ) + + self.debug("Deploying virtual machine in account 1: %s" % + self.account_1.account.name) + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + + self.debug("Deploying virtual machine in account 2: %s" % + self.account_2.account.name) + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + + networks = Network.list( + self.apiclient, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response" + ) + network_1 = networks[0] + self.debug("Default network in account 1: %s is %s" % ( + self.account_1.account.name, + network_1.name)) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=network_1.id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + vm_1, + self.services["natrule"], + ipaddressid=src_nat.id + ) + self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress) + + nat_rules = NATRule.list(self.apiclient, id=nat_rule.id) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT should return a valid port forwarding rules" + ) + + self.assertNotEqual( + len(nat_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + + self.debug("Deleting domain with force option") + try: + domain.delete(self.apiclient, cleanup=True) + except Exception as e: + self.fail("Failed to delete domain: %s" % e) + + self.debug("Waiting for account.cleanup.interval" + + " to cleanup any remaining resouces") + + configurations = Configurations.list( + self.apiclient, + name="account.cleanup.interval", + listall=True + ) + self.debug("account.cleanup.interval: %s" % + int(configurations[0].value)) + # Sleep to ensure that all resources are deleted + time.sleep(int(configurations[0].value) * 2) + self.debug("Checking if the resources in domain are deleted or not..") + accounts = Account.list( + self.apiclient, + name=self.account_1.account.name, + domainid=self.account_1.account.domainid, + listall=True + ) + + self.assertEqual( + accounts, + None, + "Account should get automatically deleted after domain removal" + ) + return + + @attr(tags=["domains", "advanced", "advancedns", "simulator"]) + def test_DeleteDomain(self): + """ Test delete domain with force option""" + + # Steps for validations + # 1. create a domain DOM + # 2. create 2 users under this domain + # 3. deploy 1 VM into each of these user accounts + # 4. create PF / FW rules for port 22 on these VMs for their + # respective accounts + # 5. delete the domain with force=false option + # Validate the following + # 1. listDomains should list the created domain + # 2. listAccounts should list the created accounts + # 3. listvirtualmachines should show the Running VMs + # 4. PF and FW rules should be shown in listFirewallRules + # 5. domain deletion should fail saying there are resources under use + + self.debug("Creating a domain for login with API domain test") + domain = Domain.create( + self.apiclient, + self.services["domain"], + parentdomainid=self.domain.id + ) + self._cleanup.append(domain) + self.debug("Domain: %s is created successfully." % domain.name) + self.debug( + "Checking if the created domain is listed in list domains API") + domains = Domain.list(self.apiclient, id=domain.id, listall=True) + + self.assertEqual( + isinstance(domains, list), + True, + "List domains shall return a valid response" + ) + self.debug("Creating 2 user accounts in domain: %s" % domain.name) + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + domainid=domain.id + ) + self.cleanup.append(self.account_1) + + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + domainid=domain.id + ) + self.cleanup.append(self.account_2) + + self.debug("Creating a tiny service offering for VM deployment") + self.service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering"], + domainid=self.domain.id + ) + self.cleanup.append(self.service_offering) + + self.debug("Deploying virtual machine in account 1: %s" % + self.account_1.account.name) + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id + ) + + self.debug("Deploying virtual machine in account 2: %s" % + self.account_2.account.name) + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id + ) + + networks = Network.list( + self.apiclient, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response" + ) + network_1 = networks[0] + self.debug("Default network in account 1: %s is %s" % ( + self.account_1.account.name, + network_1.name)) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=network_1.id, + account=self.account_1.account.name, + domainid=self.account_1.account.domainid, + listall=True, + issourcenat=True, + ) + self.assertEqual( + isinstance(src_nat_list, list), + True, + "List Public IP should return a valid source NAT" + ) + self.assertNotEqual( + len(src_nat_list), + 0, + "Length of response from listPublicIp should not be 0" + ) + + src_nat = src_nat_list[0] + + self.debug( + "Trying to create a port forwarding rule in source NAT: %s" % + src_nat.ipaddress) + #Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + vm_1, + self.services["natrule"], + ipaddressid=src_nat.id + ) + self.debug("Created PF rule on source NAT: %s" % src_nat.ipaddress) + + nat_rules = NATRule.list(self.apiclient, id=nat_rule.id) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT should return a valid port forwarding rules" + ) + + self.assertNotEqual( + len(nat_rules), + 0, + "Length of response from listLbRules should not be 0" + ) + + self.debug("Deleting domain without force option") + with self.assertRaises(Exception): + domain.delete(self.apiclient, cleanup=False) + return diff --git a/test/integration/component/test_network_offering.py b/test/integration/component/test_network_offering.py index 135c4949222..35cc01129ce 100644 --- a/test/integration/component/test_network_offering.py +++ b/test/integration/component/test_network_offering.py @@ -92,6 +92,7 @@ class Services: "network": { "name": "Test Network", "displaytext": "Test Network", + "vlan": 2370, }, "lbrule": { "name": "SSH", @@ -137,7 +138,7 @@ class Services: "publicport": 22, "protocol": 'TCP', }, - "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', + "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, @@ -1811,3 +1812,131 @@ class TestNetworkUpgrade(cloudstackTestCase): changecidr=True ) return + + +@unittest.skip("Skipped since shared network requires StartIp/endIp/gateway/netmask") +class TestSharedNetworkWithoutIp(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestSharedNetworkWithoutIp, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + self.account.delete(self.apiclient) + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced", "advancedns", "simulator", "network", "api"]) + def test_deployVmSharedNetworkWithoutIpRange(self): + """Test deployVM in shared network without startIp/endIp + """ + + # Steps for validation + # 1. create a shared network using shared network offering but do not + # specify startIp/endIp arguments + # 2. create an account + # 3. deploy a VM in this account using the above network + # Validate the following + # 1. listNetworks should return the created network + # 2. listAccounts to return the created account + # 3. VM deployment should succeed and NIC is in networks address space + # 4. delete the account + + self.debug( + "Fetching default shared network offering from nw offerings") + network_offerings = NetworkOffering.list( + self.apiclient, + listall=True, + guestiptype="Shared", + name="DefaultSharedNetworkOffering", + displaytext="Offering for Shared networks" + ) + self.assertEqual( + isinstance(network_offerings, list), + True, + "Nw offerings should have atleast a shared nw offering" + ) + shared_nw_off = network_offerings[0] + self.debug("Shared netwrk offering: %s" % shared_nw_off.name) + + self.debug("Creating a network from shared network offering") + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=shared_nw_off.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + try: + # Spawn an instance in that network + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + except Exception as e: + self.fail("Deply Vm in shared network failed! - %s" % e) + return diff --git a/test/integration/component/test_project_limits.py b/test/integration/component/test_project_limits.py index 2c6b7716403..c1ef86aade8 100644 --- a/test/integration/component/test_project_limits.py +++ b/test/integration/component/test_project_limits.py @@ -62,8 +62,8 @@ class Services: "name": "Tiny Instance", "displaytext": "Tiny Instance", "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "cpuspeed": 100, # in MHz + "memory": 64, # In MBs }, "disk_offering": { "displaytext": "Tiny Disk Offering", @@ -89,7 +89,30 @@ class Services: "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', "templatefilter": 'self', }, - "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', + "network_offering": { + "name": 'Network offering-VR services', + "displaytext": 'Network offering-VR services', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + }, + "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, @@ -156,7 +179,7 @@ class TestProjectLimits(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) def test_01_project_limits(self): """ Test project limits """ @@ -303,7 +326,7 @@ class TestProjectLimits(cloudstackTestCase): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) @unittest.skip("No provision for updating resource limits from account through API") def test_02_project_limits_normal_user(self): """ Test project limits @@ -527,7 +550,7 @@ class TestResourceLimitsProject(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) def test_03_vm_per_project(self): """Test VM limit per project """ @@ -543,7 +566,7 @@ class TestResourceLimitsProject(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 0, # Instance + 0, # Instance max=2, projectid=self.project.id ) @@ -589,7 +612,7 @@ class TestResourceLimitsProject(cloudstackTestCase): ) return - @attr(tags = ["advanced", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "eip", "advancedns", "simulator"]) def test_04_publicip_per_project(self): """Test Public IP limit per project """ @@ -607,7 +630,7 @@ class TestResourceLimitsProject(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 1, # Public Ip + 1, # Public Ip max=2, projectid=self.project.id ) @@ -674,7 +697,7 @@ class TestResourceLimitsProject(cloudstackTestCase): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) def test_05_snapshots_per_project(self): """Test Snapshot limit per project """ @@ -691,7 +714,7 @@ class TestResourceLimitsProject(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 3, # Snapshot + 3, # Snapshot max=1, projectid=self.project.id ) @@ -751,7 +774,7 @@ class TestResourceLimitsProject(cloudstackTestCase): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns", "simulator"]) def test_06_volumes_per_project(self): """Test Volumes limit per project """ @@ -768,7 +791,7 @@ class TestResourceLimitsProject(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 2, # Volume + 2, # Volume max=2, projectid=self.project.id ) @@ -800,7 +823,7 @@ class TestResourceLimitsProject(cloudstackTestCase): ) return - @attr(tags = ["advanced", "basic", "sg", "eip", "advancedns"]) + @attr(tags=["advanced", "basic", "sg", "eip", "advancedns"]) def test_07_templates_per_project(self): """Test Templates limit per project """ @@ -813,7 +836,7 @@ class TestResourceLimitsProject(cloudstackTestCase): # Reset the volume limits update_resource_limit( self.apiclient, - 2, # Volume + 2, # Volume max=5, projectid=self.project.id ) @@ -823,7 +846,7 @@ class TestResourceLimitsProject(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 4, # Template + 4, # Template max=1, projectid=self.project.id ) @@ -884,3 +907,141 @@ class TestResourceLimitsProject(cloudstackTestCase): projectid=self.project.id ) return + + +class TestMaxProjectNetworks(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestMaxProjectNetworks, + 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.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + + cls._cleanup = [ + cls.service_offering, + cls.network_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.account.delete(self.apiclient) + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced", "advancedns", "simulator", + "api", "basic", "eip", "sg"]) + def test_maxAccountNetworks(self): + """Test Limit number of guest account specific networks + """ + + # Steps for validation + # 1. Fetch max.account.networks from configurations + # 2. Create an account. Create account more that max.accout.network + # 3. Create network should fail + + self.debug("Creating project with '%s' as admin" % + self.account.account.name) + # 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) + + config = Configurations.list( + self.apiclient, + name='max.project.networks', + listall=True + ) + self.assertEqual( + isinstance(config, list), + True, + "List configurations hsould have max.project.networks" + ) + + config_value = int(config[0].value) + self.debug("max.project.networks: %s" % config_value) + + for ctr in range(config_value): + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + self.apiclient, + self.services["network"], + projectid=project.id, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % network.id) + self.debug( + "Creating network in account already having networks : %s" % + config_value) + + with self.assertRaises(Exception): + Network.create( + self.apiclient, + self.services["network"], + projectid=project.id, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug('Create network failed (as expected)') + return diff --git a/test/integration/component/test_resource_limits.py b/test/integration/component/test_resource_limits.py index 98550492a8d..f182ed17bd0 100644 --- a/test/integration/component/test_resource_limits.py +++ b/test/integration/component/test_resource_limits.py @@ -49,8 +49,10 @@ class Services: "name": "Tiny Instance", "displaytext": "Tiny Instance", "cpunumber": 1, - "cpuspeed": 100, # in MHz - "memory": 64, # In MBs + "cpuspeed": 100, + # in MHz + "memory": 64, + # In MBs }, "disk_offering": { "displaytext": "Small", @@ -76,7 +78,30 @@ class Services: "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', "templatefilter": 'self', }, - "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', + "network_offering": { + "name": 'Network offering', + "displaytext": 'Network offering', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "test network", + "displaytext": "test network" + }, + "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', # Cent OS 5.3 (64 bit) "sleep": 60, "timeout": 10, @@ -153,7 +178,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator"]) def test_01_vm_per_account(self): """Test VM limit per account """ @@ -170,7 +195,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 0, # Instance + 0, # Instance account=self.account_1.account.name, domainid=self.account_1.account.domainid, max=1 @@ -246,7 +271,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator"]) def test_02_publicip_per_account(self): """Test Public IP limit per account """ @@ -266,7 +291,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 1, # Public Ip + 1, # Public Ip account=self.account_1.account.name, domainid=self.account_1.account.domainid, max=2 @@ -389,8 +414,8 @@ class TestResourceLimitsAccount(cloudstackTestCase): ) return - @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(speed="slow") + @attr(tags=["advanced", "advancedns", "simulator"]) def test_03_snapshots_per_account(self): """Test Snapshot limit per account """ @@ -410,7 +435,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 3, # Snapshot + 3, # Snapshot account=self.account_1.account.name, domainid=self.account_1.account.domainid, max=1 @@ -546,7 +571,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator"]) def test_04_volumes_per_account(self): """Test Volumes limit per account """ @@ -566,7 +591,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 2, # Volume + 2, # Volume account=self.account_1.account.name, domainid=self.account_1.account.domainid, max=2 @@ -688,7 +713,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns"]) def test_05_templates_per_account(self): """Test Templates limit per account """ @@ -706,7 +731,7 @@ class TestResourceLimitsAccount(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 4, # Template + 4, # Template account=self.account_1.account.name, domainid=self.account_1.account.domainid, max=1 @@ -918,7 +943,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): raise Exception("Warning: Exception during cleanup : %s" % e) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator"]) def test_01_vm_per_domain(self): """Test VM limit per domain """ @@ -935,7 +960,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 0, # Instance + 0, # Instance domainid=self.account.account.domainid, max=2 ) @@ -984,7 +1009,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator"]) def test_01_publicip_per_domain(self): """Test Public IP limit per domain """ @@ -1003,7 +1028,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 1, # Public Ip + 1, # Public Ip domainid=self.account.account.domainid, max=2 ) @@ -1054,8 +1079,8 @@ class TestResourceLimitsDomain(cloudstackTestCase): ) return - @attr(speed = "slow") - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(speed="slow") + @attr(tags=["advanced", "advancedns", "simulator"]) def test_03_snapshots_per_domain(self): """Test Snapshot limit per domain """ @@ -1075,7 +1100,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 3, # Snapshot + 3, # Snapshot domainid=self.account.account.domainid, max=1 ) @@ -1138,7 +1163,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns", "simulator"]) + @attr(tags=["advanced", "advancedns", "simulator"]) def test_04_volumes_per_domain(self): """Test Volumes limit per domain """ @@ -1157,7 +1182,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 2, # Volume + 2, # Volume domainid=self.account.account.domainid, max=2 ) @@ -1191,7 +1216,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): ) return - @attr(tags = ["advanced", "advancedns"]) + @attr(tags=["advanced", "advancedns"]) def test_05_templates_per_domain(self): """Test Templates limit per domain """ @@ -1207,7 +1232,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 2, # Volume + 2, # Volume domainid=self.account.account.domainid, max=5 ) @@ -1218,7 +1243,7 @@ class TestResourceLimitsDomain(cloudstackTestCase): # Set usage_vm=1 for Account 1 update_resource_limit( self.apiclient, - 4, # Template + 4, # Template domainid=self.account.account.domainid, max=2 ) @@ -1300,3 +1325,129 @@ class TestResourceLimitsDomain(cloudstackTestCase): ) return + +class TestMaxAccountNetworks(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestMaxAccountNetworks, + 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.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + + cls._cleanup = [ + cls.service_offering, + cls.network_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + self.account.delete(self.apiclient) + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) * 2) + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags=["advanced", "advancedns", "simulator", + "api", "basic", "eip", "sg"]) + def test_maxAccountNetworks(self): + """Test Limit number of guest account specific networks + """ + + # Steps for validation + # 1. Fetch max.account.networks from configurations + # 2. Create an account. Create account more that max.accout.network + # 3. Create network should fail + + config = Configurations.list( + self.apiclient, + name='max.account.networks', + listall=True + ) + self.assertEqual( + isinstance(config, list), + True, + "List configurations should have max.account.networks" + ) + + config_value = int(config[0].value) + self.debug("max.account.networks: %s" % config_value) + + for ctr in range(config_value): + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % network.id) + self.debug( + "Creating network in account already having networks : %s" % + config_value) + + with self.assertRaises(Exception): + Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug('Create network failed (as expected)') + return diff --git a/test/integration/component/test_volumes.py b/test/integration/component/test_volumes.py index 998ba2c520f..3bad5f10254 100644 --- a/test/integration/component/test_volumes.py +++ b/test/integration/component/test_volumes.py @@ -79,10 +79,14 @@ 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": '01853327-513e-4508-9628-f1f55db1946f', + "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', }, + "custom_volume": { + "customdisksize": 2, + "diskname": "Custom disk", + }, "sleep": 50, - "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', + "ostypeid": 'bc66ada0-99e7-483b-befc-8fb0c2129b70', "mode": 'advanced', } @@ -1027,3 +1031,139 @@ class TestVolumes(cloudstackTestCase): "Check if volume exists in ListVolumes" ) return + + +class TestDeployVmWithCustomDisk(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeployVmWithCustomDisk, + 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"], + custom=True + ) + template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostypeid"] + ) + cls.services["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = template.id + + # Create VMs, NAT Rules etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.services["account"] = cls.account.account.name + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + cls.account + ] + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + + @attr(tags=["advanced", "configuration", "advancedns", "simulator", + "api", "basic", "eip", "sg"]) + def test_deployVmWithCustomDisk(self): + """Test custom disk sizes beyond range + """ + # Steps for validation + # 1. listConfigurations - custom.diskoffering.size.min + # and custom.diskoffering.size.max + # 2. deployVm with custom disk offering size < min + # 3. deployVm with custom disk offering min< size < max + # 4. deployVm with custom disk offering size > max + # Validate the following + # 2. and 4. of deploy VM should fail. + # Only case 3. should succeed. + # cleanup all created data disks from the account + + config = Configurations.list( + self.apiclient, + name="custom.diskoffering.size.min" + ) + self.assertEqual( + isinstance(config, list), + True, + "custom.diskoffering.size.min should be present in global config" + ) + # minimum size of custom disk (in GBs) + min_size = int(config[0].value) + self.debug("custom.diskoffering.size.min: %s" % min_size) + + config = Configurations.list( + self.apiclient, + name="custom.diskoffering.size.max" + ) + self.assertEqual( + isinstance(config, list), + True, + "custom.diskoffering.size.min should be present in global config" + ) + # maximum size of custom disk (in GBs) + max_size = int(config[0].value) + self.debug("custom.diskoffering.size.max: %s" % max_size) + + self.debug("Creating a volume with size less than min cust disk size") + self.services["custom_volume"]["customdisksize"] = (min_size - 1) + self.services["custom_volume"]["zoneid"] = self.zone.id + with self.assertRaises(Exception): + Volume.create_custom_disk( + self.apiclient, + self.services["custom_volume"], + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Create volume failed!") + + self.debug("Creating a volume with size more than max cust disk size") + self.services["custom_volume"]["customdisksize"] = (max_size + 1) + with self.assertRaises(Exception): + Volume.create_custom_disk( + self.apiclient, + self.services["custom_volume"], + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Create volume failed!") + + self.debug("Creating a volume with size more than min cust disk " + + "but less than max cust disk size" + ) + self.services["custom_volume"]["customdisksize"] = (min_size + 1) + try: + Volume.create_custom_disk( + self.apiclient, + self.services["custom_volume"], + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Create volume of cust disk size succeeded") + except Exception as e: + self.fail("Create volume failed with exception: %s" % e) + return diff --git a/test/integration/lib/base.py b/test/integration/lib/base.py index 4689972f0e6..5001dafb5ec 100644 --- a/test/integration/lib/base.py +++ b/test/integration/lib/base.py @@ -158,6 +158,45 @@ class User: [setattr(cmd, k, v) for k, v in kwargs.items()] return(apiclient.listUsers(cmd)) + @classmethod + def registerUserKeys(cls, apiclient, userid): + cmd = registerUserKeys.registerUserKeysCmd() + cmd.id = userid + return apiclient.registerUserKeys(cmd) + + def update(self, apiclient, **kwargs): + """Updates the user details""" + + cmd = updateUser.updateUserCmd() + cmd.id = self.id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return (apiclient.updateUser(cmd)) + + @classmethod + def update(cls, apiclient, id, **kwargs): + """Updates the user details (class method)""" + + cmd = updateUser.updateUserCmd() + cmd.id = id + [setattr(cmd, k, v) for k, v in kwargs.items()] + return (apiclient.updateUser(cmd)) + + @classmethod + def login(cls, apiclient, username, password, domain=None, domainid=None): + """Logins to the CloudStack""" + + cmd = login.loginCmd() + cmd.username = username + # MD5 hashcoded password + mdf = hashlib.md5() + mdf.update(password) + cmd.password = mdf.hexdigest() + if domain: + cmd.domain = domain + if domainid: + cmd.domainid = domainid + return apiclient.login(cmd) + class VirtualMachine: """Manage virtual machine lifecycle""" @@ -174,7 +213,8 @@ class VirtualMachine: @classmethod def create(cls, apiclient, services, templateid=None, accountid=None, domainid=None, networkids=None, serviceofferingid=None, - securitygroupids=None, projectid=None, mode='basic'): + securitygroupids=None, projectid=None, startvm=None, + diskofferingid=None, hostid=None, mode='basic'): """Create the instance""" cmd = deployVirtualMachine.deployVirtualMachineCmd() @@ -219,6 +259,12 @@ class VirtualMachine: if projectid: cmd.projectid = projectid + if startvm is not None: + cmd.startvm = startvm + + if hostid: + cmd.hostid = hostid + virtual_machine = apiclient.deployVirtualMachine(cmd) # VM should be in Running state after deploy @@ -392,12 +438,17 @@ class Volume: return Volume(apiclient.createVolume(cmd).__dict__) @classmethod - def create_custom_disk(cls, apiclient, services, - account=None, domainid=None): + def create_custom_disk(cls, apiclient, services, account=None, + domainid=None, diskofferingid=None): """Create Volume from Custom disk offering""" cmd = createVolume.createVolumeCmd() cmd.name = services["diskname"] - cmd.diskofferingid = services["customdiskofferingid"] + + if diskofferingid: + cmd.diskofferingid = diskofferingid + elif "customdiskofferingid" in services: + cmd.diskofferingid = services["customdiskofferingid"] + cmd.size = services["customdisksize"] cmd.zoneid = services["zoneid"]