Use NGIX HTTP server for testing curl integration

Change-Id: I629b4444ee8d70aaee9e4c4f92fc3a50f5db973b
This commit is contained in:
Federico Ressi 2021-06-03 11:46:31 +02:00
parent 2cde963248
commit eeacdedee0
12 changed files with 147 additions and 170 deletions

View File

@ -425,9 +425,10 @@ class CustomizedGlanceImageFixture(URLGlanceImageFixture):
command = sh.shell_command(['virt-customize', '-a', work_file]) command = sh.shell_command(['virt-customize', '-a', work_file])
execute = False execute = False
for package in self.install_packages: if self.install_packages:
execute = True execute = True
command += ['--install', package] command += ['--install', ','.join(self.install_packages)]
if execute: if execute:
sh.execute(command) sh.execute(command)

View File

@ -22,13 +22,13 @@ from tobiko.openstack.stacks import _l3ha
from tobiko.openstack.stacks import _neutron from tobiko.openstack.stacks import _neutron
from tobiko.openstack.stacks import _nova from tobiko.openstack.stacks import _nova
from tobiko.openstack.stacks import _octavia from tobiko.openstack.stacks import _octavia
from tobiko.openstack.stacks import _qos
from tobiko.openstack.stacks import _ubuntu from tobiko.openstack.stacks import _ubuntu
CentosFlavorStackFixture = _centos.CentosFlavorStackFixture CentosFlavorStackFixture = _centos.CentosFlavorStackFixture
CentosImageFixture = _centos.CentosImageFixture CentosImageFixture = _centos.CentosImageFixture
CentosServerStackFixture = _centos.CentosServerStackFixture CentosServerStackFixture = _centos.CentosServerStackFixture
CentosExternalServerStackFixture = _centos.CentosExternalServerStackFixture CentosExternalServerStackFixture = _centos.CentosExternalServerStackFixture
CentosQosServerStackFixture = _centos.CentosQosServerStackFixture
CirrosFlavorStackFixture = _cirros.CirrosFlavorStackFixture CirrosFlavorStackFixture = _cirros.CirrosFlavorStackFixture
CirrosImageFixture = _cirros.CirrosImageFixture CirrosImageFixture = _cirros.CirrosImageFixture
@ -75,13 +75,16 @@ ServerGroupStackFixture = _nova.ServerGroupStackFixture
AffinityServerGroupStackFixture = _nova.AffinityServerGroupStackFixture AffinityServerGroupStackFixture = _nova.AffinityServerGroupStackFixture
AntiAffinityServerGroupStackFixture = _nova.AntiAffinityServerGroupStackFixture AntiAffinityServerGroupStackFixture = _nova.AntiAffinityServerGroupStackFixture
QosNetworkStackFixture = _qos.QosNetworkStackFixture
QosPolicyStackFixture = _qos.QosPolicyStackFixture
QosServerStackFixture = _qos.QosServerStackFixture
UbuntuFlavorStackFixture = _ubuntu.UbuntuFlavorStackFixture UbuntuFlavorStackFixture = _ubuntu.UbuntuFlavorStackFixture
UbuntuImageFixture = _ubuntu.UbuntuImageFixture UbuntuImageFixture = _ubuntu.UbuntuImageFixture
UbuntuMinimalImageFixture = _ubuntu.UbuntuMinimalImageFixture UbuntuMinimalImageFixture = _ubuntu.UbuntuMinimalImageFixture
UbuntuServerStackFixture = _ubuntu.UbuntuServerStackFixture UbuntuServerStackFixture = _ubuntu.UbuntuServerStackFixture
UbuntuMinimalServerStackFixture = _ubuntu.UbuntuMinimalServerStackFixture UbuntuMinimalServerStackFixture = _ubuntu.UbuntuMinimalServerStackFixture
UbuntuExternalServerStackFixture = _ubuntu.UbuntuExternalServerStackFixture UbuntuExternalServerStackFixture = _ubuntu.UbuntuExternalServerStackFixture
UbuntuQosServerStackFixture = _ubuntu.UbuntuQosServerStackFixture
OctaviaLoadbalancerStackFixture = _octavia.OctaviaLoadbalancerStackFixture OctaviaLoadbalancerStackFixture = _octavia.OctaviaLoadbalancerStackFixture
OctaviaListenerStackFixture = _octavia.OctaviaListenerStackFixture OctaviaListenerStackFixture = _octavia.OctaviaListenerStackFixture

View File

@ -16,7 +16,6 @@ from __future__ import absolute_import
import tobiko import tobiko
from tobiko import config from tobiko import config
from tobiko.openstack import glance from tobiko.openstack import glance
from tobiko.openstack import nova
from tobiko.openstack.stacks import _nova from tobiko.openstack.stacks import _nova
@ -58,13 +57,3 @@ class CentosServerStackFixture(_nova.CloudInitServerStackFixture):
class CentosExternalServerStackFixture(CentosServerStackFixture, class CentosExternalServerStackFixture(CentosServerStackFixture,
_nova.ExternalServerStackFixture): _nova.ExternalServerStackFixture):
pass pass
class CentosQosServerStackFixture(CentosServerStackFixture,
_nova.QosServerStackFixture):
@property
def cloud_config(self):
return nova.cloud_config(
super(CentosQosServerStackFixture, self).cloud_config,
packages=['iperf3'])

View File

@ -299,37 +299,6 @@ class NetworkWithNetMtuWriteStackFixture(NetworkStackFixture):
return dict(value_specs, mtu=self.custom_mtu_size) return dict(value_specs, mtu=self.custom_mtu_size)
@neutron.skip_if_missing_networking_extensions('qos')
class QosPolicyStackFixture(heat.HeatStackFixture):
"""Heat stack with a QoS Policy and some QoS Policy Rules
"""
has_qos_policy = True
has_bwlimit = True
has_dscp_marking = True
bwlimit_kbps = CONF.tobiko.neutron.bwlimit_kbps
bwlimit_burst_kbps = int(0.8 * bwlimit_kbps)
direction = CONF.tobiko.neutron.direction
dscp_mark = CONF.tobiko.neutron.dscp_mark
#: Heat template file
template = _hot.heat_template_file('neutron/qos.yaml')
@neutron.skip_if_missing_networking_extensions('qos')
class NetworkQosPolicyStackFixture(NetworkStackFixture):
#: stack with the qos policy for the network
qos_stack = tobiko.required_setup_fixture(QosPolicyStackFixture)
has_qos_policy = True
@property
def network_value_specs(self):
value_specs = super(NetworkQosPolicyStackFixture,
self).network_value_specs
return dict(value_specs, qos_policy_id=self.qos_stack.qos_policy_id)
@neutron.skip_if_missing_networking_extensions('security-group') @neutron.skip_if_missing_networking_extensions('security-group')
class SecurityGroupsFixture(heat.HeatStackFixture): class SecurityGroupsFixture(heat.HeatStackFixture):
"""Heat stack with some security groups """Heat stack with some security groups

View File

@ -82,7 +82,7 @@ class FlavorStackFixture(heat.HeatStackFixture):
is_public = None is_public = None
name = None name = None
rxtx_factor = None rxtx_factor = None
swap = None swap: typing.Optional[int] = None
vcpus = None vcpus = None
@ -415,12 +415,6 @@ class ExternalServerStackFixture(ServerStackFixture, abc.ABC):
return self.network_stack.network_id return self.network_stack.network_id
class QosServerStackFixture(ServerStackFixture, abc.ABC):
#: stack with the network with a qos policy
network_stack = tobiko.required_setup_fixture(
_neutron.NetworkQosPolicyStackFixture)
class PeerServerStackFixture(ServerStackFixture, abc.ABC): class PeerServerStackFixture(ServerStackFixture, abc.ABC):
"""Server witch networking access requires passing by another Nova server """Server witch networking access requires passing by another Nova server
""" """

View File

@ -0,0 +1,62 @@
# Copyright (c) 2021 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 __future__ import absolute_import
import tobiko
from tobiko import config
from tobiko.openstack import heat
from tobiko.openstack import neutron
from tobiko.openstack.stacks import _neutron
from tobiko.openstack.stacks import _hot
from tobiko.openstack.stacks import _ubuntu
CONF = config.CONF
@neutron.skip_if_missing_networking_extensions('qos')
class QosPolicyStackFixture(heat.HeatStackFixture):
"""Heat stack with a QoS Policy and some QoS Policy Rules
"""
has_qos_policy = True
has_bwlimit = True
has_dscp_marking = True
bwlimit_kbps = CONF.tobiko.neutron.bwlimit_kbps
bwlimit_burst_kbps = int(0.8 * bwlimit_kbps)
direction = CONF.tobiko.neutron.direction
dscp_mark = CONF.tobiko.neutron.dscp_mark
#: Heat template file
template = _hot.heat_template_file('neutron/qos.yaml')
@neutron.skip_if_missing_networking_extensions('qos')
class QosNetworkStackFixture(_neutron.NetworkStackFixture):
#: stack with the qos policy for the network
qos_stack = tobiko.required_setup_fixture(QosPolicyStackFixture)
has_qos_policy = True
@property
def network_value_specs(self):
value_specs = super().network_value_specs
return dict(value_specs, qos_policy_id=self.qos_stack.qos_policy_id)
class QosServerStackFixture(_ubuntu.UbuntuServerStackFixture):
#: stack with the network with a qos policy
network_stack = tobiko.required_setup_fixture(QosNetworkStackFixture)

View File

@ -16,16 +16,13 @@ from __future__ import absolute_import
import tobiko import tobiko
from tobiko import config from tobiko import config
from tobiko.openstack import glance from tobiko.openstack import glance
from tobiko.openstack import nova
from tobiko.openstack.stacks import _nova from tobiko.openstack.stacks import _nova
CONF = config.CONF CONF = config.CONF
UBUNTU_IMAGE_VERSION = 'focal' UBUNTU_IMAGE_VERSION = 'focal'
UBUNTU_IMAGE_URL = (
f'http://cloud-images.ubuntu.com/{UBUNTU_IMAGE_VERSION}/current/'
f'{UBUNTU_IMAGE_VERSION}-server-cloudimg-amd64.img')
UBUNTU_IMAGE_VERSION_NUMBER = '20.04' UBUNTU_IMAGE_VERSION_NUMBER = '20.04'
UBUNTU_MINIMAL_IMAGE_URL = ( UBUNTU_MINIMAL_IMAGE_URL = (
@ -34,8 +31,8 @@ UBUNTU_MINIMAL_IMAGE_URL = (
f'ubuntu-{UBUNTU_IMAGE_VERSION_NUMBER}-minimal-cloudimg-amd64.img') f'ubuntu-{UBUNTU_IMAGE_VERSION_NUMBER}-minimal-cloudimg-amd64.img')
class UbuntuImageFixture(glance.URLGlanceImageFixture): class UbuntuMinimalImageFixture(glance.URLGlanceImageFixture):
image_url = CONF.tobiko.ubuntu.image_url or UBUNTU_IMAGE_URL image_url = CONF.tobiko.ubuntu.image_url or UBUNTU_MINIMAL_IMAGE_URL
image_name = CONF.tobiko.ubuntu.image_name image_name = CONF.tobiko.ubuntu.image_name
image_file = CONF.tobiko.ubuntu.image_file image_file = CONF.tobiko.ubuntu.image_file
disk_format = CONF.tobiko.ubuntu.disk_format or "qcow2" disk_format = CONF.tobiko.ubuntu.disk_format or "qcow2"
@ -45,55 +42,54 @@ class UbuntuImageFixture(glance.URLGlanceImageFixture):
connection_timeout = CONF.tobiko.ubuntu.connection_timeout or 600. connection_timeout = CONF.tobiko.ubuntu.connection_timeout or 600.
class UbuntuMinimalImageFixture(UbuntuImageFixture): class UbuntuImageFixture(UbuntuMinimalImageFixture,
image_url = UBUNTU_MINIMAL_IMAGE_URL glance.CustomizedGlanceImageFixture):
"""Ubuntu server image running an HTTP server
The server has additional commands compared to the minimal one:
iperf3
ping
"""
install_packages = ['iperf3', 'iputils-ping', 'nginx']
class UbuntuFlavorStackFixture(_nova.FlavorStackFixture): class UbuntuFlavorStackFixture(_nova.FlavorStackFixture):
ram = 256
class UbuntuMinimalFlavorStackFixture(_nova.FlavorStackFixture):
ram = 128 ram = 128
swap = 512
class UbuntuServerStackFixture(_nova.CloudInitServerStackFixture): class UbuntuMinimalServerStackFixture(_nova.CloudInitServerStackFixture):
#: Glance image used to create a Nova server instance
image_fixture = tobiko.required_setup_fixture(UbuntuImageFixture)
#: Flavor used to create a Nova server instance
flavor_stack = tobiko.required_setup_fixture(UbuntuFlavorStackFixture)
#: Setup SWAP file in bytes
swap_maxsize = 1 * 1024 * 1024 * 1024 # 1 GB
class UbuntuMinimalServerStackFixture(UbuntuServerStackFixture):
#: Glance image used to create a Nova server instance #: Glance image used to create a Nova server instance
image_fixture = tobiko.required_setup_fixture(UbuntuMinimalImageFixture) image_fixture = tobiko.required_setup_fixture(UbuntuMinimalImageFixture)
#: Flavor used to create a Nova server instance #: Flavor used to create a Nova server instance
flavor_stack = tobiko.required_setup_fixture( flavor_stack = tobiko.required_setup_fixture(UbuntuFlavorStackFixture)
UbuntuMinimalFlavorStackFixture)
#: Setup SWAP file in bytes
swap_maxsize = 512 * 1024 * 1024 # 500 MB class UbuntuServerStackFixture(UbuntuMinimalServerStackFixture):
"""Ubuntu server running an HTTP server
The server has additional commands compared to the minimal one:
iperf3
ping
"""
#: Glance image used to create a Nova server instance
image_fixture = tobiko.required_setup_fixture(UbuntuImageFixture)
# port of running HTTP server
http_port = 80
@property
def cloud_config(self):
return nova.cloud_config(
super().cloud_config,
runcmd=["sh -c 'hostname > /var/www/html/id'"])
class UbuntuExternalServerStackFixture(UbuntuMinimalServerStackFixture, class UbuntuExternalServerStackFixture(UbuntuMinimalServerStackFixture,
_nova.ExternalServerStackFixture): _nova.ExternalServerStackFixture):
pass """Ubuntu server with port on special external network
"""
class UbuntuQosServerImageFixture(UbuntuMinimalImageFixture,
glance.CustomizedGlanceImageFixture):
install_packages = ['iperf3']
class UbuntuQosServerStackFixture(UbuntuMinimalServerStackFixture,
_nova.QosServerStackFixture):
#: Glance image used to create a Nova server instance
image_fixture = tobiko.required_setup_fixture(UbuntuQosServerImageFixture)

View File

@ -26,7 +26,9 @@ from tobiko.shell import ssh
CURL_CONNECTION_ERRORS = { CURL_CONNECTION_ERRORS = {
7 # Connection refused 7, # Connection refused
22, # 404 Not Found
28, # Connection timedout
} }

View File

@ -22,7 +22,6 @@ import testtools
import tobiko import tobiko
from tobiko.openstack import keystone from tobiko.openstack import keystone
from tobiko.openstack import neutron
from tobiko.openstack import nova from tobiko.openstack import nova
from tobiko.openstack import stacks from tobiko.openstack import stacks
from tobiko.shell import curl from tobiko.shell import curl
@ -122,24 +121,6 @@ class CirrosServerStackTest(testtools.TestCase):
filenames=self.nameservers_filenames) filenames=self.nameservers_filenames)
self.assertEqual(subnet_nameservers, server_nameservers) self.assertEqual(subnet_nameservers, server_nameservers)
def test_ping_ipv4_nameservers(self):
self._test_ping_nameservers(ip_version=4)
def test_ping_ipv6_nameservers(self):
self._test_ping_nameservers(ip_version=6)
@neutron.skip_unless_is_ovs()
def _test_ping_nameservers(self, ip_version: int):
nameservers = sh.list_nameservers(ssh_client=self.stack.ssh_client,
filenames=self.nameservers_filenames,
ip_version=ip_version)
if not nameservers:
self.skipTest(f"Target server has no IPv{ip_version} "
"nameservers configured")
ping.assert_reachable_hosts(nameservers,
ssh_client=self.stack.ssh_client,
count=5)
class EvacuablesServerStackTest(CirrosServerStackTest): class EvacuablesServerStackTest(CirrosServerStackTest):

View File

@ -15,8 +15,6 @@
# under the License. # under the License.
from __future__ import absolute_import from __future__ import absolute_import
import pytest
import tobiko import tobiko
from tobiko.shell import sh from tobiko.shell import sh
from tobiko.openstack import stacks from tobiko.openstack import stacks
@ -44,13 +42,8 @@ class UbuntuMinimalServerStackTest(UbuntuServerStackTest):
stack = tobiko.required_setup_fixture( stack = tobiko.required_setup_fixture(
stacks.UbuntuMinimalServerStackFixture) stacks.UbuntuMinimalServerStackFixture)
@pytest.mark.skip(reason="ping not installed on image")
def test_ping_fixed_ipv4(self): def test_ping_fixed_ipv4(self):
pass tobiko.skip_test("ping not installed on image")
@pytest.mark.skip(reason="ping not installed on image")
def test_ping_fixed_ipv6(self): def test_ping_fixed_ipv6(self):
pass tobiko.skip_test("ping not installed on image")
def _test_ping_nameservers(self, ip_version: int):
self.skipTest("ping not installed on Ubuntu minimal image")

View File

@ -15,7 +15,6 @@
# under the License. # under the License.
from __future__ import absolute_import from __future__ import absolute_import
import random
import typing import typing
import netaddr import netaddr
@ -23,15 +22,13 @@ import testtools
import tobiko import tobiko
from tobiko.shell import curl from tobiko.shell import curl
from tobiko.shell import sh
from tobiko.shell import ssh from tobiko.shell import ssh
from tobiko.openstack import stacks from tobiko.openstack import stacks
class TestCurl(testtools.TestCase): class TestCurl(testtools.TestCase):
server_stack = tobiko.required_setup_fixture( stack = tobiko.required_setup_fixture(stacks.UbuntuServerStackFixture)
stacks.CirrosServerStackFixture)
def test_execute_curl( def test_execute_curl(
self, self,
@ -39,41 +36,31 @@ class TestCurl(testtools.TestCase):
ssh_client: typing.Optional[ssh.SSHClientFixture] = None): ssh_client: typing.Optional[ssh.SSHClientFixture] = None):
if ip_address is None: if ip_address is None:
# Use the floating IP # Use the floating IP
ip_address = self.server_stack.ip_address ip_address = self.stack.ip_address
server_id = self.server_stack.server_id http_port = self.stack.http_port
http_port = random.randint(10000, 30000) result = curl.execute_curl(scheme='http',
reply = (f"HTTP/1.1 200 OK\r\n" hostname=ip_address,
f"Content-Length:{len(server_id)}\r\n" port=http_port,
"\r\n" path='/id',
f"{server_id}") ssh_client=ssh_client,
http_server_command = f"nc -lk -p {http_port} -e echo -e '{reply}'" connect_timeout=10.,
http_server = sh.process(http_server_command, retry_count=30,
ssh_client=self.server_stack.ssh_client) retry_timeout=300.,
http_server.execute() retry_interval=10.).strip()
self.addCleanup(http_server.kill) self.assertEqual(self.stack.server_name, result)
reply = curl.execute_curl(scheme='http',
hostname=ip_address,
port=http_port,
ssh_client=ssh_client,
connect_timeout=5.,
retry_count=10,
retry_timeout=60.)
self.assertEqual(server_id, reply)
def test_execute_curl_ipv4(self): def test_execute_curl_ipv4(self):
self.test_execute_curl(ip_address=self.get_fixed_ip(ip_version=4), self.test_execute_curl(ip_address=self.get_fixed_ip(ip_version=4),
ssh_client=self.server_stack.ssh_client) ssh_client=self.stack.ssh_client)
def test_execute_curl_ipv6(self): def test_execute_curl_ipv6(self):
self.test_execute_curl(ip_address=self.get_fixed_ip(ip_version=6), self.test_execute_curl(ip_address=self.get_fixed_ip(ip_version=6),
ssh_client=self.server_stack.ssh_client) ssh_client=self.stack.ssh_client)
def get_fixed_ip(self, ip_version): def get_fixed_ip(self, ip_version):
for fixed_ip in self.server_stack.fixed_ips: for fixed_ip in self.stack.fixed_ips:
ip_address = netaddr.IPAddress(fixed_ip['ip_address']) ip_address = netaddr.IPAddress(fixed_ip['ip_address'])
if ip_version == ip_address.version: if ip_version == ip_address.version:
return ip_address return ip_address
self.skipTest( self.skipTest(f"Server {self.stack.server_id} has any "
f"Server {self.server_stack.server_id} has any " f"IPv{ip_version} address.")
f"IPv{ip_version} address.")

View File

@ -28,33 +28,33 @@ from tobiko.tripleo import overcloud
LOG = log.getLogger(__name__) LOG = log.getLogger(__name__)
class QoSBasicTest(testtools.TestCase): class QoSNetworkTest(testtools.TestCase):
"""Tests QoS basic functionality""" """Tests QoS basic functionality"""
#: Resources stack with QoS Policy and QoS Rules and Advanced server #: Resources stacks with QoS Policy and QoS Rules and Advanced server
stack = tobiko.required_setup_fixture(stacks.UbuntuQosServerStackFixture) network = tobiko.required_setup_fixture(stacks.QosNetworkStackFixture)
policy = tobiko.required_setup_fixture(stacks.QosPolicyStackFixture)
server = tobiko.required_setup_fixture(stacks.QosServerStackFixture)
def setUp(self): def setUp(self):
"""Skip these tests if OVN is configured and OSP version is lower than super().setUp()
16.1
"""
super(QoSBasicTest, self).setUp()
if (overcloud.has_overcloud() and if (overcloud.has_overcloud() and
topology.verify_osp_version('16.0', lower=True) and topology.verify_osp_version('16.0', lower=True) and
containers.ovn_used_on_overcloud()): containers.ovn_used_on_overcloud()):
# Skip these tests if OVN is configured and OSP version is lower
# than 16.1
self.skipTest("QoS not supported in this setup") self.skipTest("QoS not supported in this setup")
def test_network_qos_policy_id(self): def test_network_qos_policy_id(self):
'''Verify QoS Policy attached to the network corresponds with the QoS """Verify network policy ID"""
Policy previously created''' self.assertEqual(self.policy.qos_policy_id,
self.assertEqual(self.stack.network_stack.qos_stack.qos_policy_id, self.network.qos_policy_id)
self.stack.network_stack.qos_policy_id)
def test_server_qos_policy_id(self): def test_server_qos_policy_id(self):
self.assertIsNone(self.stack.port_details['qos_policy_id']) """Verify server policy ID"""
self.assertIsNone(self.server.port_details['qos_policy_id'])
def test_qos_bw_limit(self): def test_qos_bw_limit(self):
'''Verify BW limit using the iperf tool """Verify BW limit using the iperf3 tool"""
'''
iperf.assert_bw_limit(ssh_client=None, # localhost will act as client iperf.assert_bw_limit(ssh_client=None, # localhost will act as client
ssh_server=self.stack.peer_ssh_client) ssh_server=self.server.peer_ssh_client)