cloudstack/test/integration/component/test_network_mtu.py
Pearl Dsilva 3044d63a8b
Configurable MTU for VR (#6426)
Co-authored-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
2023-01-04 09:42:24 +01:00

396 lines
16 KiB
Python

# Licensed to the Apache Software Foundation (ASF) under one
# 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.
""" BVT tests for Network Life Cycle
"""
# Import Local Modules
from marvin.cloudstackTestCase import cloudstackTestCase
from marvin.lib.utils import cleanup_resources, get_process_status, get_host_credentials
from marvin.lib.base import (Account,
VirtualMachine,
ServiceOffering,
NATRule,
PublicIPAddress,
StaticNATRule,
FireWallRule,
Network,
NetworkOffering,
LoadBalancerRule,
Router,
NIC,
Cluster)
from marvin.lib.common import (get_domain,
get_free_vlan,
get_zone,
get_template,
get_test_template,
list_hosts,
list_publicIP,
list_nat_rules,
list_routers,
list_virtual_machines,
list_lb_rules,
list_configurations,
verifyGuestTrafficPortGroups,
verifyNetworkState)
from nose.plugins.attrib import attr
import logging
_multiprocess_shared_ = True
logger = logging.getLogger('TestNetworkWithMtuConfiguration')
stream_handler = logging.StreamHandler()
logger.setLevel(logging.DEBUG)
logger.addHandler(stream_handler)
class TestNetworkWithMtuConfiguration(cloudstackTestCase):
@classmethod
def setUpClass(cls):
cls.testClient = super(TestNetworkWithMtuConfiguration, cls).getClsTestClient()
cls.api_client = cls.testClient.getApiClient()
cls.dbclient = cls.testClient.getDbConnection()
cls.hypervisor = cls.testClient.getHypervisorInfo()
cls.domain = get_domain(cls.api_client)
cls.skip = False
if cls.hypervisor.lower() == 'simulator':
cls.skip = True
cls.services = cls.testClient.getParsedTestDataConfig()
cls.hostConfig = cls.config.__dict__["zones"][0].__dict__["pods"][0].__dict__["clusters"][0].__dict__["hosts"][
0].__dict__
# Get Zone and templates
cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
logger.debug("Creating Admin Account for domain %s on zone %s" % (cls.domain.id, cls.zone.id))
cls.account = Account.create(
cls.api_client,
cls.services["account"],
admin=True,
domainid=cls.domain.id
)
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.isolated_network_offering = NetworkOffering.create(
cls.api_client,
cls.services["network_offering"]
)
cls.isolated_network_offering.update(cls.api_client, state='Enabled')
cls._cleanup = [
cls.service_offering,
cls.isolated_network_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):
if self.skip:
self.skipTest("Skip test for simulator hypervisor")
self.apiclient = self.testClient.getApiClient()
self.dbclient = self.testClient.getDbConnection()
self.hypervisor = self.testClient.getHypervisorInfo()
self.cleanup = []
return
def tearDown(self):
try:
# Clean up, terminate the resources created
cleanup_resources(self.apiclient, self.cleanup)
self.cleanup[:] = []
except Exception as e:
raise Exception("Warning: Exception during cleanup : %s" % e)
return
'''
This test performs the following:
1. creates an Isolated network with Public and Private MTUs being configured on the respective interfaces
a. Set one of the MTUs to a value greater that the configured max - 1500 and observe that it gets set
to the maximum configurable value
2. Check router nic MTUs
3. Validates that the network has the right MTU set in the DB
'''
@attr(tags=["advanced", "isolated", "network", "xx"], required_hardware="false")
def test_01_create_isolated_network_with_mtu(self):
public_mtu = 1450
private_mtu = 2000
logger.debug("Creating an isolated network with MTU defined for both public and private interfaces")
self.isolated_network = Network.create(
self.apiclient,
self.services["isolated_network"],
networkofferingid=self.isolated_network_offering.id,
zoneid=self.zone.id,
publicmtu=public_mtu,
privatemtu=private_mtu)
logger.debug("Deploying VM")
virtual_machine = VirtualMachine.create(
self.apiclient,
self.services["virtual_machine"],
templateid=self.template.id,
serviceofferingid=self.service_offering.id,
networkids=[str(self.isolated_network.id)])
self.cleanup.append(virtual_machine)
self.cleanup.append(self.isolated_network)
# Validate network is in the Implemented state
response = verifyNetworkState(
self.apiclient,
virtual_machine.nic[0].networkid,
"implemented")
exceptionOccurred = response[0]
isNetworkInDesiredState = response[1]
exceptionMessage = response[2]
if (exceptionOccurred or (not isNetworkInDesiredState)):
self.fail(exceptionMessage)
public_ips = list_publicIP(
self.apiclient,
associatednetworkid=self.isolated_network.id
)
self.assertEqual(
isinstance(public_ips, list),
True,
"Check for list public IPs response return valid data"
)
public_ip = public_ips[0]
logger.debug("Creating Firewall rule for VM ID: %s" % virtual_machine.id)
FireWallRule.create(
self.apiclient,
ipaddressid=public_ip.id,
protocol=self.services["natrule"]["protocol"],
cidrlist=['0.0.0.0/0'],
startport=self.services["natrule"]["publicport"],
endport=self.services["natrule"]["publicport"]
)
logger.debug("Creating NAT rule for VM ID: %s" % virtual_machine.id)
nat_rule = NATRule.create(
self.apiclient,
virtual_machine,
self.services["natrule"],
public_ip.id
)
logger.debug("Ping the external network with packet size greater than configured mtu %s : %s", public_mtu, 1500)
expected = 1
check_string = "Frag needed and DF set"
cmd = "ping -M do -s {mtu} 8.8.8.8 -c1"
result = self.check_router_command(virtual_machine, nat_rule.ipaddress, cmd.format(mtu="1500"), check_string, self)
self.assertEqual(
result,
expected,
"Ping to outside world from VM should be successful!"
)
logger.debug("Ping the external network with packet size lesser than configured mtu %s : %s", public_mtu, 1200)
expected = 1
check_string = "0% packet loss"
cmd = "ping -M do -s {mtu} 8.8.8.8 -c1"
result = self.check_router_command(virtual_machine, nat_rule.ipaddress, cmd.format(mtu="1200"), check_string, self)
self.assertEqual(
result,
expected,
"Ping to outside world from VM should be successful!"
)
# Verify network mtu set
self.verify_network_mtu(self.isolated_network, public_mtu, 1500)
self.checkRouterNicMtus(self.isolated_network, public_mtu, 1500)
self.checkNetworkMtu(self.isolated_network, public_mtu, 1500)
@attr(tags=["advanced", "isolated", "network", "xx"], required_hardware="false")
def test_02_update_isolated_network_with_mtu(self):
public_mtu = 1200
private_mtu = 1100
logger.debug("Creating an isolated network with MTU defined for both public and private interfaces")
isolated_network1 = Network.create(
self.apiclient,
self.services["isolated_network"],
networkofferingid=self.isolated_network_offering.id,
zoneid=self.zone.id,
publicmtu=public_mtu,
privatemtu=private_mtu)
logger.debug("Deploying VM")
virtual_machine = VirtualMachine.create(
self.apiclient,
self.services["virtual_machine"],
templateid=self.template.id,
serviceofferingid=self.service_offering.id,
networkids=[str(isolated_network1.id)])
self.cleanup.append(virtual_machine)
self.cleanup.append(isolated_network1)
# Validate network is in the Implemented state
response = verifyNetworkState(
self.apiclient,
virtual_machine.nic[0].networkid,
"implemented")
exceptionOccurred = response[0]
isNetworkInDesiredState = response[1]
exceptionMessage = response[2]
if (exceptionOccurred or (not isNetworkInDesiredState)):
self.fail(exceptionMessage)
public_ips = list_publicIP(
self.apiclient,
associatednetworkid=isolated_network1.id
)
self.assertEqual(
isinstance(public_ips, list),
True,
"Check for list public IPs response return valid data"
)
public_ip = public_ips[0]
logger.debug("Creating Firewall rule for VM ID: %s" % virtual_machine.id)
FireWallRule.create(
self.apiclient,
ipaddressid=public_ip.id,
protocol=self.services["natrule"]["protocol"],
cidrlist=['0.0.0.0/0'],
startport=self.services["natrule"]["publicport"],
endport=self.services["natrule"]["publicport"]
)
logger.debug("Creating NAT rule for VM ID: %s" % virtual_machine.id)
nat_rule = NATRule.create(
self.apiclient,
virtual_machine,
self.services["natrule"],
public_ip.id
)
# Verify network mtu set
self.verify_network_mtu(isolated_network1, public_mtu, private_mtu)
self.checkRouterNicMtus(isolated_network1, public_mtu, private_mtu)
self.checkNetworkMtu(isolated_network1, public_mtu, private_mtu)
logger.debug("Update the network's MTU")
updated_network = isolated_network1.update(self.apiclient, id=isolated_network1.id, public_mtu=1450)
logger.debug("Ping the external network with packet size greater than configured mtu %s : %s", public_mtu, 1500)
expected = 1
check_string = "Frag needed and DF set"
cmd = "ping -M do -s {mtu} 8.8.8.8 -c1"
result = self.check_router_command(virtual_machine, nat_rule.ipaddress, cmd.format(mtu="1500"), check_string, self)
self.assertEqual(
result,
expected,
"Ping to outside world from VM should be successful!"
)
logger.debug("Ping the external network with packet size lesser than configured mtu %s : %s", public_mtu, 1100)
expected = 1
check_string = "0% packet loss"
cmd = "ping -M do -s {mtu} 8.8.8.8 -c1"
result = self.check_router_command(virtual_machine, nat_rule.ipaddress, cmd.format(mtu="1200"), check_string, self)
self.assertEqual(
result,
expected,
"Ping to outside world from VM should be successful!"
)
self.checkRouterNicMtus(updated_network, public_mtu, private_mtu)
self.checkNetworkMtu(updated_network, public_mtu, private_mtu)
def verify_network_mtu(self, network, public_mtu, private_mtu):
# Verify network mtu set
result = self.dbclient.execute("select public_mtu, private_mtu from networks where uuid='%s'"
% str(network.id))
self.assertEqual(isinstance(result, list),
True,
"Check DB query result set for valid data")
self.assertNotEqual(len(result),
0,
"Check DB Query result set")
self.assertEqual(result[0][0],
public_mtu if public_mtu < 1500 else 1500,
"DB results not matching, expected: %s found: %s " % (public_mtu, result[0][0]))
self.assertEqual(result[0][1],
private_mtu if private_mtu < 1500 else 1500,
"DB results not matching, expected: %s found: %s " % (private_mtu, result[0][1]))
def check_router_command(self, virtual_machine, public_ip, ssh_command, check_string, test_case, retries=5):
result = 'failed'
try:
ssh = virtual_machine.get_ssh_client(ipaddress=public_ip, retries=retries)
result = str(ssh.execute(ssh_command))
except Exception as e:
test_case.fail("Failed to SSH into the Virtual Machine: %s" % e)
logging.debug("Result from SSH into the Virtual Machine: %s" % result)
return result.count(check_string)
def checkRouterNicMtus(self, network, public_mtu, private_mtu):
self.debug("Listing routers for network: %s" % network.name)
self.routers = Router.list(
self.apiclient,
networkid=network.id,
listall=True
)
self.assertTrue(
isinstance(self.routers, list),
"Check listRouters response returns a valid list"
)
self.assertTrue(
len(self.routers) > 0,
"Router for the network isn't found"
)
for router in self.routers:
nics = router.nic
for nic in nics:
if nic.traffictype == 'Guest':
self.assertEqual(private_mtu, nic.mtu, "MTU not properly configured on private interface of VR")
if nic.traffictype == 'Public':
self.assertEqual(public_mtu, nic.mtu, "MTU not properly configured on public interface of VR")
def checkNetworkMtu(self, network, expected_public_mtu, expected_private_mtu):
self.assertEqual(expected_public_mtu, network.publicmtu)
self.assertEqual(expected_private_mtu, network.privatemtu)