diff --git a/test/integration/component/test_high_availability.py b/test/integration/component/test_high_availability.py new file mode 100644 index 00000000000..af2cda1d4d0 --- /dev/null +++ b/test/integration/component/test_high_availability.py @@ -0,0 +1,1080 @@ +#!/usr/bin/env python +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for high availability +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin import remoteSSHClient +import datetime + + +class Services: + """Test network offering Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "HA", + "lastname": "HA", + "username": "HA", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '55.55.0.0/11', + # Any network (For creating FW rule) + }, + "virtual_machine": { + "displayname": "VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "templates": { + "displaytext": "Public Template", + "name": "Public template", + "ostype": 'CentOS 5.3 (64-bit)', + "url": "http://download.cloud.com/releases/2.0.0/UbuntuServer-10-04-64bit.vhd.bz2", + "hypervisor": 'XenServer', + "format": 'VHD', + "isfeatured": True, + "ispublic": True, + "isextractable": True, + "templatefilter": 'self', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 100, + "mode": 'advanced' + } + + +class TestHighAvailability(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestHighAvailability, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain( + cls.api_client, + cls.services + ) + cls.zone = get_zone( + cls.api_client, + cls.services + ) + cls.pod = get_pod( + cls.api_client, + zoneid=cls.zone.id, + services=cls.services + ) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + offerha=True + ) + cls._cleanup = [ + cls.service_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + self.testClient.close() + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advanced", "advancedns", "multihost"]) + def test_01_host_maintenance_mode(self): + """Test host maintenance mode + """ + + + # Validate the following + # 1. Create Vms. Acquire IP. Create port forwarding & load balancing + # rules for Vms. + # 2. Host 1: put to maintenance mode. All Vms should failover to Host + # 2 in cluster. Vms should be in running state. All port forwarding + # rules and load balancing Rules should work. + # 3. After failover to Host 2 succeeds, deploy Vms. Deploy Vms on host + # 2 should succeed. + # 4. Host 1: cancel maintenance mode. + # 5. Host 2 : put to maintenance mode. All Vms should failover to + # Host 1 in cluster. + # 6. After failover to Host 1 succeeds, deploy VMs. Deploy Vms on + # host 1 should succeed. + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + self.assertGreaterEqual( + len(hosts), + 2, + "There must be two hosts present in a cluster" + ) + self.debug("Checking HA with hosts: %s, %s" % ( + hosts[0].name, + hosts[1].name + )) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in RUnning state" + ) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return valid list for the account" + ) + network = networks[0] + + self.debug("Associating public IP for account: %s" % + self.account.account.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Creating PF rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id + ) + + self.debug("Creating LB rule on IP with NAT: %s" % + public_ip.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Created LB rule with ID: %s" % lb_rule.id) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + + first_host = vm.hostid + self.debug("Enabling maintenance mode for host %s" % vm.hostid) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = first_host + self.apiclient.prepareHostForMaintenance(cmd) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + timeout = self.services["timeout"] + # Poll and check state of VM while it migrates from one host to another + while True: + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("VM 1 state: %s" % vm.state) + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + second_host = vm.hostid + self.assertEqual( + vm.state, + "Running", + "VM should be in Running state after enabling host maintenance" + ) + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance on other host + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 2 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + self.debug("Canceling host maintenance for ID: %s" % first_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = first_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % first_host) + + self.debug("Enabling maintenance mode for host %s" % second_host) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = second_host + self.apiclient.prepareHostForMaintenance(cmd) + self.debug("Maintenance mode enabled for host: %s" % second_host) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + # Poll and check the status of VMs + timeout = self.services["timeout"] + while True: + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in [ + "Stopping", + "Stopped", + "Running", + "Starting", + "Migrating" + ]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + + # Poll and check the status of VMs + timeout = self.services["timeout"] + while True: + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[1] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in [ + "Stopping", + "Stopped", + "Running", + "Starting", + "Migrating" + ]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + + for vm in vms: + self.debug( + "VM states after enabling maintenance mode on host: %s - %s" % + (first_host, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + # Spawn an instance on other host + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 3 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + + self.debug("Canceling host maintenance for ID: %s" % second_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = second_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % second_host) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + return + + @attr(tags = ["advanced", "advancedns", "multihost"]) + def test_02_host_maintenance_mode_with_activities(self): + """Test host maintenance mode with activities + """ + + + # Validate the following + # 1. Create Vms. Acquire IP. Create port forwarding & load balancing + # rules for Vms. + # 2. While activities are ongoing: Create snapshots, recurring + # snapshots, create templates, download volumes, Host 1: put to + # maintenance mode. All Vms should failover to Host 2 in cluster + # Vms should be in running state. All port forwarding rules and + # load balancing Rules should work. + # 3. After failover to Host 2 succeeds, deploy Vms. Deploy Vms on host + # 2 should succeed. All ongoing activities in step 3 should succeed + # 4. Host 1: cancel maintenance mode. + # 5. While activities are ongoing: Create snapshots, recurring + # snapshots, create templates, download volumes, Host 2: put to + # maintenance mode. All Vms should failover to Host 1 in cluster. + # 6. After failover to Host 1 succeeds, deploy VMs. Deploy Vms on + # host 1 should succeed. All ongoing activities in step 6 should + # succeed. + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + self.assertGreaterEqual( + len(hosts), + 2, + "There must be two hosts present in a cluster" + ) + self.debug("Checking HA with hosts: %s, %s" % ( + hosts[0].name, + hosts[1].name + )) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in RUnning state" + ) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return valid list for the account" + ) + network = networks[0] + + self.debug("Associating public IP for account: %s" % + self.account.account.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Creating PF rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id + ) + + self.debug("Creating LB rule on IP with NAT: %s" % + public_ip.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name + ) + self.debug("Created LB rule with ID: %s" % lb_rule.id) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + self.debug( + "Root volume of VM(%s): %s" % ( + virtual_machine.name, + volume.name + )) + # Create a snapshot from the ROOTDISK + self.debug("Creating snapshot on ROOT volume: %s" % volume.name) + snapshot = Snapshot.create(self.apiclient, volumes[0].id) + self.debug("Snapshot created: ID - %s" % snapshot.id) + + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id, + listall=True + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + + # Generate template from the snapshot + self.debug("Generating template from snapshot: %s" % snapshot.name) + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"] + ) + self.debug("Created template from snapshot: %s" % template.id) + + templates = list_templates( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + + self.assertEqual( + isinstance(templates, list), + True, + "List template call should return the newly created template" + ) + + self.assertEqual( + templates[0].isready, + True, + "The newly created template should be in ready state" + ) + + first_host = vm.hostid + self.debug("Enabling maintenance mode for host %s" % vm.hostid) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = first_host + self.apiclient.prepareHostForMaintenance(cmd) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + timeout = self.services["timeout"] + # Poll and check state of VM while it migrates from one host to another + while True: + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("VM 1 state: %s" % vm.state) + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + second_host = vm.hostid + self.assertEqual( + vm.state, + "Running", + "VM should be in Running state after enabling host maintenance" + ) + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % virtual_machine.id) + ssh = virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (virtual_machine.ipaddress, e) + ) + self.debug("Deploying VM in account: %s" % self.account.account.name) + # Spawn an instance on other host + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 2 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + self.debug("Canceling host maintenance for ID: %s" % first_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = first_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % first_host) + + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=virtual_machine_2.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + self.debug( + "Root volume of VM(%s): %s" % ( + virtual_machine_2.name, + volume.name + )) + # Create a snapshot from the ROOTDISK + self.debug("Creating snapshot on ROOT volume: %s" % volume.name) + snapshot = Snapshot.create(self.apiclient, volumes[0].id) + self.debug("Snapshot created: ID - %s" % snapshot.id) + + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id, + listall=True + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.assertEqual( + snapshots[0].id, + snapshot.id, + "Check snapshot id in list resources call" + ) + + # Generate template from the snapshot + self.debug("Generating template from snapshot: %s" % snapshot.name) + template = Template.create_from_snapshot( + self.apiclient, + snapshot, + self.services["templates"] + ) + self.debug("Created template from snapshot: %s" % template.id) + + templates = list_templates( + self.apiclient, + templatefilter=\ + self.services["templates"]["templatefilter"], + id=template.id + ) + + self.assertEqual( + isinstance(templates, list), + True, + "List template call should return the newly created template" + ) + + self.assertEqual( + templates[0].isready, + True, + "The newly created template should be in ready state" + ) + + self.debug("Enabling maintenance mode for host %s" % second_host) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = second_host + self.apiclient.prepareHostForMaintenance(cmd) + self.debug("Maintenance mode enabled for host: %s" % second_host) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + + # Poll and check the status of VMs + timeout = self.services["timeout"] + while True: + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + + # Poll and check the status of VMs + timeout = self.services["timeout"] + while True: + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[1] + self.debug( + "VM state after enabling maintenance on first host: %s" % + vm.state) + if vm.state in ["Stopping", + "Stopped", + "Running", + "Starting", + "Migrating"]: + if vm.state == "Running": + break + else: + time.sleep(self.services["sleep"]) + timeout = timeout - 1 + else: + self.fail( + "VM migration from one-host-to-other failed while enabling maintenance" + ) + + for vm in vms: + self.debug( + "VM states after enabling maintenance mode on host: %s - %s" % + (first_host, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + # Spawn an instance on other host + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + self.debug("VM 3 state: %s" % vm.state) + self.assertEqual( + vm.state, + "Running", + "Deployed VM should be in Running state" + ) + + self.debug("Canceling host maintenance for ID: %s" % second_host) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = second_host + self.apiclient.cancelHostMaintenance(cmd) + self.debug("Maintenance mode canceled for host: %s" % second_host) + + self.debug("Waiting for SSVMs to come up") + wait_for_ssvms( + self.apiclient, + zoneid=self.zone.id, + podid=self.pod.id, + ) + return diff --git a/test/integration/component/test_host_high_availability.py b/test/integration/component/test_host_high_availability.py new file mode 100644 index 00000000000..03ea0671558 --- /dev/null +++ b/test/integration/component/test_host_high_availability.py @@ -0,0 +1,814 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for dedicated Host high availability +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin import remoteSSHClient +import datetime + + +class Services: + """ Dedicated host HA test cases """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "HA", + "lastname": "HA", + "username": "HA", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering_with_ha": { + "name": "Tiny Instance With HA Enabled", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "service_offering_without_ha": { + "name": "Tiny Instance Without HA", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "timeout": 100, + } + +class TestHostHighAvailability(cloudstackTestCase): + """ Dedicated host HA test cases """ + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestHostHighAvailability, + 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["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering_with_ha = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_with_ha"], + offerha=True + ) + + cls.service_offering_without_ha = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_without_ha"], + offerha=False + ) + + cls._cleanup = [ + cls.service_offering_with_ha, + cls.service_offering_without_ha, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created accounts, domains etc + cleanup_resources(self.apiclient, self.cleanup) + self.testClient.close() + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(configuration = "ha.tag") + @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator"]) + def test_01_vm_deployment_with_compute_offering_with_ha_enabled(self): + """ Test VM deployments (Create HA enabled Compute Service Offering and VM) """ + + # Steps, + #1. Create a Compute service offering with the “Offer HA” option selected. + #2. Create a Guest VM with the compute service offering created above. + # Validations, + #1. Ensure that the offering is created and that in the UI the “Offer HA” field is enabled (Yes) + #The listServiceOffering API should list “offerha” as true. + #2. Select the newly created VM and ensure that the Compute offering field value lists the compute service offering that was selected. + # Also, check that the HA Enabled field is enabled “Yes”. + + #list and validate above created service offering with Ha enabled + list_service_response = list_service_offering( + self.apiclient, + id=self.service_offering_with_ha.id + ) + self.assertEqual( + isinstance(list_service_response, list), + True, + "listServiceOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_service_response), + 0, + "listServiceOfferings returned empty list." + ) + self.assertEqual( + list_service_response[0].offerha, + True, + "The service offering is not HA enabled" + ) + + #create virtual machine with the service offering with Ha enabled + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + self.debug("Deployed VM on host: %s" % vms[0].hostid) + self.assertEqual( + vms[0].haenable, + True, + "VM not created with HA enable tag" + ) + + @attr(configuration = "ha.tag") + @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + def test_02_no_vm_creation_on_host_with_haenabled(self): + """ Verify you can not create new VMs on hosts with an ha.tag """ + + # Steps, + #1. Fresh install CS (Bonita) that supports this feature + #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage + #3. When adding host3, assign the HA host tag. + #4. You should already have a compute service offering with HA already create from above. If not, create one for HA. + #5. Create VMs with the service offering with and without the HA tag + # Validations, + #Check to make sure the newly created VM is not on any HA enabled hosts + #The VM should be created only on host1 or host2 and never host3 (HA enabled) + + #create and verify virtual machine with HA enabled service offering + virtual_machine_with_ha = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + + #validate the virtual machine created is host Ha enabled + list_hosts_response = list_hosts( + self.apiclient, + id=vm.hostid + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "listHosts returned invalid object in response." + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "listHosts retuned empty list in response." + ) + + self.assertEqual( + list_hosts_response[0].hahost, + False, + "VM created on HA enabled host." + ) + + #create and verify virtual machine with Ha disabled service offering + virtual_machine_without_ha = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering_without_ha.id + ) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_without_ha.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + + #verify that the virtual machine created on the host is Ha disabled + list_hosts_response = list_hosts( + self.apiclient, + id=vm.hostid + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "listHosts returned invalid object in response." + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "listHosts returned empty list." + ) + + host = list_hosts_response[0] + + self.assertEqual( + host.hahost, + False, + "VM migrated to HA enabled host." + ) + + @attr(configuration = "ha.tag") + @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + def test_03_cant_migrate_vm_to_host_with_ha_positive(self): + """ Verify you can not migrate VMs to hosts with an ha.tag (positive) """ + + # Steps, + #1. Create a Compute service offering with the “Offer HA” option selected. + #2. Create a Guest VM with the compute service offering created above. + #3. Select the VM and migrate VM to another host. Choose a “Suitable” host (i.e. host2) + # Validations + #The option from the “Migrate instance to another host” dialog box” should list host3 as “Not Suitable” for migration. + #Confirm that the VM is migrated to the “Suitable” host you selected (i.e. host2) + + #create and verify the virtual machine with HA enabled service offering + virtual_machine_with_ha = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True, + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + + #Find out a Suitable host for VM migration + list_hosts_response = list_hosts( + self.apiclient, + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "The listHosts API returned the invalid list" + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "The listHosts returned nothing." + ) + suitableHost = None + for host in list_hosts_response: + if host.suitableformigration == True and host.hostid != vm.hostid: + suitableHost = host + break + + self.assertTrue(suitableHost is not None, "suitablehost should not be None") + + #Migration of the VM to a suitable host + self.debug("Migrating VM-ID: %s to Host: %s" % (self.vm.id, suitableHost.id)) + + cmd = migrateVirtualMachine.migrateVirtualMachineCmd() + cmd.hostid = suitableHost.id + cmd.virtualmachineid = self.vm.id + self.apiclient.migrateVirtualMachine(cmd) + + #Verify that the VM migrated to a targeted Suitable host + list_vm_response = list_virtual_machines( + self.apiclient, + id=vm.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "The listVirtualMachines returned the invalid list." + ) + + self.assertNotEqual( + list_vm_response, + None, + "The listVirtualMachines API returned nothing." + ) + + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.id, + vm.id, + "The virtual machine id and the the virtual machine from listVirtualMachines is not matching." + ) + + self.assertEqual( + vm_response.hostid, + suitableHost.id, + "The VM is not migrated to targeted suitable host." + ) + + @attr(configuration = "ha.tag") + @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + def test_04_cant_migrate_vm_to_host_with_ha_negative(self): + """ Verify you can not migrate VMs to hosts with an ha.tag (negative) """ + + # Steps, + #1. Create a Compute service offering with the “Offer HA” option selected. + #2. Create a Guest VM with the compute service offering created above. + #3. Select the VM and migrate VM to another host. Choose a “Not Suitable” host. + # Validations, + #The option from the “Migrate instance to another host” dialog box” should list host3 as “Not Suitable” for migration. + #By design, The Guest VM can STILL can be migrated to host3 if the admin chooses to do so. + + #create and verify virtual machine with HA enabled service offering + virtual_machine_with_ha = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "The listVirtualMachines returned invalid object in response." + ) + + self.assertNotEqual( + len(vms), + 0, + "The listVirtualMachines returned empty response." + ) + + vm = vms[0] + + self.debug("Deployed VM on host: %s" % vm.hostid) + + #Find out Non-Suitable host for VM migration + list_hosts_response = list_hosts( + self.apiclient, + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "listHosts returned invalid object in response." + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "listHosts returned empty response." + ) + + notSuitableHost = None + for host in list_hosts_response: + if not host.suitableformigration and host.hostid != vm.hostid: + notSuitableHost = host + break + + self.assertTrue(notSuitableHost is not None, "notsuitablehost should not be None") + + #Migrate VM to Non-Suitable host + self.debug("Migrating VM-ID: %s to Host: %s" % (vm.id, notSuitableHost.id)) + + cmd = migrateVirtualMachine.migrateVirtualMachineCmd() + cmd.hostid = notSuitableHost.id + cmd.virtualmachineid = vm.id + self.apiclient.migrateVirtualMachine(cmd) + + #Verify that the virtual machine got migrated to targeted Non-Suitable host + list_vm_response = list_virtual_machines( + self.apiclient, + id=vm.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "listVirtualMachine returned invalid object in response." + ) + + self.assertNotEqual( + len(list_vm_response), + 0, + "listVirtualMachines returned empty response." + ) + + self.assertEqual( + list_vm_response[0].id, + vm.id, + "Virtual machine id with the virtual machine from listVirtualMachine is not matching." + ) + + self.assertEqual( + list_vm_response[0].hostid, + notSuitableHost.id, + "The detination host id of migrated VM is not matching." + ) + + @attr(configuration = "ha.tag") + @attr(speed = "slow") + @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + def test_05_no_vm_with_ha_gets_migrated_to_ha_host_in_live_migration(self): + """ Verify that none of the VMs with HA enabled migrate to an ha tagged host during live migration """ + + # Steps, + #1. Fresh install CS (Bonita) that supports this feature + #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage + #3. When adding host3, assign the HA host tag. + #4. Create VMs with and without the Compute Service Offering with the HA tag. + #5. Note the VMs on host1 and whether any of the VMs have their “HA enabled” flags enabled. + #6. Put host1 into maintenance mode. + # Validations, + #1. Make sure the VMs are created on either host1 or host2 and not on host3 + #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3. + + # create and verify virtual machine with HA disabled service offering + virtual_machine_with_ha = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering_with_ha.id + ) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_with_ha.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + + vm_with_ha_enabled = vms[0] + + #Verify the virtual machine got created on non HA host + list_hosts_response = list_hosts( + self.apiclient, + id=vm_with_ha_enabled.hostid + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "Check Host is available" + ) + + self.assertEqual( + list_hosts_response[0].hahost, + False, + "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" + ) + + #put the Host in maintainance mode + self.debug("Enabling maintenance mode for host %s" % vm_with_ha_enabled.hostid) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = vm_with_ha_enabled.hostid + self.apiclient.prepareHostForMaintenance(cmd) + + timeout = self.services["timeout"] + + #verify the VM live migration happened to another running host + self.debug("Waiting for VM to come up") + wait_for_vm( + self.apiclient, + virtualmachineid=vm_with_ha_enabled.id, + interval=timeout + ) + + vms = VirtualMachine.list( + self.apiclient, + id=vm_with_ha_enabled.id, + listall=True, + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + + vm_with_ha_enabled1 = vms[0] + + list_hosts_response = list_hosts( + self.apiclient, + id=vm_with_ha_enabled1.hostid + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "Check Host is available" + ) + + self.assertEqual( + list_hosts_response[0].hahost, + False, + "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" + ) + + self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_enabled.hostid) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = vm_with_ha_enabled.hostid + self.apiclient.cancelHostMaintenance(cmd) + + @attr(configuration = "ha.tag") + @attr(speed = "slow") + @attr(tags = ["advanced", "advancedns", "sg", "basic", "eip", "simulator", "multihost"]) + def test_06_no_vm_without_ha_gets_migrated_to_ha_host_in_live_migration(self): + """ Verify that none of the VMs without HA enabled migrate to an ha tagged host during live migration """ + + # Steps, + #1. Fresh install CS (Bonita) that supports this feature + #2. Create Basic zone, pod, cluster, add 3 hosts to cluster (host1, host2, host3), secondary & primary Storage + #3. When adding host3, assign the HA host tag. + #4. Create VMs with and without the Compute Service Offering with the HA tag. + #5. Note the VMs on host1 and whether any of the VMs have their “HA enabled” flags enabled. + #6. Put host1 into maintenance mode. + # Validations, + #1. Make sure the VMs are created on either host1 or host2 and not on host3 + #2. Putting host1 into maintenance mode should trigger a live migration. Make sure the VMs are not migrated to HA enabled host3. + + # create and verify virtual machine with HA disabled service offering + virtual_machine_without_ha = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering_without_ha.id + ) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine_without_ha.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + + vm_with_ha_disabled = vms[0] + + #Verify the virtual machine got created on non HA host + list_hosts_response = list_hosts( + self.apiclient, + id=vm_with_ha_disabled.hostid + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "Check Host is available" + ) + + self.assertEqual( + list_hosts_response[0].hahost, + False, + "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" + ) + + #put the Host in maintainance mode + self.debug("Enabling maintenance mode for host %s" % vm_with_ha_disabled.hostid) + cmd = prepareHostForMaintenance.prepareHostForMaintenanceCmd() + cmd.id = vm_with_ha_disabled.hostid + self.apiclient.prepareHostForMaintenance(cmd) + + timeout = self.services["timeout"] + + #verify the VM live migration happened to another running host + self.debug("Waiting for VM to come up") + wait_for_vm( + self.apiclient, + virtualmachineid=vm_with_ha_disabled.id, + interval=timeout + ) + + vms = VirtualMachine.list( + self.apiclient, + id=vm_with_ha_disabled.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return valid response for deployed VM" + ) + + self.assertNotEqual( + len(vms), + 0, + "List VMs should return valid response for deployed VM" + ) + + list_hosts_response = list_hosts( + self.apiclient, + id=vms[0].hostid + ) + self.assertEqual( + isinstance(list_hosts_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + len(list_hosts_response), + 0, + "Check Host is available" + ) + + self.assertEqual( + list_hosts_response[0].hahost, + False, + "The virtual machine is not ha enabled so check if VM is created on host which is also not ha enabled" + ) + + self.debug("Disabling the maintenance mode for host %s" % vm_with_ha_disabled.hostid) + cmd = cancelHostMaintenance.cancelHostMaintenanceCmd() + cmd.id = vm_with_ha_disabled.hostid + self.apiclient.cancelHostMaintenance(cmd) diff --git a/test/integration/component/test_netscaler_configs.py b/test/integration/component/test_netscaler_configs.py new file mode 100644 index 00000000000..2cfe463aff4 --- /dev/null +++ b/test/integration/component/test_netscaler_configs.py @@ -0,0 +1,3024 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for netscaler configurations +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '192.168.100.213', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "netscaler_dedicated": { + "ipaddress": '192.168.100.213', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": True, + "port": 22, + }, + "network_offering_dedicated": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "specifyVlan": False, + "specifyIpRanges": False, + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "servicecapabilitylist": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "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": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestAddNetScaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestAddNetScaler, + 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._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: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_add_netscaler_device(self): + """Test add netscaler device + """ + # Validate the following + # 1. Add Netscaler device into a Zone by providing valid log in + # credentials , public , private interface and enabling Load + # Balancing feature. + # 2. Netscaler should be configured successfully. + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + netscaler = NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + self.cleanup.append(netscaler) + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("Netscaler service provider is already enabled.") + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + self.assertEqual( + ns.physicalnetworkid, + physical_network.id, + "Physical network id should match with the network in which device is configured" + ) + return + + + +class TestInvalidParametersNetscaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestInvalidParametersNetscaler, + 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._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: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_invalid_cred(self): + """Test add netscaler device with invalid credential + """ + + # Validate the following + # 1. Add Netscaler device into a Zone by providing invalid log in + # credentials , but valid public, private interface + # 2. Netscaler API should throw error + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("NetScaler service provider is already enabled.") + + self.debug("Passing invalid credential for NetScaler") + self.services["netscaler"]["username"] = random_gen() + self.services["netscaler"]["password"] = random_gen() + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + + self.debug("Username: %s, password: %s" % ( + self.services["netscaler"]["username"], + self.services["netscaler"]["password"] + )) + + with self.assertRaises(Exception): + NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + return + + @attr(tags = ["advancedns"]) + def test_invalid_public_interface(self): + """Test add netscaler device with invalid public interface + """ + + # Validate the following + # 1. Add Netscaler device into a Zone by providing valid log in + # credentials , private interface and invalid public interface + # 2. Netscaler API should throw error + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("NetScaler service provider is already enabled.") + + self.debug("Passing invalid public interface for NetScaler") + self.services["netscaler"]["publicinterface"] = random_gen() + + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + + self.debug("Public interface: %s" % + self.services["netscaler"]["publicinterface"]) + + with self.assertRaises(Exception): + NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + return + + @attr(tags = ["advancedns"]) + def test_invalid_private_interface(self): + """Test add netscaler device with invalid private interface + """ + + # Validate the following + # 1. Add Netscaler device into a Zone by providing valid log in + # credentials , public interface and invalid private interface + # 2. Netscaler API should throw error + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("NetScaler service provider is already enabled.") + + self.debug("Passing invalid private interface for NetScaler") + self.services["netscaler"]["privateinterface"] = random_gen() + + self.debug("Adding netscaler device: %s" % + self.services["netscaler"]["ipaddress"]) + + self.debug("Private interface: %s" % + self.services["netscaler"]["privateinterface"]) + + with self.assertRaises(Exception): + NetScaler.add( + self.apiclient, + self.services["netscaler"], + physicalnetworkid=physical_network.id + ) + return + + +class TestNetScalerDedicated(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerDedicated, + 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["ostype"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler_dedicated"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_dedicated"], + conservemode=False, + state="Creating", + status="Creating", + allocationstate="Creating", + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + 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_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_netscaler_dedicated_mode(self): + """Test netscaler device in dedicated mode + """ + + # Validate the following + # 1. Add Netscaler device in dedicated mode. + # 2. Netscaler should be configured successfully.It should be able to + # service only 1 account. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + True, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + + Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Deploying an instance in account: %s" % self.account_2.account.name) + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deply instacne in dedicated Network offering mode failed") + return + + + +class TestNetScalerShared(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerShared, + 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["ostype"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + 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_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_netscaler_shared_mode(self): + """Test netscaler device in shared mode + """ + + # Validate the following + # 1. Add Netscaler device in shared mode. + # 2. Netscaler should be configured successfully.It should be able to + # service only 1 account. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + return + + + +class TestNetScalerCustomCapacity(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerCustomCapacity, + 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["ostype"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + cls.services["netscaler"]["lbdevicecapacity"] = 2 + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + 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_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_3 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2, self.account_3] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_netscaler_custom_capacity(self): + """Test netscaler device with custom capacity + """ + + # Validate the following + # 1. Add Netscaler device in shared mode with capacity 3 + # 2. Netscaler should be configured successfully.It should be able to + # service only 3 accounts. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + with self.assertRaises(Exception): + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + return + + + +class TestNetScalerNoCapacity(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerNoCapacity, + 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["ostype"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + cls.services["netscaler"]["lbdevicecapacity"] = 2 + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + 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_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_3 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2, self.account_3] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_netscaler_no_capacity(self): + """Test netscaler device with no capacity remaining + """ + + # Validate the following + # 1. Add Netscaler device in shared mode with capacity 2 + # 2. Netscaler should be configured successfully.It should be able to + # service only 2 accounts. + # 3. Deploy instance for account 3 should fail + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + with self.assertRaises(Exception): + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + return + + + +class TestGuestNetworkWithNetScaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestGuestNetworkWithNetScaler, + 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["ostype"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + 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_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_guest_network(self): + """Implementing Guest Network when first VM gets deployed using the network having Netscaler as LB + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3.Create a new account/user. + # 4. Deploy the first VM using a network from the above created + # Network offering. + # In Netscaler: + # 1. Private interface of Netscaler device will be configured to make + # it part of the virtual guest network by binding the interface to + # the VLAN and subnet allocated for the virtual guest network + # 2. Private interface should be associated with a self-ip (second IP + # in the subnet) from the guest subnet. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network_1.id, + listall=True + ) + nw = network_list[0] + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_02_guest_network_multiple(self): + """Implementing Guest Network when multiple VMs gets deployed using the network having Netscaler as LB + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3.Create a new account/user. + # 4. Deploy the first VM using a network from the above created + # Network offering. + # In Netscaler: + # 1. Private interface of Netscaler device will be configured to make + # it part of the virtual guest network by binding the interface to + # the VLAN and subnet allocated for the virtual guest network + # 2. Private interface should be associated with a self-ip (second IP + # in the subnet) from the guest subnet. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network_1.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network_2.id, + listall=True + ) + nw = network_list[0] + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_03_delete_account(self): + """Delete an account that has LB rules + """ + + # Validate the following + # 1. Acquire an ipaddress. Create multiple Lb rules on this ip address + # 2. Delete this account that has LB rules + # In Netscaler: + # 1. Private interface on the netscaler LB device will be unbound to + # vlan and subnet + # 2. All the service instance and the servers that are part of this + # vlan, that were created on the Netscaler device as part of + # applying LB rules will be destroyed. + # 3. Any lb virtual server that is created using this public IP + # allocated for the account will be destroyed + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Assigning public IP for the account: %s" % + self.account_1.account.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account_1.account.name, + zoneid=self.zone.id, + domainid=self.account_1.account.domainid, + networkid=self.network.id + ) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account_1.account.name, + networkid=self.network.id + ) + self.debug("Created the load balancing rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + self.debug("Assigning VMs to LB rule") + lb_rule.assign(self.apiclient, [virtual_machine]) + + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + + self.debug("Deleting account: %s" % self.account_1.account.name) + # This is a hack. Delete first account from cleanup list + self.cleanup.pop(0).delete(self.apiclient) + self.debug("Account: %s is deleted!" % self.account_1.account.name) + + self.debug("Waiting for network.gc.interval & network.gc.wait..") + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + + +class TestGuestNetworkShutDown(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestGuestNetworkShutDown, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn few instances in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_stop_all_vms(self): + """Test Stopping all the Vms for any account that has LB rules. + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Stop all VMs in the account that has LB rules + # 3. This will result in the network being shutdown. As part of this, + # this account and the all the Lb rules for this account should get + # removed from the Netscaler + + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + self.debug("Network vlan used is: %s" % nw.vlan) + + self.debug( + "Stopping all the VM instances for the account: %s" % + self.account.account.name) + + self.vm_1.stop(self.apiclient) + self.vm_2.stop(self.apiclient) + + self.debug("Sleep for network.gc.interval + network.gc.wait") + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep((int(interval[0].value) + int(wait[0].value)) * 2) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should not have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should not have vserver configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_02_start_one_vm(self): + """Test LB rules on Netscaler after starting one Vm in account + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Stop all VMs in the account that has LB rules + # 3. This will result in the network being shutdown. As part of this, + # this account and the all the Lb rules for this account should get + # removed from the Netscaler + # 3. Start one of the VMs. LB rules should get reconfigured on + # Netscaler + + self.debug( + "starting one VM instances for the account: %s" % + self.account.account.name) + self.vm_1.start(self.apiclient) + + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_1.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid list" + ) + + for vm in vms: + self.assertEqual( + vm.state, + "Running", + "VM instance should be Up and running after start" + ) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_03_network_restart_without_cleanup(self): + """Test LB rules on Netscaler after network restart without cleanup + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Restart network->without cleanup option enabled + # 3. All existing Lb rules get added again to the netscaler. All the + # existing LB rules should continue to work. + + self.debug("Restarting the network: %s" % self.network.id) + self.network.restart(self.apiclient, cleanup=False) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_04_network_restart_with_cleanup(self): + """Test LB rules on Netscaler after network restart with cleanup + """ + + # Validate the following + # 1. Acquire IP address and create a load balancer rule + # 2. Restart network->with cleanup option enabled + # 3. All existing Lb rules get deleted and reconfigured again to the + # netscaler. All the existing LB rules should continue to work. + + self.debug("Restarting the network: %s" % self.network.id) + self.network.restart(self.apiclient, cleanup=True) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + # Find Network vlan used + network_list = Network.list( + self.apiclient, + id=self.network.id, + listall=True + ) + nw = network_list[0] + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show vlan %s" % (nw.vlan) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource "), + 1, + "Netscaler should have vlan configured for the network" + ) + + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + # Output: ERROR: No such resource [id, 123] + + self.assertNotEqual( + result.count("ERROR: No such resource"), + 1, + "Netscaler should have vlan configured for the network" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + + +class TestServiceProvider(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestServiceProvider, + 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["ostype"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + cls.netscaler_provider = nw_service_providers[0] + + if cls.netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=cls.netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Enable the service provider + NetworkServiceProvider.update( + cls.api_client, + id=cls.netscaler_provider.id, + state='Enabled' + ) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_create_nw_off_disabled(self): + """Test create network with network offering disabled + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering. Do not enable the network offering + # 3. Try to create a network with this network offering. + # 4. Network creation should fail + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + 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 + ) + return + + @attr(tags = ["advancedns"]) + def test_02_create_nw_sp_disabled(self): + """Test create network when service provider is disabled + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Disable the service provider. Create a Network offering. + # 3. Try to create a network. Network creation should fail + + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + + # Disable the service provider + NetworkServiceProvider.update( + self.apiclient, + id=self.netscaler_provider.id, + state='Disabled' + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + 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 + ) + return + + @attr(tags = ["advancedns"]) + def test_03_create_lb_sp_disabled(self): + """Test create LB rules when service provider is disabled + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering. Create instances and acquire public Ip + # 3. Disabled service provider and again try to create LB rules + # 4.Deploy VM should fail + + # Enable the service provider + NetworkServiceProvider.update( + self.apiclient, + id=self.netscaler_provider.id, + state='Enabled' + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Acquiring a public IP for Network: %s" % self.network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.debug("Created the load balancing rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + virtual_machine.name, + lb_rule.name + )) + self.debug("Disabling Netscaler service provider") + + # Disable the service provider + NetworkServiceProvider.update( + self.apiclient, + id=self.netscaler_provider.id, + state='Disabled' + ) + with self.assertRaises(Exception): + self.debug("Deploying VM in the network: %s" % self.network.id) + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + 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)] + ) + return + + + +class TestDeleteNetscaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeleteNetscaler, + 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["ostype"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + 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_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_delete_netscaler_with_lb(self): + """Test delete Netscaler when active LB rules are present + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3.Create a new account/user. + # 4. Deploy the first VM using a network from the above created + # Network offering. + # 5. Attempt to delete Netscaler load balancer from zone. + # Deletion should NOT be allowed. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Attempt to delete netscaler load balancer device") + with self.assertRaises(Exception): + self.netscaler.delete(self.apiclient) + self.debug("Attempt to delete Netscaler device failed!") + return diff --git a/test/integration/component/test_netscaler_lb.py b/test/integration/component/test_netscaler_lb.py new file mode 100644 index 00000000000..898f8b1aa15 --- /dev/null +++ b/test/integration/component/test_netscaler_lb.py @@ -0,0 +1,2964 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for netscaler load balancing +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '10.147.40.100', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "network_offering_dedicated": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "specifyVlan": False, + "specifyIpRanges": False, + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "servicecapabilitylist": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "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": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestLbSourceNat(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbSourceNat, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.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 = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_add_lb_on_source_nat(self): + """Test Create LB rule for sourceNat IP address + """ + + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Create LB rule for the sourceNat IP address. User should NOT be + # allowed to create an LB rule on source NAT + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = 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) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + src_nat_list = PublicIPAddress.list( + self.apiclient, + associatednetworkid=self.network.id, + account=self.account.account.name, + domainid=self.account.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 LB rule on source NAT IP: %s" % + src_nat.ipaddress) + # Create Load Balancer rule with source NAT + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=src_nat.id, + accountid=self.account.account.name + ) + return + + +class TestLbOnIpWithPf(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbOnIpWithPf, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.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 = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_on_ip_with_pf(self): + """Test Create LB rule for sourceNat IP address + """ + + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Create LB rule on Ip with PF rule. User should NOT be + # allowed to create an LB rule on Ip with PF + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = 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) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + ip_with_nat_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + + self.debug("Associated %s with network %s" % ( + ip_with_nat_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating PF rule for IP address: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + NATRule.create( + self.apiclient, + virtual_machine_1, + self.services["natrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id + ) + + self.debug("Trying to create LB rule on IP with NAT: %s" % + ip_with_nat_rule.ipaddress.ipaddress) + + # Create Load Balancer rule on IP already having NAT rule + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_nat_rule.ipaddress.id, + accountid=self.account.account.name + ) + return + + +class TestPfOnIpWithLb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestPfOnIpWithLb, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.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 = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_pf_on_ip_with_lb(self): + """Test Create a port forwarding rule on an Ip address that already has a LB rule. + """ + + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Create PF rule on Ip with LB rule. User should NOT be + # allowed to create an LB rule on Ip with LB + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = 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) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id + ) + return + + +class TestLbOnNonSourceNat(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbOnNonSourceNat, + 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["ostype"] + ) + + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.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 = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_on_non_source_nat(self): + """Test Create LB rule for non-sourceNat IP address + """ + + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule on it. LB rule should be + # created successfully + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = 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) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + return + + +class TestAddMultipleVmsLb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestAddMultipleVmsLb, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.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 = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_add_multiple_vms_lb(self): + """Test Add multiple Vms to an existing LB rule. + """ + + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule on it. Add multiple VMs to + # this rule. LB rule should be + # In Netscaler: For every Vm added to the LB rule: + # 1. A server and service instance is created using guest VM’s IP and + # port number on the Netscaler LB device, + # 2. This service is bound to lb virtual server corresponding to lb + # rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = 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) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug("Creating LB rule for IP address: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + ip_with_lb_rule.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Assigning virtual machines to LB rule") + lb_rule.assign(self.apiclient, [virtual_machine_1, virtual_machine_2]) + + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + 22, + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + self.debug("command: show server") + res = ssh_client.execute("show server") + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(virtual_machine_1.ipaddress), + 2, + "Server must be configured for virtual machines" + ) + self.assertEqual( + result.count(virtual_machine_2.ipaddress), + 2, + "Server must be configured for virtual machines" + ) + + self.debug("Command:show service") + res = ssh_client.execute("show service") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(virtual_machine_1.ipaddress), + 3, + "Service must be configured for virtual machines" + ) + self.assertEqual( + result.count(virtual_machine_2.ipaddress), + 3, + "Service must be configured for virtual machines" + ) + self.debug("Command:show lb vserver") + res = ssh_client.execute("show lb vserver") + + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(ip_with_lb_rule.ipaddress.ipaddress), + 2, + "virtual server must be configured for public IP address" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestMultipleLbRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestMultipleLbRules, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.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 = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_multiple_lb_publicip(self): + """Test Create multiple LB rules using different public Ips acquired + """ + + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy few more VMs. + # 3. Acquire an Ipaddress and create an LB rule for multiple Vms. + # Repeat step2 for few times Requests to all these LB rules should + # be serviced correctly. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = 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) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug( + "Associating first public IP for network: %s" % + self.network.id) + + public_ip_1 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_1.ipaddress.ipaddress, + self.network.id + )) + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip_1.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_1.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_1, virtual_machine_2]) + + self.debug( + "Associating second public IP for network: %s" % + self.network.id) + + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + self.network.id + )) + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip_2.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_2.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + public_ip_2.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine_1, virtual_machine_2]) + + try: + self.debug( + "Verifying VMs are accessible with different public Ips") + hostnames = [] + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip_1.ipaddress.ipaddress, + e)) + try: + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip_2.ipaddress.ipaddress, + e)) + return + + +class TestMultipleLbRulesSameIp(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestMultipleLbRulesSameIp, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.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 = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_multiple_lb_same_publicip(self): + """Test Create multiple LB rules using same public Ips on diff ports + """ + + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy few more VMs. + # 3. Acquire an Ipaddress and create an LB rule for multiple Vms. + # Create another Lb rule on the same Ipaddress pointing to + # different public port. Requests to all these LB rules should be + # serviced correctly. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine_1 = 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) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Deploying another VM in account: %s" % + self.account.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug( + "Associating first public IP for network: %s" % + self.network.id) + + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + self.network.id + )) + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule_1 = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + self.debug("Trying to create PF rule on IP with LB rule: %s" % + public_ip.ipaddress.ipaddress) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule_1.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule_1.name + )) + lb_rule_1.assign(self.apiclient, [ + virtual_machine_1, + virtual_machine_2 + ]) + self.debug( + "Trying to create LB rule on IP: %s with on same ports" % + public_ip.ipaddress.ipaddress) + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.debug("Create LB rule on same port failed!") + self.debug("Creating LB rule on IP: %s & public port: %s" % ( + public_ip.ipaddress.ipaddress, + str(2222))) + + self.services["lbrule"]["alg"] = 'roundrobin' + self.services["lbrule"]["publicport"] = 2222 + self.services["lbrule"]["name"] = 'SSH2' + lb_rule_2 = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule_2.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s, %s to the LB rule %s" % ( + virtual_machine_1.name, + virtual_machine_2.name, + lb_rule_2.name + )) + lb_rule_2.assign(self.apiclient, [ + virtual_machine_1, + virtual_machine_2 + ]) + + try: + self.debug("Verifying VMs are accessible on all LB rules") + hostnames = [] + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip.ipaddress.ipaddress, + e)) + try: + ssh = virtual_machine_1.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + res = str(result[0]) + self.assertIn( + res, + [virtual_machine_1.name, virtual_machine_2.name], + "The hostname should match with atleast one of instance name" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + public_ip.ipaddress.ipaddress, + e)) + return + + +class TestLoadBalancingRule(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + 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) + cls.zone = get_zone(cls.api_client, cls.services) + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_edit_name_lb_rule(self): + """Test edit name of LB rule + """ + + + # Validate the following + # 1. Create an Lb rule for couple of Vms . + # 2. Edit the name of the existing LB rule. When all the existing + # Lbrules are listed , we should see the edited name. + + self.debug("Assigning VMs to LB rule: %s" % self.lb_rule.name) + self.lb_rule.assign(self.apiclient, [self.virtual_machine]) + + self.debug("Editing name of the LB rule: %s" % self.lb_rule.name) + new_name = random_gen() + self.lb_rule.update(self.apiclient, name=new_name) + + self.debug("Verifing the name change in list Lb rules call") + lb_rules = LoadBalancerRule.list(self.apiclient, id=self.lb_rule.id) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB call should return a valid list" + ) + lb = lb_rules[0] + self.assertEqual( + lb.name, + new_name, + "LB name should be updated with the new name" + ) + return + + @attr(tags = ["advancedns"]) + def test_02_edit_lb_ports(self): + """Test edit public port of LB rule + """ + + + # Validate the following + # 1. Create an Lb rule for couple of Vms . + # 2. Edit the public/private of the existing LB rule. When all the + # existing Lbrules are listed, this should not be allowed. + + self.debug("Editing public port of the LB rule: %s" % self.lb_rule.name) + port = 8888 + with self.assertRaises(Exception): + self.lb_rule.update(self.apiclient, publicport=port) + + self.debug("Editing private port of the LB rule: %s" % self.lb_rule.name) + with self.assertRaises(Exception): + self.lb_rule.update(self.apiclient, privateport=port) + + return + + @attr(tags = ["advancedns"]) + def test_03_delete_lb_rule(self): + """Test delete LB rule + """ + + + # Validate the following + # 1. Delete existing load balancing rule + # 2. In netscaler service and port corresponding to LB rule should get + # deleted. Any request to IP should error out. + + self.debug("Deleting existing load balancing rule") + self.lb_rule.delete(self.apiclient) + + self.debug("SSH into Netscaler to verify other resources are deleted") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + self.lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Virtual server should get deleted after removing LB rule" + ) + + cmd = "show ip" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.public_ip.ipaddress.ipaddress), + 0, + "Virtual server should get deleted after removing LB rule" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +@unittest.skip("Questions - How to verify after changing public/private ports?") +class TestDeleteCreateLBRule(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeleteCreateLBRule, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_create_with_same_public_port(self): + """Test create LB rule with same public port after deleting rule""" + + + # Validate the following + # 1. Delete existing rule and create exactly same rule with different + # public port + # 2. Requests should be served correctly + + self.debug("Delete the existing LB rule: %s" % self.lb_rule.name) + self.lb_rule.delete(self.apiclient) + self.debug("LB rule deleted") + + self.debug("Create a new LB rule with different public port") + self.services["lbrule"]["publicport"] = 23 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + +class TestVmWithLb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVmWithLb, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule_1 = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_1.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls.public_ip_2 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls.lb_rule_2 = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_2.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_delete_public_ip(self): + """Test delete one public Ip with LB rules""" + + + # Validate the following + # 1. Associate 2 public Ips and create load balancing rules in it + # 2. Delete one of the public Ip + # 3. All the LB rules should be removed from that public Ip + # 4. In netscaler, make sure that all LB rules associated with that + # public Ip should get removed. + # 5. All servers and services service to that public Ip get deleted + + self.debug("Deleting public IP: %s from network: %s" % ( + self.public_ip_2.ipaddress.ipaddress, + self.network.name + )) + self.public_ip_2.delete(self.apiclient) + self.debug( + "Public Ip: %s is deleted!" % + self.public_ip_2.ipaddress.ipaddress) + lb_rules = LoadBalancerRule.list( + self.apiclient, + publicipid=self.public_ip_2.ipaddress.id, + listall=True, + ) + self.assertEqual( + lb_rules, + None, + "LB rules associated with the public Ip should get deleted" + ) + self.debug("SSH into Netscaler to verify other resources are deleted") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip_2.ipaddress.ipaddress, + self.lb_rule_2.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Virtual server should get deleted after removing LB rule" + ) + + cmd = "show ip" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.public_ip_2.ipaddress.ipaddress), + 0, + "Virtual server should get deleted after removing LB rule" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_02_stop_user_vm(self): + """Test stop user VM with LB""" + + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Stop one of the user VM + # 3. Test whether the request are not sent to stopped user VM + # 4. In netscaler, LB rules for this VM still remain configured.But + # it will be marked as being down + + self.debug("Adding instances: %s, %s to LB rule: %s" % ( + self.vm_1.name, + self.vm_2.name, + self.lb_rule_1.name)) + self.lb_rule_1.assign(self.apiclient, [self.vm_1, self.vm_2]) + self.debug("Assigned instances: %s, %s to LB rule: %s" % ( + self.vm_1.name, + self.vm_2.name, + self.lb_rule_1.name)) + self.debug("Stopping VM instance: %s" % self.vm_2.name) + self.vm_2.stop(self.apiclient) + self.debug("Stopped VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertEqual( + hostnames[0], + hostnames[1], + "Hostnames must be same as another VM is stopped" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after VM stop" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_03_start_user_vm(self): + """Test start user VM with LB""" + + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Stop one of the user VM + # 3. Test whether the request are not sent to stopped user VM + # 4. In netscaler, LB rules for this VM still remain configured.But + # it will be marked as being down + + self.debug("Starting VM instance: %s" % self.vm_2.name) + self.vm_2.start(self.apiclient) + self.debug("Starting VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Both request should be served by different instances" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after VM stop" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns", "multihost"]) + def test_04_migrate_user_vm(self): + """Test migrate user VM with LB""" + + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. migrate one Vm to another host. + # 3. Test whether the request are sent to stopped user VM after migrate + # 4. In netscaler, the LB rules are still configured. + + hosts = Host.list( + self.apiclient, + zoneid=self.vm_2.zoneid, + type='Routing' + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "Check the number of hosts in the zone" + ) + self.assertGreaterEqual( + len(hosts), + 2, + "Atleast 2 hosts should be present in a zone for VM migration" + ) + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != self.vm_2.hostid] + + host = hosts[0] + self.debug("Migrating VM-ID: %s to Host: %s" % (self.vm_2.id, host.id)) + + cmd = migrateVirtualMachine.migrateVirtualMachineCmd() + cmd.hostid = host.id + cmd.virtualmachineid = self.vm_2.id + self.apiclient.migrateVirtualMachine(cmd) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.vm_2.id + ) + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.hostid, + host.id, + "Check destination hostID of migrated VM" + ) + self.debug("Migrated VM-ID: %s to Host: %s" % (self.vm_2.id, host.id)) + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Both request should be served by different instances" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after migrate" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_05_reboot_user_vm(self): + """Test reboot user VM with LB""" + + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Reboot one of the user VM + # 3. Test whether the request are sent to both VMs after reboot + # 4. In netscaler, LB rules for this VM still remain configured. + + self.debug("Rebooting VM instance: %s" % self.vm_2.name) + self.vm_2.reboot(self.apiclient) + self.debug("Rebooting VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh_1.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh_2 = self.vm_2.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh_2.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertNotEqual( + hostnames[0], + hostnames[1], + "Both request should be served by different instances" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertNotEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should be present in netscaler after reboot" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_06_destroy_user_vm(self): + """Test destroy user VM with LB""" + + + # Validate the following + # 1. Create 2 instances and add these two for load balancing + # 2. Destroy one of the user VM + # 3. Until the time the Vm is in "Destroyed" state, the servies + # relating to this Vm will be marked as "Down". + # 4. Once the Vm gets expunged, then the servers and services + # associated with this VM should get deleted and the LB rules + # should not be pointing to this Vm anymore. + + self.debug("Destroying VM instance: %s" % self.vm_2.name) + self.vm_2.delete(self.apiclient) + self.debug("Destroying VM: %s" % self.vm_2.name) + + try: + self.debug( + "Verifying request served by only running instances") + hostnames = [] + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True + ) + self.debug("Command: hostname") + result = ssh.execute("hostname") + self.debug("Output: %s" % result) + hostnames.append(result) + self.debug("Hostnames: %s" % str(hostnames)) + + self.assertEqual( + hostnames[0], + hostnames[1], + "Both request should be served by same instance" + ) + except Exception as e: + self.fail("Exception occured during SSH: %s - %s" % ( + self.public_ip_1.ipaddress.ipaddress, + e)) + delay = list_configurations( + self.apiclient, + name='expunge.delay' + ) + wait = list_configurations( + self.apiclient, + name='expunge.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(delay[0].value) + int(wait[0].value)) + self.debug("SSH into Netscaler to rules still persist") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + + cmd = "show server" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.vm_2.ipaddress), + 0, + "The server should not be present in netscaler after destroy" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_07_delete_all_public_ip(self): + """Test delete all public Ip with LB rules""" + + + # Validate the following + # 1. Associate 2 public Ips and create load balancing rules in it + # 2. Delete all of the public Ip + # 3. All the LB rules should be removed from that public Ip + # 4. In netscaler, make sure that all LB rules associated with that + # public Ip should get removed. + # 5. All servers and services service to that public Ip get deleted + + self.debug("Deleting public IP: %s from network: %s" % ( + self.public_ip_1.ipaddress.ipaddress, + self.network.name + )) + self.public_ip_1.delete(self.apiclient) + self.debug( + "Public Ip: %s is deleted!" % + self.public_ip_1.ipaddress.ipaddress) + lb_rules = LoadBalancerRule.list( + self.apiclient, + publicipid=self.public_ip_1.ipaddress.id, + listall=True, + ) + self.assertEqual( + lb_rules, + None, + "LB rules associated with the public Ip should get deleted" + ) + self.debug("SSH into Netscaler to verify other resources are deleted") + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip_1.ipaddress.ipaddress, + self.lb_rule_1.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("ERROR: No such resource"), + 1, + "Virtual server should get deleted after removing LB rule" + ) + + cmd = "show ip" + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count(self.public_ip_1.ipaddress.ipaddress), + 0, + "Virtual server should get deleted after removing LB rule" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return diff --git a/test/integration/component/test_netscaler_lb_algo.py b/test/integration/component/test_netscaler_lb_algo.py new file mode 100644 index 00000000000..75b15d61c43 --- /dev/null +++ b/test/integration/component/test_netscaler_lb_algo.py @@ -0,0 +1,2031 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for netscaler load balancing +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '192.168.100.213', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "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": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestLbWithRoundRobin(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbWithRoundRobin, + 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["ostype"] + ) + + 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.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.network_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.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_with_round_robin(self): + """Test Create LB rule with round robin algorithm + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule with round robin algorithm + # on it. Verify that "Roundrobin" algorithm is applied when using + # this load balancing rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + ip_with_lb_rule.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbWithLeastConn(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbWithLeastConn, + 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["ostype"] + ) + + 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.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.network_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.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_with_least_conn(self): + """Test Create LB rule with least connection algorithm + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule with round robin algorithm + # on it. Verify that "leastconn" algorithm is applied when using + # this load balancing rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + + PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + ip_with_lb_rule.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'LEASTCONNECTION' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbWithSourceIp(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbWithSourceIp, + 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["ostype"] + ) + + 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.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.network_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.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_with_source_ip(self): + """Test Create LB rule with source Ip algorithm + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create LB rule with round robin algorithm + # on it. Verify that "sourceIp" algorithm is applied when using + # this load balancing rule. + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Associating public IP for network: %s" % self.network.id) + + ip_with_lb_rule = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network.id + ) + self.debug("Associated %s with network %s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + self.network.id + )) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + ip_with_lb_rule.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=ip_with_lb_rule.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + ip_with_lb_rule.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCEIPHASH' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbAlgoRrLc(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoRrLc, + 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["ostype"] + ) + 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.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_round_robin_to_least_conn(self): + """Test edit LB rule from round robin to least connection algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "RounbRobin" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "Round robin" algorithm to + # "LeastConn" After the update, Verify that "least Connection" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'leastconn')) + lb_rule.update(self.apiclient, algorithm='leastconn') + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'LEASTCONNECTION' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbAlgoLcRr(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoLcRr, + 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["ostype"] + ) + 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.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_least_conn_to_round_robin(self): + """Test edit LB rule from least conn to round robin algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "Leastconn" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "Least conn" algorithm to + # "roundrobin" After the update, Verify that "round robin" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with least conn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'LEASTCONNECTION' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'roundrobin')) + lb_rule.update(self.apiclient, algorithm='roundrobin') + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbAlgoRrSb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoRrSb, + 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["ostype"] + ) + 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.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_round_robin_to_source(self): + """Test edit LB rule from round robin to source algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "RounbRobin" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "Round robin" algorithm to + # "Source" After the update, Verify that "Source" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'source')) + lb_rule.update(self.apiclient, algorithm='source') + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCEIPHASH' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbAlgoSbRr(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoSbRr, + 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["ostype"] + ) + 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.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_source_to_round_robin(self): + """Test edit LB rule from source to round robin algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "source" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "source" algorithm to + # "roundrobin" After the update, Verify that "round robin" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCEIPHASH' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'roundrobin')) + lb_rule.update(self.apiclient, algorithm='roundrobin') + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbAlgoSbLc(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoSbLc, + 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["ostype"] + ) + 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.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_source_to_least_conn(self): + """Test edit LB rule from source to least conn algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "source" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "source" algorithm to + # "leastconn" After the update, Verify that "leastconn" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCEIPHASH' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'leastconn')) + lb_rule.update(self.apiclient, algorithm='leastconn') + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'LEASTCONNECTION' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + +class TestLbAlgoLcSb(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbAlgoLcSb, + 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["ostype"] + ) + 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.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.account, + cls.service_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + # Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + # Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_lb_leastconn_to_source(self): + """Test edit LB rule from round robin to source algo + """ + + # Validate the following + # 1. Deploy the first VM using a network from the above created + # Network offering. + # 2. Deploy another VM. + # 3. Acquire Ip address and create an Lb rule for couple of Vms using + # "leastconn" algorithm. Make sure this algorithm is respected. + # 4. Edit this existing LB rule with "leastconn" algorithm to + # "Source" After the update, Verify that "Source" + # algorithm is applied when using this load balancing rule. + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return a newly created LB rule" + ) + self.debug("Adding %s to the LB rule %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'LEASTCONNECTION' algorithm should be configured on NS" + ) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + + self.debug( + "Updating LB rule: %s with new algorithm: %s" % ( + lb_rule.name, + 'source')) + lb_rule.update(self.apiclient, algorithm='source') + + self.debug("SSH into Netscaler to check whether algorithm is configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCEIPHASH' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return diff --git a/test/integration/component/test_netscaler_lb_sticky.py b/test/integration/component/test_netscaler_lb_sticky.py new file mode 100644 index 00000000000..a921f4b3afe --- /dev/null +++ b/test/integration/component/test_netscaler_lb_sticky.py @@ -0,0 +1,1032 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for netscaler load balancing sticky policy +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler": { + "ipaddress": '192.168.100.213', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "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": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode":'advanced' + } + + +class TestLbStickyPolicy(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestLbStickyPolicy, + 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["ostype"] + ) + + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + # Creating network using the network offering created + cls.network = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.network_offering.id, + zoneid=cls.zone.id + ) + + # Spawn an instance in that network + cls.virtual_machine = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network.id)] + ) + cls.public_ip = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network.id + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cls.network_offering.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_source_based_roundrobin(self): + """Test Create a "SourceBased" stick policy for a Lb rule with "RoundRobin" algorithm + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "SourceBased" stick policy for a Lb rule with + # "RoundRobin" algorithm + + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + self.public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='SourceBased', + name='SourceBasedRR', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: SOURCEIP"), + 1, + "'SourceBased' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_02_source_based_source_algo(self): + """Test Create a "SourceBased" stick policy for a Lb rule with "Source" algorithm + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "SourceBased" stick policy for a Lb rule with + # "Source" algorithm + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='SourceBased', + name='SourceBasedSource', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: SOURCEIP"), + 1, + "'SourceBased' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCE' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_03_source_based_leastconn(self): + """Test Create a "SourceBased" stick policy for a Lb rule with leastconn algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "SourceBased" stick policy for a Lb rule with + # "leastconn" algorithm + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='SourceBased', + name='SourceBasedLeast', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: SOURCEIP"), + 1, + "'SourceBased' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'leastconn' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_04_lbcookie_based_roundrobin(self): + """Test Create a "LBCookie" stick policy for a Lb rule with roundrobin algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "LBCookie" stick policy for a Lb rule with + # "roundrobin" algorithm + + self.debug( + "Creating LB rule for IP address: %s with roundrobin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='LbCookie', + name='LbCookieRR', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: COOKIEINSERT"), + 1, + "'LBCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_05_lbcookie_source_algo(self): + """Test Create a "LBCookie" stick policy for a Lb rule with "Source" algorithm + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "LBCookie" stick policy for a Lb rule with + # "Source" algorithm + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='LbCookie', + name='LbCookieSource', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: COOKIEINSERT"), + 1, + "'LbCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCE' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_06_lbcookie_leastconn(self): + """Test Create a "LBCookie" stick policy for a Lb rule with leastconn algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "LBCookie" stick policy for a Lb rule with + # "leastconn" algorithm + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='LBCookie', + name='LbcookieLeastConn', + param={"holdtime": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: COOKIEINSERT"), + 1, + "'LbCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'leastconn' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_07_appcookie_based_roundrobin(self): + """Test Create a "AppCookie" stick policy for a Lb rule with roundrobin algo + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "AppCookie" stick policy for a Lb rule with + # "roundrobin" algorithm + + self.debug( + "Creating LB rule for IP address: %s with roundrobin algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'roundrobin' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='AppCookie', + name='AppCookieRR', + param={"name": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: RULE"), + 1, + "'AppCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: ROUNDROBIN"), + 1, + "'ROUNDROBIN' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_08_appcookie_source_algo(self): + """Test Create a "AppCookie" stick policy for a Lb rule with "Source" + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "AppCookie" stick policy for a Lb rule with + # "Source" algorithm + + self.debug( + "Creating LB rule for IP address: %s with source algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'source' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='AppCookie', + name='AppCookieSource', + param={"name": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: RULE"), + 1, + "'AppCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: SOURCEIPHASH"), + 1, + "'SOURCE' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return + + @attr(tags = ["advancedns"]) + def test_09_appcookie_leastconn(self): + """Test Create a "AppCookie" stick policy for a Lb rule with leastconn + """ + + # Validate the following + # 1. Configure Netscaler for load balancing. + # 2. Create a Network offering with LB services provided by Netscaler + # and all other services by VR. + # 3. Create a new account/user. + # 4. Deploy few VMs using a network from the above created Network + # offering. + # 5. Create a "AppCookie" stick policy for a Lb rule with + # "leastconn" algorithm + + self.debug( + "Creating LB rule for IP address: %s with leastconn algo" % + self.public_ip.ipaddress.ipaddress) + + self.services["lbrule"]["alg"] = 'leastconn' + self.services["lbrule"]["publicport"] = 80 + self.services["lbrule"]["privateport"] = 80 + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=self.public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=self.network.id + ) + self.cleanup.append(lb_rule) + self.debug("Created the load balancing rule for public IP: %s" % + self.public_ip.ipaddress.ipaddress) + + self.debug("Assigning VM instance: %s to LB rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [self.virtual_machine]) + self.debug("Assigned VM instance: %s to lb rule: %s" % ( + self.virtual_machine.name, + lb_rule.name + )) + self.debug( + "Configuring 'SourceBased' Sticky policy on lb rule: %s" % + lb_rule.name) + try: + result = lb_rule.createSticky( + self.apiclient, + methodname='AppCookie', + name='AppCookieLeastConn', + param={"name": 20} + ) + self.debug("Response: %s" % result) + except Exception as e: + self.fail("Configure sticky policy failed with exception: %s" % e) + + self.debug("SSH into Netscaler to check whether sticky policy configured properly or not?") + self.debug("SSH into netscaler: %s" % + self.services["netscaler"]["ipaddress"]) + try: + ssh_client = remoteSSHClient( + self.services["netscaler"]["ipaddress"], + self.services["netscaler"]["port"], + self.services["netscaler"]["username"], + self.services["netscaler"]["password"], + ) + cmd = "show lb vserver Cloud-VirtualServer-%s-%s" % ( + self.public_ip.ipaddress.ipaddress, + lb_rule.publicport) + self.debug("command: %s" % cmd) + res = ssh_client.execute(cmd) + result = str(res) + self.debug("Output: %s" % result) + + self.assertEqual( + result.count("Persistence: RULE"), + 1, + "'AppCookie' sticky policy should be configured on NS" + ) + + self.assertEqual( + result.count("Configured Method: LEASTCONNECTION"), + 1, + "'leastconn' algorithm should be configured on NS" + ) + + except Exception as e: + self.fail("SSH Access failed for %s: %s" % \ + (self.services["netscaler"]["ipaddress"], e)) + return diff --git a/test/integration/component/test_netscaler_nw_off.py b/test/integration/component/test_netscaler_nw_off.py new file mode 100644 index 00000000000..cd3b48e5930 --- /dev/null +++ b/test/integration/component/test_netscaler_nw_off.py @@ -0,0 +1,2370 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for multiple netscaler instances +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test netscaler 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "virtual_machine": { + "displayname": "TestVM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "netscaler_1": { + "ipaddress": '192.168.100.213', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "netscaler_2": { + "ipaddress": '192.168.100.100', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "netscaler_3": { + "ipaddress": '192.168.100.101', + "username": 'nsroot', + "password": 'nsroot', + "networkdevicetype": 'NetscalerVPXLoadBalancer', + "publicinterface": '1/1', + "privateinterface": '1/1', + "numretries": 2, + "lbdevicededicated": False, + "lbdevicecapacity": 50, + "port": 22, + }, + "network_offering_dedicated": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "specifyVlan": False, + "specifyIpRanges": False, + "serviceProviderList": { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Vpn": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "servicecapabilitylist": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount" + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "network_offering": { + "name": 'Netscaler', + "displaytext": 'Netscaler', + "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": 'Netscaler', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + }, + "network": { + "name": "Netscaler", + "displaytext": "Netscaler", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "ostypeid": '01853327-513e-4508-9628-f1f55db1946f', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestAddMultipleNetScaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestAddMultipleNetScaler, + 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._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: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_add_netscaler_device(self): + """Test add netscaler device + """ + + + # Validate the following + # 1. Add multiple instances of netscaler + # 2. Netscaler should be configured successfully. + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + self.debug("Adding netscaler device: %s" % + self.services["netscaler_1"]["ipaddress"]) + netscaler_1 = NetScaler.add( + self.apiclient, + self.services["netscaler_1"], + physicalnetworkid=physical_network.id + ) + self.cleanup.append(netscaler_1) + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("Netscaler service provider is already enabled.") + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=netscaler_1.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + self.assertEqual( + ns.physicalnetworkid, + physical_network.id, + "Physical network id should match with the network in which device is configured" + ) + + self.debug("Adding netscaler device: %s" % + self.services["netscaler_2"]["ipaddress"]) + netscaler_2 = NetScaler.add( + self.apiclient, + self.services["netscaler_2"], + physicalnetworkid=physical_network.id + ) + self.cleanup.append(netscaler_2) + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=netscaler_1.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + self.assertEqual( + ns.physicalnetworkid, + physical_network.id, + "Physical network id should match with the network in which device is configured" + ) + self.debug("Another Netscaler device is added!") + return + + +class TestAddMultipleNSDiffZone(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestAddMultipleNSDiffZone, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + cls._cleanup = [] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns", "multizone"]) + def test_add_mul_netscaler_diff_zone(self): + """Test add netscaler devices in different zones + """ + + + # Validate the following + # 1. Add multiple instances of Netscaler in different zones + # 2. Netscaler should be configured successfully. + + # Check if there are multiple zones present in the given setup + zones = Zone.list(self.apiclient, listall=True) + self.assertEqual( + isinstance(zones, list), + True, + "List Zones API should return a valid list" + ) + + # Find the number of zones configured in advanced mode + zone_list = [] + for zone in zones: + if zone.networktype == 'Advanced': + zone_list.append(zone) + + self.assertGreater( + len(zone_list), + 1, + "Atleast 2 advanced mode zones should be present for this test" + ) + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=zone_list[0].id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + self.debug("Adding netscaler device: %s" % + self.services["netscaler_1"]["ipaddress"]) + netscaler = NetScaler.add( + self.apiclient, + self.services["netscaler_1"], + physicalnetworkid=physical_network.id + ) + self.cleanup.append(netscaler_1) + self.debug("Checking if Netscaler network service provider is enabled?") + + nw_service_providers = NetworkServiceProvider.list( + self.apiclient, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + self.assertEqual( + isinstance(nw_service_providers, list), + True, + "Network service providers list should not be empty" + ) + netscaler_provider = nw_service_providers[0] + if netscaler_provider.state != 'Enabled': + self.debug("Netscaler provider is not enabled. Enabling it..") + response = NetworkServiceProvider.update( + self.apiclient, + id=netscaler_provider.id, + state='Enabled' + ) + self.assertEqual( + response.state, + "Enabled", + "Network service provider should be in enabled state" + ) + else: + self.debug("Netscaler service provider is already enabled.") + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=netscaler_1.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + self.assertEqual( + ns.physicalnetworkid, + physical_network.id, + "Physical network id should match with the network in which device is configured" + ) + + physical_networks = PhysicalNetwork.list( + self.apiclient, + zoneid=zone_list[1].id + ) + self.assertEqual( + isinstance(physical_networks, list), + True, + "There should be atleast one physical network for advanced zone" + ) + physical_network = physical_networks[0] + + self.debug("Adding netscaler device: %s" % + self.services["netscaler_2"]["ipaddress"]) + netscaler_2 = NetScaler.add( + self.apiclient, + self.services["netscaler_2"], + physicalnetworkid=physical_network.id + ) + self.cleanup.append(netscaler_2) + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=netscaler_2.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + self.assertEqual( + ns.physicalnetworkid, + physical_network.id, + "Physical network id should match with the network in which device is configured" + ) + self.debug("Another Netscaler device is added!") + return + + +class TestNetScalerSharedMode(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetScalerSharedMode, + 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"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + cls.physical_network = physical_networks[0] + cls.services["netscaler_1"]["lbdevicecapacity"] = 2 + cls.netscaler_1 = NetScaler.add( + cls.api_client, + cls.services["netscaler_1"], + physicalnetworkid=cls.physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=cls.physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + 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.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls.account_1 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.account_2 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.account_3 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.account_4 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls.account_5 = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.account_1, + cls.account_2, + cls.account_3, + cls.account_5 + ] + cls.cleanup_devices = [cls.netscaler_1] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + interval = list_configurations( + cls.api_client, + name='network.gc.interval' + ) + wait = list_configurations( + cls.api_client, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cleanup_resources(cls.api_client, cls.cleanup_devices) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_01_netscaler_shared_mode(self): + """Test netscaler device in shared mode + """ + + + # Validate the following + # 1. Add Netscaler device in shared mode with capacity 3 + # 2. Netscaler should be configured successfully.It should be able to + # service only 3 account. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler_1.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + + with self.assertRaises(Exception): + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + + self.debug("Deploy VM failed as Netscaler device capacity is full!") + return + + @attr(tags = ["advancedns"]) + def test_02_multiple_netscaler_capacilty(self): + """Test multiple netscaler devices with limited capacity + """ + + + # Validate the following + # 1. Add another netscaler device and spawn a new VM again + # 2. VM deployement should be successful + + self.debug("Adding another netscaler device: %s" % + self.services["netscaler_2"]["ipaddress"]) + self.services["netscaler_2"]["lbdevicecapacity"] = 2 + netscaler_2 = NetScaler.add( + self.apiclient, + self.services["netscaler_2"], + physicalnetworkid=self.physical_network.id + ) + self.cleanup_devices.append(netscaler_2) + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=netscaler_2.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + self.assertEqual( + ns.physicalnetworkid, + self.physical_network.id, + "Physical network id should match with the network in which device is configured" + ) + self.debug("Another Netscaler device is added!") + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + networks = Network.list( + self.apiclient, + account=self.account_3.account.name, + domainid=self.account_3.account.domainid, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "Network should be present for the account: %s" % + self.account_3.account.name + ) + self.network_3 = networks[0] + self.debug("Created network with ID: %s" % self.network_3.id) + + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_3.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_3.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + return + + @attr(tags = ["advancedns"]) + def test_03_multiple_netscaler_full_capacilty(self): + """Test netscaler device with full capacity + """ + + + # Validate the following + # 1. Spawn multiple instances for utilizing full capacity of Netscaler + # 2. Deploy VM should fail after capacity full in netscaler device + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_4 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_4.account.name, + domainid=self.account_4.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_4.id) + + self.debug("Deploying VM in account: %s" % self.account_4.account.name) + + # Spawn an instance in that network + virtual_machine_4 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_4.account.name, + domainid=self.account_4.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_4.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_4.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_4.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_4.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_5 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_5.account.name, + domainid=self.account_5.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_5.id) + + self.debug("Deploying VM in account: %s" % self.account_5.account.name) + + with self.assertRaises(Exception): + # Spawn an instance in that network + virtual_machine_5 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_5.account.name, + domainid=self.account_5.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_5.id)] + ) + self.debug("Deploy VM failed as Netscaler device capacity is full!") + return + + @attr(configuration = "network.gc") + @attr(tags = ["advancedns"]) + def test_04_delete_account_after_capacity_full(self): + """Test delete and add resouces after netscaler device capacity is full + """ + + + # Validate the following + # 1. Delete one of the account. Wait till Network.gc.wait & + # network.gc.interval time + # 2. Create an instance from another account + # 3. Deploy instance should succeed + + self.debug("Delete account: %s" % self.account_4.account.name) + self.account_4.delete(self.apiclient) + self.debug("Account: %s is deleted" % self.account_4.account.name) + + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + self.debug("Sleeping for: network.gc.interval + network.gc.wait") + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering.id) + self.network_5 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_5.account.name, + domainid=self.account_5.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_5.id) + + self.debug("Deploying VM in account: %s" % self.account_5.account.name) + + # Spawn an instance in that network + virtual_machine_5 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_5.account.name, + domainid=self.account_5.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_5.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_5.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_5.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_5.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + return + + +class TestNwOffDedicatedNetscaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNwOffDedicatedNetscaler, + 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"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + cls.services["netscaler_1"]["lbdevicecapacity"] = 3 + cls.netscaler = NetScaler.add( + cls.api_client, + cls.services["netscaler_1"], + physicalnetworkid=physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_dedicated"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.netscaler, + ] + 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_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_nw_off_dedicated_mode(self): + """Test network offering in dedicated mode device + """ + + + # Validate the following + # 1. Add Netscaler device in shared mode + # 2. Create a network offering in dedicated mode. + # 3. Try to implemenent network with that network offering. Network + # craetion should fail. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Deploy Instance with network: %s" % self.network_1.name) + with self.assertRaises(Exception): + # Spawn an instance in that network + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Created instance failed!") + return + + +class TestNwOffNetscaler(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNwOffNetscaler, + 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"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + physical_network = physical_networks[0] + cls.services["netscaler_1"]["lbdevicecapacity"] = 3 + cls.netscaler_1 = NetScaler.add( + cls.api_client, + cls.services["netscaler_1"], + physicalnetworkid=physical_network.id + ) + + cls.services["netscaler_2"].pop("lbdevicecapacity") + cls.services["netscaler_2"]["lbdevicededicated"] = True + cls.netscaler_2 = NetScaler.add( + cls.api_client, + cls.services["netscaler_2"], + physicalnetworkid=physical_network.id + ) + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_dedicated"], + conservemode=True + ) + cls.network_offering_shared = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering.update(cls.api_client, state='Enabled') + cls.network_offering_shared.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering, + cls.network_offering_shared, + cls.netscaler_1, + cls.netscaler_2, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_3 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_2, self.account_3] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_ns_shared_nw_dedicated(self): + """Test netscaler device in shared mode with network offering in dedicated mode + """ + + + # Validate the following + # 1. Add Netscaler device in shared mode + # 2. Create a network offering in dedicated mode. + # 3. Try to implemenent network with that network offering. Network + # craetion should fail. + + ns_list = NetScaler.list( + self.apiclient, + lbdeviceid=self.netscaler_1.lbdeviceid + ) + self.assertEqual( + isinstance(ns_list, list), + True, + "NetScaler list should not be empty" + ) + ns = ns_list[0] + + self.assertEqual( + ns.lbdevicededicated, + False, + "NetScaler device is configured in shared mode" + ) + self.assertEqual( + ns.lbdevicestate, + "Enabled", + "NetScaler device state should be enabled" + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + # Creating network using the network offering created + self.debug("Creating different network with network offering: %s" % + self.network_offering.id) + + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug( + "Attempt to create second network with dedicated network offering failed!") + self.debug("Deleting account: %s" % self.account_1.account.name) + self.account_1.delete(self.apiclient) + self.debug("Account: %s deleted!" % self.account_1.account.name) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + self.debug("Sleeping for: network.gc.interval + network.gc.wait") + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering_shared.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering_shared.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_3.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_3.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + return + + +class TestNwOffSToDUpgrade(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNwOffSToDUpgrade, + 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"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + cls.physical_network = physical_networks[0] + cls.services["netscaler_1"]["lbdevicecapacity"] = 3 + cls.netscaler_1 = NetScaler.add( + cls.api_client, + cls.services["netscaler_1"], + physicalnetworkid=cls.physical_network.id + ) + + cls.services["netscaler_2"].pop("lbdevicecapacity") + cls.services["netscaler_2"]["lbdevicededicated"] = True + cls.netscaler_2 = NetScaler.add( + cls.api_client, + cls.services["netscaler_2"], + physicalnetworkid=cls.physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=cls.physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering_dedicated = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_dedicated"], + conservemode=True + ) + cls.network_offering_shared = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering_dedicated.update(cls.api_client, state='Enabled') + cls.network_offering_shared.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering_dedicated, + cls.network_offering_shared, + cls.netscaler_1, + cls.netscaler_2, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_3 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2, self.account_3] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_shared_to_dedicated_upgrade(self): + """Test upgrade from shared LB isolation to dedicated LB isolation""" + + + # Validate the following + # 1. Create a dedicated and shared network offering + # 2. Configure 2 instances of Netscaler one with dedicated and other + # shared mode + # 3. Deploy instance with shared network offering in account 1. create + # LB rules + # 4. Deploy instance with shared network offering in account 2. create + # LB rules + # 5. Deploy instance with dedicated network offering in account 3. + # Create Lb rules. + # 6. Configure another instace of netscaler in dedicated mode + # 7. upgrade networkj for user 1 to dedicated network offering. + # Create LB rules. LB rule creation should be successful + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering_shared.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering_shared.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering_shared.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering_shared.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering_dedicated.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering_dedicated.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_3.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_3.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("Configuring another Netscaler device in dedicated mode") + + self.services["netscaler_3"].pop("lbdevicecapacity") + self.services["netscaler_3"]["lbdevicededicated"] = True + self.netscaler_3 = NetScaler.add( + self.apiclient, + self.services["netscaler_3"], + physicalnetworkid=self.physical_network.id + ) + + self.debug("Stopping All VMs before upgrading network for account: %s" % + self.account_1.account.name) + virtual_machine_1.stop(self.apiclient) + + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM state should be running after deployment" + ) + self.debug("All Vms are in stopped state") + self.debug("Upgrading the network: %s" % self.network_1.id) + self.network_1.update( + self.apiclient, + networkofferingid=self.network_offering_dedicated.id, + changecidr=True + ) + networks = Network.list( + self.apiclient, + id=self.network_1.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List Networks should return a valid list for given network ID" + ) + self.assertNotEqual( + len(networks), + 0, + "Length of list networks should not be 0" + ) + network = networks[0] + self.assertEqual( + network.networkofferingid, + self.network_offering_dedicated.id, + "Network offering ID should match with new offering ID" + ) + + self.debug("Starting All VMs after upgrading network for account: %s" % + self.account_1.account.name) + virtual_machine_1.start(self.apiclient) + + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + self.debug("All Vms are in running state") + try: + self.debug( + "Associating public Ip to the network: %s" % + self.network_1.name) + + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account_1.account.name, + zoneid=self.zone.id, + domainid=self.account_1.account.domainid, + networkid=self.network_1.id + ) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account_1.account.name, + networkid=self.network_1.id + ) + self.debug("Created the load balancing rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to create load balancing rule - %s" % e) + return + + +class TestNwOffDToSUpgrade(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNwOffDToSUpgrade, + 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"] + ) + + physical_networks = PhysicalNetwork.list( + cls.api_client, + zoneid=cls.zone.id + ) + if isinstance(physical_networks, list): + cls.physical_network = physical_networks[0] + cls.services["netscaler_1"]["lbdevicecapacity"] = 3 + cls.netscaler_1 = NetScaler.add( + cls.api_client, + cls.services["netscaler_1"], + physicalnetworkid=cls.physical_network.id + ) + + cls.services["netscaler_2"].pop("lbdevicecapacity") + cls.services["netscaler_2"]["lbdevicededicated"] = True + cls.netscaler_2 = NetScaler.add( + cls.api_client, + cls.services["netscaler_2"], + physicalnetworkid=cls.physical_network.id + ) + + nw_service_providers = NetworkServiceProvider.list( + cls.api_client, + name='Netscaler', + physicalnetworkid=cls.physical_network.id + ) + if isinstance(nw_service_providers, list): + netscaler_provider = nw_service_providers[0] + + if netscaler_provider.state != 'Enabled': + response = NetworkServiceProvider.update( + cls.api_client, + id=netscaler_provider.id, + state='Enabled' + ) + cls.network_offering_dedicated = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_dedicated"], + conservemode=True + ) + cls.network_offering_shared = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=True + ) + # Enable Network offering + cls.network_offering_dedicated.update(cls.api_client, state='Enabled') + cls.network_offering_shared.update(cls.api_client, state='Enabled') + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.network_offering_dedicated, + cls.network_offering_shared, + cls.netscaler_1, + cls.netscaler_2, + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account_1 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_2 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.account_3 = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account_1, self.account_2, self.account_3] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Cleanup complete!") + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advancedns"]) + def test_shared_to_dedicated_upgrade(self): + """Test upgrade from shared LB isolation to dedicated LB isolation""" + + + # Validate the following + # 1. Create a dedicated and shared network offering + # 2. Configure 2 instances of Netscaler one with dedicated and other + # shared mode + # 3. Deploy instance with shared network offering in account 1. create + # LB rules + # 4. Deploy instance with shared network offering in account 2. create + # LB rules + # 5. Deploy instance with dedicated network offering in account 3. + # Create Lb rules. + # 6. Configure another instace of netscaler in dedicated mode + # 7. upgrade networkj for user 1 to dedicated network offering. + # Create LB rules. LB rule creation should be successful + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering_shared.id) + self.network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + networkofferingid=self.network_offering_shared.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_1.id) + + self.debug("Deploying VM in account: %s" % self.account_1.account.name) + + # Spawn an instance in that network + virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_1.account.name, + domainid=self.account_1.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_1.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_1.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering_shared.id) + self.network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + networkofferingid=self.network_offering_shared.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_2.id) + + self.debug("Deploying VM in account: %s" % self.account_2.account.name) + + # Spawn an instance in that network + virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_2.account.name, + domainid=self.account_2.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_2.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_2.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + # Creating network using the network offering created + self.debug("Trying to create network with network offering: %s" % + self.network_offering_dedicated.id) + self.network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + networkofferingid=self.network_offering_dedicated.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % self.network_3.id) + self.debug("Deploying VM in account: %s" % self.account_3.account.name) + + # Spawn an instance in that network + virtual_machine_3 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account_3.account.name, + domainid=self.account_3.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network_3.id)] + ) + self.debug("Deployed VM in network: %s" % self.network_3.id) + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_3.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + + self.debug("Stopping all VMs in account: %s" % self.account_3.account.name) + virtual_machine_3.stop(self.apiclient) + + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_3.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM state should be stopped" + ) + self.debug("All user VMs stopped") + self.debug("Upgrading the network: %s" % self.network_3.id) + self.network_3.update( + self.apiclient, + networkofferingid=self.network_offering_shared.id, + changecidr=True + ) + networks = Network.list( + self.apiclient, + id=self.network_3.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List Networks should return a valid list for given network ID" + ) + self.assertNotEqual( + len(networks), + 0, + "Length of list networks should not be 0" + ) + network = networks[0] + self.assertEqual( + network.networkofferingid, + self.network_offering_shared.id, + "Network offering ID should match with new offering ID" + ) + self.debug("Starting instances in account: %s" % self.account_3.account.name) + virtual_machine_3.start(self.apiclient) + + list_vm_response = VirtualMachine.list( + self.apiclient, + id=virtual_machine_3.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % virtual_machine_3.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + try: + self.debug( + "Associating public Ip to the network: %s" % + self.network_3.name) + + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account_3.account.name, + zoneid=self.zone.id, + domainid=self.account_3.account.domainid, + networkid=self.network_3.id + ) + self.debug( + "Creating LB rule for IP address: %s with round robin algo" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account_3.account.name, + networkid=self.network_3.id + ) + self.debug("Created the load balancing rule for public IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to create load balancing rule - %s" % e) + return diff --git a/test/integration/component/test_network_offering.py b/test/integration/component/test_network_offering.py index e33c3765642..b51d0e4c8cb 100644 --- a/test/integration/component/test_network_offering.py +++ b/test/integration/component/test_network_offering.py @@ -5,9 +5,9 @@ # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY diff --git a/test/integration/component/test_redundant_router.py b/test/integration/component/test_redundant_router.py new file mode 100644 index 00000000000..c24a58a694f --- /dev/null +++ b/test/integration/component/test_redundant_router.py @@ -0,0 +1,5581 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +from random import random +import marvin +from nose.plugins.attrib import attr +from marvin.integration.lib.base import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.common import * + +#Import Local Modules +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin import remoteSSHClient + + +class Services: + """Test Services for customer defects + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "disk_offering": { + "displaytext": "Small", + "name": "Small", + "disksize": 1 + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "volume": { + "diskname": "APP Data Volume", + "size": 1, + # in GBs + "diskdevice": "/dev/xvdb", + # Data Disk + }, + "static_nat": { + "startport": 22, + "endport": 22, + "protocol": "TCP" + }, + "network_offering": { + "name": 'Network offering-RVR services', + "displaytext": 'Network off-RVR services', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Firewall,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "serviceProviderList": { + "Vpn": 'VirtualRouter', + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Firewall": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + }, + "servicecapabilitylist": { + "SourceNat": { + "SupportedSourceNatTypes": "peraccount", + "RedundantRouter": 'true', + }, + "lb": { + "SupportedLbIsolation": "dedicated" + }, + }, + }, + "host": { + "username": "root", + "password": "password", + "publicport": 22, + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + }, + "lbrule": { + "name": "SSH", + "alg": "roundrobin", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": True, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "natrule_221": { + "privateport": 22, + "publicport": 221, + "protocol": "TCP" + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '55.55.0.0/11', + # Any network (For creating FW rule) + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "sleep": 60, + "mode": 'advanced', + # Networking mode, Advanced, Basic + } + + +class TestCreateRvRNetworkOffering(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestCreateRvRNetworkOffering, + 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._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 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", "ssh"]) + def test_createRvRNetworkOffering(self): + """Test create RvR supported network offering + """ + + # Steps to validate + # 1. create a network offering + # - all services by VirtualRouter + # - enable RedundantRouter servicecapability + # 2. enable the network offering + # Validate the following + # 1. Redundant Router offering should be created successfully and + # listed in listNetworkOfferings response + + self.debug("Creating network offering with redundant VR capability") + try: + network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=True + ) + except Exception as e: + self.fail("Create network offering failed! - %s" % e) + + self.debug("Enabling network offering - %s" % network_offering.name) + # Enable Network offering + network_offering.update(self.apiclient, state='Enabled') + self.cleanup.append(network_offering) + + self.debug("Checking if the network offering created successfully?") + network_offs = NetworkOffering.list( + self.apiclient, + id=network_offering.id, + listall=True + ) + self.assertEqual( + isinstance(network_offs, list), + True, + "List network offering should not return empty response" + ) + self.assertEqual( + len(network_offs), + 1, + "List network off should have newly created network off" + ) + return + + +class TestCreateRvRNetwork(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestCreateRvRNetwork, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_createRvRNetwork(self): + """Test create network with redundant routers + """ + + # Validate the following: + # 1. listNetworkOfferings shows created offering + # 2. listNetworks should show created network in Allocated state + # 3. returns no Running routers in the network + # 4. listVirtualmachines shows VM in Running state + # 5. returns 2 routers + # - same public IP + # - same MAC address of public NIC + # - different guestip address + # - redundant state (MASTER or BACKUP) + # - same gateway for the public traffic + # 6. all routers, networks and user VMs are cleaned up + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Redundant states: %s, %s" % ( + master_router.redundantstate, + backup_router.redundantstate + )) + self.assertEqual( + master_router.publicip, + backup_router.publicip, + "Public Ip should be same for both(MASTER & BACKUP)" + ) + self.assertEqual( + master_router.redundantstate, + "MASTER", + "Redundant state of router should be MASTER" + ) + self.assertEqual( + backup_router.redundantstate, + "BACKUP", + "Redundant state of router should be BACKUP" + ) + self.assertNotEqual( + master_router.guestipaddress, + backup_router.guestipaddress, + "Both (MASTER & BACKUP) routers should not have same guest IP" + ) + + self.assertNotEqual( + master_router.guestmacaddress, + backup_router.guestmacaddress, + "Both (MASTER & BACKUP) routers should not have same guestMAC" + ) + return + + +class TestCreateRvRNetworkNonDefaultGuestCidr(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestCreateRvRNetworkNonDefaultGuestCidr, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_createRvRNetwork(self): + """Test create network with redundant routers + """ + + # Validate the following: + # 1. listNetworkOfferings shows created offering + # 2. listNetworks should show created network in Allocated state + # - gw = 192.168.2.1 and cidr = 192.168.2.0/23 + # 3. returns no Running routers in the network + # 4. listVirtualmachines shows VM in Running state + # 5. returns 2 routers + # - same public IP + # - same MAC address of public NIC + # - different guestip address + # - redundant state (MASTER or BACKUP) + # - same gateway for the public traffic + # 6. all routers, networks and user VMs are cleaned up + + # 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, + guestcidr=' 192.168.2.0/23' + ) + self.debug("Created network with ID: %s" % network.id) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + self.assertEqual( + nw_response.gateway, + '192.168.2.1', + "The gateway should be 192.168.2.1" + ) + self.assertEqual( + nw_response.cidr, + '192.168.2.0/23', + "Guest cidr should be 192.168.2.0/23" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.assertEqual( + master_router.publicip, + backup_router.publicip, + "Public Ip should be same for both(MASTER & BACKUP)" + ) + self.assertEqual( + master_router.redundantstate, + "MASTER", + "Redundant state of router should be MASTER" + ) + self.assertEqual( + backup_router.redundantstate, + "BACKUP", + "Redundant state of router should be BACKUP" + ) + self.assertNotEqual( + master_router.guestipaddress, + backup_router.guestipaddress, + "Both (MASTER & BACKUP) routers should not have same guest IP" + ) + + self.assertNotEqual( + master_router.guestmacaddress, + backup_router.guestmacaddress, + "Both (MASTER & BACKUP) routers should not have same guestMAC" + ) + return + + +class TestRVRInternals(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestRVRInternals, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_redundantVR_internals(self): + """Test redundant router internals + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # 2. listRouters in above network + # 3. deployVM in above user account in the created network + # 4. login to both Redundant Routers + # 5. login to user VM + # 6. delete user account + # Validate the following: + # 1. listNetworks lists network in Allocated state + # 2. listRouters lists no routers created yet + # 3. listRouters returns Master and Backup routers + # 4. ssh in to both routers and verify: + # - MASTER router has eth2 with public Ip address + # - BACKUP router has only guest eth0 and link local eth1 + # - Broadcast on MASTER eth2 is non-zero (0.0.0.0) + # - execute checkrouter.sh in router home and check if it is status + # "MASTER|BACKUP" as returned by the listRouters API + # 5. DNS of the user VM is set to RedundantRouter Gateway + # (/etc/resolv.conf) + # Check that the default gateway for the guest is the rvr gateway + # and not the guestIp of either of the RvRs + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Fetching the host details for double hop into router") + + hosts = Host.list( + self.apiclient, + id=master_router.hostid, + listall=True + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + master_host = hosts[0] + self.debug("Host for master router: %s" % master_host.name) + self.debug("Host for master router: %s" % master_host.ipaddress) + + hosts = Host.list( + self.apiclient, + id=backup_router.hostid, + listall=True + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + backup_host = hosts[0] + self.debug("Host for backup router: %s" % backup_host.name) + self.debug("Host for backup router: %s" % backup_host.ipaddress) + self.debug(master_router.linklocalip) + + # Check eth2 port for master router + if self.apiclient.hypervisor.lower() == 'vmware': + result = get_process_status( + self.apiclient.connection.mgtSvr, + 22, + self.apiclient.connection.user, + self.apiclient.connection.passwd, + master_router.linklocalip, + 'ifconfig eth2', + hypervisor=self.apiclient.hypervisor + ) + else: + result = get_process_status( + host.ipaddress, + self.services['host']["publicport"], + self.services['host']["username"], + self.services['host']["password"], + master_router.linklocalip, + 'ifconfig eth2' + ) + + res = str(result) + + self.debug("Command 'ifconfig eth2': %s" % result) + self.debug("Router's public Ip: %s" % master_router.publicip) + self.assertEqual( + res.count(master_router.publicip), + 1, + "master router should have the public IP configured" + ) + self.assertEqual( + result.count('Bcast:0.0.0.0'), + 0, + "Broadcast address of eth2 should not be 0.0.0.0" + ) + + # Check eth2 port for backup router + if self.apiclient.hypervisor.lower() == 'vmware': + result = get_process_status( + self.apiclient.connection.mgtSvr, + 22, + self.apiclient.connection.user, + self.apiclient.connction.passwd, + backup_router.linklocalip, + 'ifconfig eth2', + hypervisor=self.apiclient.hypervisor + ) + else: + result = get_process_status( + host.ipaddress, + self.services['host']["publicport"], + self.services['host']["username"], + self.services['host']["password"], + backup_router.linklocalip, + 'ifconfig eth2' + ) + res = str(result) + + self.debug("Command 'ifconfig eth2': %s" % result) + self.assertEqual( + res.count('Bcast:0.0.0.0'), + 1, + "backup router should NOT have the public IP configured" + ) + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should not return empty response" + ) + vm = vms[0] + + self.assertNotEqual( + vm.nic[0].gateway, + master_router.publicip, + "The gateway of user VM should be same as master router" + ) + + self.assertNotEqual( + vm.nic[0].gateway, + backup_router.publicip, + "The gateway of user VM should be same as backup router" + ) + + return + + +class TestRedundancy(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestRedundancy, + 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["ostype"] + ) + 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.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 + ) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + self.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" % self.network.id) + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(self.network.id)] + ) + self.debug("Deployed VM in network: %s" % self.network.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", "ssh"]) + def test_stopMasterRvR(self): + """Test stop MASTER RVR + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # listNetworks returns the allocated network + # 2. listRouters in above network. Lists no routers in the created + # network + # 3. deployVM in above user account in the created network. VM is + # successfully Running + # 4. listRouters that has redundantstate=MASTER. only one router is + # returned with redundantstate = MASTER for this network + # 5. stopRouter that is Master. Router goes to stopped state + # successfully + # 6. listRouters in the account and in the network. Lists old MASTER + # router in redundantstate=UNKNOWN, and the old BACKUP router as + # new MASTER + # 7. start the stopped router. Stopped rvr starts up successfully and + # is in Running state + # 8. listRouters in the account and in the network. Router shows up as + # BACKUP and NOT MASTER, should have only one BACKUP and one MASTER + # at the end, public IP of the SourceNAT should remain same after + # reboot + # 9. delete the account + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Stopping the MASTER router") + try: + cmd = stopRouter.stopRouter(cmd) + cmd.id = master_router.id + self.apiclient.stopRouter(cmd) + except Exception as e: + self.fail("Failed to stop master router: %s" % e) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=master_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'UNKNOWN', + "Redundant state of the router should be UNKNOWN" + ) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=backup_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'MASTER', + "Redundant state of the router should be MASTER" + ) + + self.debug("Starting the old MASTER router") + try: + cmd = startRouter.startRouter(cmd) + cmd.id = master_router.id + self.apiclient.startRouter(cmd) + self.debug("old MASTER router started") + except Exception as e: + self.fail("Failed to stop master router: %s" % e) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=master_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return backup router" + ) + self.assertEqual( + routers[0].redundantstate, + 'BACKUP', + "Redundant state of the router should be BACKUP" + ) + self.assertEqual( + master_router.publicip, + routers[0].publicip, + "Public IP should be same after reboot" + ) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_stopBackupRvR(self): + """Test stop BACKUP RVR + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # listNetworks returns the allocated network + # 2. listRouters in above network. Lists no routers in the created + # network + # 3. deployVM in above user account in the created network. VM is + # successfully Running + # 4. listRouters that has redundantstate=MASTER. only one router is + # returned with redundantstate = MASTER for this network + # 5. stopRouter that is BACKUP. Router goes to stopped state + # successfully + # 6. listRouters in the account and in the network. Lists old MASTER + # router in redundantstate=UNKNOWN + # 7. start the stopped router. Stopped rvr starts up successfully and + # is in Running state + # 8. listRouters in the account and in the network. Router shows up as + # BACKUP and NOT MASTER, should have only one BACKUP and one MASTER + # at the end, public IP of the SourceNAT should remain same after + # reboot + # 9. delete the account + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Stopping the BACKUP router") + try: + cmd = stopRouter.stopRouter(cmd) + cmd.id = backup_router.id + self.apiclient.stopRouter(cmd) + except Exception as e: + self.fail("Failed to stop backup router: %s" % e) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=backup_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'UNKNOWN', + "Redundant state of the router should be UNKNOWN" + ) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=master_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'MASTER', + "Redundant state of the router should be MASTER" + ) + + self.debug("Starting the old BACKUP router") + try: + cmd = startRouter.startRouter(cmd) + cmd.id = backup_router.id + self.apiclient.startRouter(cmd) + self.debug("old BACKUP router started") + except Exception as e: + self.fail("Failed to stop master router: %s" % e) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=backup_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return backup router" + ) + self.assertEqual( + routers[0].redundantstate, + 'BACKUP', + "Redundant state of the router should be BACKUP" + ) + self.assertEqual( + backup_router.publicip, + routers[0].publicip, + "Public IP should be same after reboot" + ) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_rebootMasterRvR(self): + """Test reboot master RVR + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # listNetworks returns the allocated network + # 2. listRouters in above network. Lists no routers in the created + # network + # 3. deployVM in above user account in the created network. VM is + # successfully Running + # 4. listRouters that has redundantstate=MASTER. only one router is + # returned with redundantstate = MASTER for this network + # 5. reboot router that is MASTER. Router reboots state + # successfully + # 6. lists old MASTER router in redundantstate=BACKUP and the old + # BACKUP router as new MASTER + public IP of the SourceNAT should + # remain same after the reboot + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Rebooting the master router") + try: + cmd = rebootRouter.rebootRouter(cmd) + cmd.id = master_router.id + self.apiclient.rebootRouter(cmd) + except Exception as e: + self.fail("Failed to reboot MASTER router: %s" % e) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=master_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'BACKUP', + "Redundant state of the router should be BACKUP" + ) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=backup_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'MASTER', + "Redundant state of the router should be MASTER" + ) + self.assertEqual( + master_router.publicip, + routers[0].publicip, + "Public IP should be same after reboot" + ) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_rebootBackupRvR(self): + """Test reboot backup RVR + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # listNetworks returns the allocated network + # 2. listRouters in above network. Lists no routers in the created + # network + # 3. deployVM in above user account in the created network. VM is + # successfully Running + # 4. listRouters that has redundantstate=MASTER. only one router is + # returned with redundantstate = MASTER for this network + # 5. reboot router that is BACKUP. Router reboots state + # successfully + # 6. lists old BACKUP router in redundantstate=BACKUP, and the old + # MASTER router is still MASTER+ public IP of the SourceNAT should + # remain same after the reboot + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Rebooting the backuo router") + try: + cmd = rebootRouter.rebootRouter(cmd) + cmd.id = backup_router.id + self.apiclient.rebootRouter(cmd) + except Exception as e: + self.fail("Failed to reboot BACKUP router: %s" % e) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=backup_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'BACKUP', + "Redundant state of the router should be BACKUP" + ) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=master_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'MASTER', + "Redundant state of the router should be MASTER" + ) + self.assertEqual( + master_router.publicip, + routers[0].publicip, + "Public IP should be same after reboot" + ) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_stopBackupRvR_startInstance(self): + """Test stop backup RVR and start instance + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # listNetworks returns the allocated network + # 2. listRouters in above network. Lists no routers in the created + # network + # 3. deployVM in above user account in the created network. VM is + # successfully Running + # 4. listRouters that has redundantstate=MASTER. only one router is + # returned with redundantstate = MASTER for this network + # 5. stop router that is BACKUP. + # 6. listRouters in the account and in the network + # 7. deployVM in the user account in the created network + # 8. listRouters in the account and in the network + # 9. delete the account + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Stopping the backup router") + try: + cmd = stopRouter.stopRouter(cmd) + cmd.id = backup_router.id + self.apiclient.stopRouter(cmd) + except Exception as e: + self.fail("Failed to stop BACKUP router: %s" % e) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=backup_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'UNKNOWN', + "Redundant state of the router should be UNKNOWN" + ) + + # Spawn an instance in that network + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=vm_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % self.network.name) + routers = Router.list( + self.apiclient, + networkid=self.network.id, + id=backup_router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + routers[0].redundantstate, + 'BACKUP', + "Redundant state of the router should be BACKUP" + ) + return + + +class TestApplyAndDeleteNetworkRulesOnRvR(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestApplyAndDeleteNetworkRulesOnRvR, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_apply_and__delete_NetworkRulesOnRvR(self): + """Test apply and delete network rules on redundant router + """ + + # Steps to validate + # 1. listNetworks should show the created network in allocated state + # 2. listRouters returns no running routers + # 3. VMs should be deployed and in Running state + # 4. should list MASTER and BACKUP routers + # 5. listPublicIpAddresses for networkid should show acquired IP + # 6. listRemoteAccessVpns for the network associated should show the + # VPN created + # 7. listRemoteAccessVpns for the network associated should return + # empty response + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip.ipaddress.ipaddress) + try: + static_nat = StaticNATRule.create( + self.apiclient, + self.services["fw_rule"], + ipaddressid=public_ip.ipaddress.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip.ipaddress.ipaddress) + static_nat.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=virtual_machine.id + ) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network.id, + listall=True, + isstaticnat=True + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("creating a FW rule on IP: %s" % + public_ip.ipaddress.ipaddress) + 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"] + ) + self.debug("Created a firewall rule on 22 port of IP: %s" % + public_ip.ipaddress.ipaddress) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network.id + )) + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_221"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=True + ) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule_221"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_3.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id + ) + + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine]) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + return + + +class TestEnableVPNOverRvR(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestEnableVPNOverRvR, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_enableVPNOverRvR(self): + """Test redundant router internals + """ + + # Steps to validate + # 1. listNetworks should show the created network in allocated state + # 2. listRouters returns no running routers + # 3. VMs should be deployed and in Running state + # 4. should list MASTER and BACKUP routers + # 5. listPublicIpAddresses for networkid should show acquired IP addr + # 6. listRemoteAccessVpns for the network associated should show VPN + # created + # 7. listRemoteAccessVpns for the network associated should return + # empty response + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating a remote access VPN for account: %s" % + self.account.account.name) + + try: + vpn = Vpn.create( + self.apiclient, + publicipid=public_ip.ipaddress.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + except Exception as e: + self.fail("Failed to create VPN for account: %s - %s" % ( + self.account.account.name, e)) + + try: + vpnuser = VpnUser.create( + self.apiclient, + username="root", + password="password", + account=self.account.account.name, + domainid=self.account.account.domainid + ) + except Exception as e: + self.fail("Failed to create VPN user: %s" % e) + + self.debug("Checking if the remote access VPN is created or not?") + remote_vpns = Vpn.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + publicipid=public_ip.ipaddress.id, + listall=True + ) + self.assertEqual( + isinstance(remote_vpns, list), + True, + "List remote VPNs should not return empty response" + ) + self.debug("Deleting the remote access VPN for account: %s" % + self.account.account.name) + + try: + vpn.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete VPN : %s" % e) + + self.debug("Checking if the remote access VPN is created or not?") + remote_vpns = Vpn.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + publicipid=public_ip.ipaddress.id, + listall=True + ) + self.assertEqual( + remote_vpns, + None, + "List remote VPNs should not return empty response" + ) + return + + +class TestNetworkRulesMasterDownDeleteNetworkRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetworkRulesMasterDownDeleteNetworkRules, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_applyNetworkRules_MasterDown_deleteNetworkRules(self): + """Test apply network rules when master down and delete network rules + """ + + # Steps to validate + # 1. listNetworks should show the created network in allocated state + # 2. listRouters returns no running routers + # 3. VMs should be deployed and in Running state + # 4. should list MASTER and BACKUP routers + # 5. listPublicIpAddresses for networkid should show acquired IP addr + # 6. listStaticNats for the network associated + # 7. listFirewallRules should show allowed ports open + # 8. ssh to succeed to the guestVM + # 9. listPublicIpAddresses for networkid should show acquired IP addr + # 10. listPortForwardRules to show open ports 221, 222 + # 11. ssh should succeed for both ports + # 12. listPublicIpAddresses for networkid should show acquired IP addr + # 13 and 14. listLoadBalancerRules should show associated VMs for + # public IP + # 15. ssh should succeed to the user VMs + # 16. listRouters should show one Router in MASTER state and Running + # 17. ssh should work for PF, FW, and LB ips + # 18. listRouters should show both routers MASTER and BACKUP in + # Running state + # 19. listPortForwardingRules, listFirewallRules, listLoadBalancerRule + # should return empty response + # 20. listPublicIpAddresses should show now more addresses + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Stopping router ID: %s" % master_router.id) + + try: + #Stop the router + cmd = stopRouter.stopRouterCmd() + cmd.id = master_router.id + self.apiclient.stopRouter(cmd) + except Exception as e: + self.fail("Failed to stop master router..") + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip.ipaddress.ipaddress) + try: + static_nat = StaticNATRule.create( + self.apiclient, + self.services["fw_rule"], + ipaddressid=public_ip.ipaddress.id + ) + static_nat.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=virtual_machine.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network.id, + listall=True, + isstaticnat=True + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("creating a FW rule on IP: %s" % + public_ip.ipaddress.ipaddress) + 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"] + ) + self.debug("Created a firewall rule on 22 port of IP: %s" % + public_ip.ipaddress.ipaddress) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network.id + )) + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_221"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=True + ) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule_221"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_3.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id + ) + + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine]) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Starting router ID: %s" % master_router.id) + + try: + #Stop the router + cmd = startRouter.startRouterCmd() + cmd.id = master_router.id + self.apiclient.startRouter(cmd) + except Exception as e: + self.fail("Failed to start master router..") + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running" + ) + return + + +class TestApplyDeleteNetworkRulesRebootRouter(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestApplyDeleteNetworkRulesRebootRouter, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_applyNetworkRules_MasterDown_deleteNetworkRules(self): + """Test apply network rules when master & backup routers rebooted + """ + + # Steps to validate + # 1. listNetworks should show the created network in allocated state + # 2. listRouters returns no running routers + # 3. VMs should be deployed and in Running state + # 4. should list MASTER and BACKUP routers + # 5. listPublicIpAddresses for networkid should show acquired IP addr + # 6. listStaticNats for the network associated + # 7. listFirewallRules should show allowed ports open + # 8. ssh to succeed to the guestVM + # 9. listPublicIpAddresses for networkid should show acquired IP addr + # 10. listPortForwardRules to show open ports 221, 222 + # 11. ssh should succeed for both ports + # 12. listPublicIpAddresses for networkid should show acquired IP addr + # 13 and 14. listLoadBalancerRules should show associated VMs for + # public IP + # 15. ssh should succeed to the user VMs + # 16. listRouters should show one Router in MASTER state and Running + # 17. ssh should work for PF, FW, and LB ips + # 18. listRouters should show both routers MASTER and BACKUP in + # Running state + # 19. listPortForwardingRules, listFirewallRules, listLoadBalancerRule + # should return empty response + # 20. listPublicIpAddresses should show now more addresses + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip.ipaddress.ipaddress) + try: + static_nat = StaticNATRule.create( + self.apiclient, + self.services["fw_rule"], + ipaddressid=public_ip.ipaddress.id + ) + static_nat.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=virtual_machine.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network.id, + listall=True, + isstaticnat=True + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("creating a FW rule on IP: %s" % + public_ip.ipaddress.ipaddress) + 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"] + ) + self.debug("Created a firewall rule on 22 port of IP: %s" % + public_ip.ipaddress.ipaddress) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network.id + )) + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_221"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=True + ) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_3.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id + ) + + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine]) + + self.debug("Starting router ID: %s" % master_router.id) + + for router in routers: + try: + self.debug("Rebooting router ID: %s" % master_router.id) + #Stop the router + cmd = rebootRouter.rebootRouterCmd() + cmd.id = router.id + self.apiclient.rebootRouter(cmd) + except Exception as e: + self.fail("Failed to reboot router..") + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running" + ) + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule_221"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + return + + +class TestRestartRvRNetworkWithoutCleanup(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestRestartRvRNetworkWithoutCleanup, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_restartRvRNetwork_withoutCleanup(self): + """Test apply rules after network restart + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # 2. listRouters in above network + # 3. deployVM in above user account in the created network + # 4. restartNetwork cleanup=false + # 5. listRouters in the account + # 6. delete the account + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("restarting network with cleanup=False") + try: + network.restart(self.apiclient, cleanup=False) + except Exception as e: + self.fail("Failed to cleanup network - %s" % e) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running" + ) + self.assertIn( + router.linklocalip, + [master_router.linklocalip, backup_router.linklocalip], + "Routers should have same linklocal IP after nw restart" + ) + return + + +class TestRestartRvRNetworkWithCleanup(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestRestartRvRNetworkWithCleanup, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_restartRvRNetwork_withCleanup(self): + """Test Restart network with cleanup + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # 2. listRouters in above network + # 3. deployVM in above user account in the created network + # 4. restartNetwork cleanup=false + # 5. listRouters in the account + # 6. delete the account + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("restarting network with cleanup=True") + try: + network.restart(self.apiclient, cleanup=True) + except Exception as e: + self.fail("Failed to cleanup network - %s" % e) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running" + ) + self.assertIn( + router.linklocalip, + [master_router.linklocalip, backup_router.linklocalip], + "Routers should have same linklocal IP after nw restart" + ) + return + + +class TestDeleteRvRNetwork(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeleteRvRNetwork, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_restartRvRNetwork_withCleanup(self): + """Test Restart network with cleanup + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # 2. listRouters in above network + # 3. deployVM in above user account in the created network + # 4. restartNetwork cleanup=false + # 5. listRouters in the account + # 6. delete the account + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + self.debug("Trying to delete the network with running Vms") + with self.assertRaises(Exception): + network.delete(self.apiclient, cleanup=True) + + self.debug("Network delete failed!") + self.debug("Destroying the user VMs for account: %s" % + self.account.account.name) + + try: + virtual_machine.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete guest Vm from account: %s - %s" % + (self.account.account.name, e)) + + interval = list_configurations( + self.apiclient, + name='expunge.delay' + ) + delay = int(interval[0].value) + interval = list_configurations( + self.apiclient, + name='expunge.interval' + ) + exp = int(interval[0].value) + + self.debug("Sleeping for exp delay + interval time") + # Sleep to ensure that all resources are deleted + time.sleep((delay + exp) * 2) + + self.debug("Trying to delete guest network for account: %s" % + self.account.account.name) + try: + network.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete network: %s" % e) + return + + +class TestNetworkGCRvR(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestNetworkGCRvR, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_networkGC_RvR(self): + """Test network garbage collection with RVR + """ + + # Steps to validate + # 1. createNetwork using network offering for redundant virtual router + # 2. listRouters in above network + # 3. deployVM in above user account in the created network + # 4. stop the running user VM + # 5. wait for network.gc time + # 6. listRouters + # 7. start the routers MASTER and BACK + # 8. wait for network.gc time and listRouters + # 9. delete the account + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + self.debug("Stopping the user VM: %s" % virtual_machine.name) + + try: + virtual_machine.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop guest Vm: %s - %s" % + (virtual_machine.name, e)) + + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + delay = int(interval[0].value) + interval = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + exp = int(interval[0].value) + + self.debug("Sleeping for network gc wait + interval time") + # Sleep to ensure that all resources are deleted + time.sleep((delay + exp) * 2) + + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + for router in routers: + self.assertEqual( + router.state, + "Stopped", + "Router should be in stopped state" + ) + self.debug("Starting the stopped router again") + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router should be in running state" + ) + + self.debug("Sleeping for network gc wait + interval time") + # Sleep to ensure that all resources are deleted + time.sleep((delay + exp) * 2) + + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + for router in routers: + self.assertEqual( + router.state, + "Stopped", + "Router should be in stopped state" + ) + return + + +class TestApplyRulesRestartRvRNetwork(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestApplyRulesRestartRvRNetwork, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_applyRules_restartRvRNetwork(self): + """Test apply rules after network restart + """ + + # Steps to validate + # 1. listNetworks should show the created network in allocated state + # 2. listRouters returns no running routers + # 3. VMs should be deployed and in Running state + # 4. should list MASTER and BACKUP routers + # 5. listPublicIpAddresses for networkid should show acquired IP addr + # 6. listStaticNats for the network associated + # 7. listFirewallRules should show allowed ports open + # 8. ssh to succeed to the guestVM + # 9. listPublicIpAddresses for networkid should show acquired IP addr + # 10. listPortForwardRules to show open ports 221, 222 + # 11. ssh should succeed for both ports + # 12. listPublicIpAddresses for networkid should show acquired IP addr + # 13 and 14. listLoadBalancerRules should show associated VMs for + # public IP + # 15. ssh should succeed to the user VMs + # 16. listRouters should show one Router in MASTER state and Running & + # one in BACKUP and Running + # 17. ssh should work for PF, FW, and LB ips + # 18. listRouters should show one Router in MASTER state and Running & + # one in BACKUP and Running + # 19. ssh should work for PF, FW, and LB ips + # 20. listPortForwardingRules, listFirewallRules, listLoadBalancerRule + # should return empty response + # 21. listPublicIpAddresses should show now more addresses + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + if routers[0].redundantstate == 'MASTER': + master_router = routers[0] + backup_router = routers[1] + else: + master_router = routers[1] + backup_router = routers[0] + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip.ipaddress.ipaddress) + try: + static_nat = StaticNATRule.create( + self.apiclient, + self.services["fw_rule"], + ipaddressid=public_ip.ipaddress.id + ) + static_nat.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=virtual_machine.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network.id, + listall=True, + isstaticnat=True + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("creating a FW rule on IP: %s" % + public_ip.ipaddress.ipaddress) + 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"] + ) + self.debug("Created a firewall rule on 22 port of IP: %s" % + public_ip.ipaddress.ipaddress) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network.id + )) + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule_221"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=True + ) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_3.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id + ) + + self.debug("Adding %s to the LB rule %s" % ( + virtual_machine.name, + lb_rule.name + )) + lb_rule.assign(self.apiclient, [virtual_machine]) + + self.debug("Restarting network ID: %s with cleanup true" % + network.id) + + try: + network.restart(self.apiclient, cleanup=True) + except Exception as e: + self.fail("Failed to cleanup network") + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running" + ) + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule_221"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Restarting network ID: %s with cleanup false" % + network.id) + + try: + network.restart(self.apiclient, cleanup=False) + except Exception as e: + self.fail("Failed to cleanup network") + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running" + ) + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule_221"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + + self.debug("Trying to SSH into the virtual machine") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH to guest VM succeeded") + except Exception as e: + self.fail("SSH to guest VM failed: %s" % e) + return + + +class TestUpgradeDowngradeRVR(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestUpgradeDowngradeRVR, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_upgradeVR_to_redundantVR(self): + """Test upgrade virtual router to redundant virtual router + """ + + # Steps to validate + # 1. create a network with DefaultNetworkOfferingWithSourceNATservice + # (all VR based services) + # 2. deploy a VM in the above network and listRouters + # 3. create a network Offering that has redundant router enabled and + # all VR based services + # 4. updateNetwork created above to the offfering in 3. + # 5. listRouters in the network + # 6. delete account in which resources are created + # Validate the following + # 1. listNetworks should show the created network in allocated state + # 2. VM should be deployed and in Running state and there should be + # one Router running for this network + # 3. listNetworkOfferings should show craeted offering for RvR + # 4. listNetworks shows the network still successfully implemented + # 5. listRouters shows two routers Up and Running (MASTER and BACKUP) + + network_offerings = NetworkOffering.list( + self.apiclient, + name='DefaultIsolatedNetworkOfferingWithSourceNatService', + listall=True + ) + self.assertEqual( + isinstance(network_offerings, list), + True, + "List network offering should not return empty response" + ) + + network_off_vr = network_offerings[0] + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + network_off_vr.id) + network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=network_off_vr.id, + zoneid=self.zone.id + ) + self.debug("Created network with ID: %s" % network.id) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in the account: %s" % + self.account.account.name) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for account: %s" % + self.account.account.name) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return only one router" + ) + self.assertEqual( + len(routers), + 1, + "Length of the list router should be 1" + ) + + self.debug("Upgrading the network to RVR network offering..") + try: + network.update( + self.apiclient, + networkofferingid=self.network_offering.id + ) + except Exception as e: + self.fail("Failed to upgrade the network from VR to RVR: %s" % e) + + self.debug("Listing routers for account: %s" % + self.account.account.name) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return two routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (MASTER & BACKUP)" + ) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_downgradeRvR_to_VR(self): + """Test downgrade redundant virtual router to virtual router + """ + + # Steps to validate + # 1. create a network Offering that has redundant router enabled and + # all VR based services + # 2. create a network with above offering + # 3. deploy a VM in the above network and listRouters + # 4. create a network Offering that has redundant router disabled and + # all VR based services + # 5. updateNetwork - downgrade - created above to the offfering in 4. + # 6. listRouters in the network + # 7. delete account in which resources are created + # Validate the following + # 1. listNetworkOfferings should show craeted offering for RvR + # 2. listNetworks should show the created network in allocated state + # 3. VM should be deployed and in Running state and there should be + # two routers (MASTER and BACKUP) for this network + # 4. listNetworkOfferings should show craeted offering for VR + # 5. listNetworks shows the network still successfully implemented + # 6. listRouters shows only one router for this network in Running + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in the account: %s" % + self.account.account.name) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for account: %s" % + self.account.account.name) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return two routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (MASTER & BACKUP)" + ) + + network_offerings = NetworkOffering.list( + self.apiclient, + name='DefaultIsolatedNetworkOfferingWithSourceNatService', + listall=True + ) + self.assertEqual( + isinstance(network_offerings, list), + True, + "List network offering should not return empty response" + ) + + network_off_vr = network_offerings[0] + + self.debug("Upgrading the network to RVR network offering..") + try: + network.update( + self.apiclient, + networkofferingid=network_off_vr.id + ) + except Exception as e: + self.fail("Failed to upgrade the network from VR to RVR: %s" % e) + + self.debug("Listing routers for account: %s" % + self.account.account.name) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return only one router" + ) + self.assertEqual( + len(routers), + 1, + "Length of the list router should be 1" + ) + return + + +class TestRVRWithDiffEnvs(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestRVRWithDiffEnvs, + 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["ostype"] + ) + 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.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", "ssh"]) + def test_RvR_multipods(self): + """Test RvR with muti pods + """ + + # Steps to validate + # 0. listPods should have at least 2 pods + # 1. create a network offering for redundant router + # 2. create a network out of this offering + # 3. deploy a VM in this network + # 4. listRouters + # 5. delete the account + # Validate the following + # 1. listNetworkOfferings should show created offering for RvR + # 2. listNetworks should show the created network in allocated state + # 3. VM should be deployed and in Running state + # 4. There should be two routers (MASTER and BACKUP) for this network + # ensure both routers should be on different pods + + self.debug("Checking if the current zone has 2 active pods in it..") + pods = Pod.list( + self.apiclient, + zoneid=self.zone.id, + listall=True, + allocationstate="Enabled" + ) + self.assertEqual( + isinstance(pods, list), + True, + "List pods should not return an empty response" + ) + + if len(pods) < 2: + raise unittest.SkipTest("The env don't have 2 pods req for test") + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + self.assertNotEqual( + routers[0].podid, + routers[1].podid, + "Both the routers should be in different pods" + ) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_RvR_multicluster(self): + """Test RvR with muti clusters + """ + + # Steps to validate + # 0. listClusters should have at least two clusters (if there are + # multiple pods, disable all except one with two clusters) + # 1. create a network offering for redundant router + # 2. create a network out of this offering + # 3. deploy a VM in this network on a host in either of clusters + # found in 0. (specify hostid for deployment) + # 4. listRouters + # 5. delete the account + # 6. enable all disabled pods + # Validate the following + # 1. listNetworkOfferings should show created offering for RvR + # 2. listNetworks should show the created network in allocated state + # 3. VM should be deployed and in Running state + # 4. There should be two routers (MASTER and BACKUP) for this network + # ensure both routers should be on different pods + + self.debug("Checking if the current zone has 2 active pods in it..") + pods = Pod.list( + self.apiclient, + zoneid=self.zone.id, + listall=True, + allocationstate="Enabled" + ) + self.assertEqual( + isinstance(pods, list), + True, + "List pods should not return an empty response" + ) + enabled_pod = pods[0] + + self.debug("Cheking if pod has atleast 2 clusters") + clusters = Cluster.list( + self.apiclient, + podid=enabled_pod.id, + listall=True + ) + self.assertEqual( + isinstance(clusters, list), + True, + "List clusters should not return empty response" + ) + if len(clusters) < 2: + raise unittest.SkipTest( + "The env don't have 2 clusters req for test") + + self.debug("disable all pods except one!") + if len(pods) > 1: + for pod in pods: + cmd = updatePod.updatePodCmd() + cmd.id = pod.id + cmd.allocationstate = 'Disabled' + self.apiclient.updatePod(cmd) + + self.debug("Warning: Disabled all pods in zone") + + cmd = updatePod.updatePodCmd() + cmd.id = pods[0].id + cmd.allocationstate = 'Enabled' + self.apiclient.updatePod(cmd) + self.debug("Enabled first pod for testing..") + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + + hosts = Host.list( + self.apiclient, + id=routers[0].hostid, + listall=True + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List host should return a valid data" + ) + first_host = hosts[0] + + hosts = Host.list( + self.apiclient, + id=routers[1].hostid, + listall=True + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List host should return a valid data" + ) + second_host = hosts[0] + + # Checking if the cluster IDs of both routers are different? + self.assertNotEqual( + first_host.clusterid, + second_host.clusterid, + "Both the routers should be in different clusters" + ) + self.debug("Enabling remaining pods if any..") + pods = Pod.list( + self.apiclient, + zoneid=self.zone.id, + listall=True, + allocationstate="Disabled" + ) + + for pod in pods: + cmd = updatePod.updatePodCmd() + cmd.id = pod.id + cmd.allocationstate = 'Enabled' + self.apiclient.updatePod(cmd) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_RvR_multiprimarystorage(self): + """Test RvR with muti primary storage + """ + + # Steps to validate + # 0. listStoragePools should have atleast two pools in a single + # cluster (disable pods/clusters as necessary) + # 1. create a network offering for redundant router + # 2. create a network out of this offering + # 3. deploy a VM in this network on a host in the cluster from 0 + # (specify hostid for deployment) + # 4. listRouters + # 5. delete the account + # 6. enable the clusters and pods + # Validate the following + # 1. listNetworkOfferings should show created offering for RvR + # 2. listNetworks should show the created network in allocated state + # 3. VM should be deployed and in Running state and on the specified + # host + # 4. There should be two routers (MASTER and BACKUP) for this network + # ensure both routers should be on different storage pools + + self.debug( + "Checking if the current zone has multiple active pods in it..") + pods = Pod.list( + self.apiclient, + zoneid=self.zone.id, + listall=True, + allocationstate="Enabled" + ) + self.assertEqual( + isinstance(pods, list), + True, + "List pods should not return an empty response" + ) + + enabled_pod = pods[0] + self.debug("Cheking if pod has multiple clusters") + clusters = Cluster.list( + self.apiclient, + podid=enabled_pod.id, + listall=True + ) + self.assertEqual( + isinstance(clusters, list), + True, + "List clusters should not return empty response" + ) + + enabled_cluster = clusters[0] + + self.debug("Cheking if cluster has multiple storage pools") + storage_pools = StoragePool.list( + self.apiclient, + clusterid=enabled_cluster.id, + listall=True + ) + self.assertEqual( + isinstance(storage_pools, list), + True, + "List storage pools should not return empty response" + ) + + if len(storage_pools) < 2: + raise unittest.SkipTest( + "The env don't have 2 storage pools req for test") + + self.debug("disable all pods except one!") + if len(pods) > 1: + for pod in pods: + cmd = updatePod.updatePodCmd() + cmd.id = pod.id + cmd.allocationstate = 'Disabled' + self.apiclient.updatePod(cmd) + + self.debug("Warning: Disabled all pods in zone") + + cmd = updatePod.updatePodCmd() + cmd.id = pods[0].id + cmd.allocationstate = 'Enabled' + self.apiclient.updatePod(cmd) + self.debug("Enabled first pod for testing..") + + self.debug("disable all clusters except one!") + if len(pods) > 1: + for cluster in clusters: + cmd = updateCluster.updateClusterCmd() + cmd.id = cluster.id + cmd.allocationstate = 'Disabled' + self.apiclient.updateCluster(cmd) + + self.debug("Warning: Disabled all pods in zone") + + cmd = updateCluster.updateClusterCmd() + cmd.id = clusters[0].id + cmd.allocationstate = 'Enabled' + self.apiclient.updateCluster(cmd) + self.debug("Enabled first cluster for testing..") + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Retrieving the list of hosts in the cluster") + hosts = Host.list( + self.apiclient, + clusterid=enabled_cluster.id, + listall=True + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should not return an empty response" + ) + host = hosts[0] + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)], + hostid=host.id + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + self.assertNotEqual( + routers[0].hostid, + routers[1].hostid, + "Both the routers should be in different storage pools" + ) + self.debug("Enabling remaining pods if any..") + pods = Pod.list( + self.apiclient, + zoneid=self.zone.id, + listall=True, + allocationstate="Disabled" + ) + self.assertEqual( + isinstance(pods, list), + True, + "List pods should not return an empty response" + ) + + for pod in pods: + cmd = updatePod.updatePodCmd() + cmd.id = pod.id + cmd.allocationstate = 'Enabled' + self.apiclient.updatePod(cmd) + + clusters = Cluster.list( + self.apiclient, + allocationstate="Disabled", + podid=enabled_pod.id, + listall=True + ) + + for cluster in clusters: + cmd = updateCluster.updateClusterCmd() + cmd.id = cluster.id + cmd.allocationstate = 'Enabled' + self.apiclient.updateCluster(cmd) + return + + @attr(tags=["advanced", "advancedns", "ssh"]) + def test_RvR_multihosts(self): + """Test RvR with muti hosts + """ + + # Steps to validate + # 0. listHosts should have atleast two hosts in a single cluster + # (disable pods/clusters as necessary) + # 1. create a network offering for redundant router + # 2. create a network out of this offering + # 3. deploy a VM in this network on a host in the cluster from 0 + # (specify hostid for deployment) + # 4. listRouters + # 5. delete the account + # 6. enable the clusters and pods + # Validate the following + # 1. listNetworkOfferings should show created offering for RvR + # 2. listNetworks should show the created network in allocated state + # 3. VM should be deployed and in Running state and on specified host + # 4. There should be two routers (MASTER and BACKUP) for this network + # ensure both routers should be on different hosts + + self.debug( + "Checking if the current zone has multiple active pods in it..") + pods = Pod.list( + self.apiclient, + zoneid=self.zone.id, + listall=True, + allocationstate="Enabled" + ) + self.assertEqual( + isinstance(pods, list), + True, + "List pods should not return an empty response" + ) + + enabled_pod = pods[0] + self.debug("Cheking if pod has multiple clusters") + clusters = Cluster.list( + self.apiclient, + podid=enabled_pod.id, + listall=True + ) + self.assertEqual( + isinstance(clusters, list), + True, + "List clusters should not return empty response" + ) + + enabled_cluster = clusters[0] + + self.debug("Cheking if cluster has multiple hosts") + hosts = Host.list( + self.apiclient, + clusterid=enabled_cluster.id, + listall=True + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should not return empty response" + ) + + if len(hosts) < 2: + raise unittest.SkipTest( + "The env don't have 2 hosts req for test") + + self.debug("disable all pods except one!") + if len(pods) > 1: + for pod in pods: + cmd = updatePod.updatePodCmd() + cmd.id = pod.id + cmd.allocationstate = 'Disabled' + self.apiclient.updatePod(cmd) + + self.debug("Warning: Disabled all pods in zone") + + cmd = updatePod.updatePodCmd() + cmd.id = pods[0].id + cmd.allocationstate = 'Enabled' + self.apiclient.updatePod(cmd) + self.debug("Enabled first pod for testing..") + + self.debug("disable all clusters except one!") + if len(pods) > 1: + for cluster in clusters: + cmd = updateCluster.updateClusterCmd() + cmd.id = cluster.id + cmd.allocationstate = 'Disabled' + self.apiclient.updateCluster(cmd) + + self.debug("Warning: Disabled all pods in zone") + + cmd = updateCluster.updateClusterCmd() + cmd.id = clusters[0].id + cmd.allocationstate = 'Enabled' + self.apiclient.updateCluster(cmd) + self.debug("Enabled first cluster for testing..") + + # 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) + + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response for created network" + ) + nw_response = networks[0] + + self.debug("Network state: %s" % nw_response.state) + self.assertEqual( + nw_response.state, + "Allocated", + "The network should be in allocated state after creation" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + routers, + None, + "Routers should not be spawned when network is in allocated state" + ) + + self.debug("Retrieving the list of hosts in the cluster") + hosts = Host.list( + self.apiclient, + clusterid=enabled_cluster.id, + listall=True + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should not return an empty response" + ) + host = hosts[0] + + self.debug("Deploying VM in account: %s" % self.account.account.name) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)], + hostid=host.id + ) + self.debug("Deployed VM in network: %s" % network.id) + + vms = VirtualMachine.list( + self.apiclient, + id=virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List Vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Vm should be in running state after deployment" + ) + + self.debug("Listing routers for network: %s" % network.name) + routers = Router.list( + self.apiclient, + networkid=network.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "list router should return Master and backup routers" + ) + self.assertEqual( + len(routers), + 2, + "Length of the list router should be 2 (Backup & master)" + ) + self.assertNotEqual( + routers[0].hostid, + routers[1].hostid, + "Both the routers should be in different hosts" + ) + self.debug("Enabling remaining pods if any..") + pods = Pod.list( + self.apiclient, + zoneid=self.zone.id, + listall=True, + allocationstate="Disabled" + ) + + if pods is not None: + for pod in pods: + cmd = updatePod.updatePodCmd() + cmd.id = pod.id + cmd.allocationstate = 'Enabled' + self.apiclient.updatePod(cmd) + + clusters = Cluster.list( + self.apiclient, + allocationstate="Disabled", + podid=enabled_pod.id, + listall=True + ) + if clusters is not None: + for cluster in clusters: + cmd = updateCluster.updateClusterCmd() + cmd.id = cluster.id + cmd.allocationstate = 'Enabled' + self.apiclient.updateCluster(cmd) + return diff --git a/test/integration/component/test_regions.py b/test/integration/component/test_regions.py index daf16cd1f44..252ba702b2b 100644 --- a/test/integration/component/test_regions.py +++ b/test/integration/component/test_regions.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information diff --git a/test/integration/component/test_shared_networks.py b/test/integration/component/test_shared_networks.py new file mode 100644 index 00000000000..8d602067eec --- /dev/null +++ b/test/integration/component/test_shared_networks.py @@ -0,0 +1,2986 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 tests for shared networks +""" +#Import Local Modules +import marvin +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime +import netaddr + +class Services: + """ Test shared networks """ + + def __init__(self): + self.services = { + "domain": { + "name": "DOM", + }, + "project": { + "name": "Project", + "displaytext": "Test project", + }, + "account": { + "email": "admin-XABU1@test.com", + "firstname": "admin-XABU1", + "lastname": "admin-XABU1", + "username": "admin-XABU1", + # Random characters are appended for unique + # username + "password": "fr3sca", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "network_offering": { + "name": 'MySharedOffering', + "displaytext": 'MySharedOffering', + "guestiptype": 'Shared', + "supportedservices": 'Dhcp,Dns,UserData', + "specifyVlan" : "False", + "specifyIpRanges" : "False", + "traffictype": 'GUEST', + "serviceProviderList" : { + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "UserData": 'VirtualRouter' + }, + }, + "network": { + "name": "MySharedNetwork - Test", + "displaytext": "MySharedNetwork", + "networkofferingid":"1", + "vlan" :1200, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.2", + "endip" :"172.16.15.20", + "acltype" : "Domain", + "scope":"all", + }, + "network1": { + "name": "MySharedNetwork - Test1", + "displaytext": "MySharedNetwork1", + "vlan" :1201, + "gateway" :"172.16.15.1", + "netmask" :"255.255.255.0", + "startip" :"172.16.15.21", + "endip" :"172.16.15.41", + "acltype" : "Domain", + "scope":"all", + }, + "isolated_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', + }, + }, + "isolated_network": { + "name": "Isolated Network", + "displaytext": "Isolated Network", + }, + "fw_rule": { + "startport": 22, + "endport": 22, + "cidr": '0.0.0.0/0', + }, + "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', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 90, + "timeout": 10, + "mode": 'advanced' + } + +class TestSharedNetworks(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestSharedNetworks, + 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["ostype"] + ) + + 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.api_client = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + self.cleanup_networks = [] + self.cleanup_accounts = [] + self.cleanup_domains = [] + self.cleanup_projects = [] + self.cleanup_vms = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.api_client, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + #below components is not a part of cleanup because to mandate the order and to cleanup network + try: + for vm in self.cleanup_vms: + vm.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during virtual machines cleanup : %s" % e) + + try: + for project in self.cleanup_projects: + project.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during project cleanup : %s" % e) + + try: + for account in self.cleanup_accounts: + account.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during account cleanup : %s" % e) + + try: + for domain in self.cleanup_domains: + domain.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during domain cleanup : %s" % e) + + #Wait till all resources created are cleaned up completely and then attempt to delete Network + time.sleep(self.services["sleep"]) + + try: + for network in self.cleanup_networks: + network.delete(self.api_client) + except Exception as e: + raise Exception("Warning: Exception during network cleanup : %s" % e) + return + + def test_sharedNetworkOffering_01(self): + """ Test shared network Offering 01 """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # - name = "MySharedOffering" + # - guestiptype="shared" + # - services = {Dns, Dhcp, UserData} + # - conservemode = false + # - specifyVlan = true + # - specifyIpRanges = true + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. delete the admin account + # Validations, + # 1. listAccounts name=admin-XABU1, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 3. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 4. listNetworkOfferings - name=mysharedoffering, should list enabled offering + + #Create an account + self.account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin Type account created: %s" % self.account.account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + self.debug("NetworkOffering created and enabled: %s" % self.shared_network_offering.id) + + def test_sharedNetworkOffering_02(self): + """ Test Shared Network Offering 02 """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # - name = "MySharedOffering" + # - guestiptype="shared" + # - services = {Dns, Dhcp, UserData} + # - conservemode = false + # - specifyVlan = false + # - specifyIpRanges = false + # 4. delete the admin account + # Validations, + # 1. listAccounts name=admin-XABU1, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 3. createNetworkOffering fails - vlan should be specified in advanced zone + + #Create an account + self.account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.account.account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "False" + self.services["network_offering"]["specifyIpRanges"] = "False" + + try: + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + self.fail("Network offering got created with vlan as False in advance mode and shared guest type, which is invalid case.") + except Exception as e: + self.debug("Network Offering creation failed with vlan as False in advance mode and shared guest type.") + + def test_sharedNetworkOffering_03(self): + """ Test Shared Network Offering 03 """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # - name = "MySharedOffering" + # - guestiptype="shared" + # - services = {Dns, Dhcp, UserData} + # - conservemode = false + # - specifyVlan = true + # - specifyIpRanges = false + # 4. delete the admin account + # Validations, + # 1. listAccounts name=admin-XABU1, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 3. createNetworkOffering fails - ip ranges should be specified when creating shared network offering + + + #Create an account + self.account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin Type account created: %s" % self.account.account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "False" + + try: + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + self.fail("Network offering got created with vlan as True and ip ranges as False in advance mode and with shared guest type, which is invalid case.") + except Exception as e: + self.debug("Network Offering creation failed with vlan as true and ip ranges as False in advance mode and with shared guest type.") + + def test_createSharedNetwork_All(self): + """ Test Shared Network ALL """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # - name = "MySharedOffering" + # - guestiptype="shared" + # - services = {Dns, Dhcp, UserData} + # - conservemode = false + # - specifyVlan = true + # - specifyIpRanges = true + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. createNetwork + # - name = mysharednetwork, displaytext = mysharednetwork + # - vlan = 123 (say) + # - networkofferingid = + # - gw = 172.16.15.1, startip = 172.16.15.2 , endip = 172.16.15.200, netmask=255.255.255.0 + # - scope = all + # 6. create User account - user-ASJDK + # 7. deployVirtualMachine in this account and in admin account & within networkid = + # 8. delete the admin account and the user account + # Validations, + # 1. listAccounts name=admin-XABU1, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 3. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 4. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 5. listNetworks - name = mysharednetwork should list the successfully created network, verify the guestIp ranges and CIDR are as given in the createNetwork call + # 6. No checks reqd + # 7. a. listVirtualMachines should show both VMs in running state in the user account and the admin account + # b. VM's IPs shoud be in the range of the shared network ip ranges + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.account.name) + + #Create an user account + self.user_account = Account.create( + self.api_client, + self.services["account"], + admin=False, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.user_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.user_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The user account created is not enabled." + ) + + self.debug("User type account created: %s" % self.user_account.account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "Domain" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + + self.network = Network.create( + self.api_client, + self.services["network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + + self.cleanup_networks.append(self.network) + + list_networks_response = Network.list( + self.api_client, + id=self.network.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created for scope domain: %s" % self.network.id) + + self.admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + networkids=self.network.id, + serviceofferingid=self.service_offering.id + ) + + self.cleanup_vms.append(self.admin_account_virtual_machine) + + vms = VirtualMachine.list( + self.api_client, + id=self.admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + self.debug("Virtual Machine created: %s" % self.admin_account_virtual_machine.id) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["network"]["startip"]), unicode(self.services["network"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + + self.user_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.user_account.account.name, + domainid=self.user_account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=self.network.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.user_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + self.debug("Virtual Machine created: %s" % self.user_account_virtual_machine.id) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["network"]["startip"]), unicode(self.services["network"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + + def test_createSharedNetwork_accountSpecific(self): + """ Test Shared Networm with scope account """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # create a user account = user-SOPJD + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # - name = "MySharedOffering" + # - guestiptype="shared" + # - services = {Dns, Dhcp, UserData} + # - conservemode = false + # - specifyVlan = true + # - specifyIpRanges = true + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. createNetwork + # - name = mysharednetwork, displaytext = mysharednetwork + # - vlan = 123 (say) + # - networkofferingid = + # - gw = 172.16.15.1, startip = 172.16.15.2 , endip = 172.16.15.200, netmask=255.255.255.0 + # - scope = account, account = user-SOPJD, domain = ROOT + # 6. deployVirtualMachine in this account and in admin account & within networkid = + # 7. delete the admin account and the user account + # Validations, + # 1. listAccounts name=admin-XABU1 and user-SOPJD, state=enabled returns your account + # 2. listPhysicalNetworks should return at least one active physical network + # 3. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 4. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 5. listNetworks - name = mysharednetwork should list the successfully created network, verify the guestIp ranges and CIDR are as given in the createNetwork call + # 6. VM deployed in admin account should FAIL to deploy + # VM should be deployed in user account only + # verify VM's IP is within shared network range + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.account.name) + + #Create an user account + self.user_account = Account.create( + self.api_client, + self.services["account"], + admin=False, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.user_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.user_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The user account created is not enabled." + ) + + self.debug("User type account created: %s" % self.user_account.account.name) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "Account" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + + self.network = Network.create( + self.api_client, + self.services["network"], + accountid=self.user_account.account.name, + domainid=self.user_account.account.domainid, + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + + self.cleanup_networks.append(self.network) + + list_networks_response = Network.list( + self.api_client, + id=self.network.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Network created: %s" % self.network.id) + + try: + self.admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.network.id, + serviceofferingid=self.service_offering.id + ) + self.fail("Virtual Machine got created in admin account with network created but the network used is of scope account and for user account.") + except Exception as e: + self.debug("Virtual Machine creation failed as network used have scoped only for user account.") + + self.user_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.user_account.account.name, + domainid=self.user_account.account.domainid, + networkids=self.network.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.user_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["network"]["startip"]), unicode(self.services["network"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + + def test_createSharedNetwork_domainSpecific(self): + """ Test Shared Network with scope domain """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # create a domain - DOM + # create a domain admin account = domadmin-SOPJD + # create a user in domain - DOM + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # - name = "MySharedOffering" + # - guestiptype="shared" + # - services = {Dns, Dhcp, UserData} + # - conservemode = false + # - specifyVlan = true + # - specifyIpRanges = true + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. createNetwork + # - name = mysharednetwork, displaytext = mysharednetwork + # - vlan = 123 (say) + # - networkofferingid = + # - gw = 172.16.15.1, startip = 172.16.15.2 , endip = 172.16.15.200, netmask=255.255.255.0 + # - scope = domain, domain = DOM + # 6. deployVirtualMachine in this admin, domainadmin and user account & within networkid = + # 7. delete all the accounts + # Validations, + # 1. listAccounts state=enabled returns your accounts, listDomains - DOM should be created + # 2. listPhysicalNetworks should return at least one active physical network + # 3. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 4. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 5. listNetworks - name = mysharednetwork should list the successfully created network, verify the guestIp ranges and CIDR are as given in the createNetwork call + # 6. VM should NOT be deployed in admin account + # VM should be deployed in user account and domain admin account + # verify VM's IP are within shared network range + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.account.id) + + #create domain + self.dom_domain = Domain.create( + self.api_client, + self.services["domain"], + ) + + self.cleanup_domains.append(self.dom_domain) + + #verify that the account got created with state enabled + list_domains_response = Domain.list( + self.api_client, + id=self.dom_domain.id + ) + self.assertEqual( + isinstance(list_domains_response, list), + True, + "listDomains returned invalid object in response." + ) + self.assertNotEqual( + len(list_domains_response), + 0, + "listDomains returned empty list." + ) + + self.debug("Domain created: %s" % self.dom_domain.id) + + #Create admin account + self.domain_admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.dom_domain.id + ) + + self.cleanup_accounts.append(self.domain_admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.domain_admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The domain admin account created is not enabled." + ) + + self.debug("Domain admin account created: %s" % self.domain_admin_account.account.id) + + #Create an user account + self.domain_user_account = Account.create( + self.api_client, + self.services["account"], + admin=False, + domainid=self.dom_domain.id + ) + + self.cleanup_accounts.append(self.domain_user_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.domain_user_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The domain user account created is not enabled." + ) + + self.debug("Domain user account created: %s" % self.domain_user_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "domain" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + + self.network = Network.create( + self.api_client, + self.services["network"], + domainid=self.dom_domain.id, + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + + self.cleanup_networks.append(self.network) + + list_networks_response = Network.list( + self.api_client, + id=self.network.id, + listall=True + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created: %s" % self.network.id) + + try: + self.admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.network.id, + serviceofferingid=self.service_offering.id + ) + self.fail("Virtual Machine got created in admin account with network specified but the network used is of scope domain and admin account is not part of this domain.") + except Exception as e: + self.debug("Virtual Machine creation failed as network used have scoped only for DOM domain.") + + self.domain_user_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.domain_user_account.account.name, + domainid=self.domain_user_account.account.domainid, + networkids=self.network.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.domain_user_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["network"]["startip"]), unicode(self.services["network"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + + self.domain_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.domain_admin_account.account.name, + domainid=self.domain_admin_account.account.domainid, + networkids=self.network.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.domain_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["network"]["startip"]), unicode(self.services["network"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + + def test_createSharedNetwork_projectSpecific(self): + """ Test Shared Network with scope project """ + + # Steps, + # 1. create an Admin Account - admin-XABU1 + # create a project - proj-SADJKS + # create another project - proj-SLDJK + # 2. listPhysicalNetworks in available zone + # 3. createNetworkOffering: + # - name = "MySharedOffering" + # - guestiptype="shared" + # - services = {Dns, Dhcp, UserData} + # - conservemode = false + # - specifyVlan = true + # - specifyIpRanges = true + # 4. Enable network offering - updateNetworkOffering - state=Enabled + # 5. createNetwork + # - name = mysharednetwork, displaytext = mysharednetwork + # - vlan = 123 (say) + # - networkofferingid = + # - gw = 172.16.15.1, startip = 172.16.15.2 , endip = 172.16.15.200, netmask=255.255.255.0 + # - scope = project, project = proj-SLDJK + # 6. deployVirtualMachine in admin, project and user account & within networkid = + # 7. delete all the accounts + # Validations, + # 1. listAccounts state=enabled returns your accounts, listDomains - DOM should be created + # 2. listPhysicalNetworks should return at least one active physical network + # 3. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 4. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 5. listNetworks - name = mysharednetwork should list the successfully created network, verify the guestIp ranges and CIDR are as given in the createNetwork call + # 6. VM should NOT be deployed in admin account and user account + # VM should be deployed in project account only + # verify VM's IP are within shared network range + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin account created: %s" % self.admin_account.account.id) + + self.services["project"]["name"] = "proj-SADJKS" + self.services["project"]["displaytext"] = "proj-SADJKS" + + self.project1 = Project.create( + self.api_client, + self.services["project"], + account=self.admin_account.account.name, + domainid=self.admin_account.account.domainid + ) + + self.cleanup_projects.append(self.project1) + + list_projects_response = Project.list( + self.api_client, + id=self.project1.id, + listall=True + ) + self.assertEqual( + isinstance(list_projects_response, list), + True, + "listProjects returned invalid object in response." + ) + self.assertNotEqual( + len(list_projects_response), + 0, + "listProjects should return at least one." + ) + + self.debug("Project created: %s" % self.project1.id) + + self.services["project"]["name"] = "proj-SLDJK" + self.services["project"]["displaytext"] = "proj-SLDJK" + + self.project2 = Project.create( + self.api_client, + self.services["project"], + account=self.admin_account.account.name, + domainid=self.admin_account.account.domainid + ) + + self.cleanup_projects.append(self.project2) + + list_projects_response = Project.list( + self.api_client, + id=self.project2.id, + listall=True + ) + self.assertEqual( + isinstance(list_projects_response, list), + True, + "listProjects returned invalid object in response." + ) + self.assertNotEqual( + len(list_projects_response), + 0, + "listProjects should return at least one." + ) + + self.debug("Project2 created: %s" % self.project2.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + self.debug("Shared Network found: %s" % self.shared_network_offering.id) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "account" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + + self.network = Network.create( + self.api_client, + self.services["network"], + projectid=self.project1.id, + domainid=self.admin_account.account.domainid, + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + self.cleanup_networks.append(self.network) + + list_networks_response = Network.list( + self.api_client, + id=self.network.id, + projectid=self.project1.id, + listall=True + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created: %s" % self.network.id) + + try: + self.project2_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.network.id, + projectid=self.project2.id, + serviceofferingid=self.service_offering.id + ) + self.fail("Virtual Machine got created in admin account with network specified but the network used is of scope project and the project2 is not assigned for the network.") + except Exception as e: + self.debug("Virtual Machine creation failed as network used have scoped only for project project1.") + + self.project1_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.network.id, + projectid=self.project1.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.project1_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + ip_range = list(netaddr.iter_iprange(unicode(self.services["network"]["startip"]), unicode(self.services["network"]["endip"]))) + if netaddr.IPAddress(unicode(vms[0].nic[0].ipaddress)) not in ip_range: + self.fail("Virtual machine ip should be from the ip range assigned to network created.") + + def test_createSharedNetwork_usedVlan(self): + """ Test Shared Network with used vlan 01 """ + + # Steps, + # 1. create an Admin account + # 2. create a shared NetworkOffering + # 3. enable the network offering + # 4. listPhysicalNetworks + # - vlan = guest VLAN range = 10-90 (say) + # 5. createNetwork + # - name = mysharednetwork, displaytext = mysharednetwork + # - vlan = any vlan between 10-90 + # - networkofferingid = + # - gw = 172.16.15.1, startip = 172.16.15.2 , endip = 172.16.15.200, netmask=255.255.255.0 + # - scope = all + # 6. delete admin account + # Validations, + # 1. listAccounts state=enabled returns your account + # 2. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 3. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 4. listPhysicalNetworks should return at least one active physical network + # 5. network creation should FAIL since VLAN is used for guest networks + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Domain admin account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["vlan"] = str.split(str(physical_network.vlan), "-")[0] + self.services["network"]["acltype"] = "domain" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + + try: + self.network = Network.create( + self.api_client, + self.services["network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + self.fail("Network created with used vlan id, which is invalid") + except Exception as e: + self.debug("Network creation failed because the valn id being used by another network.") + + def test_createSharedNetwork_usedVlan2(self): + """ Test Shared Network with used vlan 02 """ + + # Steps, + # 1. create an Admin account + # 2. create a shared NetworkOffering + # 3. enable the network offering + # 4. listPhysicalNetworks + # - vlan = guest VLAN range = 10-90 (say) + # 5. createNetwork + # - name = mysharednetwork, displaytext = mysharednetwork + # - vlan = any vlan beyond 10-90 (123 for eg) + # - networkofferingid = + # - gw = 172.16.15.1, startip = 172.16.15.2 , endip = 172.16.15.200, netmask=255.255.255.0 + # - scope = all + # 6. createNetwork again with same VLAN but different IP ranges and gw + # 7. delete admin account + # Validations, + # 1. listAccounts state=enabled returns your account + # 2. listNetworkOfferings - name=mysharedoffering , should list offering in disabled state + # 3. listNetworkOfferings - name=mysharedoffering, should list enabled offering + # 4. listPhysicalNetworks should return at least one active physical network + # 5. network creation shoud PASS + # 6. network creation should FAIL since VLAN is already used by previously created network + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "Domain" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + self.services["network"]["vlan"] = "567" + self.network = Network.create( + self.api_client, + self.services["network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + + self.cleanup_networks.append(self.network) + + list_networks_response = Network.list( + self.api_client, + id=self.network.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Network created: %s" % self.network.id) + + self.services["network1"]["vlan"] = self.services["network"]["vlan"] + self.services["network1"]["acltype"] = "domain" + self.services["network1"]["networkofferingid"] = self.shared_network_offering.id + self.services["network1"]["physicalnetworkid"] = physical_network.id + + try: + self.network1 = Network.create( + self.api_client, + self.services["network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + self.cleanup_networks.append(self.network1) + self.fail("Network got created with used vlan id, which is invalid") + except Exception as e: + self.debug("Network creation failed because the valn id being used by another network.") + + def test_deployVM_multipleSharedNetwork(self): + """ Test Vm deployment with multiple shared networks """ + + # Steps, + # 0. create a user account + # 1. Create two shared Networks (scope=ALL, different IP ranges) + # 2. deployVirtualMachine in both the above networkids within the user account + # 3. delete the user account + # Validations, + # 1. shared networks should be created successfully + # 2. a. VM should deploy successfully + # b. VM should bedeployed in both networks and have IP in both the networks + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "domain" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + + self.network = Network.create( + self.api_client, + self.services["network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + + self.cleanup_networks.append(self.network) + + list_networks_response = Network.list( + self.api_client, + id=self.network.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created: %s" % self.network.id) + + self.services["network1"]["acltype"] = "domain" + self.services["network1"]["networkofferingid"] = self.shared_network_offering.id + self.services["network1"]["physicalnetworkid"] = physical_network.id + + self.network1 = Network.create( + self.api_client, + self.services["network1"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + + self.cleanup_networks.append(self.network1) + + list_networks_response = Network.list( + self.api_client, + id=self.network1.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Network created: %s" % self.network1.id) + + self.network_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.network.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.network_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + self.debug("Virtual Machine created: %s" % self.network_admin_account_virtual_machine.id) + + self.assertTrue(self.network_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") + + self.network1_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.network1.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.network1_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + self.debug("Virtual Machine created: %s" % self.network1_admin_account_virtual_machine.id) + + self.assertTrue(self.network1_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") + + def test_deployVM_isolatedAndShared(self): + """ Test VM deployment in shared and isolated networks """ + + # Steps, + # 0. create a user account + # 1. Create one shared Network (scope=ALL, different IP ranges) + # 2. Create one Isolated Network + # 3. deployVirtualMachine in both the above networkids within the user account + # 4. apply FW rule and enable PF for port 22 for guest VM on isolated network + # 5. delete the user account + # Validations, + # 1. shared network should be created successfully + # 2. isolated network should be created successfully + # 3. + # a. VM should deploy successfully + # b. VM should bedeployed in both networks and have IP in both the networks + # 4. FW and PF should apply successfully, ssh into the VM should work over isolated network + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + liistall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.account.name) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + self.isolated_network_offering = NetworkOffering.create( + self.api_client, + self.services["isolated_network_offering"], + conservemode=False + ) + + self.cleanup.append(self.isolated_network_offering) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.isolated_network_offering, + self.api_client, + id=self.isolated_network_offering.id, + state="enabled" + ) + + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.isolated_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The isolated network offering state should get updated to Enabled." + ) + + self.debug("Isolated Network Offering created: %s" % self.isolated_network_offering.id) + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + #create network using the shared network offering created + self.services["network"]["acltype"] = "domain" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + self.shared_network = Network.create( + self.api_client, + self.services["network"], + domainid=self.admin_account.account.domainid, + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + + self.cleanup_networks.append(self.shared_network) + + list_networks_response = Network.list( + self.api_client, + id=self.shared_network.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + self.assertEqual( + list_networks_response[0].specifyipranges, + True, + "The network is created with ip range but the flag is set to False." + ) + + self.debug("Shared Network created: %s" % self.shared_network.id) + + self.isolated_network = Network.create( + self.api_client, + self.services["isolated_network"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkofferingid=self.isolated_network_offering.id, + zoneid=self.zone.id + ) + + self.cleanup_networks.append(self.isolated_network) + + list_networks_response = Network.list( + self.api_client, + id=self.isolated_network.id + ) + self.assertEqual( + isinstance(list_networks_response, list), + True, + "listNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_networks_response), + 0, + "listNetworks returned empty list." + ) + + self.debug("Isolated Network created: %s" % self.isolated_network.id) + + self.shared_network_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.shared_network.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.shared_network_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + self.debug("Virtual Machine created: %s" % self.shared_network_admin_account_virtual_machine.id) + + self.assertTrue(self.shared_network_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") + + self.isolated_network_admin_account_virtual_machine = VirtualMachine.create( + self.api_client, + self.services["virtual_machine"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkids=self.isolated_network.id, + serviceofferingid=self.service_offering.id + ) + vms = VirtualMachine.list( + self.api_client, + id=self.isolated_network_admin_account_virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "listVirtualMachines returned invalid object in response." + ) + self.assertNotEqual( + len(vms), + 0, + "listVirtualMachines returned empty list." + ) + + self.debug("Virtual Machine created: %s" % self.isolated_network_admin_account_virtual_machine.id) + + self.assertTrue(self.isolated_network_admin_account_virtual_machine.nic[0].ipaddress is not None, "ip should be assigned to running virtual machine") + + self.debug("Associating public IP for account: %s" % self.admin_account.account.name) + self.public_ip = PublicIPAddress.create( + self.api_client, + accountid=self.admin_account.account.name, + zoneid=self.zone.id, + domainid=self.admin_account.account.domainid, + networkid=self.isolated_network.id + ) + + self.debug("Associated %s with network %s" % (self.public_ip.ipaddress.ipaddress, self.isolated_network.id)) + self.debug("Creating PF rule for IP address: %s" % self.public_ip.ipaddress.ipaddress) + + public_ip = self.public_ip.ipaddress + + # Enable Static NAT for VM + StaticNATRule.enable( + self.api_client, + public_ip.id, + self.isolated_network_admin_account_virtual_machine.id + ) + + self.debug("Enabled static NAT for public IP ID: %s" % public_ip.id) + #Create Firewall rule on source NAT + fw_rule = FireWallRule.create( + self.api_client, + ipaddressid=self.public_ip.ipaddress, + protocol='TCP', + cidrlist=[self.services["fw_rule"]["cidr"]], + startport=self.services["fw_rule"]["startport"], + endport=self.services["fw_rule"]["endport"] + ) + self.debug("Created firewall rule: %s" % fw_rule.id) + + fw_rules = FireWallRule.list( + self.api_client, + id=fw_rule.id + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "List fw rules should return a valid firewall rules" + ) + + self.assertNotEqual( + len(fw_rules), + 0, + "Length of fw rules response should not be zero" + ) + + # Should be able to SSH VM + try: + self.debug("SSH into VM: %s" % self.isolated_network_admin_account_virtual_machine.id) + ssh = self.isolated_network_admin_account_virtual_machine.get_ssh_client(ipaddress=self.public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("SSH Access failed for %s: %s" % (self.isolated_network_admin_account_virtual_machine.ipaddress, e)) + + def test_networkWithsubdomainaccessTrue(self): + """ Test Shared Network with subdomainaccess=True """ + + # Steps, + # 1. create Network using shared network offering for scope=Account and subdomainaccess=true. + # Validations, + # (Expected) API should fail saying that subdomainaccess cannot be given when scope is Account + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "Account" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + self.services["network"]["subdomainaccess"] = "True" + + try: + self.network = Network.create( + self.api_client, + self.services["network"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + self.fail("Network creation should fail.") + except: + self.debug("Network creation failed because subdomainaccess parameter was passed when scope was account.") + + def test_networkWithsubdomainaccessFalse(self): + """ Test shared Network with subdomainaccess=False """ + + # Steps, + # 1. create Network using shared network offering for scope=Account and subdomainaccess=false + # Validations, + # (Expected) API should fail saying that subdomainaccess cannot be given when scope is Account + + #Create admin account + self.admin_account = Account.create( + self.api_client, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + self.cleanup_accounts.append(self.admin_account) + + #verify that the account got created with state enabled + list_accounts_response = Account.list( + self.api_client, + id=self.admin_account.account.id, + listall=True + ) + self.assertEqual( + isinstance(list_accounts_response, list), + True, + "listAccounts returned invalid object in response." + ) + self.assertNotEqual( + len(list_accounts_response), + 0, + "listAccounts returned empty list." + ) + self.assertEqual( + list_accounts_response[0].state, + "enabled", + "The admin account created is not enabled." + ) + + self.debug("Admin type account created: %s" % self.admin_account.account.id) + + #Verify that there should be at least one physical network present in zone. + list_physical_networks_response = PhysicalNetwork.list( + self.api_client, + zoneid=self.zone.id + ) + self.assertEqual( + isinstance(list_physical_networks_response, list), + True, + "listPhysicalNetworks returned invalid object in response." + ) + self.assertNotEqual( + len(list_physical_networks_response), + 0, + "listPhysicalNetworks should return at least one physical network." + ) + + physical_network = list_physical_networks_response[0] + + self.debug("Physical Network found: %s" % physical_network.id) + + self.services["network_offering"]["specifyVlan"] = "True" + self.services["network_offering"]["specifyIpRanges"] = "True" + + #Create Network Offering + self.shared_network_offering = NetworkOffering.create( + self.api_client, + self.services["network_offering"], + conservemode=False + ) + + self.cleanup.append(self.shared_network_offering) + + #Verify that the network offering got created + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Disabled", + "The network offering created should be bydefault disabled." + ) + + self.debug("Shared Network Offering created: %s" % self.shared_network_offering.id) + + #Update network offering state from disabled to enabled. + network_offering_update_response = NetworkOffering.update( + self.shared_network_offering, + self.api_client, + id=self.shared_network_offering.id, + state="enabled" + ) + #Verify that the state of the network offering is updated + list_network_offerings_response = NetworkOffering.list( + self.api_client, + id=self.shared_network_offering.id + ) + self.assertEqual( + isinstance(list_network_offerings_response, list), + True, + "listNetworkOfferings returned invalid object in response." + ) + self.assertNotEqual( + len(list_network_offerings_response), + 0, + "listNetworkOfferings returned empty list." + ) + self.assertEqual( + list_network_offerings_response[0].state, + "Enabled", + "The network offering state should get updated to Enabled." + ) + + #create network using the shared network offering created + self.services["network"]["acltype"] = "Account" + self.services["network"]["networkofferingid"] = self.shared_network_offering.id + self.services["network"]["physicalnetworkid"] = physical_network.id + self.services["network"]["subdomainaccess"] = "False" + + try: + self.network = Network.create( + self.api_client, + self.services["network"], + accountid=self.admin_account.account.name, + domainid=self.admin_account.account.domainid, + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id + ) + self.fail("Network creation should fail.") + except: + self.debug("Network creation failed because subdomainaccess parameter was passed when scope was account.") diff --git a/test/integration/component/test_stopped_vm.py b/test/integration/component/test_stopped_vm.py new file mode 100644 index 00000000000..68f5edc8958 --- /dev/null +++ b/test/integration/component/test_stopped_vm.py @@ -0,0 +1,2036 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" P1 for stopped Virtual Maschine life cycle +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.remoteSSHClient import remoteSSHClient +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +#Import System modules +import time + + +class Services: + """Test Stopped VM Life Cycle Services + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended in create account to + # ensure unique username generated each time + "password": "password", + }, + "virtual_machine": + { + "displayname": "testserver", + "username": "root", # VM creds for SSH + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "service_offering": + { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, # in MHz + "memory": 128, # In MBs + }, + "disk_offering": { + "displaytext": "Small volume", + "name": "Small volume", + "disksize": 20 + }, + "volume": { + "diskname": "DataDisk", + "url": '', + "format": 'VHD' + }, + "iso": # ISO settings for Attach/Detach ISO tests + { + "displaytext": "Test ISO", + "name": "testISO", + "url": "http://iso.linuxquestions.org/download/504/1819/http/gd4.tuwien.ac.at/dsl-4.4.10.iso", + # Source URL where ISO is located + "ostype": 'CentOS 5.3 (64-bit)', + "mode": 'HTTP_DOWNLOAD', # Downloading existing ISO + }, + "template": { + "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, + "displaytext": "Cent OS Template", + "name": "Cent OS Template", + "ostype": 'CentOS 5.3 (64-bit)', + "templatefilter": 'self', + "passwordenabled": True, + }, + "sleep": 60, + "timeout": 10, + #Migrate VM to hostid + "ostype": 'CentOS 5.3 (64-bit)', + # CentOS 5.3 (64-bit) + } + + +class TestDeployVM(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestDeployVM, + 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["ostype"] + ) + + # Create service offerings, 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"] + ) + # Cleanup + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.services = Services().services + self.services["virtual_machine"]["zoneid"] = self.zone.id + self.services["iso"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["template"] = self.template.id + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_01_deploy_vm_no_startvm(self): + """Test Deploy Virtual Machine with no startVM parameter + """ + + # Validate the following: + # 1. deploy Vm without specifying the startvm parameter + # 2. Should be able to login to the VM. + # 3. listVM command should return the deployed VM.State of this VM + # should be "Running". + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id, + mode=self.zone.networktype + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Running", + "VM should be in Running state after deployment" + ) + try: + ssh = self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH to VM instance failed!") + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_02_deploy_vm_startvm_true(self): + """Test Deploy Virtual Machine with startVM=true parameter + """ + + # Validate the following: + # 1. deploy Vm with the startvm=true + # 2. Should be able to login to the VM. + # 3. listVM command should return the deployed VM.State of this VM + # should be "Running". + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=True, + diskofferingid=self.disk_offering.id, + mode=self.zone.networktype + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Running", + "VM should be in Running state after deployment" + ) + try: + ssh = self.virtual_machine.get_ssh_client() + except Exception as e: + self.fail("SSH to VM instance failed!") + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_03_deploy_vm_startvm_false(self): + """Test Deploy Virtual Machine with startVM=false parameter + """ + + # Validate the following: + # 1. deploy Vm with the startvm=false + # 2. Should not be able to login to the VM. + # 3. listVM command should return the deployed VM.State of this VM + # should be "Stopped". + # 4. Check listRouters call for that account. List routers should + # return empty response + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False, + diskofferingid=self.disk_offering.id, + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM should be in Stopped state after deployment with startvm=false" + ) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + routers, + None, + "List routers should return empty response" + ) + self.debug("Destroying instance: %s" % self.virtual_machine.name) + self.virtual_machine.delete(self.apiclient) + self.debug("Instance is destroyed!") + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + self.debug("Instance destroyed..waiting till expunge interval") + + interval = list_configurations( + self.apiclient, + name='expunge.interval' + ) + delay = list_configurations( + self.apiclient, + name='expunge.delay' + ) + # Sleep to ensure that all resources are deleted + time.sleep((int(interval[0].value) + int(delay[0].value))) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.assertEqual( + list_vm_response, + None, + "Check list response returns a valid list" + ) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_04_deploy_startvm_false_attach_volume(self): + """Test Deploy Virtual Machine with startVM=false and attach volume + """ + + # Validate the following: + # 1. deploy Vm with the startvm=false. Attach volume to the instance + # 2. listVM command should return the deployed VM.State of this VM + # should be "Stopped". + # 3. Attach volume should be successful + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False, + diskofferingid=self.disk_offering.id, + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM should be in Stopped state after deployment with startvm=false" + ) + self.debug("Creating a volume in account: %s" % + self.account.account.name) + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume in account: %s" % self.account.account.name) + self.debug("Attaching volume to instance: %s" % + self.virtual_machine.name) + try: + self.virtual_machine.attach_volume(self.apiclient, volume) + except Exception as e: + self.fail("Attach volume failed!") + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_05_deploy_startvm_false_change_so(self): + """Test Deploy Virtual Machine with startVM=false and + change service offering + """ + + # Validate the following: + # 1. deploy Vm with the startvm=false. Attach volume to the instance + # 2. listVM command should return the deployed VM.State of this VM + # should be "Stopped". + # 3. Attach volume should be successful + # 4. Change service offering + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False, + diskofferingid=self.disk_offering.id, + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM should be in Stopped state after deployment with startvm=false" + ) + self.debug("Creating a volume in account: %s" % + self.account.account.name) + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume in account: %s" % self.account.account.name) + self.debug("Attaching volume to instance: %s" % + self.virtual_machine.name) + try: + self.virtual_machine.attach_volume(self.apiclient, volume) + except Exception as e: + self.fail("Attach volume failed!") + self.debug("Fetching details of medium service offering") + medium_service_offs = ServiceOffering.list( + self.apiclient, + name="Medium Instance" + ) + if isinstance(medium_service_offs, list): + medium_service_off = medium_service_offs[0] + else: + self.debug("Service offering not found! Creating a new one..") + medium_service_off = ServiceOffering.create( + self.apiclient, + self.services["service_offering"] + ) + self.cleanup.append(medium_service_off) + + self.debug("Changing service offering for instance: %s" % + self.virtual_machine.name) + try: + self.virtual_machine.change_service_offering( + self.apiclient, + medium_service_off.id + ) + except Exception as e: + self.fail("Change service offering failed: %s" % e) + + self.debug("Starting the instance: %s" % self.virtual_machine.name) + self.virtual_machine.start(self.apiclient) + self.debug("Instance: %s started" % self.virtual_machine.name) + + self.debug("Detaching the disk: %s" % volume.name) + self.virtual_machine.detach_volume(self.apiclient, volume) + self.debug("Datadisk %s detached!" % volume.name) + + volumes = Volume.list( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + id=volume.id, + listall=True + ) + self.assertEqual( + volumes, + None, + "List Volumes should not list any volume for instance" + ) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_06_deploy_startvm_attach_detach(self): + """Test Deploy Virtual Machine with startVM=false and + attach detach volumes + """ + + # Validate the following: + # 1. deploy Vm with the startvm=false. Attach volume to the instance + # 2. listVM command should return the deployed VM.State of this VM + # should be "Stopped". + # 3. Attach volume should be successful + # 4. Detach volume from instance. Detach should be successful + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False, + diskofferingid=self.disk_offering.id, + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM should be in Stopped state after deployment with startvm=false" + ) + self.debug("Creating a volume in account: %s" % + self.account.account.name) + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.debug("Created volume in account: %s" % self.account.account.name) + self.debug("Attaching volume to instance: %s" % + self.virtual_machine.name) + try: + self.virtual_machine.attach_volume(self.apiclient, volume) + except Exception as e: + self.fail("Attach volume failed!") + + self.debug("Detaching the disk: %s" % volume.name) + self.virtual_machine.detach_volume(self.apiclient, volume) + self.debug("Datadisk %s detached!" % volume.name) + + volumes = Volume.list( + self.apiclient, + virtualmachineid=self.virtual_machine.id, + type='DATADISK', + id=volume.id, + listall=True + ) + self.assertEqual( + volumes, + None, + "List Volumes should not list any volume for instance" + ) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_07_deploy_startvm_attach_iso(self): + """Test Deploy Virtual Machine with startVM=false and attach ISO + """ + + # Validate the following: + # 1. deploy Vm with the startvm=false. Attach volume to the instance + # 2. listVM command should return the deployed VM.State of this VM + # should be "Stopped". + # 3. Attach ISO to the instance. Attach ISO should be successful + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False, + diskofferingid=self.disk_offering.id, + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM should be in Stopped state after deployment with startvm=false" + ) + self.debug("Registering a ISO in account: %s" % + self.account.account.name) + iso = Iso.create( + self.apiclient, + self.services["iso"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.debug("Successfully created ISO with ID: %s" % iso.id) + try: + iso.download(self.apiclient) + self.cleanup.append(iso) + except Exception as e: + self.fail("Exception while downloading ISO %s: %s"\ + % (iso.id, e)) + + self.debug("Attach ISO with ID: %s to VM ID: %s" % ( + iso.id, + self.virtual_machine.id + )) + try: + self.virtual_machine.attach_iso(self.apiclient, iso) + except Exception as e: + self.fail("Attach ISO failed!") + + vms = VirtualMachine.list( + self.apiclient, + id=self.virtual_machine.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List vms should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.isoid, + iso.id, + "The ISO status should be reflected in list Vm call" + ) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_08_deploy_attach_volume(self): + """Test Deploy Virtual Machine with startVM=false and + attach volume already attached to different machine + """ + + # Validate the following: + # 1. deploy Vm with the startvm=false. Attach volume to the instance + # 2. listVM command should return the deployed VM.State of this VM + # should be "Stopped". + # 3. Create an instance with datadisk attached to it. Detach DATADISK + # 4. Attach the volume to first virtual machine. + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False, + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM should be in Stopped state after deployment with startvm=false" + ) + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM should be in Stopped state after deployment with startvm=false" + ) + + self.debug( + "Fetching DATADISK details for instance: %s" % + self.virtual_machine_2.name) + volumes = Volume.list( + self.apiclient, + type='DATADISK', + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(volumes, list), + True, + "List volumes should return a valid list" + ) + volume = volumes[0] + + self.debug("Detaching the disk: %s" % volume.name) + + try: + self.virtual_machine_2.detach_volume(self.apiclient, volume) + self.debug("Datadisk %s detached!" % volume.name) + except Exception as e: + self.fail("Detach volume failed!") + + self.debug("Attaching volume to instance: %s" % + self.virtual_machine_1.name) + try: + self.virtual_machine_1.attach_volume(self.apiclient, volume) + except Exception as e: + self.fail("Attach volume failed!") + + volumes = Volume.list( + self.apiclient, + virtualmachineid=self.virtual_machine_1.id, + type='DATADISK', + id=volume.id, + listall=True + ) + self.assertNotEqual( + volumes, + None, + "List Volumes should not list any volume for instance" + ) + return + + +class TestDeployHaEnabledVM(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestDeployHaEnabledVM, + 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["ostype"] + ) + + # Create service, disk offerings etc + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + offerha=True + ) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + # Cleanup + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.services = Services().services + self.services["virtual_machine"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["template"] = self.template.id + self.services["iso"]["zoneid"] = self.zone.id + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_01_deploy_ha_vm_startvm_false(self): + """Test Deploy HA enabled Virtual Machine with startvm=false + """ + + # Validate the following: + # 1. deployHA enabled Vm with the startvm parameter = false + # 2. listVM command should return the deployed VM. State of this VM + # should be "Created". + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id, + startvm=False + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Stopped", + "VM should be in Stopped state after deployment" + ) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_02_deploy_ha_vm_from_iso(self): + """Test Deploy HA enabled Virtual Machine from ISO + """ + + # Validate the following: + # 1. deployHA enabled Vm using ISO with the startvm parameter=true + # 2. listVM command should return the deployed VM. State of this VM + # should be "Running". + + self.iso = Iso.create( + self.apiclient, + self.services["iso"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + try: + # Dowanload the ISO + self.iso.download(self.apiclient) + self.cleanup.append(self.iso) + except Exception as e: + raise Exception("Exception while downloading ISO %s: %s"\ + % (self.iso.id, e)) + + self.debug("Registered ISO: %s" % self.iso.name) + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + templateid=self.iso.id, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id, + startvm=True + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Running", + "VM should be in Running state after deployment" + ) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_03_deploy_ha_vm_iso_startvm_false(self): + """Test Deploy HA enabled Virtual Machine from ISO with startvm=false + """ + + # Validate the following: + # 1. deployHA enabled Vm using ISO with the startvm parameter=false + # 2. listVM command should return the deployed VM. State of this VM + # should be "Stopped". + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id, + startvm=False + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Stopped", + "VM should be in Running state after deployment" + ) + return + + +class TestRouterStateAfterDeploy(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestRouterStateAfterDeploy, + 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["ostype"] + ) + + # Create service offerings, 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"] + ) + # Cleanup + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.services = Services().services + self.services["virtual_machine"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["template"] = self.template.id + self.services["iso"]["zoneid"] = self.zone.id + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_01_deploy_vm_no_startvm(self): + """Test Deploy Virtual Machine with no startVM parameter + """ + + # Validate the following: + # 1. deploy Vm without specifying the startvm parameter + # 2. Should be able to login to the VM. + # 3. listVM command should return the deployed VM.State of this VM + # should be "Running". + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id, + startvm=False + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Stopped", + "VM should be in stopped state after deployment" + ) + self.debug("Checking the router state after VM deployment") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + routers, + None, + "List routers should return empty response" + ) + self.debug( + "Deploying another instance (startvm=true) in the account: %s" % + self.account.account.name) + self.virtual_machine_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + diskofferingid=self.disk_offering.id, + startvm=True + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine_2.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine_2.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Running", + "VM should be in Running state after deployment" + ) + self.debug("Checking the router state after VM deployment") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should not return empty response" + ) + for router in routers: + self.debug("Router state: %s" % router.state) + self.assertEqual( + router.state, + "Running", + "Router should be in running state when instance is running in the account" + ) + self.debug("Destroying the running VM:%s" % + self.virtual_machine_2.name) + self.virtual_machine_2.delete(self.apiclient) + self.debug("Instance destroyed..waiting till expunge interval") + + interval = list_configurations( + self.apiclient, + name='expunge.interval' + ) + delay = list_configurations( + self.apiclient, + name='expunge.delay' + ) + # Sleep to ensure that all resources are deleted + time.sleep((int(interval[0].value) + int(delay[0].value)) * 2) + + self.debug("Checking the router state after VM deployment") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertNotEqual( + routers, + None, + "Router should get deleted after expunge delay+wait" + ) + return + + +class TestDeployVMBasicZone(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestDeployVMBasicZone, + 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["ostype"] + ) + + # Create service offerings, 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"] + ) + # Cleanup + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.services = Services().services + self.services["virtual_machine"]["zoneid"] = self.zone.id + self.services["iso"]["zoneid"] = self.zone.id + self.services["virtual_machine"]["template"] = self.template.id + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + @attr(tags = ["eip", "basic", "sg"]) + def test_01_deploy_vm_startvm_true(self): + """Test Deploy Virtual Machine with startVM=true parameter + """ + + # Validate the following: + # 1. deploy Vm with the startvm=true + # 2. Should be able to login to the VM. + # 3. listVM command should return the deployed VM.State of this VM + # should be "Running". + + self.debug("Checking the network type of the zone: %s" % + self.zone.networktype) + self.assertEqual( + self.zone.networktype, + 'Basic', + "Zone must be configured in basic networking mode" + ) + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=True, + diskofferingid=self.disk_offering.id, + mode=self.zone.networktype + ) + + self.debug("Deployed instance ion account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Running", + "VM should be in Running state after deployment" + ) + return + + @attr(tags = ["eip", "basic", "sg"]) + def test_02_deploy_vm_startvm_false(self): + """Test Deploy Virtual Machine with startVM=true parameter + """ + + # Validate the following: + # 1. deploy Vm with the startvm=true + # 2. Should be able to login to the VM. + # 3. listVM command should return the deployed VM.State of this VM + # should be "Running". + + self.debug("Checking the network type of the zone: %s" % + self.zone.networktype) + self.assertEqual( + self.zone.networktype, + 'Basic', + "Zone must be configured in basic networking mode" + ) + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False, + mode=self.zone.networktype + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Stopped", + "VM should be in stopped state after deployment" + ) + self.debug("Starting the instance: %s" % self.virtual_machine.name) + self.virtual_machine.start(self.apiclient) + self.debug("Started the instance: %s" % self.virtual_machine.name) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Running", + "VM should be in running state after deployment" + ) + return + + +class TestDeployVMFromTemplate(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + + cls.api_client = super( + TestDeployVMFromTemplate, + 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) + + # Create service, disk offerings etc + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"], + offerha=True + ) + cls.disk_offering = DiskOffering.create( + cls.api_client, + cls.services["disk_offering"] + ) + # Cleanup + cls._cleanup = [ + cls.service_offering, + cls.disk_offering, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.services = Services().services + self.services["virtual_machine"]["zoneid"] = self.zone.id + self.account = Account.create( + self.apiclient, + self.services["account"], + domainid=self.domain.id + ) + self.template = Template.register( + self.apiclient, + self.services["template"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + try: + self.template.download(self.apiclient) + except Exception as e: + raise Exception("Template download failed: %s" % e) + + self.cleanup = [self.account] + return + + def tearDown(self): + try: + self.debug("Cleaning up the resources") + cleanup_resources(self.apiclient, self.cleanup) + self.debug("Cleanup complete!") + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_deploy_vm_password_enabled(self): + """Test Deploy Virtual Machine with startVM=false & enabledpassword in + template + """ + + # Validate the following: + # 1. Create the password enabled template + # 2. Deploy Vm with this template and passing startvm=false + # 3. Start VM. Deploy VM should be successful and it should be in Up + # and running state + + self.debug("Deploying instance in the account: %s" % + self.account.account.name) + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id, + startvm=False, + ) + + self.debug("Deployed instance in account: %s" % + self.account.account.name) + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + + vm_response.state, + "Stopped", + "VM should be in stopped state after deployment" + ) + self.debug("Starting the instance: %s" % self.virtual_machine.name) + self.virtual_machine.start(self.apiclient) + self.debug("Started the instance: %s" % self.virtual_machine.name) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.virtual_machine.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Running", + "VM should be in running state after deployment" + ) + return + + +class TestVMAccountLimit(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMAccountLimit, + 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["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + # Create Account, VMs etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_vm_per_account(self): + """Test VM limit per account + """ + + # Validate the following + # 1. Set the resource limit for VM per account. + # 2. Deploy VMs more than limit in that account. + # 3. AIP should error out + + self.debug( + "Updating instance resource limit for account: %s" % + self.account.account.name) + # Set usage_vm=1 for Account 1 + update_resource_limit( + self.apiclient, + 0, # Instance + account=self.account.account.name, + domainid=self.account.account.domainid, + max=1 + ) + self.debug( + "Deploying VM instance in account: %s" % + self.account.account.name) + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False + ) + + # Verify VM state + self.assertEqual( + virtual_machine.state, + 'Stopped', + "Check VM state is Running or not" + ) + + # Exception should be raised for second instance (account_1) + with self.assertRaises(Exception): + VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False + ) + return + + +class TestUploadAttachVolume(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestUploadAttachVolume, + 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["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + + # Create Account, VMs etc + cls.account = Account.create( + cls.api_client, + cls.services["account"], + domainid=cls.domain.id + ) + + cls.service_offering = ServiceOffering.create( + cls.api_client, + cls.services["service_offering"] + ) + cls._cleanup = [ + cls.service_offering, + cls.account + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created instance, volumes and snapshots + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + @attr(tags = ["advanced", "eip", "advancedns", "basic", "sg"]) + def test_upload_attach_volume(self): + """Test Upload volume and attach to VM in stopped state + """ + + # Validate the following + # 1. Upload the volume using uploadVolume API call + # 2. Deploy VM with startvm=false. + # 3. Attach the volume to the deployed VM in step 2 + + self.debug( + "Uploading the volume: %s" % + self.services["volume"]["diskname"]) + try: + volume = Volume.upload( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("Uploading the volume: %s" % volume.name) + volume.wait_for_upload(self.apiclient) + self.debug("Volume: %s uploaded successfully") + except Exception as e: + self.fail("Failed to upload the volume: %s" % e) + + self.debug( + "Deploying VM instance in account: %s" % + self.account.account.name) + + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + startvm=False + ) + # Verify VM state + self.assertEqual( + virtual_machine.state, + 'Stopped', + "Check VM state is Running or not" + ) + with self.assertRaises(Exception): + virtual_machine.attach_volume(self.apiclient, volume) + self.debug("Failed to attach the volume as expected") + return + + +class TestDeployOnSpecificHost(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestDeployOnSpecificHost, + 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["ostype"] + ) + 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", + "api", "basic", "eip", "sg"]) + def test_deployVmOnGivenHost(self): + """Test deploy VM on specific host + """ + + # Steps for validation + # 1. as admin list available hosts that are Up + # 2. deployVM with hostid=above host + # 3. listVirtualMachines + # 4. destroy VM + # Validate the following + # 1. listHosts returns at least one host in Up state + # 2. VM should be in Running + # 3. VM should be on the host that it was deployed on + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + type='Routing', + state='Up', + listall=True + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "CS should have atleast one host Up and Running" + ) + + host = hosts[0] + self.debug("Deploting VM on host: %s" % host.name) + + try: + vm = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + hostid=host.id + ) + self.debug("Deploy VM succeeded") + except Exception as e: + self.fail("Deploy VM failed with exception: %s" % e) + + self.debug("Cheking the state of deployed VM") + vms = VirtualMachine.list( + self.apiclient, + id=vm.id, + listall=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List Vm should return a valid response" + ) + + vm_response = vms[0] + self.assertEqual( + vm_response.state, + "Running", + "VM should be in running state after deployment" + ) + self.assertEqual( + vm_response.hostid, + host.id, + "Host id where VM is deployed should match" + ) + return diff --git a/test/integration/component/test_tags.py b/test/integration/component/test_tags.py new file mode 100644 index 00000000000..7b8cd5774ec --- /dev/null +++ b/test/integration/component/test_tags.py @@ -0,0 +1,2325 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +""" P1 tests for tags +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +import datetime + + +class Services: + """Test tags 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": "password", + }, + "user": { + "email": "user@clogeny.com", + "firstname": "User", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "password", + }, + "other_user": { + "email": "otheruser@clogeny.com", + "firstname": "Other", + "lastname": "User", + "username": "User", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + # in MHz + "memory": 128, + # In MBs + }, + "disk_offering": { + "displaytext": "Tiny Disk Offering", + "name": "Tiny Disk Offering", + "disksize": 1 + }, + "volume": { + "diskname": "Test Volume", + }, + "virtual_machine": { + "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", + "ostype": 'CentOS 5.3 (64-bit)', + "templatefilter": 'self', + }, + "iso": + { + "displaytext": "DSL ISO", + "name": "DSL 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": False, + "ostype": 'CentOS 5.3 (64-bit)', + "mode": 'HTTP_DOWNLOAD', + # Used in Extract template, value must be HTTP_DOWNLOAD + }, + "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", + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 22, + "openfirewall": False, + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "protocol": "TCP" + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '55.55.0.0/11', + # Any network (For creating FW rule) + }, + "security_group": { + "name": 'SSH', + "protocol": 'TCP', + "startport": 22, + "endport": 22, + "cidrlist": '0.0.0.0/0', + }, + # Cent OS 5.3 (64 bit) + "sleep": 60, + "ostype": 'CentOS 5.3 (64-bit)', + "timeout": 10, + "mode": 'advanced', + } + + +class TestResourceTags(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestResourceTags, + 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, + ) + cls.zone = get_zone(cls.api_client, cls.services) + + cls.template = get_template( + cls.api_client, + cls.zone.id, + cls.services["ostype"] + ) + + # Create service offerings, 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.services["iso"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.zone.networktype + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + mode=cls.zone.networktype + ) + cls._cleanup = [ + cls.account, + cls.service_offering, + cls.disk_offering + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + print("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 = [] + self.rm_tags = [] + 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) + + for tag in self.rm_tags: + tag['tag_obj'].delete(self.apiclient, tag['resid'], + tag['restype'], + {tag['key']: tag['value']}) + + return + + @attr(tags=["advanced"]) + def test_01_lbrule_tag(self): + """ Test Create tag on LB rule and remove the LB rule + """ + # Validate the following + # 1. Configured LB rule by assigning 2vms + # 2. Create Tag on LB rule using CreateTag API + # 3. Delete the LB rule + + self.debug("Fetching the network details for account: %s" % + self.account.account.name) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should not return an empty response" + ) + network = networks[0] + self.debug("Network for the account: %s is %s" % + (self.account.account.name, network.name)) + + self.debug("Associating public IP for network: %s" % network.id) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.cleanup.append(public_ip) + + self.debug("Trying to create LB rule on IP: %s" % + public_ip.ipaddress.ipaddress) + + # Create Load Balancer rule on the public ip + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name + ) + + # Check if the LB rule created successfully + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=lb_rule.id + ) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return valid list" + ) + + self.debug("Assigning the virtual machines (%s, %s) to lb rule: %s" % + (self.vm_1.name, + self.vm_2.name, + lb_rule.name)) + + lb_rule.assign(self.apiclient, [self.vm_1, self.vm_2]) + self.debug("Creating a tag for load balancer rule") + tag = Tag.create( + self.apiclient, + resourceIds=lb_rule.id, + resourceType='LoadBalancer', + tags={'LB': 40} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='LoadBalancer', + key='LB', + account=self.account.account.name, + domainid=self.account.account.domainid, + value=40 + ) + + self.debug("Tag created: %s" % str(tags)) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + int(tags[0].value), + 40, + "The tag value should match with the original value" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + listall=True, + key='FW', + value=40 + ) + + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules should return valid list" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=lb_rule.id, + resourceType='LoadBalancer', + tags={'LB': 40} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='LoadBalancer', + key='LB', + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + + self.debug("Deleting the Load balancer rule") + try: + lb_rule.delete(self.apiclient) + except Exception as e: + self.fail("failed to delete load balancer rule! - %s" % e) + return + + @attr(tags=["advanced"]) + def test_02_natrule_tag(self): + """ Test Create tag on nat rule and remove the nat rule + """ + # Validate the following + # 1. Configured PF rule + # 2. create Tag on PF rule using CreateTag API + # 3. Delete the PF rule + + self.debug("Fetching the network details for account: %s" % + self.account.account.name) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should not return an empty response" + ) + network = networks[0] + self.debug("Network for the account: %s is %s" % + (self.account.account.name, network.name)) + + self.debug("Associating public IP for network: %s" % network.id) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.cleanup.append(public_ip) + + self.debug("Trying to create LB rule on IP: %s" % + public_ip.ipaddress.ipaddress) + + self.debug("Creating PF rule for vm: %s on Ip: %s" % + (self.vm_1.name, public_ip.ipaddress.ipaddress)) + + nat_rule = NATRule.create( + self.apiclient, + self.vm_1, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id + ) + + # Check if NAT rule created successfully + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return valid list" + ) + + self.debug("Creating a tag for port forwarding rule") + tag = Tag.create( + self.apiclient, + resourceIds=nat_rule.id, + resourceType='portForwardingRule', + tags={'PF': 40} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='portForwardingRule', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='PF', + value=40 + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + int(tags[0].value), + 40, + "The tag value should match with the original value" + ) + + nat_rules = NATRule.list( + self.apiclient, + listall=True, + key='FW', + value=40 + ) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return valid list" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=nat_rule.id, + resourceType='portForwardingRule', + tags={'PF': 40} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='portForwardingRule', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='PF', + value=40 + ) + + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + self.debug("Deleting the port forwarding rule") + try: + nat_rule.delete(self.apiclient) + except Exception as e: + self.fail("failed to delete port forwarding rule! - %s" % e) + return + + @attr(tags=["advanced"]) + def test_03_firewallrule_tag(self): + """ Test Create tag on firewall rule and remove the firewall rule + """ + # Validate the following + # 1. Configured firewall rule + # 2. create Tag on firewall rule using CreateTag API + # 3. Delete the firewall rule + + self.debug("Fetching the network details for account: %s" % + self.account.account.name) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should not return an empty response" + ) + network = networks[0] + self.debug("Network for the account: %s is %s" % + (self.account.account.name, network.name)) + + self.debug("Associating public IP for network: %s" % network.id) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.cleanup.append(public_ip) + + self.debug("Creating firewall rule on public IP: %s" % + public_ip.ipaddress.ipaddress) + # Create Firewall rule on public IP + 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"] + ) + + self.debug("Created firewall rule: %s" % fw_rule.id) + + fw_rules = FireWallRule.list( + self.apiclient, + id=fw_rule.id + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "List fw rules should return a valid firewall rules" + ) + + self.assertNotEqual( + len(fw_rules), + 0, + "Length of fw rules response should not be zero" + ) + + self.debug("Creating a tag for firewall rule") + tag = Tag.create( + self.apiclient, + resourceIds=fw_rule.id, + resourceType='FirewallRule', + tags={'FW': '40'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='FirewallRule', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='FW', + value='40' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual( + tags[0].value, + '40', + "The tag value should match with the original value" + ) + + fw_rules = FireWallRule.list( + self.apiclient, + listall=True, + key='FW', + value='40' + ) + self.assertEqual( + isinstance(fw_rules, list), + True, + "List fw rules should return a valid firewall rules" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=fw_rule.id, + resourceType='FirewallRule', + tags={'FW': '40'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='FirewallRule', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='FW', + value='40' + ) + + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + + self.debug("Deleting the firewall rule") + try: + fw_rule.delete(self.apiclient) + except Exception as e: + self.fail("failed to delete firewall rule! - %s" % e) + return + + @attr(tags=["advanced"]) + @unittest.skip("Not supported in 3.0.5") + def test_04_vpn_tag(self): + """ Test Create tag on vpn and remove the vpn + """ + # Validate the following + # 1. Enable the VPN + # 2. create Tag on VPN rule using CreateTag API + # 3. Delete the VPN rule + + self.debug("Fetching the network details for account: %s" % + self.account.account.name) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should not return an empty response" + ) + network = networks[0] + self.debug("Network for the account: %s is %s" % + (self.account.account.name, network.name)) + + self.debug("Associating public IP for network: %s" % network.id) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id + ) + self.cleanup.append(public_ip) + + nat_rule = NATRule.create( + self.apiclient, + self.vm_1, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id + ) + + # Check if NAT rule created successfully + nat_rules = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return valid list" + ) + + # User should be able to enable VPN on source NAT + self.debug("Creating VPN with public NAT IP: %s" % + public_ip.ipaddress.ipaddress) + # Assign VPN to source NAT + try: + vpn = Vpn.create( + self.apiclient, + public_ip.ipaddress.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + except Exception as e: + print e + + vpns = Vpn.list( + self.apiclient, + publicipid=public_ip.ipaddress.id, + listall=True, + ) + + self.assertEqual( + isinstance(vpns, list), + True, + "List VPNs should return a valid VPN list" + ) + + self.assertNotEqual( + len(vpns), + 0, + "Length of list VPN response should not be zero" + ) + + self.debug("Creating a tag for VPN rule") + tag = Tag.create( + self.apiclient, + resourceIds=nat_rule.id, + resourceType='VPN', + tags={'protocol': 'L2TP'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='VPN', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='protocol', + value='L2TP' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'L2TP', + "The tag value should match with the original value" + ) + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=vpn.id, + resourceType='VPN', + tags={'protocol': 'L2TP'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='VPN', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='protocol', + value='L2TP' + ) + + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + + self.debug("Disabling the VPN") + try: + vpn.delete(self.apiclient) + except Exception as e: + self.fail("failed to disable VPN! - %s" % e) + return + + @attr(tags=["advanced", "basic"]) + def test_05_vm_tag(self): + """ Test creation, listing and deletion tags on UserVM + """ + # Validate the following + # 1. Create a tag on VM using createTags API + # 2. Delete above created tag using deleteTags API + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + "The tag value should match with the original value" + ) + + vms = VirtualMachine.list( + self.apiclient, + listall=True, + key='region', + value='India' + ) + + self.assertEqual( + isinstance(vms, list), + True, + "Tag based VMs listing failed") + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + return + + @attr(tags=["advanced", "basic"]) + def test_06_template_tag(self): + """ Test creation, listing and deletion tag on templates + """ + # Validate the following + # 1. Create a tag on template/ISO using createTags API + # 2. Delete above created tag using deleteTags API + + self.debug("Stopping the virtual machine: %s" % self.vm_1.name) + #Stop virtual machine + self.vm_1.stop(self.apiclient) + + timeout = self.services["timeout"] + #Wait before server has be successfully stopped + time.sleep(self.services["sleep"]) + + while True: + list_volume = Volume.list( + self.apiclient, + virtualmachineid=self.vm_1.id, + type='ROOT', + listall=True + ) + if isinstance(list_volume, list): + break + elif timeout == 0: + raise Exception("List volumes failed.") + + time.sleep(5) + timeout = timeout - 1 + + self.volume = list_volume[0] + + self.debug("Creating template from ROOT disk of virtual machine: %s" % + self.vm_1.name) + #Create template from volume + template = Template.create( + self.apiclient, + self.services["template"], + self.volume.id + ) + self.cleanup.append(template) + self.debug("Created the template(%s). Now restarting the userVm: %s" % + (template.name, self.vm_1.name)) + self.vm_1.start(self.apiclient) + + self.debug("Creating a tag for the template") + tag = Tag.create( + self.apiclient, + resourceIds=template.id, + resourceType='Template', + tags={'OS': 'CentOS'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='Template', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='OS', + value='CentOS' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'CentOS', + 'The tag should have original value' + ) + + templates = Template.list( + self.apiclient, + templatefilter=\ + self.services["template"]["templatefilter"], + listall=True, + key='OS', + value='CentOS' + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=template.id, + resourceType='Template', + tags={'OS': 'CentOS'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='Template', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='OS', + value='CentOS' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + return + + @attr(tags=["advanced", "basic"]) + def test_07_iso_tag(self): + """ Test creation, listing and deletion tags on ISO + """ + # Validate the following + # 1. Create a tag on ISO using createTags API + # 2. Delete above created tag using deleteTags API + + iso = Iso.create( + self.apiclient, + self.services["iso"], + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("ISO created with ID: %s" % iso.id) + + list_iso_response = list_isos( + self.apiclient, + id=iso.id + ) + self.assertEqual( + isinstance(list_iso_response, list), + True, + "Check list response returns a valid list" + ) + + self.debug("Creating a tag for the ISO") + tag = Tag.create( + self.apiclient, + resourceIds=iso.id, + resourceType='ISO', + tags={'OS': 'CentOS'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='ISO', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='OS', + value='CentOS' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'CentOS', + 'The tag should have original value' + ) + + isos = Iso.list( + self.apiclient, + listall=True, + key='OS', + value='CentOS' + ) + + self.assertEqual( + isinstance(isos, list), + True, + "List isos should not return an empty response" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=iso.id, + resourceType='ISO', + tags={'OS': 'CentOS'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='ISO', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='OS', + value='CentOS' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + return + + @attr(tags=["advanced", "basic"]) + def test_08_volume_tag(self): + """ Test creation, listing and deletion tagson volume + """ + # Validate the following + # 1. Create a tag on volume using createTags API + # 2. Delete above created tag using deleteTags API + + self.debug("Creating volume for account: %s " % + self.account.account.name) + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.cleanup.append(volume) + + self.debug("Volume created in account: %s" % volume.name) + + self.debug("Creating a tag for the volume") + tag = Tag.create( + self.apiclient, + resourceIds=volume.id, + resourceType='volume', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='volume', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + + vols = Volume.list(self.apiclient, + listall=True, + key='region', + value='India' + ) + self.assertEqual( + isinstance(vols, list), + True, + "List volumes should not return empty response" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=volume.id, + resourceType='volume', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='volume', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + return + + @attr(tags=["advanced", "basic"]) + def test_09_snapshot_tag(self): + """ Test creation, listing and deletion tag son snapshot + """ + # Validate the following + # 1. Create a tag on snapshot using createTags API + # 2. Delete above created tag using deleteTags API + + self.debug("Creating snapshot on ROOT volume for VM: %s " % + self.vm_1.name) + # Get the Root disk of VM + volumes = list_volumes( + self.apiclient, + virtualmachineid=self.vm_1.id, + type='ROOT', + listall=True + ) + volume = volumes[0] + + # Create a snapshot from the ROOTDISK + snapshot = Snapshot.create(self.apiclient, volume.id) + self.debug("Snapshot created: ID - %s" % snapshot.id) + self.cleanup.append(snapshot) + + snapshots = list_snapshots( + self.apiclient, + id=snapshot.id + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Tag based snapshot listing failed") + + self.debug("Creating a tag for the snapshot") + tag = Tag.create( + self.apiclient, + resourceIds=snapshot.id, + resourceType='snapshot', + tags={'type': 'manual'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='snapshot', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='type', + value='manual' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'manual', + 'The tag should have original value' + ) + + snapshots = list_snapshots( + self.apiclient, + listall=True, + key='type', + value='manual' + ) + self.assertEqual( + isinstance(snapshots, list), + True, + "Check list response returns a valid list" + ) + self.assertNotEqual( + snapshots, + None, + "Check if result exists in list snapshots call" + ) + self.debug("Listing snapshots by tag was successful") + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=snapshot.id, + resourceType='snapshot', + tags={'type': 'manual'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='snapshot', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='type', + value='manual' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + + return + + @attr(tags=["advanced"]) + def test_10_network_tag(self): + """ Testcreation, listing and deletion tags on guest network + """ + # Validate the following + # 1. Create a tag on Network using createTags API + # 2. Delete above created tag using deleteTags API + + self.debug("Fetching the network details for account: %s" % + self.account.account.name) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should not return an empty response" + ) + network = networks[0] + self.debug("Network for the account: %s is %s" % + (self.account.account.name, network.name)) + + self.debug("Creating a tag for load balancer rule") + tag = Tag.create( + self.apiclient, + resourceIds=network.id, + resourceType='Network', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='Network', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + key='region', + value='India' + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should not return an empty response" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=network.id, + resourceType='Network', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='Network', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + return + + @attr(tags=["basic", "sg"]) + @unittest.skip("skip") + def test_11_migrate_tagged_vm_del(self): + """ Test migration of a tagged vm and delete the tag + """ + # Validate the following + # 1. Create a tag on VM using createTags API + # 2. Delete above created tag using deleteTags API + + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_1.id, + listall=True + ) + + self.assertEqual( + isinstance(vms, list), + True, + "List vms should not return empty response" + ) + source_host = vms[0].hostid + + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + resourcestate='Enabled', + type='Routing' + ) + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return valid host response" + ) + + self.debug("Available hosts: ") + for host in hosts: + self.debug("Host: %s", host.id) + + # Filtering out the source host from list host response + temp_hosts = [host for host in hosts if host.id != source_host] + dest_host = temp_hosts[0] + + self.debug("Destination host is: %s" % dest_host.id) + self.debug("Source host is: %s" % source_host.id) + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + + self.debug("Migrating the instance from: %s to %s" % + (source_host, dest_host.id)) + self.vm_1.migrate(self.apiclient, hostid=dest_host.id) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + return + + @attr(tags=["advanced", "basic"]) + def test_13_tag_case_insensitive(self): + """ Test to verify that tags are not case sensitive + """ + # Validate the following + # 1. Create a tag on VM using createTags API + # 2. Add same tag in upper case. + # 3. Verify that tag creation failed. + + self.debug("Creating a tag for user VM") + tag_1 = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag_1.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + self.debug("Creating the same tag with caps for user VM") + + try: + tag_2 = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'REGION': 'INDIA'} + ) + except Exception as e: + pass + else: + assert("Creating same tag in upper case succeeded") + + self.debug("Deleting the created tag..") + try: + tag_1.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + + return + + @attr(tags=["advanced", "basic"]) + def test_14_special_char_mutiple_tags(self): + """ Test multiple tags and with special characters on same machine + """ + # Validate the following + # 1. Create more than 10 tags to VM using createTags API + # 2. Create a tag with special characters on VM using createTags API + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={ + 'region': 'India', + 'offering': 'high', + 'type': 'webserver', + 'priority': 'critical', + 'networking': 'advanced', + 'os': 'centos', + 'backup': 'no$required', + 'rootvolume': 'NFS', + 'iso': 'na', + 'ha': 'yes', + 'test': 'test' + } + ) + self.debug("Tags created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + # Cleanup + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={ + 'region': 'India', + 'offering': 'high', + 'type': 'webserver', + 'priority': 'critical', + 'networking': 'advanced', + 'os': 'centos', + 'backup': 'no$required', + 'rootvolume': 'NFS', + 'iso': 'na', + 'ha': 'yes', + 'test': 'test' + } + ) + return + + @attr(tags=["advanced"]) + def test_15_project_tag(self): + """ Test creation, listing and deletion tags on projects + """ + # Validate the following + # 1. Create a new project + # 2. Create a tag on projects using createTags API + # 3. Delete the tag. + + # 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("Creating a tag for the project") + tag = Tag.create( + self.apiclient, + resourceIds=project.id, + resourceType='project', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='project', + projectid=project.id, + key='region', + ) + self.debug("tags = %s" % tags) + + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + + projects = Project.list( + self.apiclient, + listall=True, + key='region', + value='India' + ) + + self.assertEqual( + isinstance(projects, list), + True, + "List Project should return valid list" + ) + + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=project.id, + resourceType='project', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='project', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + return + + @attr(tags=["advanced", "basic"]) + def test_16_query_tags_other_account(self): + """ Test Query the tags from other account + """ + # Validate the following + # 1. Login with an account(account A) + # 2. Create a tags on resource(eg:VM) + # 3. Login with other account and query the tags using + # listTags API + + self.debug("Creating user accounts..") + + user_account = Account.create( + self.apiclient, + self.services["user"], + domainid=self.domain.id + ) + self.cleanup.append(user_account) + + other_user_account = Account.create( + self.apiclient, + self.services["other_user"], + domainid=self.domain.id + ) + self.cleanup.append(other_user_account) + + iso = Iso.create( + self.apiclient, + self.services["iso"], + account=user_account.account.name, + domainid=user_account.account.domainid + ) + self.debug("ISO created with ID: %s" % iso.id) + + list_iso_response = list_isos( + self.apiclient, + id=iso.id + ) + self.assertEqual( + isinstance(list_iso_response, list), + True, + "Check list response returns a valid list" + ) + + self.debug("Creating a tag for the ISO") + tag = Tag.create( + self.apiclient, + resourceIds=iso.id, + resourceType='ISO', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='ISO', + account=user_account.account.name, + domainid=user_account.account.domainid, + key='region', + ) + + self.debug("Verify listTag API using user account") + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + "The tag value should match with the original value" + ) + + self.debug("Verify listTag API using other account") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='ISO', + account=other_user_account.account.name, + domainid=other_user_account.account.domainid, + key='region', + ) + + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + + return + + @attr(tags=["advanced", "basic"]) + def test_17_query_tags_admin_account(self): + """ Test Query the tags from admin account + """ + # Validate the following + # 1. Login with an account(account A) + # 2. Create a tags on resource(eg:VM) + # 3. Login with admin account and query the tags using + # listTags API + + self.debug("Creating user accounts..") + + user_account = Account.create( + self.apiclient, + self.services["user"], + domainid=self.domain.id + ) + self.cleanup.append(user_account) + + iso = Iso.create( + self.apiclient, + self.services["iso"], + account=user_account.account.name, + domainid=user_account.account.domainid + ) + self.debug("ISO created with ID: %s" % iso.id) + + list_iso_response = list_isos( + self.apiclient, + id=iso.id + ) + self.assertEqual( + isinstance(list_iso_response, list), + True, + "Check list response returns a valid list" + ) + + self.debug("Creating a tag for the ISO") + tag = Tag.create( + self.apiclient, + resourceIds=iso.id, + resourceType='ISO', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='ISO', + account=user_account.account.name, + domainid=user_account.account.domainid, + key='region', + ) + + self.debug("Verify listTag API using user account") + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + "The tag value should match with the original value" + ) + + self.debug("Verify listTag API using admin account") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='ISO', + key='region', + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + + return + + @attr(tags=["advanced", "basic"]) + def test_18_invalid_list_parameters(self): + """ Test listAPI with invalid tags parameter + """ + # Validate the following + # 1. Create a tag on supported resource type(ex:vms) + # 2. Run the list API commands with passing invalid key parameter + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + # Add tag for removal during teardown. vm_1 is shared resource if it is tagged + # and the test fails with exception then the tag is not deleted. And + # subsequent tests fail to tag the vm_1 with same key-pair + # breaking the tests. + self.rm_tags.append({'tag_obj': tag,'restype': 'userVM', 'resid': self.vm_1.id, + 'key': 'region', 'value': 'India'}) + + self.debug("Passing invalid key parameter to the listAPI for vms") + + vms = VirtualMachine.list(self.apiclient, + listall=True, + tags={'region111': 'India'} + ) + self.assertEqual( + vms, + None, + "List vms should return empty response" + ) + + return + + @attr(tags=["advanced", "basic"]) + def test_19_delete_add_same_tag(self): + """ Test deletion and addition of same tag on a resource. + """ + + # Validate the following + # 1. Deletion of a tag without any errors. + # 2. Add same tag. + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual( + tags[0].value, + "India", + "Tag created with incorrect value" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + self.debug("Recreating the tag with same name") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual(tags[0].value, + "India", + "Tag created with incorrect value" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + return + + @attr(tags=["advanced", "basic"]) + def test_20_create_tags_multiple_resources(self): + "Test creation of same tag on multiple resources" + + self.debug("Creating volume for account: %s " % + self.account.account.name) + volume = Volume.create( + self.apiclient, + self.services["volume"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + diskofferingid=self.disk_offering.id + ) + self.cleanup.append(volume) + + self.debug("Volume created in account: %s" % volume.name) + + self.debug("Creating a tag for the volume") + tag = Tag.create( + self.apiclient, + resourceIds=volume.id, + resourceType='volume', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='volume', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + self.assertEqual( + tags[0].value, + 'India', + 'The tag should have original value' + ) + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual( + tags[0].value, + "India", + "Tag created with incorrect value" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + self.debug("Verifying if tag is actually deleted!") + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + tags, + None, + "List tags should return empty response" + ) + + return + + @attr(tags=["advanced", "basic"]) + def test_21_create_tag_stopped_vm(self): + "Test creation of tag on stopped vm." + + self.debug("Stopping the virtual machine: %s" % self.vm_1.name) + #Stop virtual machine + self.vm_1.stop(self.apiclient) + + timeout = self.services["timeout"] + #Wait before server has be successfully stopped + time.sleep(self.services["sleep"]) + + list_vm_response = list_virtual_machines( + self.apiclient, + id=self.vm_1.id + ) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s" \ + % self.vm_1.id + ) + + self.assertEqual( + isinstance(list_vm_response, list), + True, + "Check list response returns a valid list" + ) + vm_response = list_vm_response[0] + + self.assertEqual( + vm_response.state, + "Stopped", + "VM should be in stopped state after deployment" + ) + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual( + tags[0].value, + "India", + "Tag created with incorrect value" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + return + + @attr(tags=["advanced", "basic"]) + def test_22_create_tag_destroyed_vm(self): + "Test creation of tag on stopped vm." + + self.debug("Destroying instance: %s" % self.vm_1.name) + self.vm_1.delete(self.apiclient) + + self.debug("Creating a tag for user VM") + tag = Tag.create( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + self.debug("Tag created: %s" % tag.__dict__) + + tags = Tag.list( + self.apiclient, + listall=True, + resourceType='userVM', + account=self.account.account.name, + domainid=self.account.account.domainid, + key='region', + value='India' + ) + self.assertEqual( + isinstance(tags, list), + True, + "List tags should not return empty response" + ) + + self.assertEqual( + tags[0].value, + "India", + "Tag created with incorrect value" + ) + + self.debug("Deleting the created tag..") + try: + tag.delete( + self.apiclient, + resourceIds=self.vm_1.id, + resourceType='userVM', + tags={'region': 'India'} + ) + except Exception as e: + self.fail("Failed to delete the tag - %s" % e) + + return diff --git a/test/integration/component/test_vpc.py b/test/integration/component/test_vpc.py new file mode 100644 index 00000000000..82eeac10a98 --- /dev/null +++ b/test/integration/component/test_vpc.py @@ -0,0 +1,2725 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests for VPC functionality +""" +#Import Local Modules +import marvin +import unittest +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test VPC 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": "password", + }, + "domain_admin": { + "email": "domain@admin.com", + "firstname": "Domain", + "lastname": "Admin", + "username": "DoA", + # Random characters are appended for unique + # username + "password": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat,NetworkACL', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "vpc_no_name": { + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 22, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "http_rule": { + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "ICMP" + }, + "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', + }, + "domain": { + "name": "TestDomain" + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + +class TestVPC(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPC, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + cls._cleanup = [ + cls.service_offering, + cls.vpc_off + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_restart_vpc_no_networks(self): + """ Test restart VPC having no networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Restart VPC. Restart VPC should be successful + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Restarting the VPC with no network") + try: + vpc.restart(self.apiclient) + except Exception as e: + self.fail("Failed to restart VPC network - %s" % e) + + self.validate_vpc_network(vpc, state='Enabled') + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_restart_vpc_with_networks(self): + """ Test restart VPC having with networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add couple of networks to VPC. + # 3. Restart VPC. Restart network should be successful + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network_1 = 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, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + self.network_offering_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + self.network_offering_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering_no_lb) + + gateway = '10.1.2.1' # New network -> different gateway + self.debug("Creating network with network offering: %s" % + self.network_offering_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering_no_lb.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + self.debug("Restarting the VPC with no network") + try: + vpc.restart(self.apiclient) + except Exception as e: + self.fail("Failed to restart VPC network - %s" % e) + + self.validate_vpc_network(vpc, state='Enabled') + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_delete_vpc_no_networks(self): + """ Test delete VPC having no networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Delete VPC. Delete VPC should be successful + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Restarting the VPC with no network") + try: + vpc.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete VPC network - %s" % e) + + self.debug("Check if the VPC offering is deleted successfully?") + vpcs = VPC.list( + self.apiclient, + id=vpc.id + ) + self.assertEqual( + vpcs, + None, + "List VPC offerings should not return anything" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_delete_vpc_with_networks(self): + """ Test delete VPC having with networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add couple of networks to VPC. + # 3. Delete VPC. Delete network should be successful + # 4. Virtual Router should be deleted + # 5. Source NAT should be released back to pool + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network_1 = 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, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + self.network_offering_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + self.network_offering_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering_no_lb) + + gateway = '10.1.2.1' # New network -> different gateway + self.debug("Creating network with network offering: %s" % + self.network_offering_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering_no_lb.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + self.debug("Deleting the VPC with no network") + with self.assertRaises(Exception): + vpc.delete(self.apiclient) + self.debug("Delete VPC failed as there are still networks in VPC") + self.debug("Deleting the networks in the VPC") + + try: + network_1.delete(self.apiclient) + network_2.delete(self.apiclient) + except Exception as e: + self.fail("failed to delete the VPC networks: %s" % e) + + self.debug("Now trying to delete VPC") + try: + vpc.delete(self.apiclient) + except Exception as e: + self.fail("Delete to restart VPC network - %s" % e) + + self.debug("Check if the VPC offering is deleted successfully?") + vpcs = VPC.list( + self.apiclient, + id=vpc.id + ) + self.assertEqual( + vpcs, + None, + "List VPC offerings should not return anything" + ) + self.debug("Waiting for network.gc.interval to cleanup network resources") + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + self.debug("Check if VR is deleted or not?") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + routers, + None, + "List Routers for the account should not return any response" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_05_list_vpc_apis(self): + """ Test list VPC APIs + """ + + # Validate the following + # 1. Create multiple VPCs + # 2. listVPCs() by name. VPC with the provided name should be listed. + # 3. listVPCs() by displayText. VPC with the provided displayText + # should be listed. + # 4. listVPCs() by cidr. All the VPCs with the provided cidr should + # be listed. + # 5. listVPCs() by vpcofferingId.All the VPCs with the vpcofferingId + # should be listed. + # 6. listVPCs() by supported Services(). All the VPCs that provide the + # list of services should be listed. + # 7. listVPCs() by restartRequired (set to true). All the VPCs that + # require restart should be listed. + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc_1 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc_1) + + self.services["vpc"]["cidr"] = "10.1.46.1/16" + vpc_2 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc_2) + + self.debug("Check list VPC API by Name?") + vpcs = VPC.list( + self.apiclient, + name=vpc_1.name, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC shall return a valid resposne" + ) + vpc = vpcs[0] + self.assertEqual( + vpc.name, + vpc_1.name, + "VPC name should match with the existing one" + ) + + self.debug("Check list VPC API by displayText?") + vpcs = VPC.list( + self.apiclient, + displaytext=vpc_1.displaytext, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC shall return a valid resposne" + ) + vpc = vpcs[0] + self.assertEqual( + vpc.displaytext, + vpc_1.displaytext, + "VPC displaytext should match with the existing one" + ) + + self.debug("Check list VPC API by cidr?") + vpcs = VPC.list( + self.apiclient, + cidr=vpc_2.cidr, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC shall return a valid resposne" + ) + vpc = vpcs[0] + self.assertEqual( + vpc.cidr, + vpc_2.cidr, + "VPC cidr should match with the existing one" + ) + self.debug("Validating list VPC by Id") + self.validate_vpc_network(vpc_1) + + self.debug("Validating list VPC by vpcofferingId") + vpcs = VPC.list( + self.apiclient, + vpcofferingid=self.vpc_off.id, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC by vpcofferingId should return a valid response" + ) + self.debug("Length of list VPC response: %s" % len(vpcs)) + self.assertEqual( + len(vpcs), + 2, + "List VPC should return 3 enabled VPCs" + ) + for vpc in vpcs: + self.assertEqual( + vpc.vpcofferingid, + self.vpc_off.id, + "VPC offering ID should match with that of resposne" + ) + + self.debug("Validating list VPC by supportedservices") + vpcs = VPC.list( + self.apiclient, + supportedservices='Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + listall=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC by vpcofferingId should return a valid response" + ) + for vpc in vpcs: + self.assertIn( + vpc.id, + [vpc_1.id, vpc_2.id], + "VPC offering ID should match with that of resposne" + ) + self.debug("Validating list VPC by restart required") + vpcs = VPC.list( + self.apiclient, + restartrequired=True, + listall=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + if vpcs is not None: + for vpc in vpcs: + self.assertEqual( + vpc.restartrequired, + True, + "RestartRequired should be set as True" + ) + self.debug("Validating list VPC by restart required") + vpcs = VPC.list( + self.apiclient, + restartrequired=False, + listall=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC by vpcofferingId should return a valid response" + ) + if vpcs is not None: + for vpc in vpcs: + self.assertEqual( + vpc.restartrequired, + False, + "RestartRequired should be set as False" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_06_list_vpc_apis_admin(self): + """ Test list VPC APIs for different user roles + """ + + # Validate the following + # 1. list VPCS as admin User to view all the Vpcs owned by admin user + # 2. list VPCS as regular User to view all the Vpcs owned by user + # 3. list VPCS as domain admin User to view all the Vpcs owned by admin + + self.user = Account.create( + self.apiclient, + self.services["account"], + ) + self.cleanup.append(self.user) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc_1 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc_1) + + self.services["vpc"]["cidr"] = "10.1.46.1/16" + vpc_2 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.user.account.name, + domainid=self.user.account.domainid + ) + self.validate_vpc_network(vpc_2) + + self.debug("Validating list VPCs call by passing account and domain") + vpcs = VPC.list( + self.apiclient, + account=self.user.account.name, + domainid=self.user.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vpcs, list), + True, + "List VPC should return a valid response" + ) + vpc = vpcs[0] + self.assertEqual( + vpc.id, + vpc_2.id, + "List VPC should return VPC belonging to that account" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_07_restart_network_vm_running(self): + """ Test Restart VPC when there are multiple networks associated + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC + # 3. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2 + # 4. Create a PF rule using TCP protocol on port 22 for vm1 + # 5. Create a Static Nat rule for vm2 + # 6. Create an LB rule for vm3 and vm4 + # 7. Create ingress network ACL for allowing all the above rules from + # public ip range on network1 and network2. + # 8. Create egress network ACL for network1 and network2 to access + # google.com + # 9. Create a private gateway for this VPC and add a static route to + # this gateway + # 10. Create a VPN gateway for this VPC and add static route to gateway + # 11. Make sure that all the PF, LB and Static NAT rules work + # 12. Make sure that we are able to access google.com from all VM + # 13. Make sure that the newly added private gateway's and VPN + # gateway's static routes work as expected. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + self.network_offering_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + self.network_offering_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering_no_lb) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering_no_lb.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network_2 = 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, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_3 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + vm_4 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_1.ipaddress.ipaddress, + network_1.id + )) + + nat_rule = NATRule.create( + self.apiclient, + vm_1, + self.services["natrule"], + ipaddressid=public_ip_1.ipaddress.id, + openfirewall=False, + networkid=network_1.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network_1.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_2.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_2.ipaddress.id, + virtualmachineid=vm_2.id, + networkid=network_1.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_2.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_2.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network_1.id, + listall=True, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_2.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_2.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network_2.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_3.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=self.account.account.name, + networkid=network_2.id, + vpcid=vpc.id, + domainid=self.account.account.domainid + ) + + self.debug("Adding virtual machines %s and %s to LB rule" % ( + vm_3.name, vm_4.name)) + lb_rule.assign(self.apiclient, [vm_3, vm_4]) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + nwacl_lb = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + + self.debug("Adding Egress rules to network %s and %s to allow access to internet") + nwacl_internet_1 = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + nwacl_internet_2 = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + + self.debug("Checking if we can SSH into VM_1?") + try: + ssh_1 = vm_1.get_ssh_client( + ipaddress=public_ip_1.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_2?") + try: + ssh_2 = vm_2.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM using LB rule?") + try: + ssh_3 = vm_3.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_3.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_3.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_08_delete_vpc(self): + """ Test vpc deletion after account deletion + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC + # 3. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2 + # 4. Create a PF rule using TCP protocol on port 22 for vm1 + # 5. Create a Static Nat rule for vm2 + # 6. Create an LB rule for vm3 and vm4 + # 7. Create ingress network ACL for allowing all the above rules from + # public ip range on network1 and network2. + # 8. Create egress network ACL for network1 and network2 to access + # google.com + # 9. Delete account + + self.debug("Removing account from cleanup list") + self.cleanup = [] + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + self.network_offering_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + self.network_offering_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering_no_lb) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=self.network_offering_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering_no_lb.id) + network_2 = 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, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_3 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + vm_4 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_1.ipaddress.ipaddress, + network_1.id + )) + + nat_rule = NATRule.create( + self.apiclient, + vm_1, + self.services["natrule"], + ipaddressid=public_ip_1.ipaddress.id, + openfirewall=False, + networkid=network_1.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network_1.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_2.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_2.ipaddress.id, + virtualmachineid=vm_2.id, + networkid=network_1.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_2.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_2.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network_1.id, + listall=True, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_2.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_2.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network_2.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_3.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=self.account.account.name, + networkid=network_2.id, + vpcid=vpc.id, + domainid=self.account.account.domainid + ) + + self.debug("Adding virtual machines %s and %s to LB rule" % ( + vm_3.name, vm_4.name)) + lb_rule.assign(self.apiclient, [vm_3, vm_4]) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + nwacl_lb = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + + self.debug("Adding Egress rules to network %s and %s to allow access to internet") + nwacl_internet_1 = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + nwacl_internet_2 = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + + self.debug("Checking if we can SSH into VM_1?") + try: + ssh_1 = vm_1.get_ssh_client( + ipaddress=public_ip_1.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"]) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_2?") + try: + ssh_2 = vm_2.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"]) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM using LB rule?") + try: + ssh_3 = vm_3.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_3.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_3.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + self.debug("Deleting the account") + self.account.delete(self.apiclient) + + self.debug("Waiting for account to cleanup") + + interval = list_configurations( + self.apiclient, + name='account.cleanup.interval' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value)) + + self.debug("Checking if VPC is deleted after account deletion") + vpcs = VPC.list( + self.apiclient, + id=vpc.id, + listall=True + ) + self.assertEqual( + vpcs, + None, + "List VPC should not return any response" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_09_vpc_create(self): + """ Test to create vpc and verify VPC state, VR and SourceNatIP + """ + + # Validate the following: + # 1. VPC should get created with "Enabled" state. + # 2. The VR should start when VPC is created. + # 3. SourceNatIP address should be allocated to the VR + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Verify if the VPC was created with enabled state") + self.assertEqual( + vpc.state, + 'Enabled', + "VPC after creation should be in enabled state but the " + "state is %s" % vpc.state + ) + + self.debug("Verify if the Router has started") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + self.assertEqual(routers[0].state, + 'Running', + "Router should be in running state" + ) + + src_nat_list = PublicIPAddress.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True, + issourcenat=True, + vpcid=vpc.id + ) + self.assertEqual(src_nat_list[0].ipaddress, + routers[0].publicip, + "Source Nat IP address was not allocated to VR" + ) + + @attr(tags=["advanced", "intervlan"]) + def test_10_nonoverlaping_cidrs(self): + """ Test creation of multiple VPCs with non-overlapping CIDRs + """ + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("Creating a VPC network in the account: %s" % + self.account.account.name) + vpc_1 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc_1) + + self.services["vpc"]["cidr"] = "10.2.1.1/16" + self.debug( + "Creating a non-overlapping VPC network in the account: %s" % + self.account.account.name) + vpc_2 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc_2) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("Creating a overlapping VPC network in the account: %s" % + self.account.account.name) + try: + vpc_3 = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("%s" % vpc_3) + except Exception as e: + self.debug("%s" % e) + pass + else: + assert("VPC created with overlapping CIDR") + return + + @attr(tags=["advanced", "intervlan"]) + def test_11_deploy_vm_wo_network_netdomain(self): + """ Test deployment of vm in a VPC without network netdomain + """ + + # 1. Create VPC without providing networkDomain. + # 2. Add network without networkDomain to this VPC. + # 3. Deploy VM in this network. + + if self.zone.domain == None: + cmd = updateZone.updateZoneCmd() + cmd.id = self.zone.id + cmd.domain = "ROOT" + self.apiclient.updateZone(cmd) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # 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, + gateway=gateway, + vpcid=vpc.id, + ) + self.debug("Created network with ID: %s" % network.id) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.validate_vm_netdomain(virtual_machine, vpc, network, self.zone.domain) + + def validate_vm_netdomain(self, vm, vpc, network, expected_netdomain): + + self.debug("Associating public IP for network: %s" % network.name) + src_nat_ip_addr = PublicIPAddress.create( + self.apiclient, + zoneid=self.zone.id, + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + + self.debug("Associated %s with network %s" % ( + src_nat_ip_addr.ipaddress.ipaddress, + network.id + )) + + self.debug("Public IP %s" % src_nat_ip_addr.__dict__) + + # Create NAT rule + nat_rule = NATRule.create( + self.apiclient, + vm, + self.services["natrule"], + src_nat_ip_addr.ipaddress.id, + openfirewall=False, + networkid=network.id, + vpcid=vpc.id + ) + + list_nat_rule_response = NATRule.list( + self.apiclient, + id=nat_rule.id + ) + self.assertEqual( + isinstance(list_nat_rule_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertNotEqual( + len(list_nat_rule_response), + 0, + "Check Port Forwarding Rule is created" + ) + self.assertEqual( + list_nat_rule_response[0].id, + nat_rule.id, + "Check Correct Port forwarding Rule is returned" + ) + + self.debug("Adding NetworkACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + self.debug("SSHing into VM with IP address %s with NAT IP %s" % + ( + vm.ipaddress, + src_nat_ip_addr.ipaddress.ipaddress)) + try: + ssh_1 = vm.get_ssh_client( + ipaddress=src_nat_ip_addr.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + # Ping to outsite world + res = ssh_1.execute("cat /etc/resolv.conf") + + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (vm.ssh_ip, e)) + vm_domain = res[1].split(" ")[1] + self.assertEqual( + vm_domain, + expected_netdomain, + "The network domain assigned to virtual machine " + "is %s expected domain was %s" % + (vm_domain, expected_netdomain) + ) + + @attr(tags=["advanced", "intervlan"]) + def test_12_deploy_vm_with_netdomain(self): + """ Test deployment of vm in a VPC with network domain + """ + + # 1. Create VPC without providing networkDomain. + # 2. Add network with networkDomain to this VPC. + # 3. It should fail. + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + + # Creation of network with different network domain than the one + # specified in VPC should fail. + 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, + gateway=gateway, + vpcid=vpc.id, + networkdomain='test.netdomain' + ) + + @attr(tags=["advanced", "intervlan"]) + def test_13_deploy_vm_with_vpc_netdomain(self): + """ Test deployment of vm in a VPC with netdomain + """ + + # 1. Create VPC with providing networkDomain. + # 2. Add network without networkDomain to this VPC. + # 3. Deploy VM in this network, it should get VPC netdomain + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + netdomain = "cl2.internal" + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkDomain=netdomain + ) + self.validate_vpc_network(vpc) + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # 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, + gateway=gateway, + vpcid=vpc.id, + ) + self.debug("Created network with ID: %s" % network.id) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.validate_vm_netdomain(virtual_machine, vpc, network, netdomain) + + @attr(tags=["advanced", "intervlan"]) + def test_14_deploy_vm_1(self): + """ Test deployment of vm in a network from user account. But the VPC is created + without account/domain ID + """ + + # 1. Create VPC without providing account/domain ID. + # 2. Add network with using user account to this VPC. + # 3. Deploy VM in this network + + user = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % user.account.name) + self.cleanup.append(user) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + user.account.name) + + userapiclient = self.testClient.createNewApiClient( + UserName=user.account.name, + DomainName=user.account.domain, + acctType=0) + + vpc = VPC.create( + userapiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + userapiclient, + self.services["network"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.assertNotEqual(virtual_machine, + None, + "VM creation in the network failed") + + return + + @attr(tags=["advanced", "intervlan"]) + def test_15_deploy_vm_2(self): + """ Test deployment of vm in a network from domain admin account. But the VPC is created + without account/domain ID + """ + + # 1. Create VPC without providing account/domain ID. + # 2. Add network with using domain admin account to this VPC. + # 3. Deploy VM in this network + + domain = Domain.create( + self.api_client, + self.services["domain"], + ) + + user = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % user.account.name) + self.cleanup.append(user) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + user.account.name) + + #0 - User, 1 - Root Admin, 2 - Domain Admin + userapiclient = self.testClient.createNewApiClient( + UserName=user.account.name, + DomainName=self.services["domain"]["name"], + acctType=2) + + vpc = VPC.create( + userapiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + userapiclient, + self.services["network"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.assertNotEqual(virtual_machine, + None, + "VM creation in the network failed") + + return + + @attr(tags=["advanced", "intervlan"]) + def test_16_deploy_vm_for_user_by_admin(self): + """ Test deployment of vm in a network by root admin for user. + """ + + #1. As root admin account , + # Create VPC(name,zoneId,cidr,vpcOfferingId,networkDomain by passing user Account/domain ID. + #2. As the user account used in step1 , create a network as part of this VPC. + #3. Deploy Vms as part of this network. + user = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % user.account.name) + self.cleanup.append(user) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + user.account.name) + + userapiclient = self.testClient.createNewApiClient( + UserName=user.account.name, + DomainName=user.account.domain, + acctType=0) + + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + account=user.account.name, + domainid=user.account.domainid, + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + userapiclient, + self.services["network"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.assertNotEqual(virtual_machine, + None, + "VM creation in the network failed") + + return + + @attr(tags=["advanced", "intervlan"]) + def test_17_deploy_vm_for_user_by_domain_admin(self): + """ Test deployment of vm in a network by domain admin for user. + """ + + #1. As domain admin account , Create + # VPC(name,zoneId,cidr,vpcOfferingId,networkDomain + # by passing user Account/domain ID. + #2. As the user account used in step1, create network as part of this VPC + #3. Deploy Vms as part of this network. + + domain = Domain.create( + self.api_client, + self.services["domain"], + ) + + domain_admin = Account.create( + self.apiclient, + self.services["domain_admin"] + ) + self.debug("Created account: %s" % domain_admin.account.name) + self.cleanup.append(domain_admin) + da_apiclient = self.testClient.createNewApiClient( + UserName=domain_admin.account.name, + #DomainName=self.services["domain"]["name"], + DomainName=domain_admin.account.domain, + acctType=2) + + user = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % user.account.name) + self.cleanup.append(user) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + user.account.name) + + #0 - User, 1 - Root Admin, 2 - Domain Admin + userapiclient = self.testClient.createNewApiClient( + UserName=user.account.name, + DomainName=user.account.domain, + acctType=0) + + vpc = VPC.create( + da_apiclient, + self.services["vpc"], + account=user.account.name, + domainid=user.account.domainid, + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + network = Network.create( + userapiclient, + self.services["network"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + userapiclient, + self.services["virtual_machine"], + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.assertNotEqual(virtual_machine, + None, + "VM creation in the network failed") + + return + + @attr(tags=["advanced", "intervlan"]) + def test_18_create_net_for_user_diff_domain_by_doadmin(self): + """ Test creation of network by domain admin for user from different + domain. + """ + + #1. As domain admin account , Create VPC(name,zoneId,cidr,vpcOfferingId,networkDomain) without passing Account/domain ID. + #2. As any User account that is not under this domain , create a network as part of this VPC. + + domain = Domain.create( + self.api_client, + self.services["domain"], + ) + + domain_admin = Account.create( + self.apiclient, + self.services["domain_admin"] + ) + self.debug("Created account: %s" % domain_admin.account.name) + self.cleanup.append(domain_admin) + da_apiclient = self.testClient.createNewApiClient( + UserName=domain_admin.account.name, + DomainName=self.services["domain"]["name"], + acctType=2) + + user = Account.create( + self.apiclient, + self.services["account"] + ) + self.debug("Created account: %s" % user.account.name) + self.cleanup.append(user) + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + user.account.name) + + #0 - User, 1 - Root Admin, 2 - Domain Admin + userapiclient = self.testClient.createNewApiClient( + UserName=user.account.name, + DomainName=user.account.domain, + acctType=0) + + vpc = VPC.create( + da_apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + + with self.assertRaises(Exception): + network = Network.create( + userapiclient, + self.services["network"], + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + + @attr(tags=["advanced", "intervlan"]) + def test_19_create_vpc_wo_params(self): + """ Test creation of VPC without mandatory parameters + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Delete VPC. Delete VPC should be successful + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + + # Create VPC without vpcOffering param + with self.assertRaises(Exception): + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + self.services["vpc_no_name"]["cidr"] = "10.1.1.1/16" + # Create VPC without name param + with self.assertRaises(Exception): + vpc = VPC.create( + self.apiclient, + self.services["vpc_no_name"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + # Create VPC without zoneid param + with self.assertRaises(Exception): + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + vpc_wo_cidr = {"name": "TestVPC_WO_CIDR", + "displaytext": "TestVPC_WO_CIDR" + } + + # Create VPC without CIDR + with self.assertRaises(Exception): + vpc = VPC.create( + self.apiclient, + vpc_wo_cidr, + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + + @attr(tags=["advanced", "intervlan"]) + def test_20_update_vpc_name_display_text(self): + """ Test to verify updation of vpc name and display text + """ + + # Validate the following: + # 1. VPC should get created with "Enabled" state. + # 2. The VR should start when VPC is created. + # 3. SourceNatIP address should be allocated to the VR + + self.services["vpc"]["cidr"] = "10.1.1.1/16" + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # 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, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + + new_name = "New VPC" + new_display_text = "New display text" + vpc.update( + self.apiclient, + name=new_name, + displaytext=new_display_text + ) + + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual(vpc_networks[0].name, + new_name, + "Updation of VPC name failed.") + + self.assertEqual(vpc_networks[0].displaytext, + new_display_text, + "Updation of VPC display text failed.") + + +@unittest.skip("Skip") +class TestVPCHostMaintenance(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCHostMaintenance, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + hosts = Host.list( + cls.api_client, + zoneid=cls.zone.id, + listall=True, + type='Routing' + ) + + if isinstance(hosts, list): + for host in hosts: + Host.enableMaintenance( + cls.api_client, + id=host.id + ) + + timeout = cls.services["timeout"] + while True: + time.sleep(cls.services["sleep"]) + hosts_states = Host.list( + cls.api_client, + id=host.id, + listall=True + ) + if hosts_states[0].resourcestate == 'PrepareForMaintenance': + # Wait for sometimetill host goes in maintenance state + time.sleep(cls.services["sleep"]) + elif hosts_states[0].resourcestate == 'Maintenance': + time.sleep(cls.services["sleep"]) + break + elif timeout == 0: + raise unittest.SkipTest( + "Failed to enable maintenance mode on %s" % host.name) + timeout = timeout - 1 + + cls._cleanup = [ + cls.service_offering, + cls.vpc_off + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + hosts = Host.list( + cls.api_client, + zoneid=cls.zone.id, + listall=True, + type='Routing' + ) + if isinstance(hosts, list): + for host in hosts: + Host.cancelMaintenance( + cls.api_client, + id=host.id + ) + hosts_states = Host.list( + cls.api_client, + id=host.id, + listall=True + ) + if hosts_states[0].resourcestate != 'Enabled': + raise Exception( + "Failed to cancel maintenance mode on %s, e" % ( + host.name, e)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_create_vpc_host_maintenance(self): + """ Test VPC when host is in maintenance mode + """ + + # Validate the following + # 1. Put the host in maintenance mode. + # 2. Attempt to Create a VPC with cidr - 10.1.1.1/16 + # 3. VPC will be created but will be in "Disabled" state + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc, state='Disabled') + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_create_vpc_wait_gc(self): + """ Test VPC when host is in maintenance mode and wait till nw gc + """ + + # Validate the following + # 1. Put the host in maintenance mode. + # 2. Attempt to Create a VPC with cidr - 10.1.1.1/16 + # 3. Wait for the VPC GC thread to run. + # 3. VPC will be created but will be in "Disabled" state and should + # get deleted + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc, state='Disabled') + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + self.debug("Sleep till network gc thread runs..") + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + vpcs = VPC.list( + self.apiclient, + id=vpc.id, + listall=True + ) + self.assertEqual( + vpcs, + None, + "List VPC should not return anything after network gc" + ) + return diff --git a/test/integration/component/test_vpc_host_maintenance.py b/test/integration/component/test_vpc_host_maintenance.py new file mode 100644 index 00000000000..b2ffcbfb073 --- /dev/null +++ b/test/integration/component/test_vpc_host_maintenance.py @@ -0,0 +1,891 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests VM life cycle in VPC network functionality +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test VM life cycle in VPC network 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 64, + }, + "service_offering_1": { + "name": "Tiny Instance- tagged host 1", + "displaytext": "Tiny off-tagged host2", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 64, + "tags": "HOST_TAGS_HERE" + }, + "service_offering_2": { + "name": "Tiny Instance- tagged host 2", + "displaytext": "Tiny off-tagged host2", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 64, + "tags": "HOST_TAGS_HERE" + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "network_off_shared": { + "name": 'Shared Network offering', + "displaytext": 'Shared Network offering', + "guestiptype": 'Shared', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "specifyIpRanges": True, + "specifyVlan": True + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0', + "limit": 5, + # Max networks allowed as per hypervisor + # Xenserver -> 5, VMWare -> 9 + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 2222, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "http_rule": { + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "ICMP" + }, + "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', + "userdata": 'This is sample data', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +@unittest.skip("No suitable setup available for testing") +class TestVMLifeCycleHostmaintenance(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMLifeCycleHostmaintenance, + 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["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering_1 = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_1"] + ) + cls.service_offering_2 = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_2"] + ) + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + cls.nw_off_no_lb = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + cls.nw_off_no_lb.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_2 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off_no_lb.id, + zoneid=cls.zone.id, + gateway='10.1.2.1', + vpcid=cls.vpc.id + ) + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_1.id, + networkids=[str(cls.network_1.id)] + ) + # Spawn an instance in that network + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_1.id, + networkids=[str(cls.network_1.id)] + ) + cls.vm_3 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_2.id, + networkids=[str(cls.network_2.id)] + ) + routers = Router.list( + cls.api_client, + account=cls.account.account.name, + domainid=cls.account.account.domainid, + listall=True + ) + if isinstance(routers, list): + cls.vpcvr = routers[0] + + cls._cleanup = [ + cls.service_offering_1, + cls.service_offering_2, + cls.nw_off, + cls.nw_off_no_lb, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.account.delete(cls.api_client) + wait_for_cleanup(cls.api_client, ["account.cleanup.interval"]) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + # Waiting for network cleanup to delete vpc offering + wait_for_cleanup(cls.api_client, ["network.gc.wait", + "network.gc.interval"]) + cls.vpc_off.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.debug("Check the status of VPC virtual router") + routers = Router.list( + self.apiclient, + networkid=self.network_1.id, + listall=True + ) + if not isinstance(routers, list): + raise Exception("No response from list routers API") + + self.router = routers[0] + if self.router.state == "Running": + Router.stop(self.apiclient, id=self.router.id) + + self.cleanup = [] + return + + def tearDown(self): + try: + #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 + + def validate_vm_deployment(self): + """Validates VM deployment on different hosts""" + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=self.network_1.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs shall return a valid response" + ) + host_1 = vms[0].hostid + self.debug("Host for network 1: %s" % vms[0].hostid) + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=self.network_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs shall return a valid response" + ) + host_2 = vms[0].hostid + self.debug("Host for network 2: %s" % vms[0].hostid) + + self.assertNotEqual( + host_1, + host_2, + "Both the virtual machines should be deployed on diff hosts " + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_enable_maintenance_with_vpc_nw(self): + """ Test enable Maintenance Mode on Hosts which have VPC elements + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2. Make + # sure vm1 and vm3 are deployed on one host in the cluster while + # vm2 and vm4 are deployed on the other host in the cluster. This + # can be done using host's tags & service offerings with host tags + # Steps: + # 1.Enable Maintenance on one of host on which VPCVR is present + # Validations: + # 1. Successfully push the host into maintenance mode. + # 2. VMs present on the above host should successfully migrate to the + # other host present in the cluster + + self.validate_vm_deployment() + self.debug("Stop the host on which the VPC virtual router is running") + try: + Host.enableMaintenance(self.apiclient, id=self.vpcvr.hostid) + except Exception as e: + self.fail("Failed to enable maintenance mode on host: %s" % e) + + self.debug( + "Check if all instances belonging to the account are up again?") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers shall return a valid VPCVR for account" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running after migration" + ) + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "VM response should return instances running for account" + ) + for vm in vms: + self.assertEqual( + vm.state, + "Ruuning", + "Vm state should be running after migration" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_cancel_maintenance(self): + """ Test cancel Maintenance Mode on the above Hosts + Migrate VMs Back + """ + + # Steps + # 1. Cancel Maintenance Mode on the host. + # 2. Migrate the VMs back onto the host on which Maintenance mode is + # cancelled. + # Validate the following + # 1. Successfully cancel the Maintenance mode on the host. + # 2. Migrate the VMs back successfully onto the host. + # 3. Check that the network connectivity exists with the migrated VMs. + + self.debug("Cancel host maintenence on which the VPCVR is running") + try: + Host.cancelMaintenance(self.apiclient, id=self.vpcvr.hostid) + except Exception as e: + self.fail("Failed to enable maintenance mode on host: %s" % e) + + self.debug( + "Migrating the instances back to the host: %s" % + self.vpcvr.hostid) + try: + cmd = migrateSystemVm.migrateSystemVmCmd() + cmd.hostid = self.vpcvr.hostid + cmd.virtualmachineid = self.vpcvr.id + self.apiclient.migrateSystemVm(cmd) + except Exception as e: + self.fail("Failed to migrate VPCVR back: %s" % e) + + self.debug("Check the status of router after migration") + routers = Router.list( + self.apiclient, + id=self.vpcvr.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers shall return the valid response" + ) + self.assertEqual( + routers[0].state, + "Running", + "Router state should be running" + ) + # TODO: Check for the network connectivity + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_reconnect_host(self): + """ Test reconnect Host which has VPC elements + """ + + # Steps: + # 1.Reconnect one of the host on which VPC Virtual Router is present. + # Validate the following + # 1. Host should successfully reconnect. + # 2. Network connectivity to all the VMs on the host should not be + # effected due to reconnection. + + self.debug("Reconnecting the host where VPC VR is running") + try: + Host.reconnect(self.apiclient, id=self.vpcvr.hostid) + except Exception as e: + self.fail("Failed to reconnect to host: %s" % e) + + self.debug("Check the status of router after migration") + routers = Router.list( + self.apiclient, + id=self.vpcvr.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers shall return the valid response" + ) + self.assertEqual( + routers[0].state, + "Running", + "Router state should be running" + ) + # TODO: Check for the network connectivity + return + + +@unittest.skip("No suitable setup available for testing") +class TestVPCNetworkRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetworkRules, + 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["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering_1 = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_1"] + ) + cls.service_offering_2 = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_2"] + ) + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + cls.nw_off_no_lb = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + cls.nw_off_no_lb.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_2 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off_no_lb.id, + zoneid=cls.zone.id, + gateway='10.1.2.1', + vpcid=cls.vpc.id + ) + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_1.id, + networkids=[str(cls.network_1.id)] + ) + # Spawn an instance in that network + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_2.id, + networkids=[str(cls.network_1.id)] + ) + cls.vm_3 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_1.id, + networkids=[str(cls.network_2.id)] + ) + cls.vm_4 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_2.id, + networkids=[str(cls.network_2.id)] + ) + + cls._cleanup = [ + cls.service_offering_1, + cls.service_offering_2, + cls.nw_off, + cls.nw_off_no_lb, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.account.delete(cls.api_client) + wait_for_cleanup(cls.api_client, ["account.cleanup.interval"]) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + # Waiting for network cleanup to delete vpc offering + wait_for_cleanup(cls.api_client, ["network.gc.wait", + "network.gc.interval"]) + cls.vpc_off.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vm_deployment(self): + """Validates VM deployment on different hosts""" + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=self.network_1.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs shall return a valid response" + ) + host_1 = vms[0].hostid + self.debug("Host for network 1: %s" % vms[0].hostid) + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=self.network_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs shall return a valid response" + ) + host_2 = vms[0].hostid + self.debug("Host for network 2: %s" % vms[0].hostid) + + self.assertNotEqual( + host_1, + host_2, + "Both the virtual machines should be deployed on diff hosts " + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_list_pf_rules_for_vpc(self): + """ Test List Port Forwarding Rules & vms belonging to a VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2. + # Make sure vm1 and vm3 are deployed on one host in the cluster + # while vm2 and vm4 are deployed on the other host in the cluster. + # This can be done using host's tags and service offerings with + # host tags. + # 4. Create a PF rule for vms in network1. + # 5. Create a PF rule for vms in network2. + # Steps: + # 1. List all the Port Forwarding Rules belonging to a VPC + # 2. Successfully List the Port Forwarding Rules belonging to the VPC + # 3. List the VMs on network1 for selection for the PF Rule + # 4. Successfully list the VMs for Port Forwarding Rule creation + + self.debug("Associating public IP for network: %s" % + self.network_1.name) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network_1.id, + vpcid=self.vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_1.ipaddress.ipaddress, + self.network_1.id + )) + + nat_rule_1 = NATRule.create( + self.apiclient, + self.vm_1, + self.services["natrule"], + ipaddressid=public_ip_1.ipaddress.id, + openfirewall=False, + networkid=self.network_1.id, + vpcid=self.vpc.id + ) + + self.debug("Associating public IP for network: %s" % + self.network_2.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=self.network_2.id, + vpcid=self.vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + self.network_2.id + )) + + nat_rule_2 = NATRule.create( + self.apiclient, + self.vm_3, + self.services["natrule"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=False, + networkid=self.network_2.id, + vpcid=self.vpc.id + ) + + self.debug("Listing all the PF rules belonging to VPC") + nat_rules = NATRule.list( + self.apiclient, + vpcid=self.vpc.id, + listall=True + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules should return the valid list" + ) + self.assertEqual( + len(nat_rules), + 2, + "List NAT for VPC shall return all NAT rules belonging to VPC" + ) + for nat_rule in nat_rules: + self.assertEqual( + nat_rule.vpcid, + self.vpc.id, + "NAT rules should belong to VPC" + ) + + self.debug( + "Listing all the VMs belonging to VPC for network: %s" % + self.network_1.name) + vms = VirtualMachine.list( + self.apiclient, + networkid=self.network_1.id, + vpcid=self.vpc.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return the valid list" + ) + for vm in vms: + self.assertEqual( + vm.networkid, + self.network_1.id, + "List VMs should return vms belonging to network_1" + ) + return + diff --git a/test/integration/component/test_vpc_network.py b/test/integration/component/test_vpc_network.py new file mode 100644 index 00000000000..e09b4157e8b --- /dev/null +++ b/test/integration/component/test_vpc_network.py @@ -0,0 +1,2587 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests for VPC network functionality +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test VPC network 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + "servicecapabilitylist": { + }, + }, + "network_off_netscaler": { + "name": 'Network offering-netscaler', + "displaytext": 'Network offering-netscaler', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Vpn": 'VpcVirtualRouter', + "Lb": 'Netscaler', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + }, + }, + "network_off_shared": { + "name": 'Shared Network offering', + "displaytext": 'Shared Network offering', + "guestiptype": 'Shared', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "specifyIpRanges": True, + "specifyVlan": True + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 22, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "http_rule": { + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "ICMP" + }, + "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', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestVPCNetwork(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetwork, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + cls._cleanup = [ + cls.service_offering, + cls.vpc_off + ] + 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.services = Services().services + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_create_network(self): + """ Test create network in VPC + """ + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering. + # 3. Create a network offering with guest type=Isolated" that has + # all of supported Services(Vpn,dhcpdns,UserData, SourceNat,Static + # NAT,LB and PF,LB,NetworkAcl ) provided by VPCVR and conserver + # mode is ON + # 4. Create a VPC using the above VPC offering. + # 5. Create a network using the network offering created in step2 as + # part of this VPC. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + self.debug( + "Verifying list network response to check if network created?") + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response" + ) + nw = networks[0] + + self.assertEqual( + nw.networkofferingid, + self.network_offering.id, + "Network should be created from network offering - %s" % + self.network_offering.id + ) + self.assertEqual( + nw.vpcid, + vpc.id, + "Network should be created in VPC: %s" % vpc.name + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_create_network_fail(self): + """ Test create network in VPC + """ + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering. + # 3. Create a network offering with guest type=Isolated" that has + # one of supported Services(Vpn,dhcpdns,UserData, SourceNat,Static + # NAT,LB and PF,LB,NetworkAcl ) provided by VPCVR and conserver + # mode is ON + # 4. Create a VPC using the above VPC offering. + # 5. Create a network using the network offering created in step2 as + # part of this VPC. + # 6. Network creation should fail + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.services["network_offering"]["supportedservices"] = 'SourceNat' + self.services["network_offering"]["serviceProviderList"] = { + "SourceNat": 'VirtualRouter', } + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + return + + @unittest.skip("Skip - Requires netscaler setup") + @attr(tags=["netscaler", "intervlan"]) + def test_03_create_network_netscaler(self): + """ Test create network using netscaler for LB + """ + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type="Isolated that has + # LB services provided by Netscaler and all other services + # provided by VPCVR and conserver mode is "ON" + # 4. Create a VPC using the above VPC offering. + # 5. Create a network using the network offering created in step2 as + # part of this VPC + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_off_netscaler"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + self.debug( + "Verifying list network response to check if network created?") + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response" + ) + nw = networks[0] + + self.assertEqual( + nw.networkofferingid, + self.network_offering.id, + "Network should be created from network offering - %s" % + self.network_offering.id + ) + self.assertEqual( + nw.vpcid, + vpc.id, + "Network should be created in VPC: %s" % vpc.name + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_create_multiple_networks_with_lb(self): + """ Test create multiple networks with LB service (Should fail) + """ + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type=Isolated that has LB + # services Enabled and conserver mode is "ON". + # 4. Create a network using the network offering created in step3 as + # part of this VPC. + # 5. Create another network using the network offering created in + # step3 as part of this VPC + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + self.debug( + "Verifying list network response to check if network created?") + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response" + ) + nw = networks[0] + + self.assertEqual( + nw.networkofferingid, + self.network_offering.id, + "Network should be created from network offering - %s" % + self.network_offering.id + ) + self.assertEqual( + nw.vpcid, + vpc.id, + "Network should be created in VPC: %s" % vpc.name + ) + self.debug("Creating another network in VPC: %s" % vpc.name) + 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, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug( + "Network creation failed as network with LB service already exists") + return + + @attr(tags=["intervlan"]) + def test_05_create_network_ext_LB(self): + """ Test create network with external LB devices + """ + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type=Isolated that has LB + # services Enabled and conserver mode is "ON". + # 4. Create a network using the network offering created in step3 as + # part of this VPC. + # 5. Create another network using the network offering created in + # step3 as part of this VPC + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + with self.assertRaises(Exception): + NetworkOffering.create( + self.apiclient, + self.services["network_off_netscaler"], + conservemode=False + ) + self.debug("Network creation failed") + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Skipping - able to create network with RvR") + def test_06_create_network_with_rvr(self): + """ Test create network with eredundant router capability + """ + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type=Isolated that has all + # services provided by VPC VR,conserver mode ""OFF"" and Redundant + # Router capability enabled. + # 4. Create a VPC using the above VPC offering. + # 5. Create a network using the network offering created in step2 as + # part of this VPC + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + # Enable redundant router capability for the network offering + self.services["network"]["servicecapabilitylist"] = { + "SourceNat": { + "RedundantRouter": "true", + }, + } + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + 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, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Network creation failed") + return + + @attr(tags=["advanced", "intervlan"]) + def test_07_create_network_unsupported_services(self): + """ Test create network services not supported by VPC (Should fail) + """ + + # Validate the following + # 1. Create VPC Offering by specifying supported Services - + # Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # with out including LB services. + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type=Isolated that has all + # supported Services(Vpn,dhcpdns,UserData, SourceNat,Static NAT,LB + # and PF,LB,NetworkAcl ) provided by VPCVR and conserver mode is OFF + # 4. Create a VPC using the above VPC offering + # 5. Create a network using the network offering created in step2 as + # part of this VPC. + + self.debug("Creating a VPC offering without LB service") + self.services["vpc_offering"]["supportedservices"] = 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,UserData,StaticNat' + + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + self.network_offering.id) + 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, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Network creation failed as VPC doesn't have LB service") + return + + @attr(tags=["advanced", "intervlan"]) + def test_08_create_network_without_sourceNAT(self): + """ Test create network without sourceNAT service in VPC (should fail) + """ + + # Validate the following + # 1. Create VPC Offering by specifying supported Services- + # Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # with out including LB services. + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type=Isolated that does not + # have SourceNAT services enabled + # 4. Create a VPC using the above VPC offering + # 5. Create a network using the network offering created in step2 as + # part of this VPC + + self.debug("Creating a VPC offering without LB service") + self.services["vpc_offering"]["supportedservices"] = 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat' + + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering without SourceNAT service") + self.services["network_offering"]["supportedservices"] = 'Dhcp,Dns,PortForwarding,Lb,UserData,StaticNat,NetworkACL' + self.services["network_offering"]["serviceProviderList"] = { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + } + + self.debug("Creating network offering without SourceNAT") + with self.assertRaises(Exception): + NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + self.debug("Network creation failed as VPC doesn't have LB service") + return + + @attr(tags=["advanced", "intervlan"]) + def test_09_create_network_shared_nwoff(self): + """ Test create network with shared network offering + """ + + # Validate the following + # 1. Create VPC Offering by specifying supported Services - + # Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # with out including LB services + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type=shared + # 4. Create a VPC using the above VPC offering + # 5. Create a network using the network offering created in step2 + # as part of this VPC + + self.debug("Creating a VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering with guesttype=shared") + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_off_shared"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # Creating network using the network offering created + self.debug( + "Creating network with network offering without SourceNAT: %s" % + self.network_offering.id) + 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Network creation failed") + return + + @attr(tags=["advanced", "intervlan"]) + def test_10_create_network_with_conserve_mode(self): + """ Test create network with conserve mode ON + """ + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network offering with guest type=Isolated that has all + # supported Services(Vpn,dhcpdns,UserData, SourceNat,Static NAT,LB + # and PF,LB,NetworkAcl ) provided by VPCVR and conserver mode is ON + # 4. Create a VPC using the above VPC offering + # 5. Create a network using the network offering created in step2 as + # part of this VPC + + self.debug("Creating a VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering with conserve mode = ON") + + with self.assertRaises(Exception): + NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=True + ) + self.debug( + "Network creation failed as VPC support nw with conserve mode OFF") + return + +@unittest.skip("tested") +class TestVPCNetworkRanges(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetworkRanges, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + cls._cleanup = [ + cls.service_offering, + cls.vpc_off + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_create_network_outside_range(self): + """ Test create network outside cidr range of VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1 with cidr - 10.2.1.1/24 to this VPC + # 3. Network creation should fail. + + self.debug("Creating a VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network with cidr: 10.1.1.1/16") + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering") + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # Creating network using the network offering created + self.debug("Creating network outside of the VPC's network") + 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, + gateway='10.2.1.1', + vpcid=vpc.id + ) + self.debug( + "Network creation failed as network cidr range is outside of vpc") + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_create_network_outside_range(self): + """ Test create network outside cidr range of VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1 with cidr - 10.2.1.1/24 to this VPC + # 3. Network creation should fail. + + self.debug("Creating a VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network with cidr: 10.1.1.1/16") + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering") + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # Creating network using the network offering created + self.debug("Creating network outside of the VPC's network") + 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, + gateway='10.2.1.1', + vpcid=vpc.id + ) + self.debug( + "Network creation failed as network cidr range is outside of vpc") + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_create_network_inside_range(self): + """ Test create network inside cidr range of VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1 with cidr - 10.1.1.1/8 to this VPC + # 3. Network creation should fail. + + self.debug("Creating a VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network with cidr: 10.1.1.1/16") + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering") + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # Creating network using the network offering created + self.debug("Creating network inside of the VPC's network") + with self.assertRaises(Exception): + + # cidr = 10.1.1.1/8 -> netmask = 255.0.0.0, gateway = 10.1.1.1 + self.services["network"]["netmask"] = '255.0.0.0' + 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug( + "Network creation failed as network cidr range is inside of vpc") + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_create_network_overlapping_range(self): + """ Test create network overlapping cidr range of VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1 with cidr - 10.1.1.1/24 to this VPC + # 3. Add network2 with cidr - 10.1.1.1/24 to this VPC + # 4. Add network3 with cidr - 10.1.1.1/26 to this VPC + # 5. Network creation in step 3 & 4 should fail. + + self.debug("Creating a VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network with cidr: 10.1.1.1/16") + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering") + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + # 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + self.debug( + "Verifying list network response to check if network created?") + networks = Network.list( + self.apiclient, + id=network.id, + listall=True + ) + self.assertEqual( + isinstance(networks, list), + True, + "List networks should return a valid response" + ) + nw = networks[0] + + self.assertEqual( + nw.networkofferingid, + self.network_offering.id, + "Network should be created from network offering - %s" % + self.network_offering.id + ) + self.assertEqual( + nw.vpcid, + vpc.id, + "Network should be created in VPC: %s" % vpc.name + ) + + # Creating network using the network offering created + self.debug( + "Creating network with same network range as of previous network") + 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Network creation as network range 10.1.1.1/24 is same" + \ + "as that of existing network") + + self.debug("Creating network having overlapping network ranges") + with self.assertRaises(Exception): + # cidr = 10.1.1.1/8 -> netmask=255.255.255.192, gateway=10.1.1.1 + self.services["network"]["netmask"] = '255.255.255.192' + + 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, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug( + "Network creation failed as network range overlaps each other") + return + + @attr(tags=["advanced", "intervlan"]) + def test_05_create_network_diff_account(self): + """ Test create network from different account in VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1 with cidr - 10.1.1.1/24 to this VPC + # 3. Network creation should fail. + + self.debug("Creating a VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network with cidr: 10.1.1.1/16") + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Creating network offering") + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + self.debug( + "Creating the new account to create new network in VPC: %s" % + vpc.name) + account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + + # Creating network using the network offering created + self.debug("Creating network from diff account than VPC") + with self.assertRaises(Exception): + + # cidr = 10.1.1.1/8 -> netmask = 255.0.0.0, gateway = 10.1.1.1 + self.services["network"]["netmask"] = '255.0.0.0' + Network.create( + self.apiclient, + self.services["network"], + accountid=account.account.name, + domainid=account.account.domainid, + networkofferingid=self.network_offering.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug( + "Network creation failed as VPC belongs to different account") + return + + +class TestVPCNetworkUpgrade(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetworkUpgrade, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + cls._cleanup = [ + cls.service_offering, + cls.vpc_off + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Error while NW upgrade - Failed to implement network (with specified id) elements and resources as a part of network update") + def test_01_network_services_upgrade(self): + """ Test update Network that is part of a VPC to a network offering + that has more services. + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # except PF services provided by VRVPC provider, conserve mode=OFF + # 3.Create a Network offering - NO2 with all supported services + # including Pf services provided by VRVPC provider,conserve mode=OFF + # 4. Add network1(10.1.1.1/24) using N01 to this VPC. + # 5. Deploy vm1 and vm2 in network1. + # 6. Create a Static Nat and LB rules for vms in network1. + # 7. Make sure you are not allowed to create a PF rule for any Vm in + # network1 and the Static Nat and LB rules for vms work as expected + # 8. Update network1 to NO2. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + self.services["network_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,UserData,Lb,StaticNat,NetworkACL' + self.services["network_offering"]["serviceProviderList"] = { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + } + + nw_off_no_pf = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off_no_pf.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off_no_pf) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_pf.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_pf.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed another VM in network: %s" % network_1.id) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_1.ipaddress.ipaddress, + network_1.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_1.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_1.ipaddress.id, + accountid=self.account.account.name, + networkid=network_1.id, + vpcid=vpc.id, + domainid=self.account.account.domainid + ) + + self.debug("Adding virtual machines %s and %s to LB rule" % ( + vm_1.name, vm_2.name)) + lb_rule.assign(self.apiclient, [vm_1, vm_2]) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network_1.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_2.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_2.ipaddress.id, + virtualmachineid=vm_2.id, + networkid=network_1.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_2.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_2.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network_1.id, + listall=True, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_2.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + nwacl_lb = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + + self.debug( + "Adding Egress rules to network %s to access internet" % + (network_1.name)) + nwacl_internet_1 = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + + self.debug("Checking if we can SSH into VM_1? - IP: %s" % + public_ip_1.ipaddress.ipaddress) + try: + ssh_1 = vm_1.get_ssh_client( + ipaddress=public_ip_1.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_2?") + try: + ssh_2 = vm_2.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network_1.id + )) + + self.debug("Creatinng NAT rule in network shall through exception?") + with self.assertRaises(Exception): + nat_rule = NATRule.create( + self.apiclient, + vm_1, + self.services["natrule"], + ipaddressid=public_ip_3.ipaddress.id, + openfirewall=False, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Create NAT rule failed!") + + self.debug( + "Stopping all the virtual machines in network before upgrade") + try: + vm_1.stop(self.apiclient) + vm_2.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VMs, %s" % e) + + wait_for_cleanup(self.apiclient, ["expunge.interval", "expunge.delay"]) + + self.debug("Upgrading network offering to support PF services") + try: + network_1.update( + self.apiclient, + networkofferingid=nw_off.id, + changecidr=True + ) + except Exception as e: + self.fail("failed to upgrade the network offering- %s" % e) + + self.debug( + "Starting all the virtual machines in network after upgrade") + try: + vm_1.start(self.apiclient) + vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start VMs, %s" % e) + + nat_rule = NATRule.create( + self.apiclient, + vm_1, + self.services["natrule"], + ipaddressid=public_ip_3.ipaddress.id, + openfirewall=False, + networkid=network_1.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + self.debug("Checking if we can SSH into VM using NAT rule?") + try: + ssh_3 = vm_3.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_3.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_3.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_network_vpcvr2vr_upgrade(self): + """ Test update Network that is NOT part of a VPC to a nw offering + that has services that are provided by VPCVR and vice versa. + """ + + # Validate the following + # 1. Create a Network offering - NO1 with all supported services + # except PF services provided by VRVPC provider, conserve mode=OFF + # 2.Create a Network offering - NO2 with all supported services + # including Pf services provided by VR provider, conserve mode=OFF + # 3. Deploy a Vm using a network, network1 created from NO2 + # 4. Update network1 to NO1. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + self.services["network_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,UserData,Lb,StaticNat' + self.services["network_offering"]["serviceProviderList"] = { + "Vpn": 'VirtualRouter', + "Dhcp": 'VirtualRouter', + "Dns": 'VirtualRouter', + "SourceNat": 'VirtualRouter', + "PortForwarding": 'VirtualRouter', + "Lb": 'VirtualRouter', + "UserData": 'VirtualRouter', + "StaticNat": 'VirtualRouter', + } + + nw_off_vr = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off_vr.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off_vr) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + self.debug( + "Stopping all the virtual machines in network before upgrade") + try: + vm_1.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop VMs, %s" % e) + + wait_for_cleanup(self.apiclient, ["expunge.interval", "expunge.delay"]) + + self.debug("Upgrading network offering to support PF services") + with self.assertRaises(Exception): + network_1.update( + self.apiclient, + networkofferingid=nw_off_vr.id, + changecidr=True + ) + return + + +class TestVPCNetworkGc(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetworkGc, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_1.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network_1.id, + vpcid=cls.vpc.id, + domainid=cls.account.account.domainid + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) + + cls.public_ip_2 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + StaticNATRule.enable( + cls.api_client, + ipaddressid=cls.public_ip_2.ipaddress.id, + virtualmachineid=cls.vm_1.id, + networkid=cls.network_1.id + ) + cls.nwacl_lb = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["lbrule"], + traffictype='Ingress' + ) + cls.nwacl_internet_1 = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["http_rule"], + traffictype='Egress' + ) + cls._cleanup = [ + cls.account, + cls.service_offering, + cls.vpc_off, + cls.nw_off + ] + 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() + # Stop all the VMs as part of test + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + for vm in vms: + if vm.state == "Running": + cmd = stopVirtualMachine.stopVirtualMachineCmd() + cmd.id = vm.id + self.apiclient.stopVirtualMachine(cmd) + self.cleanup = [] + return + + def tearDown(self): + # Start all the VMs after test execution + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + for vm in vms: + if vm.state == "Stopped": + cmd = startVirtualMachine.startVirtualMachineCmd() + cmd.id = vm.id + self.apiclient.startVirtualMachine(cmd) + + try: + #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 + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_wait_network_gc(self): + """ Test stop all the Vms that are part of the a Network + (Wait for network GC).Start 1 Vm from the network. + """ + + # Validate the following + # 1. Stop vm1 and vm2 + # 2. Wait for network GC + # 3. When the network GC thread is run, NIC relating to this guest + # network will get hot unplugged. + # 4. All the PF/Static NAT/LB rules for this network should be cleaned + # from VPCVR. + # 5. All network Acl should be cleaned from VPCVR. + # 6. All the network rules pertaining to the network in "Implemented" + # state should continue to work. + + self.debug("Waiting for network garbage collection thread to run") + # Wait for the network garbage collection thread to run + wait_for_cleanup(self.apiclient, + ["network.gc.interval", "network.gc.wait"]) + self.debug("Check if the VPC router is in stopped state?") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers shall return a valid response" + ) + router = routers[0] + # TODO: Add some more assertions + self.assertEqual( + router.state, + "Stopped", + "Router state should be stopped after netwrok.gc.interval" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_start_vm_network_gc(self): + """ Test network rules after starting an instance in VPC + """ + + # Validate the following + # 1. Stop vm1 and vm2 + # 2. Wait for network GC. Start 1st VM + # 3. All the network rules created shall continue to work. + + self.debug("Waiting for network garbage collection thread to run") + # Wait for the network garbage collection thread to run + wait_for_cleanup(self.apiclient, + ["network.gc.interval", "network.gc.wait"]) + + self.debug("Starting one of the virtual machine") + try: + self.vm_1.start(self.apiclient) + except Exception as e: + self.fail("Failed to start virtual machine: %s, %s" % + (self.vm_1.name, e)) + + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_2?") + try: + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_restart_vpcvr(self): + """ Test Stop all the Vms that are part of the a Network + (Wait for network GC).Restart VPCVR. + """ + + # Validate the following + # 1. Stop vm3 and vm4 + # 2. Wait for network GC. Restart VPC VR + # 3. All the network rules created shall continue to work. + + self.debug("Starting instances 1 and 2") + try: + self.vm_1.start(self.apiclient) + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start Virtual machines") + + self.debug("Waiting for network garbage collection thread to run") + # Wait for the network garbage collection thread to run + wait_for_cleanup(self.apiclient, + ["network.gc.interval", "network.gc.wait"]) + + self.debug("Finding the VPC virtual router for account: %s" % + self.account.account.name) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers shall return a valid list" + ) + vpcvr = routers[0] + self.debug("restarting the VPC virtual router") + try: + Router.reboot( + self.apiclient, + id=vpcvr.id + ) + except Exception as e: + self.fail("Failed to reboot the virtual router: %s, %s" % + (vpcvr.id, e)) + + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_2?") + try: + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.debug("Result: %s" % result) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return diff --git a/test/integration/component/test_vpc_network_lbrules.py b/test/integration/component/test_vpc_network_lbrules.py new file mode 100644 index 00000000000..6f7b05fd754 --- /dev/null +++ b/test/integration/component/test_vpc_network_lbrules.py @@ -0,0 +1,1025 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests for VPC network functionality - Load Balancing Rules +""" +#Import Local Modules +#import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +#from marvin.cloudstackAPI import +#from marvin.integration.lib.utils import +from marvin.integration.lib.base import (stopRouter, + startRouter, + Account, + VpcOffering, + VPC, + ServiceOffering, + NATRule, + NetworkACL, + PublicIPAddress, + NetworkOffering, + Network, + VirtualMachine, + LoadBalancerRule, + StaticNATRule) +from marvin.integration.lib.common import (get_domain, + get_zone, + get_template, + cleanup_resources, + wait_for_cleanup, + list_routers) + +class Services: + """Test VPC network services Load Balancing Rules Test data + """ + + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "host1":None, + "host2":None, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 1000, + "memory": 512, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + "servicecapabilitylist": { + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 22, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "lbrule_http": { + "name": "HTTP", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 80, + "publicport": 8888, + "openfirewall": False, + "startport": 80, + "endport": 8888, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "http_rule": { + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + +class TestVPCNetworkLBRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetworkLBRules, + 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["ostype"] + ) + 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: + print ("Warning: Exception during cleanup : %s" % e) + #raise Exception("Warning: Exception during cleanup : %s" % e) + return + + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self._cleanup = [self.account] + self.debug("Creating a VPC offering..") + self.vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(self.vpc_off) + self.debug("Enabling the VPC offering created") + self.vpc_off.update(self.apiclient, state='Enabled') + + self.debug("Creating a VPC network in the account: %s" % self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + self.vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self._cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + self.debug("Warning: Exception during cleanup : %s" % e) + #raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def get_Router_For_VPC(self): + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + self.assertNotEqual(len(routers), + 0, + "Check list router response" + ) + router = routers[0] + return router + + + def stop_VPC_VRouter(self): + router = self.get_Router_For_VPC() + self.debug("Stopping router ID: %s" % router.id) + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + self.assertEqual(router.state, + 'Stopped', + "Check list router response for router state" + ) + return router + + def start_VPC_VRouter(self, router): + # Start the VPC Router + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + zoneid=self.zone.id + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + self.assertEqual(router.state, + 'Running', + "Check list router response for router state" + ) + + def check_ssh_into_vm(self, vm, public_ip, testnegative=False): + self.debug("Checking if we can SSH into VM=%s on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + try: + vm.get_ssh_client(ipaddress=public_ip.ipaddress.ipaddress) + if not testnegative: + self.debug("SSH into VM=%s on public_ip=%s is successfully" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.fail("SSH into VM=%s on public_ip=%s is successfully" % (vm.name, public_ip.ipaddress.ipaddress)) + except: + if not testnegative: + self.fail("Failed to SSH into VM - %s" % (public_ip.ipaddress.ipaddress)) + else: + self.debug("Failed to SSH into VM - %s" % (public_ip.ipaddress.ipaddress)) + + def check_wget_from_vm(self, vm, public_ip, testnegative=False): + import urllib + self.debug("Checking if we can wget from a VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + try: + urllib.urlretrieve("http://%s/test.html" % public_ip.ipaddress.ipaddress, filename="test.html") + if not testnegative: + self.debug("Successesfull to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.fail("Successesfull to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + except: + if not testnegative: + self.fail("Failed to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.debug("Failed to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + + def create_StaticNatRule_For_VM(self, vm, public_ip, network): + self.debug("Enabling static NAT for IP: %s" % + public_ip.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=vm.id, + networkid=network.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip.ipaddress.ipaddress, e)) + + def create_NatRule_For_VM(self, vm, public_ip, network): + self.debug("Creatinng NAT rule in network for vm with public IP") + nat_rule = NATRule.create(self.apiclient, + vm, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id, + openfirewall=False, + networkid=network.id, + vpcid=self.vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create(self.apiclient, + networkid=network.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + self.debug('nwacl_nat=%s' % nwacl_nat.__dict__) + return nat_rule + + def acquire_Public_IP(self, network): + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create(self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=None, #network.id, + vpcid=self.vpc.id + ) + self.debug("Associated %s with network %s" % (public_ip.ipaddress.ipaddress, + network.id + )) + return public_ip + + def create_VPC(self, cidr='10.1.2.1/16'): + self.debug("Creating a VPC offering..") + self.services["vpc_offering"]["name"] = self.services["vpc_offering"]["name"] + str(cidr) + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(self.vpc_off) + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("Creating a VPC network in the account: %s" % self.account.account.name) + self.services["vpc"]["cidr"] = cidr + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return vpc + + def create_Network(self, net_offerring, gateway='10.1.1.1',vpc=None): + try: + self.debug('Create NetworkOffering') + net_offerring["name"] = "NET_OFF-" + str(gateway) + nw_off = NetworkOffering.create(self.apiclient, + net_offerring, + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + self.debug('Created and Enabled NetworkOffering') + + self.services["network"]["name"] = "NETWORK-" + str(gateway) + self.debug('Adding Network=%s' % self.services["network"]) + obj_network = Network.create(self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id if vpc else self.vpc.id + ) + self.debug("Created network with ID: %s" % obj_network.id) + return obj_network + except: + self.fail('Unable to create a Network with offering=%s' % net_offerring) + + def create_VM_in_Network(self, network, host_id=None): + try: + self.debug('Creating VM in network=%s' % network.name) + vm = 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(network.id)], + hostid=host_id + ) + self.debug('Created VM=%s in network=%s' % (vm.id, network.name)) + + return vm + except: + self.fail('Unable to create VM in a Network=%s' % network.name) + + def create_LB_Rule(self, public_ip, network, vmarray, services=None): + self.debug("Creating LB rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + objservices = None + if services: + objservices = services + else: + objservices = self.services["lbrule"] + + lb_rule = LoadBalancerRule.create( + self.apiclient, + objservices, + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id, + vpcid=self.vpc.id, + domainid=self.account.account.domainid + ) + self.debug("Adding virtual machines %s and %s to LB rule" % (vmarray)) + lb_rule.assign(self.apiclient, vmarray) + return lb_rule + + def create_egress_Internet_Rule(self, network): + self.debug("Adding Egress rules to network %s and %s to allow access to internet" % (network.name,self.services["http_rule"])) + nwacl_internet_1 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + + return nwacl_internet_1 + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_01_VPC_LBRulesListing(self): + """ Test case no 210 and 227: List Load Balancing Rules belonging to a VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 and vm2 in network1. + # 6. Deploy vm3 and vm4 in network2. + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 8. Use the Create LB rule for vm3 amd vm4 in network2. + # 11. List LB rule + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + self.debug("deploying VMs in network: %s" % network_2.name) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_2) + vm_4 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule1 = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2]) + public_ip_2 = self.acquire_Public_IP(network_2) + lb_rule2 = self.create_LB_Rule(public_ip_2, network_2, [vm_3, vm_4]) + lb_rules = LoadBalancerRule.list(self.apiclient, + id=lb_rule1.id, + listall=True + ) + self.failIfEqual(lb_rules, + None, + "Failed to list the LB Rule" + ) + lb_rules = LoadBalancerRule.list(self.apiclient, + id=lb_rule2.id, + listall=True + ) + self.failIfEqual(lb_rules, + None, + "Failed to list the LB Rule" + ) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_02_VPC_LBRulesAndVMListing(self): + """ Test case no 211 and 228: List only VMs suitable for the Virtual Network on VPC for LB Rule + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 and vm2 in network1 on primary host. + # 6. Deploy vm3 and vm4 in network2 on secondary host. + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 9. List LB rule for network1 list vms on network1 for selection of LB rule. + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_2) + self.debug('vm_3=%s' % vm_3.id) + vm_4 = self.create_VM_in_Network(network_2) + self.debug('vm_4=%s' % vm_4.id) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2]) + lb_rules = LoadBalancerRule.list(self.apiclient, + id=lb_rule.id, + listall=True + ) + self.failIfEqual(lb_rules, + None, + "Failed to list the LB Rule" + ) + vms = VirtualMachine.list(self.apiclient, + networkid=network_1.id, + listall=True + ) + self.failIfEqual(vms, + None, + "Failed to list the VMs in network=%s" % network_1.name + ) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_03_VPC_CreateLBRuleInMultipleNetworks(self): + """ Test case no 212 : Create LB rules for 1 network which is part of a two/multiple virtual networks of a + VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1, vm2 and vm3 in network1 on primary host. + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 8. Add vm3 to LB rule. + # 9. wget a file and check for LB rule. + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2], self.services["lbrule_http"]) + lb_rule.assign(self.apiclient, [vm_3]) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_04_VPC_CreateLBRuleInMultipleNetworksVRStoppedState(self): + """ Test case no 222 : Create LB rules for a two/multiple virtual networks of a + VPC using a new Public IP Address available with the VPC when the Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1, vm2 and vm3 in network1 on primary host. + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 8. Add vm3 to LB rule. + # 9. wget a file and check for LB rule. + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2], self.services["lbrule_http"]) + lb_rule.assign(self.apiclient, [vm_3]) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_05_VPC_CreateAndDeleteLBRule(self): + """ Test case no 214 : Delete few(not all) LB rules for a single virtual network of a + VPC belonging to a single Public IP Address when the Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1, vm2 and vm3 in network1 on primary host. + # 6. Use the Create LB rule for http and ssh vm1, vm2 and vm3 in network1. + # 7. wget and ssh and check for LB rule. + # 8. Delete ssh LB Rule. + # 9. ssh LB should fail. + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule_http = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3], self.services["lbrule_http"]) + lb_rule_nat = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3]) + self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + lb_rule_nat.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_06_VPC_CreateAndDeleteLBRuleVRStopppedState(self): + """ Test case no 224 : Delete few(not all) LB rules for a single virtual network of + a VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1, vm2 and vm3 in network1 on primary host. + # 6. Use the Create LB rule for http and ssh vm1, vm2 and vm3 in network1. + # 7. wget and ssh and check for LB rule. + # 8. Delete ssh LB Rule. + # 9. ssh LB should fail. + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule_http = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3], self.services["lbrule_http"]) + lb_rule_nat = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3]) + self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + lb_rule_nat.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_07_VPC_CreateAndDeleteAllLBRule(self): + """ Test case no 215 : Delete all LB rules for a single virtual network of a + VPC belonging to a single Public IP Address when the Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1, vm2 and vm3 in network1 on primary host. + # 6. Use the Create LB rule for http and ssh vm1, vm2 and vm3 in network1. + # 7. wget and ssh and check for LB rule. + # 8. Delete all LB Rule. + # 9. ssh and http LB should fail. + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule_http = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3], self.services["lbrule_http"]) + lb_rule_nat = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3]) + self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + lb_rule_nat.delete() + lb_rule_http.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_08_VPC_CreateAndDeleteAllLBRuleVRStoppedState(self): + """ Test case no 225 and 226 : Delete all LB rules for a single virtual network of a + VPC belonging to a single Public IP Address when the Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1, vm2 and vm3 in network1 on primary host. + # 6. Use the Create LB rule for http and ssh vm1, vm2 and vm3 in network1. + # 7. wget and ssh and check for LB rule. + # 8. Delete all LB Rule. + # 9. ssh and http LB should fail. + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule_http = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3], self.services["lbrule_http"]) + lb_rule_nat = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2, vm_3]) + self.debug('lb_rule_http=%s' % lb_rule_http.__dict__) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + lb_rule_nat.delete() + lb_rule_http.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_09_VPC_LBRuleCreateFailMultipleVPC(self): + """ Test case no 234 : User should not be allowed to create a LB rule for a VM that belongs to a different VPC. + """ + + # Validate the following + # 1. Create a VPC1 with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC1. + # 1. Create a VPC2 with cidr - 10.1.2.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 4. Add network2(10.1.2.1/24) using N01 to this VPC2. + # 5. Deploy vm1 and vm2 in network1 on primary host. + # 6. Deploy vm3 and vm4 in network2 on secondary host. + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 9. wget and check LB Rule + # 10. create LB rule for vm3 and vm4 in VPC1 + # 11. LB rule creation should fail + + network_1 = self.create_Network(self.services["network_offering"]) + + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vpc2 = self.create_VPC() + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1',vpc2) + vm_3 = self.create_VM_in_Network(network_2) + vm_4 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2]) + self.debug('lb_rule=%s' % lb_rule.__dict__) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + try: + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_3, vm_4]) + self.fail('Successfully created LB rule for vm_3, vm_4 in network1') + except: + self.debug('Failed to Create LB rule vm_3 and vm_4') + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_10_VPC_FailedToCreateLBRuleNonVPCNetwork(self): + """ Test case no 216 and 235: User should not be allowed to create a LB rule for a VM that does not belong to any VPC. + """ + + # Validate the following + # 1. Create a VPC1 with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC1. + # 2. Create a Network offering - NO1 with all supported services + # 4. Add network2(10.1.2.1/24) using N01 to this VPC1. + # 5. Deploy vm1 and vm3 in network1 and network 2 on primary host. + # 6. Deploy vm2 and vm4 in network2 and network 3 on secondary host. + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 9. wget and check LB Rule + # 10. create LB rule for vm3 and vm4 in VPC1 + # 11. LB rule creation should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_3 = self.create_VM_in_Network(network_2) + network_3 = self.create_Network(self.services["network_offering_no_lb"], '10.1.3.1') + vm_4 = self.create_VM_in_Network(network_3) + self.debug('vm_4=%s' % vm_4.id) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2]) + self.debug('lb_rule=%s' % lb_rule.__dict__) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + try: + lb_rule = self.create_LB_Rule(public_ip_1, network_2, [vm_3, vm_4]) + self.fail('Successfully created LB rule for vm_3, vm_4 in network2') + except: + self.debug('Failed to Create LB rule vm_3 and vm_4 in network2') + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_11_VPC_LBRuleCreateNotAllowed(self): + """ Test case no 217 and 236: User should not be allowed to create a LB rule for a + VM that does not belong to the same network but belongs to the same VPC. + """ + + # Validate the following + # 1. Create a VPC1 with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC1. + # 2. Create a Network offering - NO1 with all supported services + # 4. Add network2(10.1.2.1/24) using N01 to this VPC1. + # 5. Deploy vm1 and vm3 in network1 and network 2 primary host. + # 6. Deploy vm2 and vm4 in network1 and network 2 on secondary host. + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 9. wget and check LB Rule + # 10. create LB rule for vm3 and vm1 in VPC1 + # 11. LB rule creation should fail + + network_1 = self.create_Network(self.services["network_offering"]) + + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_3 = self.create_VM_in_Network(network_2) + vm_4 = self.create_VM_in_Network(network_2) + self.debug('vm_4=%s' % vm_4.id) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_1, vm_2]) + self.debug('lb_rule=%s' % lb_rule.__dict__) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + try: + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_3, vm_1]) + self.fail('Successfully created LB rule for vm_3, vm_1 in network1') + except: + self.debug('Failed to Create LB rule vm_3 and vm_1') + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_12_VPC_LBRuleCreateFailForRouterIP(self): + """ Test case no 218 and 237: User should not be allowed to create a LB rule on an Ipaddress that Source Nat enabled. + """ + + # Validate the following + # 1. Create a VPC1 with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC1. + # 2. Create a Network offering - NO1 with all supported services + # 5. Deploy vm1 and vm2 in network1 and network 2 primary host. + # 6. Get source NAT public ip of router + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 8. LB rule creation should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + router = self.get_Router_For_VPC() + public_ip_1 = router.publicip + self.debug('router.publicip=%s' % public_ip_1) + try: + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_2, vm_1]) + self.fail('Successfully created LB rule for vm_2, vm_1 in network1 %s=' % lb_rule.__dict__) + except: + self.debug('Failed to Create LB rule vm_2 and vm_1') + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_13_VPC_LBRuleCreateFailForPFSourceNATIP(self): + """ Test case no 219 : User should not be allowed to create a LB rule on an Ipaddress that already has a PF rule. + """ + + # Validate the following + # 1. Create a VPC1 with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC1. + # 2. Create a Network offering - NO1 with all supported services + # 5. Deploy vm1 and vm2 in network1 and network 2 primary host. + # 6. aquire public ip address + # 6. Create a PP rule for vm1 + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 8. LB rule creation should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + nat_rule1 = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.debug('nat_rule1=%s' % nat_rule1.__dict__) + try: + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_2, vm_1]) + self.fail('Successfully created LB rule for vm_2, vm_1 in network1 %s=' % lb_rule.__dict__) + except: + self.debug('Failed to Create LB rule vm_2 and vm_1') + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_14_VPC_LBRuleCreateFailForStaticNatRule(self): + """ Test case no 220 : User should not be allowed to create a LB rule on an Ipaddress that already has a Static Nat rule. + """ + + # Validate the following + # 1. Create a VPC1 with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC1. + # 2. Create a Network offering - NO1 with all supported services + # 5. Deploy vm1 and vm2 in network1 and network 2 primary host. + # 6. aquire public ip address. + # 7. Create a StaticNat Rule rule for vm1. + # 8. Succesessfully wget a file from vm1. + # 9. Use the Create LB rule for vm1 and vm2 in network1. + # 10. LB rule creation should fail. + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + self.create_StaticNatRule_For_VM(vm_1, public_ip_1, network_1) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + try: + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_2, vm_1]) + self.fail('Successfully created LB rule for vm_2, vm_1 in network1 %s=' % lb_rule.__dict__) + except: + self.debug('Failed to Create LB rule vm_2 and vm_1') + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_15_VPC_RleaseIPForLBRuleCreated(self): + """ Test case no 221 : Release Ip address that has a LB rule assigned to it. + """ + + # Validate the following + # 1. Create a VPC1 with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC1. + # 2. Create a Network offering - NO1 with all supported services + # 5. Deploy vm1 and vm2 in network1 and network 2 primary host. + # 6. aquire public ip address + # 6. Create a StaticNat Rule rule for vm1 + # 7. Use the Create LB rule for vm1 and vm2 in network1. + # 8. LB rule creation should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + lb_rule = self.create_LB_Rule(public_ip_1, network_1, [vm_2, vm_1]) + public_ip_1.delete() + lb_rules = LoadBalancerRule.list(self.apiclient, + id=lb_rule.id, + listall=True + ) + self.assertEqual(lb_rules, + None, + "Failed LB rule is present on the VR" + ) + + + return diff --git a/test/integration/component/test_vpc_network_pfrules.py b/test/integration/component/test_vpc_network_pfrules.py new file mode 100644 index 00000000000..95254d84eb6 --- /dev/null +++ b/test/integration/component/test_vpc_network_pfrules.py @@ -0,0 +1,876 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests for VPC network functionality - Port Forwarding Rules. +""" +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.integration.lib.base import (stopRouter, + startRouter, + Account, + VpcOffering, + VPC, + ServiceOffering, + NATRule, + NetworkACL, + PublicIPAddress, + NetworkOffering, + Network, + VirtualMachine, + LoadBalancerRule, + StaticNATRule) +from marvin.integration.lib.common import (get_domain, + get_zone, + get_template, + cleanup_resources, + wait_for_cleanup, + list_routers) + + +class Services: + """Test VPC network services - Port Forwarding Rules Test Data Class. + """ + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "host1":None, + "host2":None, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 1000, + "memory": 512, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + "servicecapabilitylist": { + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 22, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "lbrule_http": { + "name": "HTTP", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 80, + "publicport": 8888, + "openfirewall": False, + "startport": 80, + "endport": 8888, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "http_rule": { + "privateport": 80, + "publicport": 80, + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestVPCNetworkPFRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetworkPFRules, + 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["ostype"] + ) + 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: + print("Warning: Exception during cleanup : %s" % e) + #raise Exception("Warning: Exception during cleanup : %s" % e) + return + + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self._cleanup = [self.account] + self.debug("Creating a VPC offering..") + self.vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(self.vpc_off) + self.debug("Enabling the VPC offering created") + self.vpc_off.update(self.apiclient, state='Enabled') + + self.debug("Creating a VPC network in the account: %s" % self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + self.vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self._cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + except Exception as e: + self.debug("Warning: Exception during cleanup : %s" % e) + #raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def get_Router_For_VPC(self): + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + self.assertNotEqual(len(routers), + 0, + "Check list router response" + ) + router = routers[0] + return router + + + def stop_VPC_VRouter(self): + router = self.get_Router_For_VPC() + self.debug("Stopping router ID: %s" % router.id) + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + self.assertEqual(router.state, + 'Stopped', + "Check list router response for router state" + ) + return router + + def start_VPC_VRouter(self, router): + # Start the VPC Router + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + zoneid=self.zone.id + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + self.assertEqual(router.state, + 'Running', + "Check list router response for router state" + ) + + def check_ssh_into_vm(self, vm, public_ip, testnegative=False): + self.debug("Checking if we can SSH into VM=%s on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + try: + vm.get_ssh_client(ipaddress=public_ip.ipaddress.ipaddress) + if not testnegative: + self.debug("SSH into VM=%s on public_ip=%s is successfully" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.fail("SSH into VM=%s on public_ip=%s is successfully" % (vm.name, public_ip.ipaddress.ipaddress)) + except: + if not testnegative: + self.fail("Failed to SSH into VM - %s" % (public_ip.ipaddress.ipaddress)) + else: + self.debug("Failed to SSH into VM - %s" % (public_ip.ipaddress.ipaddress)) + + def check_wget_from_vm(self, vm, public_ip, testnegative=False): + import urllib + self.debug("Checking if we can wget from a VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + try: + urllib.urlretrieve("http://%s/test.html" % public_ip.ipaddress.ipaddress, filename="test.html") + if not testnegative: + self.debug("Successesfull to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.fail("Successesfull to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + except: + if not testnegative: + self.fail("Failed to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.debug("Failed to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + + def create_StaticNatRule_For_VM(self, vm, public_ip, network): + self.debug("Enabling static NAT for IP: %s" % + public_ip.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=vm.id, + networkid=network.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip.ipaddress.ipaddress, e)) + + def create_NatRule_For_VM(self, vm, public_ip, network, services=None): + self.debug("Creatinng NAT rule in network for vm with public IP") + if not services: + services = self.services["natrule"] + nat_rule = NATRule.create(self.apiclient, + vm, + services, + ipaddressid=public_ip.ipaddress.id, + openfirewall=False, + networkid=network.id, + vpcid=self.vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create(self.apiclient, + networkid=network.id, + services=services, + traffictype='Ingress' + ) + self.debug('nwacl_nat=%s' % nwacl_nat.__dict__) + return nat_rule + + def acquire_Public_IP(self, network): + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create(self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=None, #network.id, + vpcid=self.vpc.id + ) + self.debug("Associated %s with network %s" % (public_ip.ipaddress.ipaddress, + network.id + )) + return public_ip + + def create_VPC(self, cidr='10.1.2.1/16'): + self.debug("Creating a VPC offering..") + self.services["vpc_offering"]["name"] = self.services["vpc_offering"]["name"] + str(cidr) + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(self.vpc_off) + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("Creating a VPC network in the account: %s" % self.account.account.name) + self.services["vpc"]["cidr"] = cidr + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return vpc + + def create_Network(self, net_offerring, gateway='10.1.1.1',vpc=None): + try: + self.debug('Create NetworkOffering') + net_offerring["name"] = "NET_OFF-" + str(gateway) + nw_off = NetworkOffering.create(self.apiclient, + net_offerring, + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + self.debug('Created and Enabled NetworkOffering') + + self.services["network"]["name"] = "NETWORK-" + str(gateway) + self.debug('Adding Network=%s' % self.services["network"]) + obj_network = Network.create(self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id if vpc else self.vpc.id + ) + self.debug("Created network with ID: %s" % obj_network.id) + return obj_network + except: + self.fail('Unable to create a Network with offering=%s' % net_offerring) + + def create_VM_in_Network(self, network, host_id=None): + try: + self.debug('Creating VM in network=%s' % network.name) + vm = 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(network.id)], + hostid=host_id + ) + self.debug('Created VM=%s in network=%s' % (vm.id, network.name)) + + return vm + except: + self.fail('Unable to create VM in a Network=%s' % network.name) + + def create_LB_Rule(self, public_ip, network, vmarray, services=None): + self.debug("Creating LB rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + objservices = None + if services: + objservices = services + else: + objservices = self.services["lbrule"] + + lb_rule = LoadBalancerRule.create( + self.apiclient, + objservices, + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id, + vpcid=self.vpc.id, + domainid=self.account.account.domainid + ) + self.debug("Adding virtual machines %s and %s to LB rule" % (vmarray)) + lb_rule.assign(self.apiclient, vmarray) + return lb_rule + + def create_egress_Internet_Rule(self, network): + self.debug("Adding Egress rules to network %s and %s to allow access to internet" % (network.name,self.services["http_rule"])) + nwacl_internet_1 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["http_rule"], + traffictype='Ingress' + ) + + return nwacl_internet_1 + + + @attr(tags=["advanced", "intervlan"]) + def test_01_network_services_VPC_StopCreatePF(self): + """ Test case no 204 : Create PF rules for a single virtual network of a VPC, + using a new Public IP Address available with the VPC when Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Stop the VPC Virtual Router. + # 6. Use the Create PF rule for vm in network1. + # 7. Start VPC Virtual Router. + # 8. Successfully ssh into the Guest VM using the PF rule + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + router = self.stop_VPC_VRouter() + self.create_NatRule_For_VM( vm_1, public_ip_1, network_1) + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_network_services_VPC_CreatePF(self): + """ Test case no 190 : Create PF rules for a single virtual network of a VPC using a + new Public IP Address available with the VPC when Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Use the Create PF rule for vm in network1. + # 6. Successfully ssh into the Guest VM using the PF rule + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + self.create_NatRule_For_VM( vm_1, public_ip_1, network_1) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_03_network_services_VPC_StopCreateMultiplePF(self): + """ Test case no 205 : Create PF rules for a two/multiple virtual networks of a VPC using + a new Public IP Address available with the VPC when Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 in network1. + # 6. Deploy vm2 in network2. + # 7. Stop the VPC Virtual Router. + # 8. Use the Create PF rule for vm1 in network1. + # 9. Use the Create PF rule for vm2 in network2. + # 10. Start VPC Virtual Router. + # 11. Successfully ssh into the Guest VM1 and VM2 using the PF rule + + network_1 = self.create_Network(self.services["network_offering_no_lb"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + public_ip_2 = self.acquire_Public_IP(network_2) + router = self.stop_VPC_VRouter() + self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + self.create_NatRule_For_VM(vm_2, public_ip_2, network_2) + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_04_network_services_VPC_CreateMultiplePF(self): + """ Test case no 191 : Create PF rules for a two/multiple virtual networks of a VPC using a + new Public IP Address available with the VPC when Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 in network1. + # 6. Deploy vm2 in network2. + # 7. Use the Create PF rule for vm1 in network1. + # 8. Use the Create PF rule for vm2 in network2. + # 9. Start VPC Virtual Router. + # 10. Successfully ssh into the Guest VM1 and VM2 using the PF rule + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + public_ip_2 = self.acquire_Public_IP(network_2) + router = self.stop_VPC_VRouter() + self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + self.create_NatRule_For_VM(vm_2, public_ip_2, network_2) + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_05_network_services_VPC_StopDeletePF(self): + """ Test case no 207 : Delete few(not all) PF rules for a single virtual network of + a VPC belonging to a single Public IP Address when Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Use the Create PF rule for vm in network1. + # 6. Successfully ssh into the Guest VM using the PF rule. + # 7. Successfully wget a file on http server of VM1. + # 8. Stop the VPC Virtual Router. + # 9. Delete internet PF rule + # 10. Start VPC Virtual Router. + # 11. wget a file present on http server of VM1 should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + http_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1, self.services["http_rule"]) + #http_rule = self.create_egress_Internet_Rule(network_1) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + router = self.stop_VPC_VRouter() + http_rule.delete() + self.start_VPC_VRouter(router) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_06_network_services_VPC_DeletePF(self): + """ Test case no 193 : Delete few(not all) PF rules for a single virtual network of + a VPC belonging to a single Public IP Address when Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Use the Create PF rule for vm in network1. + # 6. Successfully ssh into the Guest VM using the PF rule. + # 7. Successfully wget a file on http server of VM1. + # 9. Delete internet PF rule + # 10. wget a file present on http server of VM1 should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + http_rule=self.create_NatRule_For_VM(vm_1, public_ip_1, network_1, self.services["http_rule"]) + #http_rule = self.create_egress_Internet_Rule(network_1) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + http_rule.delete() + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_07_network_services_VPC_StopDeleteAllPF(self): + """ Test case no 208 : Delete all PF rules for a single virtual network of a + VPC belonging to a single Public IP Address when Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Use the Create PF rule for vm in network1. + # 6. Successfully ssh into the Guest VM using the PF rule. + # 7. Successfully wget a file on http server of VM1. + # 8. Stop the VPC Virtual Router. + # 9. Delete all PF rule + # 10. Start VPC Virtual Router. + # 11. wget a file present on http server of VM1 should fail + # 12. ssh into Guest VM using the PF rule should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + nat_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + http_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1, self.services["http_rule"]) + #http_rule = self.create_egress_Internet_Rule(network_1) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + router = self.stop_VPC_VRouter() + http_rule.delete() + nat_rule.delete() + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_08_network_services_VPC_DeleteAllPF(self): + """ Test case no 194 : Delete all PF rules for a single virtual network of a + VPC belonging to a single Public IP Address when Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Use the Create PF rule for vm in network1. + # 6. Successfully ssh into the Guest VM using the PF rule. + # 7. Successfully wget a file on http server of VM1. + # 8. Delete all PF rule + # 9. wget a file present on http server of VM1 should fail + # 10. ssh into Guest VM using the PF rule should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + nat_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + http_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1, self.services["http_rule"]) + #http_rule = self.create_egress_Internet_Rule(network_1) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + http_rule.delete() + nat_rule.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_09_network_services_VPC_StopDeleteAllMultiplePF(self): + """ Test case no 209 : Delete all PF rules for two/multiple virtual networks of a VPC. + Observe the status of the Public IP Addresses of the rules when Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16. + # 2. Create a Network offering - NO1 with all supported services. + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 and vm2 in network1. + # 6. Deploy vm3 and vm4 in network2. + # 7. Use the Create PF rule ssh and http for vm1 and vm2 in network1. + # 8. Use the Create PF rule ssh and http for vm3 and vm4 in network2. + # 9. Successfully ssh into the Guest vm1, vm2, vm3 and vm4 using the PF rule. + # 10. Succesfully wget a file from http server present on vm1, vm2, vm3 and vm4. + # 11. Stop VPC Virtual Router. + # 12. Delete all PF rultes for vm1, vm2, vm3 and vm4. + # 12. Start VPC Virtual Router. + # 13. Fail to ssh and http to vm1, vm2, vm3 and vm4. + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_2) + vm_4 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + public_ip_2 = self.acquire_Public_IP(network_1) + nat_rule1 = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + nat_rule2 = self.create_NatRule_For_VM(vm_2, public_ip_2, network_1) + http_rule1 = self.create_egress_Internet_Rule(network_1) + nat_rule3 = self.create_NatRule_For_VM(vm_3, public_ip_1, network_2) + nat_rule4 = self.create_NatRule_For_VM(vm_4, public_ip_2, network_2) + http_rule2 = self.create_egress_Internet_Rule(network_2) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) + self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_2, public_ip_2, testnegative=False) + self.check_wget_from_vm(vm_3, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_4, public_ip_2, testnegative=False) + router = self.stop_VPC_VRouter() + nat_rule1.delete() + nat_rule2.delete() + nat_rule3.delete() + nat_rule4.delete() + http_rule1.delete() + http_rule2.delete() + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=True) + self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=True) + self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_2, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_3, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_4, public_ip_2, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_10_network_services_VPC_DeleteAllMultiplePF(self): + """ Test case no 195: Delete all PF rules for two/multiple virtual networks of a VPC. + Observe the status of the Public IP Addresses of the rules when Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16. + # 2. Create a Network offering - NO1 with all supported services. + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 and vm2 in network1. + # 6. Deploy vm3 and vm4 in network2. + # 7. Use the Create PF rule ssh and http for vm1 and vm2 in network1. + # 8. Use the Create PF rule ssh and http for vm3 and vm4 in network2. + # 9. Successfully ssh into the Guest vm1, vm2, vm3 and vm4 using the PF rule. + # 10. Succesfully wget a file from http server present on vm1, vm2, vm3 and vm4. + # 12. Delete all PF rultes for vm1, vm2, vm3 and vm4. + # 13. Fail to ssh and http to vm1, vm2, vm3 and vm4. + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_2) + vm_4 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + public_ip_2 = self.acquire_Public_IP(network_1) + nat_rule1 = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + nat_rule2 = self.create_NatRule_For_VM(vm_2, public_ip_2, network_1) + http_rule1 = self.create_egress_Internet_Rule(network_1) + nat_rule3 = self.create_NatRule_For_VM(vm_3, public_ip_1, network_2) + nat_rule4 = self.create_NatRule_For_VM(vm_4, public_ip_2, network_2) + http_rule2 = self.create_egress_Internet_Rule(network_2) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) + self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_2, public_ip_2, testnegative=False) + self.check_wget_from_vm(vm_3, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_4, public_ip_2, testnegative=False) + nat_rule1.delete() + nat_rule2.delete() + nat_rule3.delete() + nat_rule4.delete() + http_rule1.delete() + http_rule2.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=True) + self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=True) + self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_2, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_3, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_4, public_ip_2, testnegative=True) + return diff --git a/test/integration/component/test_vpc_network_staticnatrule.py b/test/integration/component/test_vpc_network_staticnatrule.py new file mode 100644 index 00000000000..3b3d41a2573 --- /dev/null +++ b/test/integration/component/test_vpc_network_staticnatrule.py @@ -0,0 +1,710 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests for VPC network functionality - Port Forwarding Rules. +""" +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import cloudstackTestCase, unittest +from marvin.integration.lib.base import (stopRouter, + startRouter, + Account, + VpcOffering, + VPC, + ServiceOffering, + NATRule, + NetworkACL, + PublicIPAddress, + NetworkOffering, + Network, + VirtualMachine, + LoadBalancerRule, + StaticNATRule) +from marvin.integration.lib.common import (get_domain, + get_zone, + get_template, + cleanup_resources, + wait_for_cleanup, + list_routers) + + +class Services: + """Test VPC network services - Port Forwarding Rules Test Data Class. + """ + def __init__(self): + self.services = { + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + # Random characters are appended for unique + # username + "password": "password", + }, + "host1":None, + "host2":None, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 1000, + "memory": 512, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + "servicecapabilitylist": { + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 22, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "lbrule_http": { + "name": "HTTP", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 80, + "publicport": 8888, + "openfirewall": False, + "startport": 80, + "endport": 8888, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "http_rule": { + "privateport": 80, + "publicport": 80, + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestVPCNetworkPFRules(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCNetworkPFRules, + 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["ostype"] + ) + 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: + print("Warning: Exception during cleanup : %s" % e) + #raise Exception("Warning: Exception during cleanup : %s" % e) + return + + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self._cleanup = [self.account] + self.debug("Creating a VPC offering..") + self.vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(self.vpc_off) + self.debug("Enabling the VPC offering created") + self.vpc_off.update(self.apiclient, state='Enabled') + + self.debug("Creating a VPC network in the account: %s" % self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + self.vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=self.vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self._cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + except Exception as e: + self.debug("Warning: Exception during cleanup : %s" % e) + #raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def get_Router_For_VPC(self): + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + self.assertNotEqual(len(routers), + 0, + "Check list router response" + ) + router = routers[0] + return router + + + def stop_VPC_VRouter(self): + router = self.get_Router_For_VPC() + self.debug("Stopping router ID: %s" % router.id) + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + self.assertEqual(router.state, + 'Stopped', + "Check list router response for router state" + ) + return router + + def start_VPC_VRouter(self, router): + # Start the VPC Router + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + routers = list_routers(self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + zoneid=self.zone.id + ) + self.assertEqual(isinstance(routers, list), + True, + "Check for list routers response return valid data" + ) + router = routers[0] + self.assertEqual(router.state, + 'Running', + "Check list router response for router state" + ) + + def check_ssh_into_vm(self, vm, public_ip, testnegative=False): + self.debug("Checking if we can SSH into VM=%s on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + try: + vm.get_ssh_client(ipaddress=public_ip.ipaddress.ipaddress) + if not testnegative: + self.debug("SSH into VM=%s on public_ip=%s is successfully" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.fail("SSH into VM=%s on public_ip=%s is successfully" % (vm.name, public_ip.ipaddress.ipaddress)) + except: + if not testnegative: + self.fail("Failed to SSH into VM - %s" % (public_ip.ipaddress.ipaddress)) + else: + self.debug("Failed to SSH into VM - %s" % (public_ip.ipaddress.ipaddress)) + + def check_wget_from_vm(self, vm, public_ip, testnegative=False): + import urllib + self.debug("Checking if we can wget from a VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + try: + urllib.urlretrieve("http://%s/test.html" % public_ip.ipaddress.ipaddress, filename="test.html") + if not testnegative: + self.debug("Successesfull to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.fail("Successesfull to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + except: + if not testnegative: + self.fail("Failed to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + else: + self.debug("Failed to wget from VM=%s http server on public_ip=%s" % (vm.name, public_ip.ipaddress.ipaddress)) + + def create_StaticNatRule_For_VM(self, vm, public_ip, network): + self.debug("Enabling static NAT for IP: %s" % + public_ip.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=vm.id, + networkid=network.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip.ipaddress.ipaddress, e)) + + def create_NatRule_For_VM(self, vm, public_ip, network, services=None): + self.debug("Creatinng NAT rule in network for vm with public IP") + if not services: + services = self.services["natrule"] + nat_rule = NATRule.create(self.apiclient, + vm, + services, + ipaddressid=public_ip.ipaddress.id, + openfirewall=False, + networkid=network.id, + vpcid=self.vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create(self.apiclient, + networkid=network.id, + services=services, + traffictype='Ingress' + ) + self.debug('nwacl_nat=%s' % nwacl_nat.__dict__) + return nat_rule + + def acquire_Public_IP(self, network): + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create(self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=None, #network.id, + vpcid=self.vpc.id + ) + self.debug("Associated %s with network %s" % (public_ip.ipaddress.ipaddress, + network.id + )) + return public_ip + + def create_VPC(self, cidr='10.1.2.1/16'): + self.debug("Creating a VPC offering..") + self.services["vpc_offering"]["name"] = self.services["vpc_offering"]["name"] + str(cidr) + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(self.vpc_off) + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("Creating a VPC network in the account: %s" % self.account.account.name) + self.services["vpc"]["cidr"] = cidr + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + return vpc + + def create_Network(self, net_offerring, gateway='10.1.1.1',vpc=None): + try: + self.debug('Create NetworkOffering') + net_offerring["name"] = "NET_OFF-" + str(gateway) + nw_off = NetworkOffering.create(self.apiclient, + net_offerring, + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + self.debug('Created and Enabled NetworkOffering') + + self.services["network"]["name"] = "NETWORK-" + str(gateway) + self.debug('Adding Network=%s' % self.services["network"]) + obj_network = Network.create(self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id if vpc else self.vpc.id + ) + self.debug("Created network with ID: %s" % obj_network.id) + return obj_network + except: + self.fail('Unable to create a Network with offering=%s' % net_offerring) + + def create_VM_in_Network(self, network, host_id=None): + try: + self.debug('Creating VM in network=%s' % network.name) + vm = 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(network.id)], + hostid=host_id + ) + self.debug('Created VM=%s in network=%s' % (vm.id, network.name)) + + return vm + except: + self.fail('Unable to create VM in a Network=%s' % network.name) + + def create_LB_Rule(self, public_ip, network, vmarray, services=None): + self.debug("Creating LB rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + objservices = None + if services: + objservices = services + else: + objservices = self.services["lbrule"] + + lb_rule = LoadBalancerRule.create( + self.apiclient, + objservices, + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id, + vpcid=self.vpc.id, + domainid=self.account.account.domainid + ) + self.debug("Adding virtual machines %s and %s to LB rule" % (vmarray)) + lb_rule.assign(self.apiclient, vmarray) + return lb_rule + + def create_egress_Internet_Rule(self, network): + self.debug("Adding Egress rules to network %s and %s to allow access to internet" % (network.name,self.services["http_rule"])) + nwacl_internet_1 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["http_rule"], + traffictype='Ingress' + ) + + return nwacl_internet_1 + + + @attr(tags=["advanced", "intervlan"]) + def test_01_VPC_StaticNatRuleCreateStoppedState(self): + """ Test case no extra : + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Stop the VPC Virtual Router. + # 6. Use the Create PF rule for vm in network1. + # 7. Start VPC Virtual Router. + # 8. Successfully ssh into the Guest VM using the PF rule + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + router = self.stop_VPC_VRouter() + self.create_NatRule_For_VM( vm_1, public_ip_1, network_1) + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_VPC_CreateStaticNatRule(self): + """ Test case no 229 : Create Static NAT Rule for a single virtual network of + a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Use the Create Static Nat rule for vm in network1. + # 6. Successfully ssh into the Guest VM using the PF rule + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + self.create_StaticNatRule_For_VM( vm_1, public_ip_1, network_1) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_03_VPC_StopCreateMultipleStaticNatRuleStopppedState(self): + """ Test case no extra : Create Static Nat Rule rules for a two/multiple virtual networks of a VPC using + a new Public IP Address available with the VPC when Virtual Router is in Stopped State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 in network1. + # 6. Deploy vm2 in network2. + # 7. Stop the VPC Virtual Router. + # 8. Use the Create PF rule for vm1 in network1. + # 9. Use the Create PF rule for vm2 in network2. + # 10. Start VPC Virtual Router. + # 11. Successfully ssh into the Guest VM1 and VM2 using the PF rule + + network_1 = self.create_Network(self.services["network_offering_no_lb"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + public_ip_2 = self.acquire_Public_IP(network_2) + router = self.stop_VPC_VRouter() + self.create_StaticNatRule_For_VM(vm_1, public_ip_1, network_1) + self.create_StaticNatRule_For_VM(vm_2, public_ip_2, network_2) + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_04_VPC_CreateMultipleStaticNatRule(self): + """ Test case no 230 : Create Static NAT Rules for a two/multiple virtual networks of + a VPC using a new Public IP Address available with the VPC when the Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 in network1. + # 6. Deploy vm2 in network2. + # 7. Use the Create PF rule for vm1 in network1. + # 8. Use the Create PF rule for vm2 in network2. + # 9. Start VPC Virtual Router. + # 10. Successfully ssh into the Guest VM1 and VM2 using the PF rule + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + public_ip_2 = self.acquire_Public_IP(network_2) + router = self.stop_VPC_VRouter() + self.create_StaticNatRule_For_VM(vm_1, public_ip_1, network_1) + self.create_StaticNatRule_For_VM(vm_2, public_ip_2, network_2) + self.start_VPC_VRouter(router) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_05_network_services_VPC_DeleteAllPF(self): + """ Test case no 232: Delete all Static NAT Rules for a single virtual network of + a VPC belonging to a single Public IP Address when the Virtual Router is in Running State + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a Network offering - NO1 with all supported services + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Deploy vm1 in network1. + # 5. Use the Create PF rule for vm in network1. + # 6. Successfully ssh into the Guest VM using the PF rule. + # 7. Successfully wget a file on http server of VM1. + # 8. Delete all PF rule + # 9. wget a file present on http server of VM1 should fail + # 10. ssh into Guest VM using the PF rule should fail + + network_1 = self.create_Network(self.services["network_offering"]) + vm_1 = self.create_VM_in_Network(network_1) + public_ip_1 = self.acquire_Public_IP(network_1) + nat_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + http_rule = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1, self.services["http_rule"]) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + http_rule.delete() + nat_rule.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Implemented but not executed: VPC with multiple network fails to set PF rule.") + def test_06_network_services_VPC_DeleteAllMultiplePF(self): + """ Test case no 233: Delete all Static NAT rules for two/multiple virtual networks of a VPC. + Observe the status of the Public IP Addresses of the rules when the Virtual Router is in Running State. + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16. + # 2. Create a Network offering - NO1 with all supported services. + # 3. Add network1(10.1.1.1/24) using N01 to this VPC. + # 4. Add network2(10.1.2.1/24) using N01 to this VPC. + # 5. Deploy vm1 and vm2 in network1. + # 6. Deploy vm3 and vm4 in network2. + # 7. Use the Create PF rule ssh and http for vm1 and vm2 in network1. + # 8. Use the Create PF rule ssh and http for vm3 and vm4 in network2. + # 9. Successfully ssh into the Guest vm1, vm2, vm3 and vm4 using the PF rule. + # 10. Succesfully wget a file from http server present on vm1, vm2, vm3 and vm4. + # 12. Delete all PF rultes for vm1, vm2, vm3 and vm4. + # 13. Fail to ssh and http to vm1, vm2, vm3 and vm4. + + network_1 = self.create_Network(self.services["network_offering"]) + network_2 = self.create_Network(self.services["network_offering_no_lb"], '10.1.2.1') + vm_1 = self.create_VM_in_Network(network_1) + vm_2 = self.create_VM_in_Network(network_1) + vm_3 = self.create_VM_in_Network(network_2) + vm_4 = self.create_VM_in_Network(network_2) + public_ip_1 = self.acquire_Public_IP(network_1) + public_ip_2 = self.acquire_Public_IP(network_1) + nat_rule1 = self.create_NatRule_For_VM(vm_1, public_ip_1, network_1) + nat_rule2 = self.create_NatRule_For_VM(vm_2, public_ip_2, network_1) + http_rule1 = self.create_egress_Internet_Rule(network_1) + nat_rule3 = self.create_NatRule_For_VM(vm_3, public_ip_1, network_2) + nat_rule4 = self.create_NatRule_For_VM(vm_4, public_ip_2, network_2) + http_rule2 = self.create_egress_Internet_Rule(network_2) + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=False) + self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=False) + self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=False) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_2, public_ip_2, testnegative=False) + self.check_wget_from_vm(vm_3, public_ip_1, testnegative=False) + self.check_wget_from_vm(vm_4, public_ip_2, testnegative=False) + nat_rule1.delete() + nat_rule2.delete() + nat_rule3.delete() + nat_rule4.delete() + http_rule1.delete() + http_rule2.delete() + self.check_ssh_into_vm(vm_1, public_ip_1, testnegative=True) + self.check_ssh_into_vm(vm_2, public_ip_2, testnegative=True) + self.check_ssh_into_vm(vm_3, public_ip_1, testnegative=True) + self.check_ssh_into_vm(vm_4, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_1, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_2, public_ip_2, testnegative=True) + self.check_wget_from_vm(vm_3, public_ip_1, testnegative=True) + self.check_wget_from_vm(vm_4, public_ip_2, testnegative=True) + return diff --git a/test/integration/component/test_vpc_offerings.py b/test/integration/component/test_vpc_offerings.py new file mode 100644 index 00000000000..5cf62b83621 --- /dev/null +++ b/test/integration/component/test_vpc_offerings.py @@ -0,0 +1,1201 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +import unittest + +""" Component tests for inter VLAN functionality +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test inter VLAN 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 2222, + "endport": 2222, + "cidrlist": '0.0.0.0/0', + "protocol": 'TCP' + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestVPCOffering(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVPCOffering, + 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["ostype"] + ) + 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: + #Clean up, terminate the created network offering + self.account.delete(self.apiclient) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + self.debug("VPC network created successfully - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_create_vpc_offering(self): + """ Test create VPC offering + """ + + # Steps for validation + # 1. Create VPC Offering by specifying all supported Services + # 2. VPC offering should be created successfully. + + self.debug("Creating inter VPC offering") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.debug("Check if the VPC offering is created successfully?") + self.cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Skipping - Issue: Deleting account doesn't clean VPC") + def test_02_deploy_vms_in_vpc_nw(self): + """Test deploy virtual machines in VPC networks""" + + # 1. Create VPC Offering by specifying all supported Services + # (Vpn,dhcpdns,UserData, SourceNat,Static NAT and PF,LB,NetworkAcl) + # 2. Create a VPC using the above VPC offering + # 3. Create a network as part of this VPC. + # 4. Deploy few Vms. + # 5. Create a LB rule for this VM. + # 6. Create a PF rule for this VM. + # 7. Create a Static Nat rule for this VM. + # 8. Create Ingress rules on the network to open the above created + # LB PF and Static Nat rule + # 9. Create Egress Network ACL for this network to access google.com. + # 10. Enable VPN services + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # 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, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id, + vpcid=vpc.id, + domainid=self.account.account.domainid + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network.id + )) + + nat_rule = NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip_2.ipaddress.id, + openfirewall=False, + networkid=network.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + networkacl_1 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + networkacl_2 = NetworkACL.create( + self.apiclient, + networkid=network.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + self.debug("Checking if we can SSH into VM?") + try: + virtual_machine.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + ) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_2.ipaddress.ipaddress, e)) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_3.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_3.ipaddress.id, + virtualmachineid=virtual_machine.id, + networkid=network.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_3.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_3.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network.id, + listall=True, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_3.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + # TODO: Remote Access VPN is not yet supported in VPC +# self.debug("Associating public IP for network: %s" % network.name) +# public_ip_4 = PublicIPAddress.create( +# self.apiclient, +# accountid=self.account.account.name, +# zoneid=self.zone.id, +# domainid=self.account.account.domainid, +# networkid=network.id, +# vpcid=vpc.id +# ) +# self.debug("Associated %s with network %s" % ( +# public_ip_4.ipaddress.ipaddress, +# network.id +# )) +# +# self.debug("Creating a remote access VPN for account: %s" % +# self.account.account.name) +# +# try: +# vpn = Vpn.create( +# self.apiclient, +# publicipid=public_ip_4.ipaddress.id, +# account=self.account.account.name, +# domainid=self.account.account.domainid, +# networkid=network.id, +# vpcid=vpc.id +# ) +# except Exception as e: +# self.fail("Failed to create VPN for account: %s - %s" % ( +# self.account.account.name, e)) +# +# try: +# vpnuser = VpnUser.create( +# self.apiclient, +# username="root", +# password="password", +# account=self.account.account.name, +# domainid=self.account.account.domainid +# ) +# except Exception as e: +# self.fail("Failed to create VPN user: %s" % e) +# +# self.debug("Checking if the remote access VPN is created or not?") +# remote_vpns = Vpn.list( +# self.apiclient, +# account=self.account.account.name, +# domainid=self.account.account.domainid, +# publicipid=public_ip_4.ipaddress.id, +# listall=True +# ) +# self.assertEqual( +# isinstance(remote_vpns, list), +# True, +# "List remote VPNs should not return empty response" +# ) +# self.debug("Deleting the remote access VPN for account: %s" % +# self.account.account.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_vpc_off_without_lb(self): + """Test VPC offering without load balancing service""" + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services except + # LB services. + # 2. Create a VPC using the above VPC offering. + # 3. Create a network as part of this VPC. + # 4. Deploy few Vms. + # 5. Try to create a LB rule for this VM. LB creation should fail + + self.debug( + "Creating a VPC offering with Vpn,dhcpdns,UserData," + + " SourceNat,Static NAT and PF services" + ) + + self.services["vpc_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL' + self.services["network_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL' + self.services["network_offering"]["serviceProviderList"] = { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + } + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # 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, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + + self.debug("Deploying virtual machines in network: %s" % vpc.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + vpc.id + )) + + self.debug("Trying to LB rule for IP address: %s" % + public_ip.ipaddress.ipaddress) + with self.assertRaises(Exception): + LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip.ipaddress.id, + accountid=self.account.account.name, + networkid=network.id, + vpcid=vpc.id + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_vpc_off_without_static_nat(self): + """Test VPC offering without static NAT service""" + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services except + # static NAT services. + # 2. Create a VPC using the above VPC offering. + # 3. Create a network as part of this VPC. + # 4. Deploy few Vms + # 5. Try to create NAT rule for this VMStatic NAT creation should fail + + self.debug("Creating a VPC offering with Vpn,dhcpdns,UserData," + + "SourceNat,lb and PF services") + + self.services["vpc_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,Lb,UserData,PortForwarding,NetworkACL' + self.services["network_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,Lb,UserData,PortForwarding,NetworkACL' + self.services["network_offering"]["serviceProviderList"] = { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + } + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # 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, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + + self.debug("Deploying virtual machines in network: %s" % vpc.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + + with self.assertRaises(Exception): + static_nat = StaticNATRule.create( + self.apiclient, + self.services["fw_rule"], + ipaddressid=public_ip.ipaddress.id + ) + static_nat.enable( + self.apiclient, + ipaddressid=public_ip.ipaddress.id, + virtualmachineid=virtual_machine.id + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_05_vpc_off_without_pf(self): + """Test VPC offering without port forwarding service""" + + # Validate the following + # 1. Create VPC Offering by specifying all supported Services except + # PF services. + # 2. Create a VPC using the above VPC offering. + # 3. Create a network as part of this VPC. + # 4. Deploy few Vms. + # 5. Try to create a PF rule for this VM. PF creation should fail + + self.debug( + "Creating a VPC offering with Vpn,dhcpdns,UserData," + + "SourceNat,Static NAT and lb services" + ) + + self.services["vpc_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,Lb,UserData,StaticNat,NetworkACL' + self.services["network_offering"]["supportedservices"] = 'Vpn,Dhcp,Dns,SourceNat,Lb,UserData,StaticNat,NetworkACL' + self.services["network_offering"]["serviceProviderList"] = { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + } + + self.network_offering = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + self.network_offering.update(self.apiclient, state='Enabled') + self._cleanup.append(self.network_offering) + + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + gateway = vpc.cidr.split('/')[0] + # Split the cidr to retrieve gateway + # for eg. cidr = 10.0.0.1/24 + # Gateway = 10.0.0.1 + + # 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, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Deploying virtual machines in network: %s" % vpc.name) + # Spawn an instance in that network + virtual_machine = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + + self.debug("Associating public IP for network: %s" % network.name) + public_ip = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network.id + )) + + self.debug("Trying to create NAT rule for the IP: %s" % + public_ip.ipaddress.ipaddress) + with self.assertRaises(Exception): + NATRule.create( + self.apiclient, + virtual_machine, + self.services["natrule"], + ipaddressid=public_ip.ipaddress.id, + openfirewall=True + ) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Skipping - API should not allow to create VPC offering without SourceNAT, Firewall") + def test_06_vpc_off_invalid_services(self): + """Test VPC offering with invalid services""" + + # Validate the following + # 1. Creating VPC Offering with no SourceNat service should FAIL. + # 2. Creating VPC Offering with services NOT supported by VPC + # like Firewall should not be allowed + # 3. Creating VPC Offering with services NOT supported by VPC + # like Firewall should not be allowed + + self.debug("Creating a VPC offering without sourceNAT") + self.services["vpc_offering"]["supportedservices"] = 'Dhcp,Dns,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat' + + with self.assertRaises(Exception): + VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.debug("Creating a VPC offering without Firewall") + self.services["vpc_offering"]["supportedservices"] = 'Dhcp,Dns,PortForwarding,Vpn,SourceNat,Lb,UserData,StaticNat' + + with self.assertRaises(Exception): + VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.debug("Creating a VPC offering with only sourceNAT service") + self.services["vpc_offering"]["supportedservices"] = 'SourceNat' + + try: + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + self.validate_vpc_offering(vpc_off) + # Appending to cleanup to delete after test + self.cleanup.append(vpc_off) + except Exception as e: + self.fail("Failed to create the VPC offering - %s" % e) + return + + @attr(tags=["advanced", "intervlan"]) + def test_07_update_vpc_off(self): + """Test update VPC offering""" + + # Validate the following + # 1. Create a VPC Offering. + # 2. Disable this VPC offering. + # 3. Create a VPC using this VPC offering. VPC creation should fail. + # 4. Enable the VPC offering again and create VPC. VPC should be + # created successfully + # 5. Change name and displaytext of the VPCOffering. Name and + # displaytext chnages should be reflected in listVPCPffering call + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Disabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + with self.assertRaises(Exception): + VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.debug("VPC network creation failed! (Test succeeded)") + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + self.debug("Updating name & display text of the vpc offering created") + new_name = random_gen() + new_displaytext = random_gen() + + try: + vpc_off.update( + self.apiclient, + name=new_name, + displaytext=new_displaytext + ) + except Exception as e: + self.fail("Failed to update VPC offering- %s" % e) + + self.debug("Cheking if the changes are reflected to listVPC call?") + vpc_offs = vpc_off.list( + self.apiclient, + id=vpc_off.id, + listall=True + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings shall return a valid list" + ) + list_reposnse_vpc = vpc_offs[0] + self.assertEqual( + list_reposnse_vpc.name, + new_name, + "VPC off Name should be updated with new one" + ) + self.assertEqual( + list_reposnse_vpc.displaytext, + new_displaytext, + "VPC off display text should be updated with new one" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_08_list_vpc_off(self): + """Test list VPC offering""" + + # Validate the following + # 1. Create multiple VPC Offerings + # 2. Delete few of the VPC offerings + # 3. List all the VPC offerings. Deleted VPC offering should not be + # returned by list VPC offerings command + # 4. List offerings by ID. Only offering having ID should get listed + # 5. List VPC Offerings by displaytext. Only offerings with same + # display text should be listed + # 6. List VPC Offerings by name. Only offerings with same + # name should be listed + # 7. List VPC Offerings by supported services. Only offerings with same + # supported services should be listed + # 8. All VPC offering in "Enabled" state should get listed. + # 9. All VPC offering in "Disabled" state should get listed + + self.debug("Creating multiple VPC offerings") + self.services["vpc_offering"]["supportedservices"] = 'SourceNat' + + vpc_off_1 = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + self.cleanup.append(vpc_off_1) + self.validate_vpc_offering(vpc_off_1) + self.debug("Disabling the VPC offering created") + vpc_off_1.update(self.apiclient, state='Disabled') + + vpc_off_2 = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.cleanup.append(vpc_off_2) + self.validate_vpc_offering(vpc_off_2) + self.debug("Enabling the VPC offering created") + vpc_off_2.update(self.apiclient, state='Enabled') + + vpc_off_3 = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self.cleanup.append(vpc_off_3) + self.validate_vpc_offering(vpc_off_3) + self.debug("Enabling the VPC offering created") + vpc_off_3.update(self.apiclient, state='Enabled') + + vpc_off_4 = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + self.validate_vpc_offering(vpc_off_4) + self.debug("Enabling the VPC offering created") + vpc_off_4.update(self.apiclient, state='Enabled') + + self.debug("Deleting the VPC offering: %s" % vpc_off_4.name) + vpc_off_4.delete(self.apiclient) + + self.debug("Cheking if listVPCOff return the deleted VPC off") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_off_4.id, + listall=True + ) + self.assertEqual( + vpc_offs, + None, + "List VPC offerings should nt return any response for deleted offering" + ) + + self.debug("Validating the listVPCOfferings repsonse by ids") + self.validate_vpc_offering(vpc_off_3) + + self.debug("ListVPCOfferings by displaytext & verifying the response") + vpc_offs = VpcOffering.list( + self.apiclient, + displaytext=vpc_off_3.displaytext, + listall=True + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings shall return a valid response" + ) + list_vpc_off_response = vpc_offs[0] + self.assertIn( + vpc_off_3.id, + [vpc.id for vpc in vpc_offs], + "ListVPC Off with displaytext should return same VPC off" + ) + + self.debug("ListVPCOfferings by name and verifying the response") + vpc_offs = VpcOffering.list( + self.apiclient, + name=vpc_off_2.name, + listall=True + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings shall return a valid response" + ) + list_vpc_off_response = vpc_offs[0] + self.assertEqual( + list_vpc_off_response.id, + vpc_off_2.id, + "ListVPC Off with name should return same VPC off" + ) + + self.debug( + "ListVPCOfferings by supported services & verifying the response") + vpc_offs = VpcOffering.list( + self.apiclient, + supportedservices='SourceNat', + listall=True + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings shall return a valid response" + ) + for vpc_off in vpc_offs: + self.debug(vpc_off) + self.assertEqual( + 'SourceNat' in str(vpc_off), + True, + "ListVPC Off with name should return same VPC off" + ) + + self.debug("ListVPCOfferings by state & verifying the response") + vpc_offs = VpcOffering.list( + self.apiclient, + state='Enabled', + listall=True + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings shall return a valid response" + ) + for vpc_off in vpc_offs: + self.assertEqual( + vpc_off.state, + 'Enabled', + "List VPC offering should return only offerings that are enabled" + ) + + self.debug("ListVPCOfferings by state & verifying the response") + vpc_offs = VpcOffering.list( + self.apiclient, + state='Disabled', + listall=True + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings shall return a valid response" + ) + for vpc_off in vpc_offs: + self.assertEqual( + vpc_off.state, + 'Disabled', + "List VPC offering should return only offerings that are disabled" + ) + return diff --git a/test/integration/component/test_vpc_routers.py b/test/integration/component/test_vpc_routers.py new file mode 100644 index 00000000000..5beb0a12214 --- /dev/null +++ b/test/integration/component/test_vpc_routers.py @@ -0,0 +1,1398 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests for VPC - Router Operations +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test VPC Router 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 64, + }, + "service_offering_new": { + "name": "Small Instance", + "displaytext": "Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Vpn,Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Vpn": 'VpcVirtualRouter', + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Vpn,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0' + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 2222, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "http_rule": { + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "TCP" + }, + "virtual_machine": { + "displayname": "Test VM", + "username": "root", + "password": "password", + "ssh_port": 22, + "hypervisor": 'XenServer', + # Hypervisor type should be same as + # hypervisor type of cluster + "privateport": 22, + "publicport": 22, + "protocol": 'TCP', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + +class TestVPCRoutersBasic(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.apiclient = super( + TestVPCRoutersBasic, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient, cls.services) + cls.zone = get_zone(cls.apiclient, cls.services) + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offering"] + ) + cls.vpc_off = VpcOffering.create( + cls.apiclient, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.apiclient, state='Enabled') + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup = [cls.account] + cls._cleanup.append(cls.vpc_off) + #cls.debug("Enabling the VPC offering created") + cls.vpc_off.update(cls.apiclient, state='Enabled') + + #cls.debug("creating a VPC network in the account: %s" % + # cls.account.account.name) + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.apiclient, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls._cleanup.append(cls.service_offering) + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.apiclient, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + wait_for_cleanup(cls.apiclient, ["account.cleanup.interval"]) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + + return + + def tearDown(self): + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + def migrate_router(self, router): + """ Migrate the router """ + + self.debug("Checking if the host is available for migration?") + hosts = Host.list(self.apiclient, zoneid=self.zone.id, type='Routing') + + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + if len(hosts) < 2: + raise unittest.SkipTest( + "No host available for migration. Test requires atleast 2 hosts") + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != router.hostid] + host = hosts[0] + self.debug("Validating if the network rules work properly or not?") + + self.debug("Migrating VM-ID: %s from %s to Host: %s" % ( + router.id, + router.hostid, + host.id + )) + try: + + #Migrate the router + cmd = migrateSystemVm.migrateSystemVmCmd() + cmd.isAsync = "false" + cmd.hostid = host.id + cmd.virtualmachineid = router.id + self.apiclient.migrateSystemVm(cmd) + + except Exception as e: + self.fail("Failed to migrate instance, %s" % e) + + self.debug("Waiting for Router mgiration ....") + time.sleep(240) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertEqual(router.hostid, host.id, "Migration to host %s failed. The router host is" + "still %s" % (host.id, router.hostid)) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_stop_start_router_after_creating_vpc(self): + """ Test to stop and start router after creation of VPC + """ + + # Validate following: + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Stop the VPC Virtual Router which is created as a result of VPC creation. + # 3. Start the Stopped VPC Virtual Router + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + + # Stop the VPC Router + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + router = routers[0] + self.debug("Stopping the router with ID: %s" % router.id) + + #Stop the router + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + #List router should have router in stopped state + self.assertEqual( + router_response[0].state, + 'Stopped', + "Check list router response for router state" + ) + + self.debug("Stopped the router with ID: %s" % router.id) + + # Start The Router + self.debug("Starting the router with ID: %s" % router.id) + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + #List router should have router in running state + self.assertEqual( + router_response[0].state, + 'Running', + "Check list router response for router state" + ) + self.debug("Started the router with ID: %s" % router.id) + + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_reboot_router_after_creating_vpc(self): + """ Test to reboot the router after creating a VPC + """ + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Reboot the VPC Virtual Router which is created as a result of VPC creation. + # Stop the VPC Router + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + router = routers[0] + + self.debug("Rebooting the router ...") + #Reboot the router + cmd = rebootRouter.rebootRouterCmd() + cmd.id = router.id + self.apiclient.rebootRouter(cmd) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + #List router should have router in running state and same public IP + self.assertEqual( + router_response[0].state, + 'Running', + "Check list router response for router state" + ) + return + + + @attr(tags=["advanced", "intervlan"]) + def test_03_destroy_router_after_creating_vpc(self): + """ Test to destroy the router after creating a VPC + """ + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Destroy the VPC Virtual Router which is created as a result of VPC creation. + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + + Router.destroy( self.apiclient, + id=routers[0].id + ) + + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + False, + "List Routers should be empty" + ) + return + + @unittest.skip("Needs hosts") + @attr(tags=["advanced", "intervlan"]) + def test_04_migrate_router_after_creating_vpc(self): + """ Test migration of router to another host after creating VPC """ + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + self.migrate_router(routers[0]) + return + + @unittest.skip("Fails") + @attr(tags=["advanced", "intervlan"]) + def test_05_change_service_offerring_vpc(self): + """ Tests to change service offering of the Router after + creating a vpc + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Change the service offerings of the VPC Virtual Router which is created as a result of VPC creation. + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + + #Stop the router + router = routers[0] + self.debug("Stopping the router with ID: %s" % router.id) + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering_new"] + ) + self.debug("Changing service offering for the Router %s" % router.id) + try: + router = Router.change_service_offering(self.apiclient, + router.id, + service_offering.id + ) + except: + self.fail("Changing service offering failed") + + self.debug("Router %s" % router) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + router = routers[0] + self.assertEqual( + router.serviceofferingid, + service_offering.id, + "Changing service offering failed as id is %s and expected" + "is %s" % (router.serviceofferingid, service_offering.id) + ) + return + +class TestVPCRouterOneNetwork(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.apiclient = super( + TestVPCRouterOneNetwork, + cls + ).getClsTestClient().getApiClient() + cls.services = Services().services + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient, cls.services) + cls.zone = get_zone(cls.apiclient, cls.services) + cls.template = get_template( + cls.apiclient, + cls.zone.id, + cls.services["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offering"] + ) + cls.vpc_off = VpcOffering.create( + cls.apiclient, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.apiclient, state='Enabled') + + cls.account = Account.create( + cls.apiclient, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + cls._cleanup = [cls.account] + + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.apiclient, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.apiclient, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.apiclient, state='Enabled') + cls._cleanup.append(cls.nw_off) + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.apiclient, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + cls.apiclient, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + vm_2 = VirtualMachine.create( + cls.apiclient, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + + # Spawn an instance in that network + vm_3 = VirtualMachine.create( + cls.apiclient, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + + vms = VirtualMachine.list( + cls.apiclient, + account=cls.account.account.name, + domainid=cls.account.account.domainid, + listall=True + ) + public_ip_1 = PublicIPAddress.create( + cls.apiclient, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + nat_rule = NATRule.create( + cls.apiclient, + vm_1, + cls.services["natrule"], + ipaddressid=public_ip_1.ipaddress.id, + openfirewall=False, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + nwacl_nat = NetworkACL.create( + cls.apiclient, + networkid=cls.network_1.id, + services=cls.services["natrule"], + traffictype='Ingress' + ) + + public_ip_2 = PublicIPAddress.create( + cls.apiclient, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + try: + StaticNATRule.enable( + cls.apiclient, + ipaddressid=public_ip_2.ipaddress.id, + virtualmachineid=vm_2.id, + networkid=cls.network_1.id + ) + except Exception as e: + cls.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_2.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + cls.apiclient, + networkid=cls.network_1.id, + listall=True, + isstaticnat=True, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) +# cls.assertEqual( +# isinstance(public_ips, list), +# True, +# "List public Ip for network should list the Ip addr" +# ) +# cls.assertEqual( +# public_ips[0].ipaddress, +# public_ip_2.ipaddress.ipaddress, +# "List public Ip for network should list the Ip addr" +# ) +# + + public_ip_3 = PublicIPAddress.create( + cls.apiclient, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + + lb_rule = LoadBalancerRule.create( + cls.apiclient, + cls.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network_1.id, + vpcid=cls.vpc.id, + domainid=cls.account.account.domainid + ) + + lb_rule.assign(cls.apiclient, [vm_3]) + + nwacl_lb = NetworkACL.create( + cls.apiclient, + networkid=cls.network_1.id, + services=cls.services["lbrule"], + traffictype='Ingress' + ) + + nwacl_internet_1 = NetworkACL.create( + cls.apiclient, + networkid=cls.network_1.id, + services=cls.services["http_rule"], + traffictype='Egress' + ) + + private_gateway = PrivateGateway.create( + cls.apiclient, + gateway='10.1.3.1', + ipaddress='10.1.3.100', + netmask='255.255.255.0', + vlan=678, + vpcid=cls.vpc.id + ) + cls.gateways = PrivateGateway.list( + cls.apiclient, + id=private_gateway.id, + listall=True + ) + static_route = StaticRoute.create( + cls.apiclient, + cidr='11.1.1.1/24', + gatewayid=private_gateway.id + ) + cls.static_routes = StaticRoute.list( + cls.apiclient, + id=static_route.id, + listall=True + ) + + cls._cleanup = [ + cls.service_offering, + cls.vpc_off + ] + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.apiclient, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + wait_for_cleanup(cls.apiclient, ["account.cleanup.interval"]) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + interval = list_configurations( + self.apiclient, + name='network.gc.interval' + ) + wait = list_configurations( + self.apiclient, + name='network.gc.wait' + ) + # Sleep to ensure that all resources are deleted + time.sleep(int(interval[0].value) + int(wait[0].value)) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("We should be allowed to ping virtual gateway") + self.debug("VM gateway: %s" % self.vm_1.nic[0].gateway) + + res = ssh_1.execute("ping -c 1 %s" % self.vm_1.nic[0].gateway) + self.debug("ping -c 1 %s: %s" % (self.vm_1.nic[0].gateway, res)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to VM gateway should be successful" + ) + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + return + + def validate_network_rules(self): + """ Validate network rules + """ + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + public_ips = PublicIPAddress.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + for vm, public_ip in zip(vms, public_ips): + try: + ssh_1 = vm.get_ssh_client( + ipaddress=public_ip.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + def migrate_router(self, router): + """ Migrate the router """ + + self.debug("Checking if the host is available for migration?") + hosts = Host.list(self.apiclient, zoneid=self.zone.id, type='Routing') + + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + if len(hosts) < 2: + raise unittest.SkipTest( + "No host available for migration. Test requires atleast 2 hosts") + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != router.hostid] + host = hosts[0] + self.debug("Validating if the network rules work properly or not?") + + self.debug("Migrating VM-ID: %s from %s to Host: %s" % ( + router.id, + router.hostid, + host.id + )) + try: + + #Migrate the router + cmd = migrateSystemVm.migrateSystemVmCmd() + cmd.isAsync = "false" + cmd.hostid = host.id + cmd.virtualmachineid = router.id + self.apiclient.migrateSystemVm(cmd) + + except Exception as e: + self.fail("Failed to migrate instance, %s" % e) + + self.debug("Waiting for Router mgiration ....") + time.sleep(240) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + + self.assertEqual(router.hostid, host.id, "Migration to host %s failed. The router host is" + "still %s" % (host.id, router.hostid)) + return + + + @attr(tags=["advanced", "intervlan"]) + def test_01_start_stop_router_after_addition_of_one_guest_network(self): + """ Test start/stop of router after addition of one guest network + """ + # Validations + #1. Create a VPC with cidr - 10.1.1.1/16 + #2. Add network1(10.1.1.1/24) to this VPC. + #3. Deploy vm1,vm2 and vm3 such that they are part of network1. + #4. Create a PF /Static Nat/LB rule for vms in network1. + #5. Create ingress network ACL for allowing all the above rules from a public ip range on network1. + #6. Create egress network ACL for network1 to access google.com. + #7. Create a private gateway for this VPC and add a static route to this gateway. + #8. Create a VPN gateway for this VPC and add a static route to this gateway. + #9. Make sure that all the PF,LB and Static NAT rules work as expected. + #10. Make sure that we are able to access google.com from all the user Vms. + #11. Make sure that the newly added private gateway's and VPN gateway's static routes work as expected + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + #self.validate_network_rules() + self.assertEqual( + isinstance(self.gateways, list), + True, + "List private gateways should return a valid response" + ) + self.assertEqual( + isinstance(self.static_routes, list), + True, + "List static route should return a valid response" + ) + + # Stop the VPC Router + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + router = routers[0] + self.debug("Stopping the router with ID: %s" % router.id) + + #Stop the router + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + #List router should have router in stopped state + self.assertEqual( + router_response[0].state, + 'Stopped', + "Check list router response for router state" + ) + + self.debug("Stopped the router with ID: %s" % router.id) + + # Start The Router + self.debug("Starting the router with ID: %s" % router.id) + cmd = startRouter.startRouterCmd() + cmd.id = router.id + self.apiclient.startRouter(cmd) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + #List router should have router in running state + self.assertEqual( + router_response[0].state, + 'Running', + "Check list router response for router state" + ) + self.debug("Started the router with ID: %s" % router.id) + + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_reboot_router_after_addition_of_one_guest_network(self): + """ Test reboot of router after addition of one guest network + """ + # Validations + #1. Create a VPC with cidr - 10.1.1.1/16 + #2. Add network1(10.1.1.1/24) to this VPC. + #3. Deploy vm1,vm2 and vm3 such that they are part of network1. + #4. Create a PF /Static Nat/LB rule for vms in network1. + #5. Create ingress network ACL for allowing all the above rules from a public ip range on network1. + #6. Create egress network ACL for network1 to access google.com. + #7. Create a private gateway for this VPC and add a static route to this gateway. + #8. Create a VPN gateway for this VPC and add a static route to this gateway. + #9. Make sure that all the PF,LB and Static NAT rules work as expected. + #10. Make sure that we are able to access google.com from all the user Vms. + #11. Make sure that the newly added private gateway's and VPN gateway's static routes work as expected + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + self.assertEqual( + isinstance(self.gateways, list), + True, + "List private gateways should return a valid response" + ) + self.assertEqual( + isinstance(self.static_routes, list), + True, + "List static route should return a valid response" + ) + + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + router = routers[0] + + self.debug("Rebooting the router ...") + #Reboot the router + cmd = rebootRouter.rebootRouterCmd() + cmd.id = router.id + self.apiclient.rebootRouter(cmd) + + #List routers to check state of router + router_response = list_routers( + self.apiclient, + id=router.id + ) + self.assertEqual( + isinstance(router_response, list), + True, + "Check list response returns a valid list" + ) + #List router should have router in running state and same public IP + self.assertEqual( + router_response[0].state, + 'Running', + "Check list router response for router state" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_destroy_router_after_addition_of_one_guest_network(self): + """ Test destroy of router after addition of one guest network + """ + # Validations + #1. Create a VPC with cidr - 10.1.1.1/16 + #2. Add network1(10.1.1.1/24) to this VPC. + #3. Deploy vm1,vm2 and vm3 such that they are part of network1. + #4. Create a PF /Static Nat/LB rule for vms in network1. + #5. Create ingress network ACL for allowing all the above rules from a public ip range on network1. + #6. Create egress network ACL for network1 to access google.com. + #7. Create a private gateway for this VPC and add a static route to this gateway. + #8. Create a VPN gateway for this VPC and add a static route to this gateway. + #9. Make sure that all the PF,LB and Static NAT rules work as expected. + #10. Make sure that we are able to access google.com from all the user Vms. + #11. Make sure that the newly added private gateway's and VPN gateway's static routes work as expected + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + self.assertEqual( + isinstance(self.gateways, list), + True, + "List private gateways should return a valid response" + ) + self.assertEqual( + isinstance(self.static_routes, list), + True, + "List static route should return a valid response" + ) + + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + + Router.destroy( self.apiclient, + id=routers[0].id + ) + + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + False, + "List Routers should be empty" + ) + return + + @unittest.skip("Untested - hosts not available") + @attr(tags=["advanced", "intervlan"]) + def test_04_migrate_router_after_addition_of_one_guest_network(self): + """ Test migrate of router after addition of one guest network + """ + # Validations + #1. Create a VPC with cidr - 10.1.1.1/16 + #2. Add network1(10.1.1.1/24) to this VPC. + #3. Deploy vm1,vm2 and vm3 such that they are part of network1. + #4. Create a PF /Static Nat/LB rule for vms in network1. + #5. Create ingress network ACL for allowing all the above rules from a public ip range on network1. + #6. Create egress network ACL for network1 to access google.com. + #7. Create a private gateway for this VPC and add a static route to this gateway. + #8. Create a VPN gateway for this VPC and add a static route to this gateway. + #9. Make sure that all the PF,LB and Static NAT rules work as expected. + #10. Make sure that we are able to access google.com from all the user Vms. + #11. Make sure that the newly added private gateway's and VPN gateway's static routes work as expected + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + self.assertEqual( + isinstance(self.gateways, list), + True, + "List private gateways should return a valid response" + ) + self.assertEqual( + isinstance(self.static_routes, list), + True, + "List static route should return a valid response" + ) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + self.migrate_router(routers[0]) + return + + @unittest.skip("Fails") + @attr(tags=["advanced", "intervlan"]) + def test_05_chg_srv_off_router_after_addition_of_one_guest_network(self): + """ Test to change service offering of router after addition of one guest network + """ + # Validations + #1. Create a VPC with cidr - 10.1.1.1/16 + #2. Add network1(10.1.1.1/24) to this VPC. + #3. Deploy vm1,vm2 and vm3 such that they are part of network1. + #4. Create a PF /Static Nat/LB rule for vms in network1. + #5. Create ingress network ACL for allowing all the above rules from a public ip range on network1. + #6. Create egress network ACL for network1 to access google.com. + #7. Create a private gateway for this VPC and add a static route to this gateway. + #8. Create a VPN gateway for this VPC and add a static route to this gateway. + #9. Make sure that all the PF,LB and Static NAT rules work as expected. + #10. Make sure that we are able to access google.com from all the user Vms. + #11. Make sure that the newly added private gateway's and VPN gateway's static routes work as expected + + self.validate_vpc_offering(self.vpc_off) + self.validate_vpc_network(self.vpc) + self.assertEqual( + isinstance(self.gateways, list), + True, + "List private gateways should return a valid response" + ) + self.assertEqual( + isinstance(self.static_routes, list), + True, + "List static route should return a valid response" + ) + + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List Routers should return a valid list" + ) + + #Stop the router + router = routers[0] + self.debug("Stopping the router with ID: %s" % router.id) + cmd = stopRouter.stopRouterCmd() + cmd.id = router.id + self.apiclient.stopRouter(cmd) + + service_offering = ServiceOffering.create( + self.apiclient, + self.services["service_offering_new"] + ) + self.debug("Changing service offering for the Router %s" % router.id) + try: + router = Router.change_service_offering(self.apiclient, + router.id, + service_offering.id + ) + except: + self.fail("Changing service offering failed") + + self.debug("Router %s" % router) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + router = routers[0] + self.assertEqual( + router.serviceofferingid, + service_offering.id, + "Changing service offering failed as id is %s and expected" + "is %s" % (router.serviceofferingid, service_offering.id) + ) + return + diff --git a/test/integration/component/test_vpc_vm_life_cycle.py b/test/integration/component/test_vpc_vm_life_cycle.py new file mode 100644 index 00000000000..247599e7251 --- /dev/null +++ b/test/integration/component/test_vpc_vm_life_cycle.py @@ -0,0 +1,3603 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests VM life cycle in VPC network functionality +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test VM life cycle in VPC network 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "service_offering_1": { + "name": "Tiny Instance- tagged host 1", + "displaytext": "Tiny off-tagged host2", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + "tags": "HOST_TAGS_HERE" + }, + "service_offering_2": { + "name": "Tiny Instance- tagged host 2", + "displaytext": "Tiny off-tagged host2", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + "tags": "HOST_TAGS_HERE" + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "network_off_shared": { + "name": 'Shared Network offering', + "displaytext": 'Shared Network offering', + "guestiptype": 'Shared', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "specifyIpRanges": True, + "specifyVlan": True + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0', + "limit": 5, + # Max networks allowed as per hypervisor + # Xenserver -> 5, VMWare -> 9 + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 2222, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "http_rule": { + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "ICMP" + }, + "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', + "userdata": 'This is sample data', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestVMLifeCycleVPC(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMLifeCycleVPC, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + cls.nw_off_no_lb = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + cls.nw_off_no_lb.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_2 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off_no_lb.id, + zoneid=cls.zone.id, + gateway='10.1.2.1', + vpcid=cls.vpc.id + ) + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + # Spawn an instance in that network + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + cls.vm_3 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_2.id)] + ) + + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_1.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network_1.id, + vpcid=cls.vpc.id, + domainid=cls.account.account.domainid + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) + + cls.public_ip_2 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + cls.nat_rule = NATRule.create( + cls.api_client, + cls.vm_1, + cls.services["natrule"], + ipaddressid=cls.public_ip_2.ipaddress.id, + openfirewall=False, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + # Opening up the ports in VPC + cls.nwacl_nat = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["natrule"], + traffictype='Ingress' + ) + + cls.nwacl_lb = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["lbrule"], + traffictype='Ingress' + ) + + cls.nwacl_internet_1 = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["http_rule"], + traffictype='Egress' + ) + cls._cleanup = [ + cls.service_offering, + cls.nw_off, + cls.nw_off_no_lb, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.account.delete(cls.api_client) + wait_for_cleanup(cls.api_client, ["account.cleanup.interval"]) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + # Waiting for network cleanup to delete vpc offering + wait_for_cleanup(cls.api_client, ["network.gc.wait", "network.gc.interval"]) + cls.vpc_off.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + def validate_network_rules(self): + """Validates if the network rules work properly or not?""" + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_1?") + try: + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_2.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_deploy_instance_in_network(self): + """ Test deploy an instance in VPC networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # Steps: + # 1. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2 using + # the default CentOS 6.2 Template + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_stop_instance_in_network(self): + """ Test stop an instance in VPC networks + """ + + # Validate the following + # 1. Stop the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Stopping the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.stop(self.apiclient) + self.vm_2.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop the virtual instances, %s" % e) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules shall return a valid list" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules shall return a valid list" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_start_instance_in_network(self): + """ Test start an instance in VPC networks + """ + + # Validate the following + # 1. Start the virtual machines. + # 2. Vm should be started successfully. + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Starting the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.start(self.apiclient) + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the virtual instances, %s" % e) + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_reboot_instance_in_network(self): + """ Test reboot an instance in VPC networks + """ + + # Validate the following + # 1. Reboot the virtual machines. + # 2. Vm should be started successfully. + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Starting the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.reboot(self.apiclient) + self.vm_2.reboot(self.apiclient) + except Exception as e: + self.fail("Failed to reboot the virtual instances, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_05_destroy_instance_in_network(self): + """ Test destroy an instance in VPC networks + """ + + # Validate the following + # 1. Destory the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Destroying the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.delete(self.apiclient) + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to stop the virtual instances, %s" % e) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules shall return a valid list" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules shall return a valid list" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_06_recover_instance_in_network(self): + """ Test recover an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Recovering the expunged virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.recover(self.apiclient) + self.vm_2.recover(self.apiclient) + except Exception as e: + self.fail("Failed to recover the virtual instances, %s" % e) + + self.debug("Starting the two instances..") + try: + self.vm_1.start(self.apiclient) + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the instances, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_07_migrate_instance_in_network(self): + """ Test migrate an instance in VPC networks + """ + + # Validate the following + # 1. Migrate the virtual machines to other hosts + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Checking if the host is available for migration?") + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + type='Routing' + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + if len(hosts) < 2: + raise unittest.SkipTest( + "No host available for migration. Test requires atleast 2 hosts") + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != self.vm_1.hostid] + + host = hosts[0] + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Migrating VM-ID: %s to Host: %s" % ( + self.vm_1.id, + host.id + )) + + try: + self.vm_1.migrate(self.apiclient, hostid=host.id) + except Exception as e: + self.fail("Failed to migrate instance, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_08_user_data(self): + """ Test user data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the user data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the userdata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/user-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertEqual( + res.count( + self.services["virtual_machine"]["userdata"]), + 1, + "Verify user data from router" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_09_meta_data(self): + """ Test meta data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the meta data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the metadata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/meta-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertNotEqual( + res, + None, + "Meta data should be returned from router" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_10_expunge_instance_in_network(self): + """ Test expunge an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Delete virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.delete(self.apiclient) + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy the virtual instances, %s" % e) + + self.debug( + "Waiting for expunge interval to cleanup the network and VMs") + + wait_for_cleanup( + self.apiclient, + ["expunge.interval", "expunge.delay"] + ) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + nat_rules, + None, + "List NAT rules should not return anything" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + lb_rules, + None, + "List LB rules should not return anything" + ) + return + + +class TestVMLifeCycleSharedNwVPC(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMLifeCycleSharedNwVPC, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + cls.nw_off_no_lb = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_no_lb"], + conservemode=False + ) + cls.shared_nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_off_shared"], + conservemode=False + ) + # Enable Network offering + cls.shared_nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_2 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.shared_nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.2.1', + vpcid=cls.vpc.id + ) + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id), + str(cls.network_2.id)] + ) + # Spawn an instance in that network + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id), + str(cls.network_2.id)] + ) + cls.vm_3 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id), + str(cls.network_2.id)] + ) + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_1.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network_1.id, + vpcid=cls.vpc.id, + domainid=cls.account.account.domainid + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2, cls.vm_3]) + + cls.public_ip_2 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + cls.nat_rule = NATRule.create( + cls.api_client, + cls.vm_1, + cls.services["natrule"], + ipaddressid=cls.public_ip_2.ipaddress.id, + openfirewall=False, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + # Opening up the ports in VPC + cls.nwacl_nat = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["natrule"], + traffictype='Ingress' + ) + + cls.nwacl_lb = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["lbrule"], + traffictype='Ingress' + ) + + cls.nwacl_internet_1 = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["http_rule"], + traffictype='Egress' + ) + cls._cleanup = [ + cls.service_offering, + cls.nw_off, + cls.shared_nw_off, + cls.vpc_off + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.account.delete(cls.api_client) + wait_for_cleanup(cls.api_client, ["account.cleanup.interval"]) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + def validate_network_rules(self): + """Validating if the network rules (PF/LB) works properly or not?""" + + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("We should be allowed to ping virtual gateway") + self.debug("VM gateway: %s" % self.vm_1.nic[0].gateway) + + res = ssh_1.execute("ping -c 1 %s" % self.vm_1.nic[0].gateway) + self.debug("ping -c 1 %s: %s" % (self.vm_1.nic[0].gateway, res)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to VM gateway should be successful" + ) + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_deploy_instance_in_network(self): + """ Test deploy an instance in VPC networks + """ + + # Validate the following + # 1. Successful deployment of the User VM. + # 2. Ping any host in the public Internet successfully. + # 3. Ping the gateways of the VPC's guest network and the + # Shared Guest Network successfully. + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_stop_instance_in_network(self): + """ Test stop an instance in VPC networks + """ + + # Validate the following + # 1. Stop the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + + self.debug("Stopping one of the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_2.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop the virtual instances, %s" % e) + + self.debug("Check if the instance is in stopped state?") + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Stopped", + "Virtual machine should be in stopped state" + ) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_start_instance_in_network(self): + """ Test start an instance in VPC networks + """ + + # Validate the following + # 1. Start the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + + self.debug("Starting one of the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the virtual instances, %s" % e) + + self.debug("Check if the instance is in stopped state?") + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Virtual machine should be in running state" + ) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_reboot_instance_in_network(self): + """ Test reboot an instance in VPC networks + """ + + # Validate the following + # 1. Reboot the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + + self.debug("Restarting the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.reboot(self.apiclient) + self.vm_2.reboot(self.apiclient) + except Exception as e: + self.fail("Failed to reboot the virtual instances, %s" % e) + + self.debug("Check if the instance is in stopped state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return a valid list" + ) + for vm in vms: + self.assertEqual( + vm.state, + "Running", + "Virtual machine should be in running state" + ) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_05_destroy_instance_in_network(self): + """ Test destroy an instance in VPC networks + """ + + # Validate the following + # 1. Destroy one of the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Destroying one of the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy the virtual instances, %s" % e) + + self.debug("Check if the instance is in stopped state?") + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Expunging", + "Virtual machine should be in expunging state" + ) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_06_recover_instance_in_network(self): + """ Test recover an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Recovering the expunged virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_2.recover(self.apiclient) + except Exception as e: + self.fail("Failed to recover the virtual instances, %s" % e) + + self.debug("Check if the instance is in stopped state?") + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Stopped", + "Virtual machine should be in stopped state" + ) + + self.debug("Starting the instance: %s" % self.vm_2.name) + try: + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the instances, %s" % e) + + vms = VirtualMachine.list( + self.apiclient, + id=self.vm_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List virtual machines should return a valid list" + ) + vm = vms[0] + self.assertEqual( + vm.state, + "Running", + "Virtual machine should be in running state" + ) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_07_migrate_instance_in_network(self): + """ Test migrate an instance in VPC networks + """ + + # Validate the following + # 1. Migrate the virtual machines to other hosts + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Checking if the host is available for migration?") + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + type='Routing' + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + if len(hosts) < 2: + raise unittest.SkipTest( + "No host available for migration. Test requires atleast 2 hosts") + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != self.vm_1.hostid] + + host = hosts[0] + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + + self.debug("Migrating VM-ID: %s to Host: %s" % ( + self.vm_1.id, + host.id + )) + + try: + self.vm_1.migrate(self.apiclient, hostid=host.id) + except Exception as e: + self.fail("Failed to migrate instance, %s" % e) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_08_user_data(self): + """ Test user data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the user data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the userdata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/user-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertEqual( + res.count( + self.services["virtual_machine"]["userdata"]), + 1, + "Verify user data from router" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_09_meta_data(self): + """ Test meta data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the meta data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the metadata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/meta-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertNotEqual( + res, + None, + "Meta data should be returned from router" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_10_expunge_instance_in_network(self): + """ Test expunge an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + + self.debug("Delete virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy the virtual instances, %s" % e) + + self.debug( + "Waiting for expunge interval to cleanup the network and VMs") + + wait_for_cleanup( + self.apiclient, + ["expunge.interval", "expunge.delay"] + ) + + self.debug("Validating if network rules are coonfigured properly?") + self.validate_network_rules() + + self.debug( + "Deleting the rest of the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.delete(self.apiclient) + self.vm_3.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy the virtual instances, %s" % e) + + self.debug( + "Waiting for expunge interval to cleanup the network and VMs") + + wait_for_cleanup( + self.apiclient, + ["expunge.interval", "expunge.delay"] + ) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + nat_rules, + None, + "List NAT rules should not return anything" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + lb_rules, + None, + "List LB rules should not return anything" + ) + return + + +class TestVMLifeCycleBothIsolated(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMLifeCycleBothIsolated, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + cls.nw_off_no_lb = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_no_lb"], + conservemode=False + ) + + # Enable Network offering + cls.nw_off_no_lb.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_2 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off_no_lb.id, + zoneid=cls.zone.id, + gateway='10.1.2.1', + vpcid=cls.vpc.id + ) + cls._cleanup = [ + cls.service_offering, + cls.nw_off, + cls.nw_off_no_lb, + cls.vpc_off + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.account.delete(cls.api_client) + wait_for_cleanup(cls.api_client, ["account.cleanup.interval"]) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + def validate_network_rules(self): + """Validating if the network rules (PF/LB) works properly or not?""" + + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("We should be allowed to ping virtual gateway") + self.debug("VM gateway: %s" % self.vm_1.nic[0].gateway) + + res = ssh_1.execute("ping -c 1 %s" % self.vm_1.nic[0].gateway) + self.debug("ping -c 1 %s: %s" % (self.vm_1.nic[0].gateway, res)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to VM gateway should be successful" + ) + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_deploy_vm_two_isolated_nw(self): + """ Test deploy virtual machine in two isolated networks""" + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # Steps: + # 1. Deploy a VM such that the VM is part of both networks-network1 + # and network2. Fail to deploy a VM. + + self.debug("Validating the VPC offering created") + self.validate_vpc_offering(self.vpc_off) + + self.debug("Validating VPC created in setup class") + self.validate_vpc_network(self.vpc) + + self.debug("Deploying virtual machine in two isolated networks") + with self.assertRaises(Exception): + 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_1.id), + str(self.network_2.id)] + ) + self.debug("Deploy VM in 2 isolated networks failed") + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_deploy_vm_vpcvr_stopped(self): + """ Test deploy virtual machine when VPC VR in stopped state""" + + # Validate the following + # Pre-Req: + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) to this VPC. + # 3. Stop the VPC Virtual Router + # Steps: + # 1. Deploy a VM using the default CentOS 6.2 Template + + self.debug("Finding the virtual router for network: %s" % + self.network_1.name) + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=self.network_1.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should return router for network: %s" % + self.network_1.name + ) + router = routers[0] + + self.debug("Check state of VPC virtual router, state: %s" % + router.state) + if router.state == "Running": + self.debug("Router state is running, stop it!") + Router.stop(self.apiclient, id=router.id) + + self.debug("Check the router state again") + routers = Router.list( + self.apiclient, + id=router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should return router for network: %s" % + self.network_1.name + ) + router = routers[0] + self.assertEqual( + router.state, + "Stopped", + "Router state should be stopped" + ) + self.debug("Deploy an instance in network: %s with stopped VPCVR" % + self.network_1.name) + try: + vm = 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_1.id)] + ) + except Exception as e: + self.fail("Failed to deploy the virtual instance: %s" % e) + + self.debug("Verify the deployment of virtual instace") + vms = VirtualMachine.list( + self.apiclient, + id=vm.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List vms shall return a valid resposnse" + ) + vm_response = vms[0] + self.assertEqaul( + vm_response.state, + "Running", + "VM state should be running after deployment" + ) + return + + +class TestVMLifeCycleStoppedVPCVR(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMLifeCycleStoppedVPCVR, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + cls.nw_off_no_lb = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + cls.nw_off_no_lb.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_2 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off_no_lb.id, + zoneid=cls.zone.id, + gateway='10.1.2.1', + vpcid=cls.vpc.id + ) + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + # Spawn an instance in that network + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_1.id)] + ) + cls.vm_3 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering.id, + networkids=[str(cls.network_2.id)] + ) + + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_1.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network_1.id, + vpcid=cls.vpc.id, + domainid=cls.account.account.domainid + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) + + cls.public_ip_2 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + cls.nat_rule = NATRule.create( + cls.api_client, + cls.vm_1, + cls.services["natrule"], + ipaddressid=cls.public_ip_2.ipaddress.id, + openfirewall=False, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + # Opening up the ports in VPC + cls.nwacl_nat = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["natrule"], + traffictype='Ingress' + ) + + cls.nwacl_lb = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["lbrule"], + traffictype='Ingress' + ) + + cls.nwacl_internet = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["http_rule"], + traffictype='Egress' + ) + cls._cleanup = [ + cls.service_offering, + cls.nw_off, + cls.nw_off_no_lb, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.account.delete(cls.api_client) + wait_for_cleanup(cls.api_client, ["account.cleanup.interval"]) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + # Waiting for network cleanup to delete vpc offering + wait_for_cleanup(cls.api_client, ["network.gc.wait", + "network.gc.interval"]) + cls.vpc_off.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.debug("Check the status of VPC virtual router") + routers = Router.list( + self.apiclient, + networkid=self.network_1.id, + listall=True + ) + if not isinstance(routers, list): + raise Exception("No response from list routers API") + + self.router = routers[0] + if self.router.state == "Running": + Router.stop(self.apiclient, id=self.router.id) + + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + def validate_network_rules(self): + """Validates if the network rules work properly or not?""" + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_1?") + try: + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_2.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_deploy_instance_in_network(self): + """ Test deploy an instance in VPC networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # Steps: + # 1. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2 using + # the default CentOS 6.2 Template + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_stop_instance_in_network(self): + """ Test stop an instance in VPC networks + """ + + # Validate the following + # 1. Stop the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Stopping the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.stop(self.apiclient) + self.vm_2.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop the virtual instances, %s" % e) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules shall return a valid list" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules shall return a valid list" + ) + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_03_start_instance_in_network(self): + """ Test start an instance in VPC networks + """ + + # Validate the following + # 1. Start the virtual machines. + # 2. Vm should be started successfully. + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Starting the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.start(self.apiclient) + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the virtual instances, %s" % e) + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_04_reboot_instance_in_network(self): + """ Test reboot an instance in VPC networks + """ + + # Validate the following + # 1. Reboot the virtual machines. + # 2. Vm should be started successfully. + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Starting the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.reboot(self.apiclient) + self.vm_2.reboot(self.apiclient) + except Exception as e: + self.fail("Failed to reboot the virtual instances, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_05_destroy_instance_in_network(self): + """ Test destroy an instance in VPC networks + """ + + # Validate the following + # 1. Destory the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Destroying the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.delete(self.apiclient) + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to stop the virtual instances, %s" % e) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules shall return a valid list" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules shall return a valid list" + ) + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_06_recover_instance_in_network(self): + """ Test recover an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Recovering the expunged virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.recover(self.apiclient) + self.vm_2.recover(self.apiclient) + except Exception as e: + self.fail("Failed to recover the virtual instances, %s" % e) + + self.debug("Starting the two instances..") + try: + self.vm_1.start(self.apiclient) + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the instances, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_07_migrate_instance_in_network(self): + """ Test migrate an instance in VPC networks + """ + + # Validate the following + # 1. Migrate the virtual machines to other hosts + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Checking if the host is available for migration?") + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + type='Routing' + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + if len(hosts) < 2: + raise unittest.SkipTest( + "No host available for migration. Test requires atleast 2 hosts") + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != self.vm_1.hostid] + + host = hosts[0] + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Migrating VM-ID: %s to Host: %s" % ( + self.vm_1.id, + host.id + )) + + try: + self.vm_1.migrate(self.apiclient, hostid=host.id) + except Exception as e: + self.fail("Failed to migrate instance, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_08_user_data(self): + """ Test user data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the user data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the userdata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/user-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertEqual( + res.count( + self.services["virtual_machine"]["userdata"]), + 1, + "Verify user data from router" + ) + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_09_meta_data(self): + """ Test meta data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the meta data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the metadata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/meta-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertNotEqual( + res, + None, + "Meta data should be returned from router" + ) + return + + @unittest.skip("Skipping - Not able to SSH if VPCVR is stopped") + @attr(tags=["advanced", "intervlan"]) + def test_10_expunge_instance_in_network(self): + """ Test expunge an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Delete virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.delete(self.apiclient) + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy the virtual instances, %s" % e) + + self.debug( + "Waiting for expunge interval to cleanup the network and VMs") + + wait_for_cleanup( + self.apiclient, + ["expunge.interval", "expunge.delay"] + ) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + nat_rules, + None, + "List NAT rules should not return anything" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + lb_rules, + None, + "List LB rules should not return anything" + ) + return + + +@unittest.skip("Skip - Requires Tagged hosts setup") +class TestVMLifeCycleDiffHosts(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMLifeCycleDiffHosts, + 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["ostype"] + ) + cls.services["virtual_machine"]["zoneid"] = cls.zone.id + cls.services["virtual_machine"]["template"] = cls.template.id + + cls.service_offering_1 = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_1"] + ) + cls.service_offering_2 = ServiceOffering.create( + cls.api_client, + cls.services["service_offering_2"] + ) + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.account = Account.create( + cls.api_client, + cls.services["account"], + admin=True, + domainid=cls.domain.id + ) + + cls.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + + cls.vpc_off.update(cls.api_client, state='Enabled') + + cls.services["vpc"]["cidr"] = '10.1.1.1/16' + cls.vpc = VPC.create( + cls.api_client, + cls.services["vpc"], + vpcofferingid=cls.vpc_off.id, + zoneid=cls.zone.id, + account=cls.account.account.name, + domainid=cls.account.account.domainid + ) + + cls.nw_off = NetworkOffering.create( + cls.api_client, + cls.services["network_offering"], + conservemode=False + ) + # Enable Network offering + cls.nw_off.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_1 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off.id, + zoneid=cls.zone.id, + gateway='10.1.1.1', + vpcid=cls.vpc.id + ) + cls.nw_off_no_lb = NetworkOffering.create( + cls.api_client, + cls.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + cls.nw_off_no_lb.update(cls.api_client, state='Enabled') + + # Creating network using the network offering created + cls.network_2 = Network.create( + cls.api_client, + cls.services["network"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + networkofferingid=cls.nw_off_no_lb.id, + zoneid=cls.zone.id, + gateway='10.1.2.1', + vpcid=cls.vpc.id + ) + # Spawn an instance in that network + cls.vm_1 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_1.id, + networkids=[str(cls.network_1.id)] + ) + # Spawn an instance in that network + cls.vm_2 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_1.id, + networkids=[str(cls.network_1.id)] + ) + cls.vm_3 = VirtualMachine.create( + cls.api_client, + cls.services["virtual_machine"], + accountid=cls.account.account.name, + domainid=cls.account.account.domainid, + serviceofferingid=cls.service_offering_2.id, + networkids=[str(cls.network_2.id)] + ) + + cls.public_ip_1 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + cls.lb_rule = LoadBalancerRule.create( + cls.api_client, + cls.services["lbrule"], + ipaddressid=cls.public_ip_1.ipaddress.id, + accountid=cls.account.account.name, + networkid=cls.network_1.id, + vpcid=cls.vpc.id, + domainid=cls.account.account.domainid + ) + cls.lb_rule.assign(cls.api_client, [cls.vm_1, cls.vm_2]) + + cls.public_ip_2 = PublicIPAddress.create( + cls.api_client, + accountid=cls.account.account.name, + zoneid=cls.zone.id, + domainid=cls.account.account.domainid, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + cls.nat_rule = NATRule.create( + cls.api_client, + cls.vm_1, + cls.services["natrule"], + ipaddressid=cls.public_ip_2.ipaddress.id, + openfirewall=False, + networkid=cls.network_1.id, + vpcid=cls.vpc.id + ) + + # Opening up the ports in VPC + cls.nwacl_nat = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["natrule"], + traffictype='Ingress' + ) + + cls.nwacl_lb = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["lbrule"], + traffictype='Ingress' + ) + + cls.nwacl_internet = NetworkACL.create( + cls.api_client, + networkid=cls.network_1.id, + services=cls.services["http_rule"], + traffictype='Egress' + ) + cls._cleanup = [ + cls.service_offering_1, + cls.service_offering_2, + cls.nw_off, + cls.nw_off_no_lb, + ] + return + + @classmethod + def tearDownClass(cls): + try: + cls.account.delete(cls.api_client) + wait_for_cleanup(cls.api_client, ["account.cleanup.interval"]) + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + + # Waiting for network cleanup to delete vpc offering + wait_for_cleanup(cls.api_client, ["network.gc.wait", + "network.gc.interval"]) + cls.vpc_off.delete(cls.api_client) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.debug("Check the status of VPC virtual router") + routers = Router.list( + self.apiclient, + networkid=self.network_1.id, + listall=True + ) + if not isinstance(routers, list): + raise Exception("No response from list routers API") + + self.router = routers[0] + if self.router.state == "Running": + Router.stop(self.apiclient, id=self.router.id) + + self.cleanup = [] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vm_deployment(self): + """Validates VM deployment on different hosts""" + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=self.network_1.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs shall return a valid response" + ) + host_1 = vms[0].hostid + self.debug("Host for network 1: %s" % vms[0].hostid) + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=self.network_2.id, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs shall return a valid response" + ) + host_2 = vms[0].hostid + self.debug("Host for network 2: %s" % vms[0].hostid) + + self.assertNotEqual( + host_1, + host_2, + "Both the virtual machines should be deployed on diff hosts " + ) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + def validate_network_rules(self): + """Validates if the network rules work properly or not?""" + try: + ssh_1 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_1?") + try: + ssh_2 = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_2.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (self.public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_deploy_instance_in_network(self): + """ Test deploy an instance in VPC networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # Steps: + # 1. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2 using + # the default CentOS 6.2 Template + + self.validate_vm_deployment() + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_stop_instance_in_network(self): + """ Test stop an instance in VPC networks + """ + + # Validate the following + # 1. Stop the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Stopping the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.stop(self.apiclient) + self.vm_2.stop(self.apiclient) + except Exception as e: + self.fail("Failed to stop the virtual instances, %s" % e) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules shall return a valid list" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules shall return a valid list" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_start_instance_in_network(self): + """ Test start an instance in VPC networks + """ + + # Validate the following + # 1. Start the virtual machines. + # 2. Vm should be started successfully. + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Starting the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.start(self.apiclient) + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the virtual instances, %s" % e) + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_reboot_instance_in_network(self): + """ Test reboot an instance in VPC networks + """ + + # Validate the following + # 1. Reboot the virtual machines. + # 2. Vm should be started successfully. + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Starting the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.reboot(self.apiclient) + self.vm_2.reboot(self.apiclient) + except Exception as e: + self.fail("Failed to reboot the virtual instances, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_05_destroy_instance_in_network(self): + """ Test destroy an instance in VPC networks + """ + + # Validate the following + # 1. Destory the virtual machines. + # 2. Rules should be still configured on virtual router. + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Destroying the virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.delete(self.apiclient) + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to stop the virtual instances, %s" % e) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + isinstance(nat_rules, list), + True, + "List NAT rules shall return a valid list" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + isinstance(lb_rules, list), + True, + "List LB rules shall return a valid list" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_06_recover_instance_in_network(self): + """ Test recover an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Recovering the expunged virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.recover(self.apiclient) + self.vm_2.recover(self.apiclient) + except Exception as e: + self.fail("Failed to recover the virtual instances, %s" % e) + + self.debug("Starting the two instances..") + try: + self.vm_1.start(self.apiclient) + self.vm_2.start(self.apiclient) + except Exception as e: + self.fail("Failed to start the instances, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_07_migrate_instance_in_network(self): + """ Test migrate an instance in VPC networks + """ + + # Validate the following + # 1. Migrate the virtual machines to other hosts + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Checking if the host is available for migration?") + hosts = Host.list( + self.apiclient, + zoneid=self.zone.id, + type='Routing' + ) + + self.assertEqual( + isinstance(hosts, list), + True, + "List hosts should return a valid list" + ) + if len(hosts) < 2: + raise unittest.SkipTest( + "No host available for migration. Test requires atleast 2 hosts") + + # Remove the host of current VM from the hosts list + hosts[:] = [host for host in hosts if host.id != self.vm_1.hostid] + + host = hosts[0] + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Migrating VM-ID: %s to Host: %s" % ( + self.vm_1.id, + host.id + )) + + try: + self.vm_1.migrate(self.apiclient, hostid=host.id) + except Exception as e: + self.fail("Failed to migrate instance, %s" % e) + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + return + + @attr(tags=["advanced", "intervlan"]) + def test_08_user_data(self): + """ Test user data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the user data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the userdata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/user-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertEqual( + res.count( + self.services["virtual_machine"]["userdata"]), + 1, + "Verify user data from router" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_09_meta_data(self): + """ Test meta data in virtual machines + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy a vm in network1 and a vm in network2 using userdata + # Steps + # 1.Query for the meta data for both the user vms from both networks + # User should be able to query the user data for the vms belonging to + # both the networks from the VR + + try: + ssh = self.vm_1.get_ssh_client( + ipaddress=self.public_ip_1.ipaddress.ipaddress) + self.debug("SSH into VM is successfully") + except Exception as e: + self.fail("Failed to SSH into instance") + + # Find router associated with user account + routers = Router.list( + self.apiclient, + zoneid=self.zone.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "Check list response returns a valid list" + ) + router = routers[0] + self.debug("check the metadata with that of present in router") + try: + cmds = [ + "wget http://%s/latest/meta-data" % router.guestipaddress, + "cat user-data", + ] + for c in cmds: + result = ssh.execute(c) + self.debug("%s: %s" % (c, result)) + except Exception as e: + self.fail("Failed to SSH in Virtual machine: %s" % e) + + res = str(result) + self.assertNotEqual( + res, + None, + "Meta data should be returned from router" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_10_expunge_instance_in_network(self): + """ Test expunge an instance in VPC networks + """ + + # Validate the following + # 1. Recover the virtual machines. + # 2. Vm should be in stopped state. State both the instances + # 3. Make sure that all the PF,LB and Static NAT rules on this VM + # works as expected. + # 3. Make sure that we are able to access google.com from this user Vm + + self.debug("Validating if the network rules work properly or not?") + self.validate_network_rules() + + self.debug("Delete virtual machines in account: %s" % + self.account.account.name) + try: + self.vm_1.delete(self.apiclient) + self.vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy the virtual instances, %s" % e) + + self.debug( + "Waiting for expunge interval to cleanup the network and VMs") + + wait_for_cleanup( + self.apiclient, + ["expunge.interval", "expunge.delay"] + ) + + # Check if the network rules still exists after Vm stop + self.debug("Checking if NAT rules ") + nat_rules = NATRule.list( + self.apiclient, + id=self.nat_rule.id, + listall=True + ) + self.assertEqual( + nat_rules, + None, + "List NAT rules should not return anything" + ) + + lb_rules = LoadBalancerRule.list( + self.apiclient, + id=self.lb_rule.id, + listall=True + ) + self.assertEqual( + lb_rules, + None, + "List LB rules should not return anything" + ) + return diff --git a/test/integration/component/test_vpc_vms_deployment.py b/test/integration/component/test_vpc_vms_deployment.py new file mode 100644 index 00000000000..b3a05d45614 --- /dev/null +++ b/test/integration/component/test_vpc_vms_deployment.py @@ -0,0 +1,2458 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +""" Component tests VM deployment in VPC network functionality +""" +#Import Local Modules +import marvin +from nose.plugins.attrib import attr +from marvin.cloudstackTestCase import * +from marvin.cloudstackAPI import * +from marvin.integration.lib.utils import * +from marvin.integration.lib.base import * +from marvin.integration.lib.common import * +from marvin.remoteSSHClient import remoteSSHClient +import datetime + + +class Services: + """Test VM deployment in VPC network 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": "password", + }, + "service_offering": { + "name": "Tiny Instance", + "displaytext": "Tiny Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 128, + }, + "network_offering": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "Lb": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "network_offering_no_lb": { + "name": 'VPC Network offering', + "displaytext": 'VPC Network off', + "guestiptype": 'Isolated', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,UserData,StaticNat,NetworkACL', + "traffictype": 'GUEST', + "availability": 'Optional', + "useVpc": 'on', + "serviceProviderList": { + "Dhcp": 'VpcVirtualRouter', + "Dns": 'VpcVirtualRouter', + "SourceNat": 'VpcVirtualRouter', + "PortForwarding": 'VpcVirtualRouter', + "UserData": 'VpcVirtualRouter', + "StaticNat": 'VpcVirtualRouter', + "NetworkACL": 'VpcVirtualRouter' + }, + }, + "vpc_offering": { + "name": 'VPC off', + "displaytext": 'VPC off', + "supportedservices": 'Dhcp,Dns,SourceNat,PortForwarding,Lb,UserData,StaticNat', + }, + "vpc": { + "name": "TestVPC", + "displaytext": "TestVPC", + "cidr": '10.0.0.1/24' + }, + "network": { + "name": "Test Network", + "displaytext": "Test Network", + "netmask": '255.255.255.0', + "limit": 5, + # Max networks allowed as per hypervisor + # Xenserver -> 5, VMWare -> 9 + }, + "lbrule": { + "name": "SSH", + "alg": "leastconn", + # Algorithm used for load balancing + "privateport": 22, + "publicport": 2222, + "openfirewall": False, + "startport": 22, + "endport": 2222, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "natrule": { + "privateport": 22, + "publicport": 22, + "startport": 22, + "endport": 22, + "protocol": "TCP", + "cidrlist": '0.0.0.0/0', + }, + "fw_rule": { + "startport": 1, + "endport": 6000, + "cidr": '0.0.0.0/0', + # Any network (For creating FW rule) + "protocol": "TCP" + }, + "http_rule": { + "startport": 80, + "endport": 80, + "cidrlist": '0.0.0.0/0', + "protocol": "ICMP" + }, + "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', + }, + "ostype": 'CentOS 5.3 (64-bit)', + # Cent OS 5.3 (64 bit) + "sleep": 60, + "timeout": 10, + "mode": 'advanced' + } + + +class TestVMDeployVPC(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + cls.api_client = super( + TestVMDeployVPC, + 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["ostype"] + ) + 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.vpc_off = VpcOffering.create( + cls.api_client, + cls.services["vpc_offering"] + ) + cls.vpc_off.update(cls.api_client, state='Enabled') + cls._cleanup = [ + cls.service_offering, + cls.vpc_off + ] + return + + @classmethod + def tearDownClass(cls): + try: + #Cleanup resources used + cleanup_resources(cls.api_client, cls._cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def setUp(self): + self.apiclient = self.testClient.getApiClient() + self.dbclient = self.testClient.getDbConnection() + self.account = Account.create( + self.apiclient, + self.services["account"], + admin=True, + domainid=self.domain.id + ) + self.cleanup = [self.account] + return + + def tearDown(self): + try: + #Clean up, terminate the created network offerings + cleanup_resources(self.apiclient, self.cleanup) + wait_for_cleanup(self.apiclient, [ + "network.gc.interval", + "network.gc.wait"]) + + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def validate_vpc_offering(self, vpc_offering): + """Validates the VPC offering""" + + self.debug("Check if the VPC offering is created successfully?") + vpc_offs = VpcOffering.list( + self.apiclient, + id=vpc_offering.id + ) + self.assertEqual( + isinstance(vpc_offs, list), + True, + "List VPC offerings should return a valid list" + ) + self.assertEqual( + vpc_offering.name, + vpc_offs[0].name, + "Name of the VPC offering should match with listVPCOff data" + ) + self.debug( + "VPC offering is created successfully - %s" % + vpc_offering.name) + return + + def validate_vpc_network(self, network, state=None): + """Validates the VPC network""" + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=network.id + ) + self.assertEqual( + isinstance(vpc_networks, list), + True, + "List VPC network should return a valid list" + ) + self.assertEqual( + network.name, + vpc_networks[0].name, + "Name of the VPC network should match with listVPC data" + ) + if state: + self.assertEqual( + vpc_networks[0].state, + state, + "VPC state should be '%s'" % state + ) + self.debug("VPC network validated - %s" % network.name) + return + + @attr(tags=["advanced", "intervlan"]) + def test_01_deploy_vms_in_network(self): + """ Test deploy VMs in VPC networks + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a network offering with guest type=Isolated that has all + # the supported Services(Vpn,dhcpdns,UserData, SourceNat,Static NAT + # and PF,LB,NetworkAcl ) provided by VPCVR and conserver mode is ON + # 3. Create a network - N1 using the network offering created in step2 + # as part of this VPC. + # 4. Create a network - N2 using a network offering similar to the one + # created in step2 but without Lb services enabled,as part of VPC + # 5. Create a network - N3 using the network offering similar to one + # created in step2 but without Lb services , as part of this VPC + # 6. Deploy few vms in all the 3 networks + # Steps: + # 1. Delete the 1st network + # 2. Vms that are part of other network should still be accessible + # and in "Running" state. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + nw_off_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + nw_off_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.3.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_3.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_3.name) + vm_3 = 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(network_3.id)] + ) + self.debug("Deployed VM in network: %s" % network_3.id) + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + self.debug("Deleting the virtual machine in network1: %s" % + network_1.name) + try: + vm_1.delete(self.apiclient) + except Exception as e: + raise Exception("Failed to delete Virtual machine: %s" % e) + + # Wait for expunge interval to cleanup VM + wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) + + # wait for network.gc to ensure that routers are deleted + wait_for_cleanup( + self.apiclient, + ["network.gc.interval", "network.gc.wait"] + ) + + self.debug("Deleting the network: %s" % network_1.name) + try: + network_1.delete(self.apiclient) + except Exception as e: + self.fail("Failed to deleted network: %s" % e) + + self.debug("After deleting first network other VMs" + + "should still be accessible") + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + state="Running", + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + self.assertEqual( + len(vms), + 2, + "Only 2 VMs should be in running state as first nw is deleted" + ) + + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_02_deploy_vms_delete_network(self): + """ Test deploy VMs in VPC networks and delete one of the network + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a network offering with guest type=Isolated that has all + # the supported Services(Vpn,dhcpdns,UserData, SourceNat,Static NAT + # and PF,LB,NetworkAcl ) provided by VPCVR and conserver mode is ON + # 3. Create a network - N1 using the network offering created in step2 + # as part of this VPC. + # 4. Create a network - N2 using a network offering similar to the one + # created in step2 but without Lb services enabled,as part of VPC + # 5. Create a network - N3 using the network offering similar to one + # created in step2 but without Lb services , as part of this VPC + # 6. Deploy few vms in all the 3 networks + # Steps: + # 1. Delete the 2nd network + # 2. Vms that are part of other network should still be accessible + # and in "Running" state. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + nw_off_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + nw_off_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.3.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_3.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_3.name) + vm_3 = 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(network_3.id)] + ) + self.debug("Deployed VM in network: %s" % network_3.id) + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + self.debug("Finding the VPC virtual router for network: %s" % + network_2.name) + routers = Router.list( + self.apiclient, + networkid=network_2.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should retirn a valid router for network2" + ) + router = routers[0] + + self.debug("Deleting the virtual machine in network1: %s" % + network_2.name) + try: + vm_2.delete(self.apiclient) + except Exception as e: + raise Exception("Failed to delete Virtual machine: %s" % e) + + # Wait for expunge interval to cleanup VM + wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) + + # wait for network.gc to ensure that routers are deleted + wait_for_cleanup( + self.apiclient, + ["network.gc.interval", "network.gc.wait"] + ) + + self.debug("Deleting the network: %s" % network_2.name) + try: + network_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to deleted network: %s" % e) + + self.debug("Restarting the VPCVR: %s" % router.name) + cmd = rebootRouter.rebootRouterCmd() + cmd.id = router.id + self.apiclient.rebootRouter(cmd) + + self.debug("Check status of router after reboot") + routers = Router.list( + self.apiclient, + id=router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should retirn a valid router for network2" + ) + router = routers[0] + self.assertEqual( + router.state, + "Running", + "Router state should be running after reboot" + ) + + self.debug("After deleting first network other VMs" + + "should still be accessible") + + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + state="Running", + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + self.assertEqual( + len(vms), + 2, + "Only 2 VMs should be in running state as first nw is deleted" + ) + + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_03_deploy_vms_delete_add_network(self): + """ Test deploy VMs, delete one of the network and add another one + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a network offering with guest type=Isolated that has all + # the supported Services(Vpn,dhcpdns,UserData, SourceNat,Static NAT + # and PF,LB,NetworkAcl ) provided by VPCVR and conserver mode is ON + # 3. Create a network - N1 using the network offering created in step2 + # as part of this VPC. + # 4. Create a network - N2 using a network offering similar to the one + # created in step2 but without Lb services enabled,as part of VPC + # 5. Create a network - N3 using the network offering similar to one + # created in step2 but without Lb services , as part of this VPC + # 6. Deploy few vms in all the 3 networks + # Steps: + # 1. Delete the 1st network + # 2. Add another network in VPC and deploy VM in that network + # 2. Vms that are part of other network should still be accessible + # and in "Running" state. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + nw_off_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + nw_off_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.3.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_3.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_3.name) + vm_3 = 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(network_3.id)] + ) + self.debug("Deployed VM in network: %s" % network_3.id) + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + self.debug("Finding the VPC virtual router for network: %s" % + network_2.name) + routers = Router.list( + self.apiclient, + networkid=network_2.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should retirn a valid router for network2" + ) + router = routers[0] + + self.debug("Deleting the virtual machine in network1: %s" % + network_1.name) + try: + vm_1.delete(self.apiclient) + except Exception as e: + raise Exception("Failed to delete Virtual machine: %s" % e) + + # Wait for expunge interval to cleanup VM + wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) + + # wait for network.gc to ensure that routers are deleted + wait_for_cleanup( + self.apiclient, + ["network.gc.interval", "network.gc.wait"] + ) + + self.debug("Deleting the network: %s" % network_1.name) + try: + network_1.delete(self.apiclient) + except Exception as e: + self.fail("Failed to deleted network: %s" % e) + + self.debug("Check if the network is deleted or not?") + networks = Network.list( + self.apiclient, + id=network_1.id, + listall=True + ) + + self.assertEqual( + networks, + None, + "ListNetwork response should be empty as network is deleted" + ) + + self.debug("Create a new netowrk in VPC: %s" % vpc.name) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + + network_4 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.4.1', + vpcid=vpc.id + ) + + self.debug("deploying VMs in network: %s" % network_4.name) + # Spawn an instance in that network + vm_4 = 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(network_4.id)] + ) + self.debug("Deployed VM in network: %s" % network_4.id) + + self.debug("After deleting first network other VMs" + + "should still be accessible") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + state="Running", + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + self.assertEqual( + len(vms), + 3, + "Only 2 VMs should be in running state as first nw is deleted" + ) + + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_04_deploy_vms_delete_add_network_noLb(self): + """ Test deploy VMs, delete one network without LB and add another one + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Create a network offering with guest type=Isolated that has all + # the supported Services(Vpn,dhcpdns,UserData, SourceNat,Static NAT + # and PF,LB,NetworkAcl ) provided by VPCVR and conserver mode is ON + # 3. Create a network - N1 using the network offering created in step2 + # as part of this VPC. + # 4. Create a network - N2 using a network offering similar to the one + # created in step2 but without Lb services enabled,as part of VPC + # 5. Create a network - N3 using the network offering similar to one + # created in step2 but without Lb services , as part of this VPC + # 6. Deploy few vms in all the 3 networks + # Steps: + # 1. Delete the 2nd network + # 2. Add another network in VPC and deploy VM in that network + # 2. Vms that are part of other network should still be accessible + # and in "Running" state. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + nw_off_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + nw_off_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_3 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.3.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_3.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_3.name) + vm_3 = 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(network_3.id)] + ) + self.debug("Deployed VM in network: %s" % network_3.id) + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + self.debug("Finding the VPC virtual router for network: %s" % + network_2.name) + + routers = Router.list( + self.apiclient, + networkid=network_2.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should retirn a valid router for network2" + ) + router = routers[0] + + self.debug("Deleting the virtual machine in network1: %s" % + network_1.name) + try: + vm_1.delete(self.apiclient) + except Exception as e: + raise Exception("Failed to delete Virtual machine: %s" % e) + + # Wait for expunge interval to cleanup VM + wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) + + # wait for network.gc to ensure that routers are deleted + wait_for_cleanup( + self.apiclient, + ["network.gc.interval", "network.gc.wait"] + ) + + self.debug("Deleting the network: %s" % network_1.name) + try: + network_1.delete(self.apiclient) + except Exception as e: + self.fail("Failed to deleted network: %s" % e) + + self.debug("Check if the network is deleted or not?") + networks = Network.list( + self.apiclient, + id=network_1.id, + listall=True + ) + + self.assertEqual( + networks, + None, + "ListNetwork response should be empty as network is deleted" + ) + + self.debug("Create a new netowrk in VPC: %s" % vpc.name) + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + + network_4 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.4.1', + vpcid=vpc.id + ) + + self.debug("deploying VMs in network: %s" % network_4.name) + # Spawn an instance in that network + vm_4 = 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(network_4.id)] + ) + self.debug("Deployed VM in network: %s" % network_4.id) + + self.debug("Restarting the VPCVR: %s" % router.name) + cmd = rebootRouter.rebootRouterCmd() + cmd.id = router.id + self.apiclient.rebootRouter(cmd) + + self.debug("Check status of router after reboot") + routers = Router.list( + self.apiclient, + id=router.id, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers should retirn a valid router for network2" + ) + router = routers[0] + self.assertEqual( + router.state, + "Running", + "Router state should be running after reboot" + ) + + self.debug("After deleting first network other VMs" + + "should still be accessible") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + state="Running", + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + self.assertEqual( + len(vms), + 3, + "Only 2 VMs should be in running state as first nw is deleted" + ) + + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_05_create_network_max_limit(self): + """ Test create networks in VPC upto maximum limit for hypervisor + """ + + # Validate the following + # 1. Create a VPC and add maximum # of supported networks to the VPC. + # 2. Deploy Vms in each of these networks. + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Empty list to store all of the network and VM elements + networks = [] + vms = [] + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.0.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + nw_off_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + nw_off_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + configs = Configurations.list( + self.apiclient, + name='vpc.max.networks', + listall=True + ) + if not isinstance(configs, list): + raise Exception("Failed to find max network allowed for VPC") + + self.services["network"]["limit"] = int(configs[0].value) + + # Create networks till max limit of hypervisor + for i in range(self.services["network"]["limit"] - 1): + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + gateway = '10.1.' + str(i + 1) + '.1' + self.debug("Gateway for new network: %s" % gateway) + + network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network.id) + networks.append(network) + + self.debug( + "Trying to create one more network than limit in VPC: %s" % vpc.name) + gateway = '10.1.' + str(self.services["network"]["limit"]) + '.1' + + with self.assertRaises(Exception): + Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + + self.debug("Deleting one of the existing networks") + try: + network_1.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete network: %s - %s" % + (network_1.name, e)) + + self.debug("Creating a new network in VPC: %s" % vpc.name) + network = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway=gateway, + vpcid=vpc.id + ) + self.debug("Created a new network: %s" % network.name) + networks.append(network) + + self.debug("Deploying VMs in each of the networks created in VPC") + for network in networks: + self.debug("deploying VMs in network: %s" % network.name) + # Spawn an instance in that network + vm = 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(network.id)] + ) + self.debug("Deployed VM in network: %s" % network.id) + vms.append(vm) + + self.debug("Check if VM deployed successfully or not?") + list_vms = VirtualMachine.list( + self.apiclient, + id=vm.id, + listall=True + ) + self.assertEqual( + isinstance(list_vms, list), + True, + "List VMs should return a valid response" + ) + self.assertEqual( + list_vms[0].state, + "Running", + "Vm should be in running state" + ) + return + + @attr(tags=["advanced", "intervlan"]) + def test_06_delete_network_vm_running(self): + """ Test delete network having running instances in VPC + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2. + # 4. Attempt to delete network1. Delete network should fail. + # 5. Destroy all Vms in network1 & wait for the Vms to get expunged + # 6. Attempt to delete network1. Delete network shall succeed + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + nw_off_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + nw_off_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed another VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_3 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + vm_4 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + self.debug("Trying to delete network: %s" % network_1.name) + with self.assertRaises(Exception): + network_1.delete(self.apiclient) + self.debug("Delete netwpork failed as there are running instances") + + self.debug("Destroying all the instances in network1: %s" % + network_1.name) + try: + vm_1.delete(self.apiclient) + vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy virtual machines - %s" % e) + + # Wait for expunge interval to cleanup VM + wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) + + # wait for network.gc to ensure that routers are deleted + wait_for_cleanup( + self.apiclient, + ["network.gc.interval", "network.gc.wait"] + ) + + self.debug("List virtual machines to ensure that VMs are expunged") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=network_1.id, + listall=True + ) + self.assertEqual( + vms, + None, + "List Vms shall return an empty response" + ) + self.debug("Trying to delete network again now (should succeed)..") + try: + network_1.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete network: %s, %s" % (network_1.name, e)) + + self.debug("Destroying all the instances in network1: %s" % + network_2.name) + try: + vm_3.delete(self.apiclient) + vm_4.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy virtual machines - %s" % e) + + # Wait for expunge interval to cleanup VM + wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) + + # wait for network.gc to ensure that routers are deleted + wait_for_cleanup( + self.apiclient, + ["network.gc.interval", "network.gc.wait"]) + + self.debug("List virtual machines to ensure that VMs are expunged") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=network_2.id, + listall=True + ) + self.assertEqual( + vms, + None, + "List Vms shall return an empty response" + ) + self.debug("Trying to delete network again now (should succeed)..") + try: + network_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete network: %s, %s" % (network_2.name, e)) + + self.debug("Virtual router should be in running state") + routers = Router.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(routers, list), + True, + "List routers shall not return an emptty response" + ) + for router in routers: + self.assertEqual( + router.state, + "Running", + "Router state should be running" + ) + return + + @attr(tags=["advanced", "intervlan"]) + @unittest.skip("Not tested") + def test_07_delete_network_with_rules(self): + """ Test delete network that has PF/staticNat/LB rules/Network Acl + """ + + # Validate the following + # 1. Create a VPC with cidr - 10.1.1.1/16 + # 2. Add network1(10.1.1.1/24) and network2(10.1.2.1/24) to this VPC. + # 3. Deploy vm1 and vm2 in network1 and vm3 and vm4 in network2. + # 4. Create a PF /Static Nat/LB rule for vms in network1. + # 5. Create a PF /Static Nat/LB rule for vms in network2. + # 6. Create ingress network ACL for allowing all the above rules from + # public ip range on network1 and network2. + # 7. Create egress network ACL for network1 and network2 to access + # google.com. + # 8. Create a private gateway for this VPC and add a static route to + # this gateway + # 9. Create a VPN gateway for this VPC and add a static route to this + # gateway. + # 10. Make sure that all the PF,LB, Static NAT rules work as expected + # 11. Make sure that we are able to access google from all user Vms + # 12. Make sure that the newly added private gateway's and VPN + # gateway's static routes work as expected. + # Steps: + # 1. Delete the 1st network. + # 2. Delete account + # Validations: + # 1. As part of network deletion all the resources attached with + # network should get deleted. All other VMs and rules shall work as + # expected + # 2. All the resources associated with account should be deleted + + # Remove account from cleanup list, we will delete it at end of test + self.cleanup = [] + + self.debug("Creating a VPC offering..") + vpc_off = VpcOffering.create( + self.apiclient, + self.services["vpc_offering"] + ) + + self._cleanup.append(vpc_off) + self.validate_vpc_offering(vpc_off) + + self.debug("Enabling the VPC offering created") + vpc_off.update(self.apiclient, state='Enabled') + + self.debug("creating a VPC network in the account: %s" % + self.account.account.name) + self.services["vpc"]["cidr"] = '10.1.1.1/16' + vpc = VPC.create( + self.apiclient, + self.services["vpc"], + vpcofferingid=vpc_off.id, + zoneid=self.zone.id, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.validate_vpc_network(vpc) + + nw_off = NetworkOffering.create( + self.apiclient, + self.services["network_offering"], + conservemode=False + ) + # Enable Network offering + nw_off.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % nw_off.id) + network_1 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off.id, + zoneid=self.zone.id, + gateway='10.1.1.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_1.id) + + nw_off_no_lb = NetworkOffering.create( + self.apiclient, + self.services["network_offering_no_lb"], + conservemode=False + ) + # Enable Network offering + nw_off_no_lb.update(self.apiclient, state='Enabled') + self._cleanup.append(nw_off) + + # Creating network using the network offering created + self.debug("Creating network with network offering: %s" % + nw_off_no_lb.id) + network_2 = Network.create( + self.apiclient, + self.services["network"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + networkofferingid=nw_off_no_lb.id, + zoneid=self.zone.id, + gateway='10.1.2.1', + vpcid=vpc.id + ) + self.debug("Created network with ID: %s" % network_2.id) + + self.debug("deploying VMs in network: %s" % network_1.name) + # Spawn an instance in that network + vm_1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed VM in network: %s" % network_1.id) + vm_2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + accountid=self.account.account.name, + domainid=self.account.account.domainid, + serviceofferingid=self.service_offering.id, + networkids=[str(network_1.id)] + ) + self.debug("Deployed another VM in network: %s" % network_1.id) + + self.debug("deploying VMs in network: %s" % network_2.name) + # Spawn an instance in that network + vm_3 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + vm_4 = 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(network_2.id)] + ) + self.debug("Deployed VM in network: %s" % network_2.id) + + self.debug("Check if deployed VMs are in running state?") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + listall=True + ) + self.assertEqual( + isinstance(vms, list), + True, + "List VMs should return a valid response" + ) + for vm in vms: + self.debug("VM name: %s, VM state: %s" % (vm.name, vm.state)) + self.assertEqual( + vm.state, + "Running", + "Vm state should be running for each VM deployed" + ) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_1 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip.ipaddress.ipaddress, + network_1.id + )) + + nat_rule = NATRule.create( + self.apiclient, + vm_1, + self.services["natrule"], + ipaddressid=public_ip_1.ipaddress.id, + openfirewall=False, + networkid=network_1.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + self.debug("Associating public IP for network: %s" % network_1.name) + public_ip_2 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_1.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_2.ipaddress.ipaddress, + network_1.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_2.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_2.ipaddress.id, + virtualmachineid=vm_2.id, + networkid=network_1.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_2.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_2.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network_1.id, + listall=True, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_2.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_3 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_2.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_3.ipaddress.ipaddress, + network_2.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_3.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_3.ipaddress.id, + accountid=self.account.account.name, + networkid=network_2.id, + vpcid=vpc.id, + domainid=self.account.account.domainid + ) + + self.debug("Adding virtual machines %s and %s to LB rule" % ( + vm_3.name, vm_4.name)) + lb_rule.assign(self.apiclient, [vm_3, vm_4]) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + nwacl_lb = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + + self.debug( + "Adding Egress rules to network to allow access to internet") + nwacl_internet_1 = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + nwacl_internet_2 = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + + self.debug("Creating private gateway in VPC: %s" % vpc.name) + private_gateway = PrivateGateway.create( + self.apiclient, + gateway='10.1.3.1', + ipaddress='10.1.3.2', + netmask='255.255.255.0', + vlan=678, + vpcid=vpc.id + ) + self.debug("Check if the private gateway created successfully?") + gateways = PrivateGateway.list( + self.apiclient, + id=private_gateway.id, + listall=True + ) + self.assertEqaul( + isinstance(gateways, list), + True, + "List private gateways should return a valid response" + ) + self.debug("Creating static route for this gateway") + static_route = StaticRoute.create( + self.apiclient, + cidr='10.1.3.0/24', + gatewayid=private_gateway.id + ) + self.debug("Check if the static route created successfully?") + static_routes = StaticRoute.list( + self.apiclient, + id=static_route.id, + listall=True + ) + self.assertEqaul( + isinstance(static_routes, list), + True, + "List static route should return a valid response" + ) + + self.debug("Associating public IP for network: %s" % network_2.name) + public_ip_5 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_2.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_5.ipaddress.ipaddress, + network_2.id + )) + + nat_rule = NATRule.create( + self.apiclient, + vm_3, + self.services["natrule"], + ipaddressid=public_ip_5.ipaddress.id, + openfirewall=False, + networkid=network_2.id, + vpcid=vpc.id + ) + + self.debug("Adding NetwrokACl rules to make NAT rule accessible") + nwacl_nat = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["natrule"], + traffictype='Ingress' + ) + + self.debug("Associating public IP for network: %s" % network_2.name) + public_ip_6 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_2.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_6.ipaddress.ipaddress, + network_2.id + )) + self.debug("Enabling static NAT for IP: %s" % + public_ip_6.ipaddress.ipaddress) + try: + StaticNATRule.enable( + self.apiclient, + ipaddressid=public_ip_6.ipaddress.id, + virtualmachineid=vm_3.id, + networkid=network_2.id + ) + self.debug("Static NAT enabled for IP: %s" % + public_ip_6.ipaddress.ipaddress) + except Exception as e: + self.fail("Failed to enable static NAT on IP: %s - %s" % ( + public_ip_6.ipaddress.ipaddress, e)) + + public_ips = PublicIPAddress.list( + self.apiclient, + networkid=network_2.id, + listall=True, + isstaticnat=True, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + isinstance(public_ips, list), + True, + "List public Ip for network should list the Ip addr" + ) + self.assertEqual( + public_ips[0].ipaddress, + public_ip_6.ipaddress.ipaddress, + "List public Ip for network should list the Ip addr" + ) + + self.debug("Associating public IP for network: %s" % vpc.name) + public_ip_7 = PublicIPAddress.create( + self.apiclient, + accountid=self.account.account.name, + zoneid=self.zone.id, + domainid=self.account.account.domainid, + networkid=network_2.id, + vpcid=vpc.id + ) + self.debug("Associated %s with network %s" % ( + public_ip_7.ipaddress.ipaddress, + network_2.id + )) + + self.debug("Creating LB rule for IP address: %s" % + public_ip_7.ipaddress.ipaddress) + + lb_rule = LoadBalancerRule.create( + self.apiclient, + self.services["lbrule"], + ipaddressid=public_ip_7.ipaddress.id, + accountid=self.account.account.name, + networkid=network_2.id, + vpcid=vpc.id, + domainid=self.account.account.domainid + ) + + self.debug("Adding virtual machines %s and %s to LB rule" % ( + vm_3.name, vm_4.name)) + lb_rule.assign(self.apiclient, [vm_3, vm_4]) + + self.debug("Adding NetwrokACl rules to make PF and LB accessible") + nwacl_lb = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["lbrule"], + traffictype='Ingress' + ) + + self.debug( + "Adding Egress rules to network to allow access to internet") + nwacl_internet_3 = NetworkACL.create( + self.apiclient, + networkid=network_1.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + nwacl_internet_4 = NetworkACL.create( + self.apiclient, + networkid=network_2.id, + services=self.services["http_rule"], + traffictype='Egress' + ) + + self.debug("Creating private gateway in VPC: %s" % vpc.name) + private_gateway = PrivateGateway.create( + self.apiclient, + gateway='10.1.4.1', + ipaddress='10.1.4.2', + netmask='255.255.255.0', + vlan=678, + vpcid=vpc.id + ) + self.debug("Check if the private gateway created successfully?") + gateways = PrivateGateway.list( + self.apiclient, + id=private_gateway.id, + listall=True + ) + self.assertEqaul( + isinstance(gateways, list), + True, + "List private gateways should return a valid response" + ) + self.debug("Creating static route for this gateway") + static_route = StaticRoute.create( + self.apiclient, + cidr='10.1.4.0/24', + gatewayid=private_gateway.id + ) + self.debug("Check if the static route created successfully?") + static_routes = StaticRoute.list( + self.apiclient, + id=static_route.id, + listall=True + ) + self.assertEqaul( + isinstance(static_routes, list), + True, + "List static route should return a valid response" + ) + + self.debug("Restaring the network 1 (%s) with cleanup=True" % + network_1.name) + try: + network_1.restart(self.apiclient, cleanup=True) + except Exception as e: + self.fail( + "Failed to restart network: %s, %s" % + (network_1.name, e)) + + self.debug("Checking if we can SSH into VM_1?") + try: + ssh_1 = vm_1.get_ssh_client( + ipaddress=public_ip_1.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_1.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_1.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_2?") + try: + ssh_2 = vm_2.get_ssh_client( + ipaddress=public_ip_2.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_2.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_2.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM using LB rule?") + try: + ssh_3 = vm_3.get_ssh_client( + ipaddress=public_ip_3.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_3.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_3.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Trying to delete network: %s" % network_1.name) + with self.assertRaises(Exception): + network_1.delete(self.apiclient) + self.debug("Delete netwpork failed as there are running instances") + + self.debug("Destroying all the instances in network1: %s" % + network_1.name) + try: + vm_1.delete(self.apiclient) + vm_2.delete(self.apiclient) + except Exception as e: + self.fail("Failed to destroy virtual machines - %s" % e) + + # Wait for expunge interval to cleanup VM + wait_for_cleanup(self.apiclient, ["expunge.delay", "expunge.interval"]) + + # wait for network.gc to ensure that routers are deleted + wait_for_cleanup( + self.apiclient, + ["network.gc.interval", "network.gc.wait"] + ) + + self.debug("List virtual machines to ensure that VMs are expunged") + vms = VirtualMachine.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid, + networkid=network_1.id, + listall=True + ) + self.assertEqual( + vms, + None, + "List Vms shall return an empty response" + ) + self.debug("Trying to delete network again now (should succeed)..") + try: + network_1.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete network: %s, %s" % (network_1.name, e)) + + self.debug("Checking if we can SSH into VM_3?") + try: + ssh_4 = vm_3.get_ssh_client( + ipaddress=public_ip_5.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + # Ping to outsite world + res = ssh_5.execute("ping -c 1 www.google.com") + # res = 64 bytes from maa03s17-in-f20.1e100.net (74.125.236.212): + # icmp_req=1 ttl=57 time=25.9 ms + # --- www.l.google.com ping statistics --- + # 1 packets transmitted, 1 received, 0% packet loss, time 0ms + # rtt min/avg/max/mdev = 25.970/25.970/25.970/0.000 ms + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_5.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM_2?") + try: + ssh_5 = vm_3.get_ssh_client( + ipaddress=public_ip_6.ipaddress.ipaddress, + reconnect=True, + port=self.services["natrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_5.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_6.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Checking if we can SSH into VM using LB rule?") + try: + ssh_6 = vm_3.get_ssh_client( + ipaddress=public_ip_7.ipaddress.ipaddress, + reconnect=True, + port=self.services["lbrule"]["publicport"] + ) + self.debug("SSH into VM is successfully") + + self.debug("Verifying if we can ping to outside world from VM?") + res = ssh_6.execute("ping -c 1 www.google.com") + except Exception as e: + self.fail("Failed to SSH into VM - %s, %s" % + (public_ip_7.ipaddress.ipaddress, e)) + + result = str(res) + self.assertEqual( + result.count("1 received"), + 1, + "Ping to outside world from VM should be successful" + ) + + self.debug("Deleting the account..") + try: + self.account.delete(self.apiclient) + except Exception as e: + self.fail("Failed to delete account: %s" % + self.account.account.name) + wait_for_cleanup(self.apiclient, ["account.cleanup.interval"]) + + self.debug("Check if the VPC network is created successfully?") + vpc_networks = VPC.list( + self.apiclient, + id=vpc.id + ) + self.assertEqual( + vpc_networks, + None, + "List VPC network should not return a valid list" + ) + networks = Network.list( + self.apiclient, + account=self.account.account.name, + domainid=self.account.account.domainid + ) + self.assertEqual( + networks, + None, + "List networks shall not return any response" + ) + return + diff --git a/test/integration/smoke/test_deploy_vm.py b/test/integration/smoke/test_deploy_vm.py new file mode 100644 index 00000000000..5c8e0636cff --- /dev/null +++ b/test/integration/smoke/test_deploy_vm.py @@ -0,0 +1,153 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +#Test from the Marvin - Testing in Python wiki + +#All tests inherit from cloudstackTestCase +from marvin.cloudstackTestCase import cloudstackTestCase + +#Import Integration Libraries + +#base - contains all resources as entities and defines create, delete, list operations on them +from marvin.integration.lib.base import Account, VirtualMachine, ServiceOffering + +#utils - utility classes for common cleanup, external library wrappers etc +from marvin.integration.lib.utils import cleanup_resources + +#common - commonly used methods for all tests are listed here +from marvin.integration.lib.common import get_zone, get_domain, get_template + +class TestData(object): + """Test data object that is required to create resources + """ + def __init__(self): + self.testdata = { + #data to create an account + "account": { + "email": "test@test.com", + "firstname": "Test", + "lastname": "User", + "username": "test", + "password": "password", + }, + #data reqd for virtual machine creation + "virtual_machine" : { + "name" : "testvm", + "displayname" : "Test VM", + }, + #small service offering + "service_offering": { + "small": { + "name": "Small Instance", + "displaytext": "Small Instance", + "cpunumber": 1, + "cpuspeed": 100, + "memory": 256, + }, + }, + "ostype": 'CentOS 5.3 (64-bit)', + } + + +class TestDeployVM(cloudstackTestCase): + """Test deploy a VM into a user account + """ + + def setUp(self): + self.testdata = TestData().testdata + self.apiclient = self.testClient.getApiClient() + + # Get Zone, Domain and Default Built-in template + self.domain = get_domain(self.apiclient, self.testdata) + self.zone = get_zone(self.apiclient, self.testdata) + self.testdata["mode"] = self.zone.networktype + self.template = get_template(self.apiclient, self.zone.id, self.testdata["ostype"]) + + #create a user account + self.account = Account.create( + self.apiclient, + self.testdata["account"], + domainid=self.domain.id + ) + #create a service offering + self.service_offering = ServiceOffering.create( + self.apiclient, + self.testdata["service_offering"]["small"] + ) + #build cleanup list + self.cleanup = [ + self.service_offering, + self.account + ] + + def test_deploy_vm(self): + """Test Deploy Virtual Machine + + # Validate the following: + # 1. Virtual Machine is accessible via SSH + # 2. listVirtualMachines returns accurate information + """ + self.virtual_machine = VirtualMachine.create( + self.apiclient, + self.testdata["virtual_machine"], + accountid=self.account.name, + zoneid=self.zone.id, + domainid=self.account.domainid, + serviceofferingid=self.service_offering.id, + templateid=self.template.id + ) + + list_vms = VirtualMachine.list(self.apiclient, id=self.virtual_machine.id) + + self.debug( + "Verify listVirtualMachines response for virtual machine: %s"\ + % self.virtual_machine.id + ) + + self.assertEqual( + isinstance(list_vms, list), + True, + "List VM response was not a valid list" + ) + self.assertNotEqual( + len(list_vms), + 0, + "List VM response was empty" + ) + + vm = list_vms[0] + self.assertEqual( + vm.id, + self.virtual_machine.id, + "Virtual Machine ids do not match" + ) + self.assertEqual( + vm.name, + self.virtual_machine.name, + "Virtual Machine names do not match" + ) + self.assertEqual( + vm.state, + "Running", + msg="VM is not in Running state" + ) + + def tearDown(self): + try: + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + self.debug("Warning! Exception in tearDown: %s" % e) \ No newline at end of file diff --git a/tools/marvin/marvin/sandbox/advanced/sandbox.cfg b/tools/marvin/marvin/sandbox/advanced/sandbox.cfg deleted file mode 100644 index 01a84730dad..00000000000 --- a/tools/marvin/marvin/sandbox/advanced/sandbox.cfg +++ /dev/null @@ -1,209 +0,0 @@ -{ - "zones": [ - { - "name": "Sandbox-Simulator", - "guestcidraddress": "10.1.1.0/24", - "dns1": "10.147.28.6", - "physical_networks": [ - { - "providers": [ - { - "broadcastdomainrange": "ZONE", - "name": "VirtualRouter" - }, - { - "broadcastdomainrange": "ZONE", - "name": "VpcVirtualRouter" - }, - { - "broadcastdomainrange": "ZONE", - "name": "InternalLb" - } - ], - "name": "Sandbox-pnet", - "tags": [ - "cloud-simulator-public" - ], - "broadcastdomainrange": "Zone", - "vlan": "675-679", - "traffictypes": [ - { - "typ": "Guest" - }, - { - "typ": "Management", - "simulator": "cloud-simulator-mgmt" - }, - { - "typ": "Public", - "simulator": "cloud-simulator-public" - } - ], - "isolationmethods": [ - "VLAN" - ] - }, - { - "providers": [ - { - "broadcastdomainrange": "ZONE", - "name": "VirtualRouter" - }, - { - "broadcastdomainrange": "ZONE", - "name": "VpcVirtualRouter" - }, - { - "broadcastdomainrange": "ZONE", - "name": "InternalLb" - } - ], - "name": "Sandbox-pnet2", - "tags": [ - "cloud-simulator-guest" - ], - "broadcastdomainrange": "Zone", - "vlan": "800-1000", - "traffictypes": [ - { - "typ": "Guest", - "simulator": "cloud-simulator-guest" - } - ], - "isolationmethods": [ - "VLAN" - ] - } - ], - "securitygroupenabled": "false", - "ipranges": [ - { - "startip": "10.147.31.150", - "endip": "10.147.31.159", - "netmask": "255.255.255.0", - "vlan": "31", - "gateway": "10.147.31.1" - } - ], - "networktype": "Advanced", - "pods": [ - { - "endip": "10.147.29.159", - "name": "POD0", - "startip": "10.147.29.150", - "netmask": "255.255.255.0", - "clusters": [ - { - "clustername": "C0", - "hypervisor": "Simulator", - "hosts": [ - { - "username": "root", - "url": "http://simulator0", - "password": "password" - } - ], - "clustertype": "CloudManaged", - "primaryStorages": [ - { - "url": "nfs://10.147.28.6:/export/home/sandbox/primary", - "name": "PS0" - } - ] - } - ], - "gateway": "10.147.29.1" - } - ], - "internaldns1": "10.147.28.6", - "secondaryStorages": [ - { - "url": "nfs://10.147.28.6:/export/home/sandbox/sstor" - } - ] - } - ], - "dbSvr": { - "dbSvr": "localhost", - "passwd": "cloud", - "db": "cloud", - "port": 3306, - "user": "cloud" - }, - "logger": [ - { - "name": "TestClient", - "file": "testclient.log" - }, - { - "name": "TestCase", - "file": "testcase.log" - } - ], - "globalConfig": [ - { - "name": "storage.cleanup.interval", - "value": "300" - }, - { - "name": "direct.agent.load.size", - "value": "1000" - }, - { - "name": "default.page.size", - "value": "10000" - }, - { - "name": "instance.name", - "value": "QA" - }, - { - "name": "workers", - "value": "10" - }, - { - "name": "vm.op.wait.interval", - "value": "5" - }, - { - "name": "account.cleanup.interval", - "value": "600" - }, - { - "name": "guest.domain.suffix", - "value": "sandbox.simulator" - }, - { - "name": "expunge.delay", - "value": "60" - }, - { - "name": "vm.allocation.algorithm", - "value": "random" - }, - { - "name": "expunge.interval", - "value": "60" - }, - { - "name": "expunge.workers", - "value": "3" - }, - { - "name": "secstorage.allowed.internal.sites", - "value": "10.147.28.0/24" - }, - { - "name": "check.pod.cidrs", - "value": "true" - } - ], - "mgtSvr": [ - { - "mgtSvrIp": "localhost", - "passwd": "password", - "user": "root", - "port": 8096 - } - ] -} \ No newline at end of file