From fe5ab4aa9186bcd8b38daef80f2f83794cef7a23 Mon Sep 17 00:00:00 2001 From: Ashutosh K Date: Sun, 23 Mar 2014 21:15:45 -0700 Subject: [PATCH] CLOUDSTACK-4840: Final set of test cases for Multiple IPs per NIC feature --- .../component/test_multiple_ips_per_nic.py | 442 +++++++++++++++++- tools/marvin/marvin/config/config.cfg | 10 +- tools/marvin/marvin/integration/lib/base.py | 13 +- 3 files changed, 459 insertions(+), 6 deletions(-) diff --git a/test/integration/component/test_multiple_ips_per_nic.py b/test/integration/component/test_multiple_ips_per_nic.py index dcbb453e7eb..486a7d36396 100644 --- a/test/integration/component/test_multiple_ips_per_nic.py +++ b/test/integration/component/test_multiple_ips_per_nic.py @@ -37,18 +37,21 @@ from marvin.integration.lib.base import (Account, PublicIPAddress, StaticNATRule, FireWallRule, - NATRule) + NATRule, + Router) from marvin.integration.lib.common import (get_domain, get_zone, get_template, get_free_vlan, setSharedNetworkParams, createEnabledNetworkOffering, - shouldTestBeSkipped) + shouldTestBeSkipped, + wait_for_cleanup) from nose.plugins.attrib import attr from marvin.codes import PASS, ISOLATED_NETWORK, VPC_NETWORK, SHARED_NETWORK, FAIL from ddt import ddt, data +import time def createNetwork(self, networkType): """Create a network of given type (isolated/shared/isolated in VPC)""" @@ -851,3 +854,438 @@ class TestNetworkRules(cloudstackTestCase): public_ip.delete(self.apiclient) return + +@ddt +class TestVmNetworkOperations(cloudstackTestCase): + """Test VM and Network operations with network rules created on secondary IP + """ + + @classmethod + def setUpClass(cls): + cloudstackTestClient = super(TestVmNetworkOperations,cls).getClsTestClient() + cls.api_client = cloudstackTestClient.getApiClient() + + # Fill services from the external config file + cls.services = cloudstackTestClient.getConfigParser().parsedDict + + # Get Zone, Domain and templates + cls.domain = get_domain(cls.api_client, cls.services) + cls.zone = get_zone(cls.api_client, cls.services) + cls.mode = str(cls.zone.networktype).lower() + 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] + cls.services["shared_network_offering"]["specifyVlan"] = "True" + cls.services["shared_network_offering"]["specifyIpRanges"] = "True" + + cls.shared_network_offering = CreateEnabledNetworkOffering(cls.api_client, cls.services["shared_network_offering"]) + cls._cleanup.append(cls.shared_network_offering) + + if cls.mode == "advanced": + cls.isolated_network_offering = CreateEnabledNetworkOffering(cls.api_client, cls.services["isolated_network_offering"]) + cls._cleanup.append(cls.isolated_network_offering) + cls.isolated_network_offering_vpc = CreateEnabledNetworkOffering(cls.api_client, cls.services["nw_offering_isolated_vpc"]) + cls._cleanup.append(cls.isolated_network_offering_vpc) + cls.vpc_off = VpcOffering.create(cls.api_client, cls.services["vpc_offering"]) + cls.vpc_off.update(cls.api_client, state='Enabled') + cls._cleanup.append(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.cleanup = [ ] + return + + def tearDown(self): + try: + # Clean up, terminate the resources created + cleanup_resources(self.apiclient, self.cleanup) + except Exception as e: + raise Exception("Warning: Exception during cleanup : %s" % e) + return + + def VerifyStaticNatForPublicIp(self, ipaddressid, natrulestatus): + """ List public IP and verify that NAT rule status for the IP is as desired """ + + publiciplist = PublicIPAddress.list(self.apiclient, id=ipaddressid, listall=True) + self.assertEqual(validateList(publiciplist)[0], PASS, "Public IP list validation failed") + self.assertEqual(publiciplist[0].isstaticnat, natrulestatus, "isstaticnat should be %s, it is %s" % + (natrulestatus, publiciplist[0].isstaticnat)) + + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_delete_vm(self, value): + """ Test delete VM and verify network rules are cleaned up""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Destroy the virtual machine + # 7. Verify that nat rule does not exist and static nat is not enabled for + # secondary IP + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + # Add secondary IPs to default NIC of VM + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + # Acquire public IP addresses in the network + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + # Create Firewall and natrule for 1st IP and static nat rule for 2nd IP + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + # Delete VM + virtual_machine.delete(self.apiclient) + + # Wait for VMs to expunge + wait_for_cleanup(self.api_client, ["expunge.delay", "expunge.interval"]) + + # Make sure the VM is expunged + retriesCount = 20 + while True: + vms = VirtualMachine.list(self.apiclient, id=virtual_machine.id) + if vms is None: + break + elif retriesCount == 0: + self.fail("Failed to expunge vm even after 20 minutes") + time.sleep(60) + retriesCount -= 1 + + # Try to list nat rule + with self.assertRaises(Exception): + NATRule.list(self.apiclient, id=natrule.id, listall=True) + + # Verify static nat rule is no longer enabled + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, False) + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_recover_vm(self, value): + """ Test recover VM operation with VM having secondary IPs""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Destroy the virtual machine and recover it + # 7. Verify that nat and static nat rules exist + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + virtual_machine.delete(self.apiclient) + virtual_machine.recover(self.apiclient) + + retriesCount = 10 + while True: + vms = VirtualMachine.list(self.apiclient, id=virtual_machine.id) + self.assertEqual(validateList(vms)[0], PASS, "vms list validation failed") + if str(vms[0].state).lower() == "stopped": + break + elif retriesCount == 0: + self.fail("Failed to recover vm even after 10 mins") + time.sleep(60) + retriesCount -= 1 + + natrules = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrules)[0], PASS, "nat rules validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_network_restart_cleanup_true(self, value): + """Test network restart (cleanup True) with VM having secondary IPs and related network rules""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Restart the network with cleanup option True + # 7. Verify that nat and static nat rules exist after network restart + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + network.restart(self.apiclient, cleanup=True) + + natrulelist = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrulelist)[0], PASS, "nat rules list validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_network_restart_cleanup_false(self, value): + """Test network restart (cleanup True) with VM having secondary IPs and related network rules""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Restart the network with cleanup option False + # 7. Verify that nat and static nat rules exist after network restart + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + network.restart(self.apiclient, cleanup=False) + + natrulelist = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrulelist)[0], PASS, "nat rules list validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + return + + @data(ISOLATED_NETWORK, SHARED_NETWORK, VPC_NETWORK) + @attr(tags=["advanced"]) + def test_reboot_router_VM(self, value): + """ Test reboot router and persistence of network rules""" + + # Steps: + # 1. Create Account and create network in it (isoalted/ shared/ vpc) + # 2. Deploy a VM in this network and account + # 3. Add 2 secondary IPs to the default nic of VM + # 4. Acquire 2 public IPs in the network + # 5. For 1st public IP create nat rule to 1st private IP, for 2nd public IP, create + # static nat rule to 2nd private IP + # 6. Reboot router VM + # 7. Verify that nat and static nat rules exist after router restart + + self.account = Account.create(self.apiclient,self.services["account"],domainid=self.domain.id) + self.cleanup.append(self.account) + + network = createNetwork(self, value) + + try: + virtual_machine = VirtualMachine.create(self.apiclient,self.services["virtual_machine"], + networkids=[network.id],serviceofferingid=self.service_offering.id, + accountid=self.account.name,domainid=self.account.domainid) + except Exception as e: + self.fail("vm creation failed: %s" % e) + + try: + ipaddress_1 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + ipaddress_2 = NIC.addIp(self.apiclient, id=virtual_machine.nic[0].id) + except Exception as e: + self.fail("Failed while adding secondary IP to NIC of vm %s" % virtual_machine.id) + + try: + public_ip_1 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + + public_ip_2 = PublicIPAddress.create(self.api_client,accountid=self.account.name, + zoneid=self.zone.id,domainid=self.account.domainid, + networkid=network.id, vpcid = network.vpcid if value == VPC_NETWORK else None) + except Exception as e: + self.fail("Exception while acquiring public ip address: %s" % e) + + if value != VPC_NETWORK: + FireWallRule.create(self.apiclient,ipaddressid=public_ip_1.ipaddress.id, + protocol='TCP', cidrlist=[self.services["fwrule"]["cidr"]], + startport=self.services["fwrule"]["startport"],endport=self.services["fwrule"]["endport"]) + + natrule = NATRule.create(self.api_client, virtual_machine, + self.services["natrule"],ipaddressid=public_ip_1.ipaddress.id, + networkid=network.id, vmguestip = ipaddress_1.ipaddress) + + StaticNATRule.enable(self.apiclient, public_ip_2.ipaddress.id, virtual_machine.id, + network.id, vmguestip=ipaddress_2.ipaddress) + + routers = Router.list(self.apiclient, networkid=network.id, listall=True) + self.assertEqual(validateList(routers)[0], PASS, "routers list validation failed") + + Router.reboot(self.apiclient, id=routers[0].id) + + natrulelist = NATRule.list(self.apiclient, id=natrule.id, listall=True) + self.assertEqual(validateList(natrulelist)[0], PASS, "nat rules list validation failed") + + self.VerifyStaticNatForPublicIp(public_ip_2.ipaddress.id, True) + return diff --git a/tools/marvin/marvin/config/config.cfg b/tools/marvin/marvin/config/config.cfg index 356a2911912..dfc426301b9 100644 --- a/tools/marvin/marvin/config/config.cfg +++ b/tools/marvin/marvin/config/config.cfg @@ -126,14 +126,20 @@ "name": "SharedNwOffering", "displaytext": "SharedNwOffering", "guestiptype": "Shared", - "supportedservices": "Dhcp,Dns,UserData", + "supportedservices": "Dhcp,Dns,SourceNat,PortForwarding,Vpn,Firewall,Lb,UserData,StaticNat", "specifyVlan" : "False", "specifyIpRanges" : "False", "traffictype": "GUEST", "serviceProviderList" : { "Dhcp": "VirtualRouter", "Dns": "VirtualRouter", - "UserData": "VirtualRouter" + "SourceNat": "VirtualRouter", + "PortForwarding": "VirtualRouter", + "Vpn": "VirtualRouter", + "Firewall": "VirtualRouter", + "Lb": "VirtualRouter", + "UserData": "VirtualRouter", + "StaticNat": "VirtualRouter" } }, "security_group" : { "name": "custom_Sec_Grp" }, diff --git a/tools/marvin/marvin/integration/lib/base.py b/tools/marvin/marvin/integration/lib/base.py index 775b289b149..9fbf9e64984 100755 --- a/tools/marvin/marvin/integration/lib/base.py +++ b/tools/marvin/marvin/integration/lib/base.py @@ -1236,7 +1236,8 @@ class NATRule: @classmethod def create(cls, apiclient, virtual_machine, services, ipaddressid=None, - projectid=None, openfirewall=False, networkid=None, vpcid=None): + projectid=None, openfirewall=False, networkid=None, vpcid=None, + vmguestip=None): """Create Port forwarding rule""" cmd = createPortForwardingRule.createPortForwardingRuleCmd() @@ -1265,6 +1266,10 @@ class NATRule: if vpcid: cmd.vpcid = vpcid + + if vmguestip: + cmd.vmguestip = vmguestip + return NATRule(apiclient.createPortForwardingRule(cmd).__dict__) def delete(self, apiclient): @@ -1331,7 +1336,8 @@ class StaticNATRule: return(apiclient.listIpForwardingRules(cmd)) @classmethod - def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None): + def enable(cls, apiclient, ipaddressid, virtualmachineid, networkid=None, + vmguestip=None): """Enables Static NAT rule""" cmd = enableStaticNat.enableStaticNatCmd() @@ -1339,6 +1345,9 @@ class StaticNATRule: cmd.virtualmachineid = virtualmachineid if networkid: cmd.networkid = networkid + + if vmguestip: + cmd.vmguestip = vmguestip apiclient.enableStaticNat(cmd) return