From 894413e362a588cc0612cfeac2b11617f4954eac Mon Sep 17 00:00:00 2001 From: Prasanna Santhanam Date: Tue, 14 May 2013 10:24:27 +0530 Subject: [PATCH] Marvin IP cleared tests for various cloudstack components One big blob of all the tests that were posted for IP clearance several months ago. IP clearance VOTE has passed on general@ Ref: http://markmail.org/thread/xareczan2kx4hhom RAT check passed. --- .../component/test_high_availability.py | 1080 ++++ .../component/test_host_high_availability.py | 814 +++ .../component/test_netscaler_configs.py | 3024 +++++++++ .../component/test_netscaler_lb.py | 2964 +++++++++ .../component/test_netscaler_lb_algo.py | 2031 ++++++ .../component/test_netscaler_lb_sticky.py | 1032 +++ .../component/test_netscaler_nw_off.py | 2370 +++++++ .../component/test_network_offering.py | 4 +- .../component/test_redundant_router.py | 5581 +++++++++++++++++ test/integration/component/test_regions.py | 1 - .../component/test_shared_networks.py | 2986 +++++++++ test/integration/component/test_stopped_vm.py | 2036 ++++++ test/integration/component/test_tags.py | 2325 +++++++ test/integration/component/test_vpc.py | 2725 ++++++++ .../component/test_vpc_host_maintenance.py | 891 +++ .../integration/component/test_vpc_network.py | 2587 ++++++++ .../component/test_vpc_network_lbrules.py | 1025 +++ .../component/test_vpc_network_pfrules.py | 876 +++ .../test_vpc_network_staticnatrule.py | 710 +++ .../component/test_vpc_offerings.py | 1201 ++++ .../integration/component/test_vpc_routers.py | 1398 +++++ .../component/test_vpc_vm_life_cycle.py | 3603 +++++++++++ .../component/test_vpc_vms_deployment.py | 2458 ++++++++ test/integration/smoke/test_deploy_vm.py | 153 + .../marvin/sandbox/advanced/sandbox.cfg | 209 - 25 files changed, 43872 insertions(+), 212 deletions(-) create mode 100644 test/integration/component/test_high_availability.py create mode 100644 test/integration/component/test_host_high_availability.py create mode 100644 test/integration/component/test_netscaler_configs.py create mode 100644 test/integration/component/test_netscaler_lb.py create mode 100644 test/integration/component/test_netscaler_lb_algo.py create mode 100644 test/integration/component/test_netscaler_lb_sticky.py create mode 100644 test/integration/component/test_netscaler_nw_off.py create mode 100644 test/integration/component/test_redundant_router.py create mode 100644 test/integration/component/test_shared_networks.py create mode 100644 test/integration/component/test_stopped_vm.py create mode 100644 test/integration/component/test_tags.py create mode 100644 test/integration/component/test_vpc.py create mode 100644 test/integration/component/test_vpc_host_maintenance.py create mode 100644 test/integration/component/test_vpc_network.py create mode 100644 test/integration/component/test_vpc_network_lbrules.py create mode 100644 test/integration/component/test_vpc_network_pfrules.py create mode 100644 test/integration/component/test_vpc_network_staticnatrule.py create mode 100644 test/integration/component/test_vpc_offerings.py create mode 100644 test/integration/component/test_vpc_routers.py create mode 100644 test/integration/component/test_vpc_vm_life_cycle.py create mode 100644 test/integration/component/test_vpc_vms_deployment.py create mode 100644 test/integration/smoke/test_deploy_vm.py delete mode 100644 tools/marvin/marvin/sandbox/advanced/sandbox.cfg 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