4a4e9f3baf
Change-Id: Ibca1716cc2f86ffbd3a448162802b2c890fc7ff9 Closes-bug: #1527123
568 lines
22 KiB
Python
568 lines
22 KiB
Python
# Copyright 2015 Mirantis, Inc.
|
|
#
|
|
# Licensed 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 copy import deepcopy
|
|
import subprocess
|
|
|
|
from devops.helpers import helpers as devops_helpers
|
|
from proboscis import asserts
|
|
from proboscis import test
|
|
|
|
from fuelweb_test.helpers import decorators
|
|
from fuelweb_test.helpers import os_actions
|
|
from fuelweb_test import logger
|
|
from fuelweb_test import settings
|
|
from fuelweb_test.settings import iface_alias
|
|
from fuelweb_test.tests import base_test_case
|
|
|
|
|
|
@test(groups=["jumbo_frames"])
|
|
class TestJumboFrames(base_test_case.TestBasic):
|
|
|
|
interfaces = {
|
|
iface_alias('eth0'): ['fuelweb_admin'],
|
|
iface_alias('eth1'): ['public'],
|
|
iface_alias('eth2'): ['management'],
|
|
iface_alias('eth3'): ['private'],
|
|
iface_alias('eth4'): ['storage'],
|
|
}
|
|
|
|
interfaces_update = [{
|
|
'name': iface_alias('eth3'),
|
|
'interface_properties': {
|
|
'mtu': 9000,
|
|
'disable_offloading': False
|
|
},
|
|
}]
|
|
|
|
def check_node_iface_mtu(self, node, iface, mtu):
|
|
"""Check mtu on environment node network interface."""
|
|
|
|
return "mtu {0}".format(mtu) in self.get_node_iface(node, iface)
|
|
|
|
def get_node_iface(self, node, iface):
|
|
"""Get environment node network interface."""
|
|
|
|
command = "sudo ip link show {0}".format(iface)
|
|
return ''.join(node.execute(command)['stdout'])
|
|
|
|
def set_host_iface_mtu(self, iface, mtu):
|
|
"""Set devops/fuel-qa host network interface mtu."""
|
|
|
|
command = "sudo ip link set {0} mtu {1}".format(iface, mtu).split()
|
|
return subprocess.call(command, stderr=subprocess.STDOUT)
|
|
|
|
def get_host_iface(self, iface):
|
|
"""Get devops/fuel-qa host network interface."""
|
|
|
|
command = "sudo ip link show {0}".format(iface).split()
|
|
return subprocess.check_output(command, stderr=subprocess.STDOUT)
|
|
|
|
def get_host_bridge_ifaces(self, bridge_name):
|
|
"""Get list of devops/fuel-qa host network bridge interfaces."""
|
|
|
|
command = "sudo brctl show {0}".format(bridge_name).split()
|
|
ifaces = subprocess.check_output(command, stderr=subprocess.STDOUT)
|
|
|
|
ifaces = ifaces.splitlines()[1:]
|
|
bridge_iface = ifaces[0].split()[-1]
|
|
ifaces = map(lambda iface: iface.strip(), ifaces[1:])
|
|
ifaces.append(bridge_iface)
|
|
|
|
return ifaces
|
|
|
|
def boot_instance_on_node(self, hypervisor_name, label, boot_timeout=300,
|
|
need_floating_ip=True):
|
|
instance = self.os_conn.create_server_for_migration(
|
|
neutron=True,
|
|
availability_zone="nova:{0}".format(hypervisor_name), label=label)
|
|
logger.info("New instance {0} created on {1}"
|
|
.format(instance.id, hypervisor_name))
|
|
ip = self.os_conn.get_nova_instance_ip(instance, net_name=label,
|
|
type='fixed')
|
|
logger.info("Instance {0} has IP {1}".format(instance.id, ip))
|
|
|
|
if not need_floating_ip:
|
|
return self.os_conn.nova.servers.get(instance.id)
|
|
|
|
ip = self.os_conn.assign_floating_ip(instance)
|
|
logger.info("Floating address {0} associated with instance {1}"
|
|
.format(ip.ip, instance.id))
|
|
|
|
logger.info("Wait for ping from instance {}".format(instance.id))
|
|
devops_helpers.wait(
|
|
lambda: devops_helpers.tcp_ping(ip.ip, 22),
|
|
timeout=boot_timeout,
|
|
timeout_msg=("Instance {0} is unreachable for {1} seconds".
|
|
format(instance.id, boot_timeout)))
|
|
|
|
return self.os_conn.nova.servers.get(instance.id)
|
|
|
|
def ping_instance_from_instance(self, source_instance,
|
|
destination_instance,
|
|
net_from, net_to, size, count=1):
|
|
creds = ("cirros", "cubswin:)")
|
|
destination_ip = self.os_conn.get_nova_instance_ip(
|
|
destination_instance, net_name=net_to, type='fixed')
|
|
source_ip = self.os_conn.get_nova_instance_ip(
|
|
source_instance, net_name=net_from, type='floating')
|
|
|
|
with self.fuel_web.get_ssh_for_node("slave-01") as ssh:
|
|
command = "ping -s {0} {1}".format(size, destination_ip)
|
|
if count:
|
|
command = "{0} -c {1}".format(command, count)
|
|
logger.info(
|
|
"Try to ping private address {0} from {1} with {2} {3} bytes "
|
|
"packet(s): {4}".format(destination_ip, source_ip, count, size,
|
|
command))
|
|
ping = self.os_conn.execute_through_host(ssh, source_ip, command,
|
|
creds)
|
|
logger.info("Ping result: \n"
|
|
"{0}\n"
|
|
"{1}\n"
|
|
"exit_code={2}".format(ping['stdout'], ping['stderr'],
|
|
ping['exit_code']))
|
|
|
|
return 0 == ping['exit_code']
|
|
|
|
def check_mtu_size_between_instances(self, mtu_offset, diff_net=False):
|
|
"""Check private network mtu size
|
|
|
|
Scenario:
|
|
1. Boot two instances on different compute hosts
|
|
2. Ping one from another with 1472 bytes package
|
|
3. Ping one from another with 8972 bytes package
|
|
4. Ping one from another with 8973 bytes package
|
|
5. Ping one from another with 14472 bytes package
|
|
6. Delete instances
|
|
|
|
"""
|
|
cluster_id = self.fuel_web.get_last_created_cluster()
|
|
self.os_conn = os_actions.OpenStackActions(
|
|
self.fuel_web.get_public_vip(cluster_id))
|
|
|
|
net_name = self.fuel_web.get_cluster_predefined_networks_name(
|
|
cluster_id)['private_net']
|
|
net_destination = net_name
|
|
need_floating_ip = True
|
|
hypervisors = self.os_conn.get_hypervisors()
|
|
|
|
if diff_net:
|
|
net_destination = 'private1'
|
|
need_floating_ip = False
|
|
net1 = self.os_conn.create_network(net_destination)['network']
|
|
subnet1 = self.os_conn.create_subnet('private1_subnet', net1['id'],
|
|
'192.168.200.0/24')
|
|
router = self.os_conn.get_router_by_name('router04')
|
|
self.os_conn.add_router_interface(router['id'], subnet1['id'])
|
|
|
|
destination_instance = self.boot_instance_on_node(
|
|
hypervisors[1].hypervisor_hostname, label=net_destination,
|
|
need_floating_ip=need_floating_ip)
|
|
source_instance = self.boot_instance_on_node(
|
|
hypervisors[0].hypervisor_hostname, label=net_name)
|
|
|
|
logger.info("Wait for ping from instance {}".format(
|
|
destination_instance))
|
|
devops_helpers.wait(
|
|
lambda: self.ping_instance_from_instance(
|
|
source_instance, destination_instance, net_name,
|
|
net_destination, size=15, count=3),
|
|
interval=10,
|
|
timeout=600,
|
|
timeout_msg=("Instance {0} is unreachable for 600 seconds".
|
|
format(destination_instance.id)))
|
|
|
|
for mtu in [1500, 9000, 9001]:
|
|
size = mtu - 28 - mtu_offset
|
|
if mtu <= 9000:
|
|
asserts.assert_true(
|
|
self.ping_instance_from_instance(
|
|
source_instance, destination_instance, net_name,
|
|
net_destination, size=size, count=3),
|
|
"Ping response was not received for "
|
|
"{} bytes package".format(mtu))
|
|
else:
|
|
asserts.assert_false(
|
|
self.ping_instance_from_instance(
|
|
source_instance, destination_instance, net_name,
|
|
net_destination, size=size, count=3),
|
|
"Ping response was not received for "
|
|
"{} bytes package".format(mtu))
|
|
|
|
for instance in [source_instance, destination_instance]:
|
|
self.os_conn.delete_instance(instance)
|
|
self.os_conn.verify_srv_deleted(instance)
|
|
|
|
@test(depends_on=[base_test_case.SetupEnvironment.prepare_slaves_5],
|
|
groups=["prepare_5_slaves_with_jumbo_frames"])
|
|
def prepare_5_slaves_with_jumbo_frames(self):
|
|
"""Setup jumbo frames on private bridge on host
|
|
|
|
Scenario:
|
|
1. Find bridge with name "private"
|
|
2. Set mtu 9000 for all bridge interfaces
|
|
3. Make snapshot ready_with_5_slaves_jumbo_frames
|
|
|
|
Duration 5m
|
|
Snapshot ready_with_5_slaves_jumbo_frames
|
|
|
|
"""
|
|
self.check_run("ready_with_5_slaves_jumbo_frames")
|
|
self.env.revert_snapshot("ready_with_5_slaves")
|
|
|
|
devops_env = self.env.d_env
|
|
private_bridge = devops_env.get_network(name='private').bridge_name()
|
|
logger.info(
|
|
"Search for {0} interfaces for update".format(private_bridge))
|
|
|
|
bridge_interfaces = self.get_host_bridge_ifaces(private_bridge)
|
|
logger.info("Found {0} interfaces for update: {1}".format(
|
|
len(bridge_interfaces), bridge_interfaces))
|
|
|
|
for iface in bridge_interfaces:
|
|
self.set_host_iface_mtu(iface, 9000)
|
|
logger.info("MTU of {0} was changed to 9000".format(iface))
|
|
logger.debug("New {0} interface properties:\n{1}"
|
|
.format(iface, self.get_host_iface(iface)))
|
|
|
|
self.env.make_snapshot(
|
|
"ready_with_5_slaves_jumbo_frames", is_make=True)
|
|
|
|
@test(depends_on=[prepare_5_slaves_with_jumbo_frames],
|
|
groups=["jumbo_frames_neutron_vlan"])
|
|
@decorators.log_snapshot_after_test
|
|
def jumbo_frames_neutron_vlan(self):
|
|
"""Verify jumbo frames between instances on HA Neutron VLAN
|
|
|
|
Scenario:
|
|
1. Revert snapshot ready_with_5_slaves_jumbo_frames
|
|
2. Create cluster with neutron VLAN
|
|
3. Add 3 node with controller role
|
|
4. Add 2 nodes with compute role
|
|
5. Set mtu=9000 on private interface
|
|
6. Deploy the cluster
|
|
7. Run network verification
|
|
8. Check MTU on private interface
|
|
9. Run MTU size check
|
|
10. Run OSTF
|
|
|
|
Duration 120m
|
|
Snapshot ready_jumbo_frames_neutron_vlan
|
|
|
|
"""
|
|
self.show_step(1, initialize=True)
|
|
self.env.revert_snapshot("ready_with_5_slaves_jumbo_frames")
|
|
|
|
self.show_step(2)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
mode=settings.DEPLOYMENT_MODE_HA,
|
|
settings={
|
|
"net_provider": 'neutron',
|
|
"net_segment_type": settings.NEUTRON_SEGMENT['vlan'],
|
|
}
|
|
)
|
|
|
|
self.fuel_web.update_nodes(
|
|
cluster_id,
|
|
{
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['controller'],
|
|
'slave-03': ['controller'],
|
|
'slave-04': ['compute'],
|
|
'slave-05': ['compute'],
|
|
}
|
|
)
|
|
|
|
self.show_step(5)
|
|
slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
|
|
for node in slave_nodes:
|
|
self.fuel_web.update_node_networks(
|
|
node['id'], self.interfaces,
|
|
override_ifaces_params=self.interfaces_update)
|
|
|
|
self.show_step(6)
|
|
self.fuel_web.deploy_cluster_wait(cluster_id)
|
|
|
|
self.show_step(7)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(8)
|
|
for node_name in ['slave-01', 'slave-02', 'slave-03',
|
|
'slave-04', 'slave-05']:
|
|
node = self.fuel_web.get_nailgun_node_by_name(node_name)
|
|
with self.env.d_env.get_ssh_to_remote(node['ip']) as remote:
|
|
for iface in self.interfaces_update:
|
|
asserts.assert_true(
|
|
self.check_node_iface_mtu(remote, iface['name'], 9000),
|
|
"MTU on {0} is not 9000. "
|
|
"Actual value: {1}".format(
|
|
remote.host,
|
|
self.get_node_iface(remote, iface['name'])))
|
|
|
|
self.show_step(9)
|
|
self.check_mtu_size_between_instances(mtu_offset=0)
|
|
|
|
self.show_step(10)
|
|
self.fuel_web.run_ostf(cluster_id=cluster_id)
|
|
self.env.make_snapshot("ready_jumbo_frames_neutron_vlan")
|
|
|
|
@test(depends_on=[prepare_5_slaves_with_jumbo_frames],
|
|
groups=["jumbo_frames_neutron_vxlan"])
|
|
@decorators.log_snapshot_after_test
|
|
def jumbo_frames_neutron_vxlan(self):
|
|
"""Verify jumbo frames between instances on HA and Neutron VXLAN
|
|
|
|
Scenario:
|
|
1. Revert snapshot ready_with_5_slaves_jumbo_frames
|
|
2. Create cluster with neutron VXLAN
|
|
3. Add 3 node with controller role
|
|
4. Add 2 nodes with compute role
|
|
5. Set mtu=9000 on private interface
|
|
6. Deploy the cluster
|
|
7. Run network verification
|
|
8. Check MTU on private interface
|
|
9. Run MTU size check
|
|
10. Run OSTF
|
|
|
|
Duration 120m
|
|
Snapshot ready_jumbo_frames_neutron_vxlan
|
|
|
|
"""
|
|
self.show_step(1, initialize=True)
|
|
self.env.revert_snapshot("ready_with_5_slaves_jumbo_frames")
|
|
|
|
self.show_step(2)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
mode=settings.DEPLOYMENT_MODE_HA,
|
|
settings={
|
|
"net_provider": 'neutron',
|
|
"net_segment_type": settings.NEUTRON_SEGMENT['tun'],
|
|
}
|
|
)
|
|
|
|
self.show_step(3)
|
|
self.show_step(4)
|
|
self.fuel_web.update_nodes(
|
|
cluster_id,
|
|
{
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['controller'],
|
|
'slave-03': ['controller'],
|
|
'slave-04': ['compute'],
|
|
'slave-05': ['compute'],
|
|
}
|
|
)
|
|
|
|
self.show_step(5)
|
|
slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
|
|
for node in slave_nodes:
|
|
self.fuel_web.update_node_networks(
|
|
node['id'], self.interfaces,
|
|
override_ifaces_params=self.interfaces_update)
|
|
|
|
self.show_step(6)
|
|
self.fuel_web.deploy_cluster_wait(cluster_id)
|
|
|
|
self.show_step(7)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(8)
|
|
for node_name in ['slave-01', 'slave-02', 'slave-03',
|
|
'slave-04', 'slave-05']:
|
|
node = self.fuel_web.get_nailgun_node_by_name(node_name)
|
|
with self.env.d_env.get_ssh_to_remote(node['ip']) as remote:
|
|
for iface in self.interfaces_update:
|
|
asserts.assert_true(
|
|
self.check_node_iface_mtu(remote, iface['name'], 9000),
|
|
"MTU on {0} is not 9000. "
|
|
"Actual value: {1}".format(
|
|
remote.host,
|
|
self.get_node_iface(remote, iface['name'])))
|
|
|
|
self.show_step(9)
|
|
self.check_mtu_size_between_instances(mtu_offset=50)
|
|
|
|
self.show_step(10)
|
|
self.fuel_web.run_ostf(cluster_id=cluster_id)
|
|
self.env.make_snapshot("ready_jumbo_frames_neutron_vxlan")
|
|
|
|
@test(depends_on=[prepare_5_slaves_with_jumbo_frames],
|
|
groups=["jumbo_frames_neutron_diff_net_vlan"])
|
|
@decorators.log_snapshot_after_test
|
|
def jumbo_frames_neutron_diff_net_vlan(self):
|
|
"""Verify jumbo frames between instances in different networks on HA
|
|
and Neutron VLAN
|
|
|
|
Scenario:
|
|
1. Revert snapshot ready_with_5_slaves_jumbo_frames
|
|
2. Create cluster with neutron VLAN
|
|
3. Add 3 node with controller role
|
|
4. Add 2 nodes with compute role
|
|
5. Set mtu=9000 on private interface
|
|
6. Deploy the cluster
|
|
7. Run network verification
|
|
8. Check MTU on private interface
|
|
9. Run MTU size check
|
|
10. Run OSTF
|
|
|
|
Duration 120m
|
|
Snapshot jumbo_frames_neutron_diff_bond_vlan
|
|
|
|
"""
|
|
self.show_step(1, initialize=True)
|
|
self.env.revert_snapshot("ready_with_5_slaves_jumbo_frames")
|
|
|
|
self.show_step(2)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
mode=settings.DEPLOYMENT_MODE_HA,
|
|
settings={
|
|
"net_provider": 'neutron',
|
|
"net_segment_type": settings.NEUTRON_SEGMENT['vlan'],
|
|
}
|
|
)
|
|
|
|
self.show_step(3)
|
|
self.show_step(4)
|
|
self.fuel_web.update_nodes(
|
|
cluster_id,
|
|
{
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['controller'],
|
|
'slave-03': ['controller'],
|
|
'slave-04': ['compute'],
|
|
'slave-05': ['compute'],
|
|
}
|
|
)
|
|
|
|
self.show_step(5)
|
|
slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
|
|
for node in slave_nodes:
|
|
self.fuel_web.update_node_networks(
|
|
node['id'],
|
|
interfaces_dict=deepcopy(self.interfaces),
|
|
override_ifaces_params=self.interfaces_update)
|
|
|
|
self.show_step(6)
|
|
self.fuel_web.deploy_cluster_wait(cluster_id)
|
|
|
|
self.show_step(7)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(8)
|
|
for node_name in ['slave-01', 'slave-02', 'slave-03',
|
|
'slave-04', 'slave-05']:
|
|
node = self.fuel_web.get_nailgun_node_by_name(node_name)
|
|
with self.env.d_env.get_ssh_to_remote(node['ip']) as remote:
|
|
for iface in self.interfaces_update:
|
|
asserts.assert_true(
|
|
self.check_node_iface_mtu(remote, iface['name'], 9000),
|
|
"MTU on {0} is not 9000. "
|
|
"Actual value: {1}".format(
|
|
remote.host,
|
|
self.get_node_iface(remote, iface['name'])))
|
|
|
|
self.show_step(9)
|
|
self.check_mtu_size_between_instances(mtu_offset=0, diff_net=True)
|
|
|
|
self.show_step(10)
|
|
self.fuel_web.run_ostf(cluster_id=cluster_id)
|
|
self.env.make_snapshot("jumbo_frames_neutron_diff_net_vlan")
|
|
|
|
@test(depends_on=[prepare_5_slaves_with_jumbo_frames],
|
|
groups=["jumbo_frames_neutron_diff_net_vxlan"])
|
|
@decorators.log_snapshot_after_test
|
|
def jumbo_frames_neutron_diff_net_vxlan(self):
|
|
"""Verify jumbo frames between instances in different networks on HA
|
|
and Neutron VXLAN
|
|
|
|
Scenario:
|
|
1. Revert snapshot ready_with_5_slaves_jumbo_frames
|
|
2. Create cluster with neutron VXLAN
|
|
3. Add 3 node with controller role
|
|
4. Add 2 nodes with compute role
|
|
5. Set mtu=9000 on private interface
|
|
6. Deploy the cluster
|
|
7. Run network verification
|
|
8. Check MTU on private interface
|
|
9. Run MTU size check
|
|
10. Run OSTF
|
|
|
|
Duration 120m
|
|
Snapshot jumbo_frames_neutron_diff_bond_vxlan
|
|
|
|
"""
|
|
self.show_step(1, initialize=True)
|
|
self.env.revert_snapshot("ready_with_5_slaves_jumbo_frames")
|
|
|
|
self.show_step(2)
|
|
cluster_id = self.fuel_web.create_cluster(
|
|
name=self.__class__.__name__,
|
|
mode=settings.DEPLOYMENT_MODE_HA,
|
|
settings={
|
|
"net_provider": 'neutron',
|
|
"net_segment_type": settings.NEUTRON_SEGMENT['tun'],
|
|
}
|
|
)
|
|
|
|
self.show_step(3)
|
|
self.show_step(4)
|
|
self.fuel_web.update_nodes(
|
|
cluster_id,
|
|
{
|
|
'slave-01': ['controller'],
|
|
'slave-02': ['controller'],
|
|
'slave-03': ['controller'],
|
|
'slave-04': ['compute'],
|
|
'slave-05': ['compute'],
|
|
}
|
|
)
|
|
|
|
self.show_step(5)
|
|
slave_nodes = self.fuel_web.client.list_cluster_nodes(cluster_id)
|
|
for node in slave_nodes:
|
|
self.fuel_web.update_node_networks(
|
|
node['id'],
|
|
interfaces_dict=deepcopy(self.interfaces),
|
|
override_ifaces_params=self.interfaces_update)
|
|
|
|
self.show_step(6)
|
|
self.fuel_web.deploy_cluster_wait(cluster_id)
|
|
|
|
self.show_step(7)
|
|
self.fuel_web.verify_network(cluster_id)
|
|
|
|
self.show_step(8)
|
|
for node_name in ['slave-01', 'slave-02', 'slave-03',
|
|
'slave-04', 'slave-05']:
|
|
node = self.fuel_web.get_nailgun_node_by_name(node_name)
|
|
with self.env.d_env.get_ssh_to_remote(node['ip']) as remote:
|
|
for iface in self.interfaces_update:
|
|
asserts.assert_true(
|
|
self.check_node_iface_mtu(remote, iface['name'], 9000),
|
|
"MTU on {0} is not 9000. "
|
|
"Actual value: {1}".format(
|
|
remote.host,
|
|
self.get_node_iface(remote, iface['name'])))
|
|
|
|
self.show_step(9)
|
|
self.check_mtu_size_between_instances(mtu_offset=50, diff_net=True)
|
|
|
|
self.show_step(10)
|
|
self.fuel_web.run_ostf(cluster_id=cluster_id)
|
|
self.env.make_snapshot("jumbo_frames_neutron_diff_net_vxlan")
|