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])
execute = False
for package in self.install_packages:
if self.install_packages:
execute = True
command += ['--install', package]
command += ['--install', ','.join(self.install_packages)]
if execute:
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 _nova
from tobiko.openstack.stacks import _octavia
from tobiko.openstack.stacks import _qos
from tobiko.openstack.stacks import _ubuntu
CentosFlavorStackFixture = _centos.CentosFlavorStackFixture
CentosImageFixture = _centos.CentosImageFixture
CentosServerStackFixture = _centos.CentosServerStackFixture
CentosExternalServerStackFixture = _centos.CentosExternalServerStackFixture
CentosQosServerStackFixture = _centos.CentosQosServerStackFixture
CirrosFlavorStackFixture = _cirros.CirrosFlavorStackFixture
CirrosImageFixture = _cirros.CirrosImageFixture
@ -75,13 +75,16 @@ ServerGroupStackFixture = _nova.ServerGroupStackFixture
AffinityServerGroupStackFixture = _nova.AffinityServerGroupStackFixture
AntiAffinityServerGroupStackFixture = _nova.AntiAffinityServerGroupStackFixture
QosNetworkStackFixture = _qos.QosNetworkStackFixture
QosPolicyStackFixture = _qos.QosPolicyStackFixture
QosServerStackFixture = _qos.QosServerStackFixture
UbuntuFlavorStackFixture = _ubuntu.UbuntuFlavorStackFixture
UbuntuImageFixture = _ubuntu.UbuntuImageFixture
UbuntuMinimalImageFixture = _ubuntu.UbuntuMinimalImageFixture
UbuntuServerStackFixture = _ubuntu.UbuntuServerStackFixture
UbuntuMinimalServerStackFixture = _ubuntu.UbuntuMinimalServerStackFixture
UbuntuExternalServerStackFixture = _ubuntu.UbuntuExternalServerStackFixture
UbuntuQosServerStackFixture = _ubuntu.UbuntuQosServerStackFixture
OctaviaLoadbalancerStackFixture = _octavia.OctaviaLoadbalancerStackFixture
OctaviaListenerStackFixture = _octavia.OctaviaListenerStackFixture

View File

@ -16,7 +16,6 @@ from __future__ import absolute_import
import tobiko
from tobiko import config
from tobiko.openstack import glance
from tobiko.openstack import nova
from tobiko.openstack.stacks import _nova
@ -58,13 +57,3 @@ class CentosServerStackFixture(_nova.CloudInitServerStackFixture):
class CentosExternalServerStackFixture(CentosServerStackFixture,
_nova.ExternalServerStackFixture):
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)
@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')
class SecurityGroupsFixture(heat.HeatStackFixture):
"""Heat stack with some security groups

View File

@ -82,7 +82,7 @@ class FlavorStackFixture(heat.HeatStackFixture):
is_public = None
name = None
rxtx_factor = None
swap = None
swap: typing.Optional[int] = None
vcpus = None
@ -415,12 +415,6 @@ class ExternalServerStackFixture(ServerStackFixture, abc.ABC):
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):
"""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
from tobiko import config
from tobiko.openstack import glance
from tobiko.openstack import nova
from tobiko.openstack.stacks import _nova
CONF = config.CONF
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_MINIMAL_IMAGE_URL = (
@ -34,8 +31,8 @@ UBUNTU_MINIMAL_IMAGE_URL = (
f'ubuntu-{UBUNTU_IMAGE_VERSION_NUMBER}-minimal-cloudimg-amd64.img')
class UbuntuImageFixture(glance.URLGlanceImageFixture):
image_url = CONF.tobiko.ubuntu.image_url or UBUNTU_IMAGE_URL
class UbuntuMinimalImageFixture(glance.URLGlanceImageFixture):
image_url = CONF.tobiko.ubuntu.image_url or UBUNTU_MINIMAL_IMAGE_URL
image_name = CONF.tobiko.ubuntu.image_name
image_file = CONF.tobiko.ubuntu.image_file
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.
class UbuntuMinimalImageFixture(UbuntuImageFixture):
image_url = UBUNTU_MINIMAL_IMAGE_URL
class UbuntuImageFixture(UbuntuMinimalImageFixture,
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):
ram = 256
class UbuntuMinimalFlavorStackFixture(_nova.FlavorStackFixture):
ram = 128
swap = 512
class UbuntuServerStackFixture(_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):
class UbuntuMinimalServerStackFixture(_nova.CloudInitServerStackFixture):
#: Glance image used to create a Nova server instance
image_fixture = tobiko.required_setup_fixture(UbuntuMinimalImageFixture)
#: Flavor used to create a Nova server instance
flavor_stack = tobiko.required_setup_fixture(
UbuntuMinimalFlavorStackFixture)
flavor_stack = tobiko.required_setup_fixture(UbuntuFlavorStackFixture)
#: 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,
_nova.ExternalServerStackFixture):
pass
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)
"""Ubuntu server with port on special external network
"""

View File

@ -26,7 +26,9 @@ from tobiko.shell import ssh
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
from tobiko.openstack import keystone
from tobiko.openstack import neutron
from tobiko.openstack import nova
from tobiko.openstack import stacks
from tobiko.shell import curl
@ -122,24 +121,6 @@ class CirrosServerStackTest(testtools.TestCase):
filenames=self.nameservers_filenames)
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):

View File

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

View File

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

View File

@ -28,33 +28,33 @@ from tobiko.tripleo import overcloud
LOG = log.getLogger(__name__)
class QoSBasicTest(testtools.TestCase):
class QoSNetworkTest(testtools.TestCase):
"""Tests QoS basic functionality"""
#: Resources stack with QoS Policy and QoS Rules and Advanced server
stack = tobiko.required_setup_fixture(stacks.UbuntuQosServerStackFixture)
#: Resources stacks with QoS Policy and QoS Rules and Advanced server
network = tobiko.required_setup_fixture(stacks.QosNetworkStackFixture)
policy = tobiko.required_setup_fixture(stacks.QosPolicyStackFixture)
server = tobiko.required_setup_fixture(stacks.QosServerStackFixture)
def setUp(self):
"""Skip these tests if OVN is configured and OSP version is lower than
16.1
"""
super(QoSBasicTest, self).setUp()
super().setUp()
if (overcloud.has_overcloud() and
topology.verify_osp_version('16.0', lower=True) and
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")
def test_network_qos_policy_id(self):
'''Verify QoS Policy attached to the network corresponds with the QoS
Policy previously created'''
self.assertEqual(self.stack.network_stack.qos_stack.qos_policy_id,
self.stack.network_stack.qos_policy_id)
"""Verify network policy ID"""
self.assertEqual(self.policy.qos_policy_id,
self.network.qos_policy_id)
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):
'''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
ssh_server=self.stack.peer_ssh_client)
ssh_server=self.server.peer_ssh_client)