From f572c7ab74508366b3b2ccbb2c0e6eeaa872fd36 Mon Sep 17 00:00:00 2001 From: dahn Date: Fri, 6 May 2022 00:53:31 +0200 Subject: [PATCH] Gateways after Nic update on Shared Network tests (#6355) * initial code to set up test * validations in marvin test --- .../smoke/test_gateway_on_shared_networks.py | 241 ++++++++++++++++++ tools/marvin/marvin/lib/base.py | 13 +- 2 files changed, 250 insertions(+), 4 deletions(-) create mode 100644 test/integration/smoke/test_gateway_on_shared_networks.py diff --git a/test/integration/smoke/test_gateway_on_shared_networks.py b/test/integration/smoke/test_gateway_on_shared_networks.py new file mode 100644 index 00000000000..dd2982f569d --- /dev/null +++ b/test/integration/smoke/test_gateway_on_shared_networks.py @@ -0,0 +1,241 @@ +# 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 Local Modules +from marvin.cloudstackAPI import * +from marvin.cloudstackTestCase import cloudstackTestCase +import unittest +from marvin.lib.base import (NetworkOffering, + Network, + ServiceOffering, + VirtualMachine, + Template, + PublicIpRange, + NIC + ) +from marvin.lib.common import (get_domain, + get_zone, + get_template, + find_storage_pool_type, + get_builtin_template_info) +from marvin.codes import ( + PASS, + FAILED, + JOB_FAILED, + JOB_CANCELLED, + JOB_SUCCEEDED +) +from nose.plugins.attrib import attr +import time + + +class TestGatewayOnSharedNetwork(cloudstackTestCase): + + @classmethod + def setUpClass(cls): + try: + testClient = super(TestGatewayOnSharedNetwork, cls).getClsTestClient() + cls.apiclient = testClient.getApiClient() + cls.services = testClient.getParsedTestDataConfig() + cls._cleanup = [] + # Get Zone, Domain and templates + cls.domain = get_domain(cls.apiclient) + cls.zone = get_zone(cls.apiclient, testClient.getZoneForTests()) + cls.services['mode'] = cls.zone.networktype + cls.hypervisor = testClient.getHypervisorInfo() + + cls.service_offering = ServiceOffering.create( + cls.apiclient, + cls.services["service_offering"] + ) + cls._cleanup.append(cls.service_offering) + + builtin_info = get_builtin_template_info(cls.apiclient, cls.zone.id) + cls.services["template"]["url"] = builtin_info[0] + cls.services["template"]["hypervisor"] = builtin_info[1] + cls.services["template"]["format"] = builtin_info[2] + + cls.template = get_template( + cls.apiclient, + cls.zone.id + ) + + # # Register new template + # cls.template = Template.register( + # cls.apiclient, + # cls.services["template"], + # zoneid=cls.zone.id, + # hypervisor=cls.hypervisor + # ) + # cls._cleanup.append(cls.template) + + cls.services["shared_network_offering"]["specifyVlan"] = "True" + cls.services["shared_network_offering"]["specifyIpRanges"] = "True" + cls.shared_network_offering = NetworkOffering.create( + cls.apiclient, + cls.services["shared_network_offering"], + conservemode=False + ) + cls._cleanup.append(cls.shared_network_offering) + NetworkOffering.update( + cls.shared_network_offering, + cls.apiclient, + id=cls.shared_network_offering.id, + state="enabled" + ) + + except Exception as e: + cls.tearDownClass() + raise unittest.SkipTest("Exception in setUpClass: %s" % e) + + + @classmethod + def tearDownClass(cls): + cls.debug(f"tearing down TestGatewayOnSharedNetwork") + super(TestGatewayOnSharedNetwork, cls).tearDownClass() + + def setUp(self): + self.cleanup = [] + + def tearDown(self): + self.debug(f"tearing down test in TestGatewayOnSharedNetwork") + super(TestGatewayOnSharedNetwork, self).tearDown() + + @attr(tags=["advanced", "advancedns"], required_hardware="false") + def test_updating_nics_on_two_shared_networks(self): + """ + Test updating vm nics on two shared networks + Works as follows: + - Create two shared networks, with different IP ranges (eg network1, network2). + - Create two VMs on each shared network (eg vm1 on network1, vm2 on network2) and stop them. + - Add additional IP range to each shared network. The two additional IP ranges have same start IP and end IP, + but different gateway and netmask (eg network1-iprange2, network2-iprange2). + - Update IP address of the two vms, by specifying new IP address on additional IP ranges. The new gateway and + netmask should be updated correctly (eg vm1 on network1-iprange2, vm2 on network2-iprange2). + """ + # - Create two shared networks, with different IP ranges (eg network1, network2). + self.services["shared_network"]["netmask"] = "255.255.255.0" + self.services["shared_network"]["gateway"] = "192.168.1.1" + self.services["shared_network"]["startip"] = "192.168.1.2" + self.services["shared_network"]["endip"] = "192.168.1.20" + self.services["shared_network"]["vlan"] = "111" + testnet = self.services["shared_network"] + self.debug(f"========= network 1 : {testnet}") + + self.network1 = Network.create( + self.apiclient, + self.services["shared_network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + self._cleanup.append(self.network1) + + self.services["shared_network"]["netmask"] = "255.255.255.0" + self.services["shared_network"]["gateway"] = "192.168.2.1" + self.services["shared_network"]["startip"] = "192.168.2.2" + self.services["shared_network"]["endip"] = "192.168.2.20" + self.services["shared_network"]["vlan"] = "222" + self.network2 = Network.create( + self.apiclient, + self.services["shared_network"], + networkofferingid=self.shared_network_offering.id, + zoneid=self.zone.id, + ) + self._cleanup.append(self.network2) + + # - Create two VMs on each shared network (eg vm1 on network1, vm2 on network2) and stop them. + vm_data = self.services["virtual_machine"] + self.debug(f"============virtual machine data : {vm_data}") + virtual_machine1 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + networkids=[self.network1.id], + zoneid=self.zone.id + ) + self.cleanup.append(virtual_machine1) + virtual_machine1.stop(self.apiclient) + virtual_machine2 = VirtualMachine.create( + self.apiclient, + self.services["virtual_machine"], + templateid=self.template.id, + serviceofferingid=self.service_offering.id, + networkids=[self.network2.id], + zoneid=self.zone.id + ) + self.cleanup.append(virtual_machine2) + virtual_machine2.stop(self.apiclient) + # - Add additional IP range to each shared network. The two additional IP ranges have same start IP and end IP, + # but different gateway and netmask (eg network1-iprange2, network2-iprange2). + self.services["vlan_ip_range"]["netmask"] = "255.255.255.224" + self.services["vlan_ip_range"]["gateway"] = "192.168.3.1" + self.services["vlan_ip_range"]["startip"] = "192.168.3.2" + self.services["vlan_ip_range"]["endip"] = "192.168.3.20" + self.services["vlan_ip_range"]["vlan"] = "111" + range1 = PublicIpRange.create(self.apiclient, self.services["vlan_ip_range"], networkid=self.network1.id) + self.debug(f"============range 1 : {range1}") + + self.services["vlan_ip_range"]["netmask"] = "255.255.255.192" + self.services["vlan_ip_range"]["gateway"] = "192.168.3.21" + self.services["vlan_ip_range"]["startip"] = "192.168.3.2" + self.services["vlan_ip_range"]["endip"] = "192.168.3.20" + self.services["vlan_ip_range"]["vlan"] = "222" + range2 = PublicIpRange.create(self.apiclient, self.services["vlan_ip_range"], networkid=self.network2.id) + + # - Update IP address of the two vms, by specifying new IP address on additional IP ranges. The new gateway and + # netmask should be updated correctly (eg vm1 on network1-iprange2, vm2 on network2-iprange2). + nic1id = NIC.list(self.apiclient, virtualmachineid=virtual_machine1.id, networkid=self.network1.id)[0].id + NIC.updateIp(self.apiclient, id=nic1id, ipaddress="192.168.3.2") + nics = NIC.list(self.apiclient, virtualmachineid=virtual_machine1.id, networkid=self.network1.id) + self.check_nic(nics, self.network1, range1) + + nic2id = NIC.list(self.apiclient, virtualmachineid=virtual_machine2.id, networkid=self.network2.id)[0].id + NIC.updateIp(self.apiclient, id=nic2id, ipaddress="192.168.3.2") + nics = NIC.list(self.apiclient, virtualmachineid=virtual_machine2.id, networkid=self.network2.id) + self.check_nic(nics, self.network2, range2) + + + return + + def check_nic(self, nics, network, range): + # network = Network.list(self.apiclient, id=network_obj.id)[0] + self.assertEqual( + len(nics), + 1, + "VM should have only one nic" + ) + self.assertNotEqual( + nics[0].netmask, + network.netmask, + "netmask is from the primary range of the network" + ) + self.assertNotEqual( + nics[0].gateway, + network.gateway, + "gateway is from the primary range of the network" + ) + self.assertEqual( + nics[0].netmask, + range.vlan.netmask, + f"netmask should be from the extra range {range}, of network {network}." + ) + self.assertEqual( + nics[0].gateway, + range.vlan.gateway, + f"gateway should be from the extra range {range}, of network {network}." + ) diff --git a/tools/marvin/marvin/lib/base.py b/tools/marvin/marvin/lib/base.py index 274b8b92528..5b38c655011 100755 --- a/tools/marvin/marvin/lib/base.py +++ b/tools/marvin/marvin/lib/base.py @@ -3627,7 +3627,7 @@ class PublicIpRange: self.__dict__.update(items) @classmethod - def create(cls, apiclient, services, account=None, domainid=None, forsystemvms=None): + def create(cls, apiclient, services, account=None, domainid=None, forsystemvms=None, networkid=None): """Create VlanIpRange""" cmd = createVlanIpRange.createVlanIpRangeCmd() @@ -3635,15 +3635,18 @@ class PublicIpRange: cmd.gateway = services["gateway"] if "netmask" in services: cmd.netmask = services["netmask"] - cmd.forvirtualnetwork = services["forvirtualnetwork"] + if "forvirtualnetwork" in services: + cmd.forvirtualnetwork = services["forvirtualnetwork"] if "startip" in services: cmd.startip = services["startip"] if "endip" in services: cmd.endip = services["endip"] - cmd.zoneid = services["zoneid"] + if "zoneid" in services: + cmd.zoneid = services["zoneid"] if "podid" in services: cmd.podid = services["podid"] - cmd.vlan = services["vlan"] + if "vlan" in services: + cmd.vlan = services["vlan"] if "ip6gateway" in services: cmd.ip6gateway = services["ip6gateway"] if "ip6cidr" in services: @@ -3655,6 +3658,8 @@ class PublicIpRange: cmd.domainid = domainid if forsystemvms: cmd.forsystemvms = forsystemvms + if networkid: + cmd.networkid = networkid return PublicIpRange(apiclient.createVlanIpRange(cmd).__dict__)