mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
396 lines
16 KiB
Python
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)
|