ccamposr 77bddb9256 Bump hacking
Fixes some new PEP8 errors that appear with jobs running on new ubuntu
version, and temporarily filters out the larger I202 error ("Additional
 newline in a group of imports").

This patch updates the hacking and flake8-import-order versions.

Copied from:
https://review.opendev.org/c/openstack/ovn-octavia-provider/+/936855

Change-Id: Ice4513eedc4fd6f054c19d1854eff00aeb5c35a1
2024-12-05 11:33:40 +01:00

350 lines
14 KiB
Python

# Copyright 2020 Red Hat, Inc.
# All Rights Reserved.
#
# 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.
import re
import time
import netaddr
from neutron_lib import constants
from neutron_tempest_plugin.common import ip
from neutron_tempest_plugin.common import ssh
from oslo_log import log
from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions
from whitebox_neutron_tempest_plugin.tests.scenario import base
CONF = config.CONF
WB_CONF = CONF.whitebox_neutron_plugin_options
LOG = log.getLogger(__name__)
def get_capture_script(result_file, interface):
return """#!/bin/bash
export LC_ALL=en_US.UTF-8
tcpdump -Qin -i %(interface)s -vvneA -s0 -l icmp &> %(result_file)s &
""" % {'result_file': result_file,
'interface': interface}
# TODO(eolivare): create a parent class for BaseBroadcastTest and
# BaseMulticastTest with common code
class BaseBroadcastTest(object):
vlan_transparent = False
servers = []
# Import configuration options
receivers_count = WB_CONF.broadcast_receivers_count
capture_output_file = "/tmp/capture_broadcast_out"
# the following values can be used to send ping messages including once the
# text "Hi here"
broadcast_message = "Hi here"
broadcast_message_pattern = "486920686572652e"
ping_size = 23
@classmethod
def skip_checks(cls):
super(BaseBroadcastTest, cls).skip_checks()
advanced_image_available = (
CONF.neutron_plugin_options.advanced_image_ref or
CONF.neutron_plugin_options.default_image_is_advanced)
if not advanced_image_available:
skip_reason = "This test require advanced tools for this test"
raise cls.skipException(skip_reason)
@classmethod
def resource_setup(cls):
super(BaseBroadcastTest, cls).resource_setup()
if CONF.neutron_plugin_options.default_image_is_advanced:
cls.flavor_ref = CONF.compute.flavor_ref
cls.image_ref = CONF.compute.image_ref
cls.username = CONF.validation.image_ssh_user
else:
cls.flavor_ref = (
CONF.neutron_plugin_options.advanced_image_flavor_ref)
cls.image_ref = CONF.neutron_plugin_options.advanced_image_ref
cls.username = CONF.neutron_plugin_options.advanced_image_ssh_user
# setup basic topology for servers we can log into it
try:
if cls.vlan_transparent:
cls.network = cls.create_network(
vlan_transparent=cls.vlan_transparent)
else:
cls.network = cls.create_network()
except exceptions.ServerFault as exc:
msg = 'Backend does not support VLAN Transparency.'
if exc.resp_body['message'] == msg:
raise cls.skipException(msg)
else:
raise exc
cls.subnet = cls.create_subnet(cls.network)
cls.router = cls.create_router_by_client()
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
cls.keypair = cls.create_keypair()
cls.secgroup = cls.os_primary.network_client.create_security_group(
name='secgroup_bcast')
cls.security_groups.append(cls.secgroup['security_group'])
cls.create_loginable_secgroup_rule(
secgroup_id=cls.secgroup['security_group']['id'])
cls.create_pingable_secgroup_rule(
secgroup_id=cls.secgroup['security_group']['id'])
def _create_server(self, server_type, vlan_tag=None, scheduler_hints=None):
network_id = self.network['id']
if self.vlan_transparent:
server_index = len(self.servers)
vlan_ipmask = self.vlan_ipmast_template.format(
ip_last_byte=server_index + 10)
allowed_address_pairs = [{'ip_address': vlan_ipmask}]
port = self.create_port(
network={'id': network_id},
security_groups=[self.secgroup['security_group']['id']],
allowed_address_pairs=allowed_address_pairs)
networks = [{'port': port['id']}]
else:
networks = [{'uuid': network_id}]
params = {
'flavor_ref': self.flavor_ref,
'image_ref': self.image_ref,
'key_name': self.keypair['name'],
'networks': networks,
'security_groups': [
{'name': self.secgroup['security_group']['name']}],
'name': data_utils.rand_name(server_type)
}
if not (CONF.compute.min_compute_nodes > 1):
LOG.debug('number of compute nodes is not higher than 1 - '
'scheduler_hints will not be used')
elif scheduler_hints:
params['scheduler_hints'] = scheduler_hints
server = self.create_server(**params)['server']
self.wait_for_server_active(server)
port = self.client.list_ports(device_id=server['id'])['ports'][0]
access_ip_address = self.create_floatingip(
port=port)['floating_ip_address']
server['ssh_client'] = ssh.Client(access_ip_address,
self.username,
pkey=self.keypair['private_key'])
# enable icmp broadcast responses
server['ssh_client'].execute_script(
"sysctl net.ipv4.icmp_echo_ignore_broadcasts=0", become_root=True)
if self.vlan_transparent:
# configure transparent vlan on server
vlan_tag = vlan_tag or self.vlan_tag
server['vlan_device'] = self._configure_vlan_transparent(
port, server['ssh_client'], vlan_ipmask, vlan_tag)
self.servers.append(server)
return server
def _prepare_capture_script(self, server):
interface = server['vlan_device'] if self.vlan_transparent else 'any'
capture_script = get_capture_script(
result_file=self.capture_output_file,
interface=interface)
server['ssh_client'].execute_script(
'echo "%s" > /tmp/capture_script.sh' % capture_script)
def _check_broadcast_conectivity(self, sender, receivers,
nonreceivers=[], num_pings=1):
def _message_received(client, msg, file_path):
result = client.execute_script(
"cat {path} || echo '{path} not exists yet'".format(
path=file_path))
return msg in result
def _validate_number_of_messages(client, file_path, expected_count):
"""This function validates number of packets that reached a VM
The function compares actual received number of packets per group
with the expected number.
"""
result = client.execute_script(
"cat {path} || echo '{path} not exists yet'".format(
path=file_path))
# We need to make sure that exactly the expected count
# of messages reached receiver, no more and no less
LOG.debug('result = %s', result)
count = len(
re.findall(self.broadcast_message, result))
self.assertEqual(
count, expected_count,
'Received number of messages ({}) differs '
'from the expected ({})'.format(
count, num_pings))
# tcpdump started both on receivers and nonreceivers
for server in receivers + nonreceivers:
self._prepare_capture_script(server)
server['ssh_client'].execute_script(
"bash /tmp/capture_script.sh", become_root=True)
if not self.vlan_transparent:
cidr = self.subnet['cidr']
else:
cidr = self.vlan_ipmast_template.format(ip_last_byte=0)
broadcast_ip = netaddr.IPNetwork(cidr).broadcast
# waiting until tcpdump capturing on receivers
time.sleep(2)
sender['ssh_client'].execute_script(
("ping -b %(broadcast_ip)s -s %(ping_size)d "
"-c %(num_pings)d -p %(ping_pattern)s") % {
'broadcast_ip': broadcast_ip,
'ping_size': self.ping_size,
'num_pings': num_pings,
'ping_pattern': self.broadcast_message_pattern})
# waiting until packets reached receivers
time.sleep(2)
# num_ping packets expected on each receiver server
for server in receivers:
server['ssh_client'].execute_script(
"killall tcpdump && sleep 2", become_root=True)
LOG.debug('Validating number of messages on '
'receiver %s', server['id'])
_validate_number_of_messages(
server['ssh_client'], self.capture_output_file, num_pings)
# No packets expected on each nonreceiver server
for server in nonreceivers:
server['ssh_client'].execute_script(
"killall tcpdump && sleep 2", become_root=True)
LOG.debug('Validating number of messages on '
'receiver %s', server['id'])
_validate_number_of_messages(
server['ssh_client'], self.capture_output_file, 0)
class BroadcastTestIPv4(BaseBroadcastTest, base.TrafficFlowTest):
# IP version specific parameters
_ip_version = constants.IP_VERSION_4
any_addresses = constants.IPv4_ANY
class BroadcastTestIPv4Common(BroadcastTestIPv4):
@decorators.idempotent_id('7f33370a-5f46-4452-8b2f-166acda1720f')
def test_broadcast_same_network(self):
"""Test broadcast messaging between servers on the same network
[Sender server] -> (Broadcast network) -> [Receiver server]
Scenario:
1. Create VMs for sender, receiver(s) on a common internal network
and send broadcast ping messages
2. Verify that all broadcast packets reach the other hosts
In case of vlan_transparent, broadcast packets will be captured on VLAN
interfaces
"""
sender = self._create_server('broadcast-sender')
receivers = []
for i in range(self.receivers_count):
# even VMs scheduled on a different compute from the sender
# odd VMs scheduled on the same compute than the sender
if i % 2 == 0:
scheduler_hints = {'different_host': sender['id']}
else:
scheduler_hints = {'same_host': sender['id']}
receivers.append(self._create_server(
'broadcast-receiver', scheduler_hints=scheduler_hints))
self._check_broadcast_conectivity(sender=sender,
receivers=receivers,
num_pings=2)
class BroadcastTestVlanTransparency(BroadcastTestIPv4):
required_extensions = ['vlan-transparent', 'allowed-address-pairs']
vlan_transparent = True
vlan_tag = 123
vlan_ipmast_template = '192.168.111.{ip_last_byte}/24'
def _configure_vlan_transparent(self, port, ssh_client, vlan_ip, vlan_tag):
ip_command = ip.IPCommand(ssh_client=ssh_client)
for address in ip_command.list_addresses(port=port):
port_iface = address.device.name
break
else:
self.fail("Parent port fixed IP not found on server.")
subport_iface = ip_command.configure_vlan_transparent(
port=port, vlan_tag=vlan_tag, ip_addresses=[vlan_ip])
for address in ip_command.list_addresses(ip_addresses=vlan_ip):
self.assertEqual(subport_iface, address.device.name)
self.assertEqual(port_iface, address.device.parent)
break
else:
self.fail("Sub-port fixed IP not found on server.")
return subport_iface
@decorators.idempotent_id('7ea12762-31af-4bf2-9219-c54212171010')
def test_broadcast_vlan_transparency(self):
"""Test broadcast messaging between servers on the same network, but
using different VLANs
[Sender server] -> (Broadcast network) -> [Receiver server]
Scenario:
1. Create VMs for sender, receiver(s) on a common internal network
and send broadcast ping messages
2. Verify that all broadcast packets reach the other hosts within
a common VLAN and that receivers with different VLANs do not
receive those messages
"""
vlan_groups = (self.vlan_tag, self.vlan_tag + 1)
senders = {}
receivers = {}
for vlan_group in vlan_groups:
senders[vlan_group] = self._create_server(
'broadcast-sender-%d' % vlan_group, vlan_tag=vlan_group)
receivers[vlan_group] = []
for i in range(self.receivers_count):
# even VMs scheduled on a different compute from the sender
# odd VMs scheduled on the same compute than the sender
if i % 2 == 0:
scheduler_hints = {
'different_host': senders[vlan_group]['id']}
else:
scheduler_hints = {'same_host': senders[vlan_group]['id']}
receivers[vlan_group].append(
self._create_server('broadcast-receiver-%d' % vlan_group,
vlan_tag=vlan_group,
scheduler_hints=scheduler_hints))
self._check_broadcast_conectivity(
sender=senders[vlan_groups[0]],
receivers=receivers[vlan_groups[0]],
nonreceivers=receivers[vlan_groups[1]], num_pings=2)
self._check_broadcast_conectivity(
sender=senders[vlan_groups[1]],
receivers=receivers[vlan_groups[1]],
nonreceivers=receivers[vlan_groups[0]], num_pings=2)