
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
329 lines
15 KiB
Python
329 lines
15 KiB
Python
# Copyright 2022 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.
|
|
|
|
from neutron_lib import constants
|
|
from neutron_tempest_plugin.common import ssh
|
|
from neutron_tempest_plugin.common import utils
|
|
from neutron_tempest_plugin import config
|
|
from neutron_tempest_plugin.scenario import base
|
|
from oslo_log import log
|
|
import paramiko
|
|
from tempest.lib.common.utils import data_utils
|
|
from tempest.lib import decorators
|
|
from tempest.lib import exceptions as lib_exc
|
|
|
|
|
|
CONF = config.CONF
|
|
LOG = log.getLogger(__name__)
|
|
|
|
|
|
class NetworkDefaultSecGroupTest(base.BaseTempestTestCase):
|
|
credentials = ['primary', 'admin']
|
|
required_extensions = ['router', 'security-group']
|
|
|
|
@classmethod
|
|
def resource_setup(cls):
|
|
super(NetworkDefaultSecGroupTest, cls).resource_setup()
|
|
# setup basic topology for servers we can log into it
|
|
cls.network = cls.create_network()
|
|
cls.subnet = cls.create_subnet(cls.network, reserve_cidr=True)
|
|
cls.router = cls.create_router_by_client()
|
|
cls.create_router_interface(cls.router['id'], cls.subnet['id'])
|
|
cls.keypair = cls.create_keypair()
|
|
|
|
def create_vm_testing_sec_grp(self, num_servers=2, security_groups=None,
|
|
separate_nets=False):
|
|
servers, fips, server_ssh_clients = ([], [], [])
|
|
for i in range(num_servers):
|
|
# if separate_nets is True, each VM is connected to a different
|
|
# tenant network
|
|
if separate_nets and len(self.networks) < i + 1:
|
|
new_network = self.create_network()
|
|
new_subnet = self.create_subnet(new_network, reserve_cidr=True)
|
|
self.create_router_interface(self.router['id'],
|
|
new_subnet['id'])
|
|
network_id = self.networks[-1]['id']
|
|
servers.append(self.create_server(
|
|
flavor_ref=CONF.compute.flavor_ref,
|
|
image_ref=CONF.compute.image_ref,
|
|
key_name=self.keypair['name'],
|
|
networks=[{'uuid': network_id}],
|
|
security_groups=security_groups))
|
|
for i, server in enumerate(servers):
|
|
if separate_nets:
|
|
network_id = self.networks[i]['id']
|
|
else:
|
|
network_id = self.networks[0]['id']
|
|
port = self.client.list_ports(
|
|
network_id=network_id, device_id=server['server'][
|
|
'id'])['ports'][0]
|
|
fips.append(self.create_and_associate_floatingip(port['id']))
|
|
server_ssh_clients.append(ssh.Client(
|
|
fips[i]['floating_ip_address'], CONF.validation.image_ssh_user,
|
|
pkey=self.keypair['private_key']))
|
|
return server_ssh_clients, fips, servers
|
|
|
|
def _check_connectivity_udp(self, ssh_server, ssh_client, server_ip,
|
|
port_num, should_succeed=True, server_id=''):
|
|
"""Check connectivity to a UDP port
|
|
|
|
:param ssh_client(RemoteClient): SSH client of the client side
|
|
:param ssh_server(RemoteClient)): SSH client of the server side
|
|
:param server_ip(dict): The IP address of the server's side (either
|
|
FIP or internal IP)
|
|
:param port_num(int): The UDP port
|
|
:param should_succeed(boolean): Should the connection be successful
|
|
:param server_id(str): ID of server where nc listens
|
|
"""
|
|
def _run_commands(cmd1, cmd2, cmd3, cmd4, cmd5):
|
|
ssh_server.exec_command(cmd1)
|
|
# cmd2 needs to be executed with execute_script method on RHEL8
|
|
# instances because it includes a command that runs in background
|
|
# An exception will be launched for RHEL7 and cirros instances and
|
|
# exec_command method will be used for them
|
|
try:
|
|
ssh_server.execute_script(cmd2)
|
|
except paramiko.SSHException:
|
|
ssh_server.exec_command(cmd2)
|
|
ssh_client.exec_command(cmd3)
|
|
output = ssh_server.exec_command(cmd5)
|
|
if should_succeed:
|
|
result = expected_output in output
|
|
else:
|
|
result = expected_output not in output
|
|
ssh_server.exec_command(cmd4)
|
|
return result
|
|
|
|
# Creating a script on the server to write sg_check
|
|
# to /tmp/1 file
|
|
expected_output = "sg_check_" + server_id
|
|
cmd1 = ("echo '#!/bin/sh\necho {expected_output} > /tmp/{server_ip}' "
|
|
"> /tmp/{server_ip}.sh && chmod +x /tmp/{server_ip}.sh && "
|
|
"touch /tmp/{server_ip}".format(
|
|
expected_output=expected_output, server_ip=server_ip))
|
|
# Listen on UDP port and execute the script when a connection is made
|
|
cmd2 = ("sudo nc -l -u -p {port_num} -e /tmp/{server_ip}.sh > "
|
|
"/dev/null &\n".format(port_num=port_num, server_ip=server_ip))
|
|
# Make sure that ncat listener process is running
|
|
# It takes a bit on RHEL to launch a ncat listener process
|
|
cmd2 += ("for i in `seq 1 5`; do\n"
|
|
"$(PATH=$PATH:/usr/sbin which pidof) nc && exit 0\n"
|
|
"sleep 0.2\n"
|
|
"done\n"
|
|
"exit 1\n")
|
|
# Initiate a UDP connection
|
|
cmd3 = "echo sg | nc -w 10 -u %s %s" % (server_ip, port_num)
|
|
# Kill the nc process to avoid process creation failure
|
|
cmd4 = 'sudo kill -9 $($(PATH=$PATH:/usr/sbin which pidof) nc) || true'
|
|
cmd5 = "cat /tmp/{server_ip}".format(server_ip=server_ip)
|
|
|
|
try:
|
|
result = _run_commands(cmd1, cmd2, cmd3, cmd4, cmd5)
|
|
except base.SSH_EXC_TUPLE as ssh_e:
|
|
LOG.debug(ssh_e)
|
|
self._log_console_output()
|
|
self._log_local_network_status()
|
|
raise
|
|
return result
|
|
|
|
@decorators.idempotent_id('921f91f8-7734-4c42-8934-a1438d45747b')
|
|
def test_securitygroup_udp(self):
|
|
"""Test connectivity between VMs when they have security group with
|
|
UDP port configured
|
|
"""
|
|
PORT_UDP = 60000
|
|
secgrp_name = 'udp-secgrp'
|
|
secgrp = self.os_primary.network_client.create_security_group(
|
|
name=secgrp_name)
|
|
self.security_groups.append(secgrp['security_group'])
|
|
self.create_loginable_secgroup_rule(
|
|
secgroup_id=secgrp['security_group']['id'])
|
|
ssh_clients, fips, servers = self.create_vm_testing_sec_grp(
|
|
security_groups=[{'name': secgrp_name}])
|
|
|
|
# Testing the negative case before adding UDP port sec group rule
|
|
# Using FIP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[1],
|
|
ssh_client=ssh_clients[0],
|
|
server_ip=fips[1]['floating_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=False,
|
|
server_id=servers[1]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[1]['server']['id'])))
|
|
# Testing the negative case before adding UDP port sec group rule
|
|
# Using internal IP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[1],
|
|
ssh_client=ssh_clients[0],
|
|
server_ip=fips[1]['fixed_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=False,
|
|
server_id=servers[1]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[1]['server']['id'])))
|
|
|
|
rulesets = [{'protocol': constants.PROTO_NAME_UDP,
|
|
'port_range_min': PORT_UDP,
|
|
'port_range_max': PORT_UDP,
|
|
'direction': 'ingress',
|
|
'remote_ip_prefix': '0.0.0.0/0'}]
|
|
self.create_secgroup_rules(rulesets,
|
|
secgrp['security_group']['id'])
|
|
# Testing the UDP connectivity after adding UDP port sec group rule
|
|
# Using FIP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[0],
|
|
ssh_client=ssh_clients[1],
|
|
server_ip=fips[0]['floating_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=True,
|
|
server_id=servers[0]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[0]['server']['id'])))
|
|
# Testing the UDP connectivity after adding UDP port sec group rule
|
|
# Using internal IP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[0],
|
|
ssh_client=ssh_clients[1],
|
|
server_ip=fips[0]['fixed_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=True,
|
|
server_id=servers[0]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[0]['server']['id'])))
|
|
|
|
@decorators.idempotent_id('db6ab68e-0b9b-46e8-9b15-c9612da57a08')
|
|
def test_securitygroup_udp_dns(self):
|
|
"""Test connectivity between VMs on two different tenant networks
|
|
through the DNS port (UDP port 53)
|
|
"""
|
|
PORT_UDP = 53
|
|
secgrp_name = 'udp-dns-secgrp'
|
|
secgrp = self.os_primary.network_client.create_security_group(
|
|
name=secgrp_name)
|
|
self.security_groups.append(secgrp['security_group'])
|
|
self.create_loginable_secgroup_rule(
|
|
secgroup_id=secgrp['security_group']['id'])
|
|
ssh_clients, fips, servers = self.create_vm_testing_sec_grp(
|
|
security_groups=[{'name': secgrp_name}], separate_nets=True)
|
|
|
|
# Testing the negative case before adding UDP port sec group rule
|
|
# Using FIP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[1],
|
|
ssh_client=ssh_clients[0],
|
|
server_ip=fips[1]['floating_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=False,
|
|
server_id=servers[1]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[1]['server']['id'])))
|
|
# Testing the negative case before adding UDP port sec group rule
|
|
# Using internal IP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[1],
|
|
ssh_client=ssh_clients[0],
|
|
server_ip=fips[1]['fixed_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=False,
|
|
server_id=servers[1]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[1]['server']['id'])))
|
|
|
|
rulesets = [{'protocol': constants.PROTO_NAME_UDP,
|
|
'port_range_min': PORT_UDP,
|
|
'port_range_max': PORT_UDP,
|
|
'direction': 'ingress',
|
|
'remote_ip_prefix': '0.0.0.0/0'}]
|
|
self.create_secgroup_rules(rulesets,
|
|
secgrp['security_group']['id'])
|
|
# Testing the UDP connectivity after adding UDP port sec group rule
|
|
# Using FIP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[0],
|
|
ssh_client=ssh_clients[1],
|
|
server_ip=fips[0]['floating_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=True,
|
|
server_id=servers[0]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[0]['server']['id'])))
|
|
# Testing the UDP connectivity after adding UDP port sec group rule
|
|
# Using internal IP
|
|
utils.wait_until_true(
|
|
lambda: self._check_connectivity_udp(
|
|
ssh_server=ssh_clients[0],
|
|
ssh_client=ssh_clients[1],
|
|
server_ip=fips[0]['fixed_ip_address'],
|
|
port_num=PORT_UDP,
|
|
should_succeed=True,
|
|
server_id=servers[0]['server']['id']),
|
|
exception=RuntimeError(
|
|
"Timed out waiting for message from server {!r} ".format(
|
|
servers[0]['server']['id'])))
|
|
|
|
@decorators.attr(type='negative')
|
|
@decorators.idempotent_id('cc5f679e-7196-4e68-8a82-10b73bf11e48')
|
|
def test_remove_security_group_negative(self):
|
|
# Create "existing security group"
|
|
existing_sg = self.os_primary.network_client.create_security_group(
|
|
name=data_utils.rand_name('test_sg'))
|
|
|
|
# Create "not existing security group"
|
|
not_existing_sg = self.os_primary.network_client.create_security_group(
|
|
name=data_utils.rand_name('test_sg'))
|
|
self.delete_security_group(not_existing_sg['security_group'])
|
|
|
|
# Create the VM
|
|
server_args = {
|
|
'flavor_ref': CONF.compute.flavor_ref,
|
|
'image_ref': CONF.compute.image_ref,
|
|
'key_name': self.keypair['name'],
|
|
'networks': [{'uuid': self.network['id']}]
|
|
}
|
|
server = self.create_server(**server_args)
|
|
LOG.info('test_negative server: %s', server['server'])
|
|
|
|
# Try to remove "Existing SG ID" that is not associated to VM Network
|
|
# from VM.
|
|
self.assertRaises(
|
|
lib_exc.NotFound,
|
|
self.os_primary.servers_client.remove_security_group,
|
|
server_id=server['server']['id'],
|
|
name=existing_sg['security_group']['id'])
|
|
|
|
# Try to remove "Not Existing SG ID" from VM.
|
|
self.assertRaises(
|
|
lib_exc.NotFound,
|
|
self.os_primary.servers_client.remove_security_group,
|
|
server_id=server['server']['id'],
|
|
name=not_existing_sg['security_group']['id'])
|