Skip functional test cases requiring Keystone credentials

Change-Id: Ib2143b49f8028ec6e4476dece8f8072cd9690967
This commit is contained in:
Federico Ressi 2020-09-22 15:22:17 +02:00
parent efe9febf9a
commit 7d20c11226
24 changed files with 160 additions and 54 deletions

View File

@ -18,7 +18,7 @@ import io
import os
import tempfile
import time
import typing
import typing # noqa
from oslo_log import log
import requests
@ -27,6 +27,7 @@ import tobiko
from tobiko.config import get_bool_env
from tobiko.openstack.glance import _client
from tobiko.openstack.glance import _io
from tobiko.openstack import keystone
LOG = log.getLogger(__name__)
@ -79,15 +80,19 @@ class GlanceImageStatus(object):
IMPORTING = u'importing'
@keystone.skip_unless_has_keystone_credentials()
class GlanceImageFixture(_client.HasGlanceClientMixin, tobiko.SharedFixture):
image_name = None # type: str
username = None # type: str
password = None # type: str
image_name: typing.Optional[str] = None
username: typing.Optional[str] = None
password: typing.Optional[str] = None
image = None
wait_interval = 5.
def __init__(self, image_name=None, username=None, password=None):
def __init__(self,
image_name: typing.Optional[str] = None,
username: typing.Optional[str] = None, password:
typing.Optional[str] = None):
super(GlanceImageFixture, self).__init__()
if image_name:
@ -333,7 +338,7 @@ class FileGlanceImageFixture(UploadGranceImageFixture):
class URLGlanceImageFixture(FileGlanceImageFixture):
image_url = None # type: str
image_url: typing.Optional[str] = None
def __init__(self, image_url=None, **kwargs):
super(URLGlanceImageFixture, self).__init__(**kwargs)

View File

@ -25,6 +25,7 @@ import tobiko
from tobiko import config
from tobiko.openstack.heat import _client
from tobiko.openstack.heat import _template
from tobiko.openstack import keystone
LOG = log.getLogger(__name__)
@ -58,6 +59,7 @@ def heat_stack_parameters(obj, stack=None):
return parameters
@keystone.skip_unless_has_keystone_credentials()
class HeatStackFixture(tobiko.SharedFixture):
"""Manages Heat stacks."""

View File

@ -16,9 +16,11 @@ from __future__ import absolute_import
import collections
import tobiko
from tobiko.openstack import keystone
from tobiko.openstack.neutron import _client
@keystone.skip_unless_has_keystone_credentials()
class NetworkingExtensionsFixture(tobiko.SharedFixture):
client = None

View File

@ -72,7 +72,9 @@ class PingInterfaceManager(tobiko.SharedFixture):
usage = get_ping_usage(ssh_client)
interface = find_ping_interface(usage=usage,
interfaces=self.interfaces)
interface = interface or self.default_interface
if not interface:
LOG.error('Ping interface not found: using the default one')
interface = self.default_interface
LOG.debug('Assign Ping interface %r to SSH client %r',
interface, ssh_client)
self.client_interfaces[ssh_client] = interface
@ -349,3 +351,38 @@ class InetToolsPingInterface(PingInterface):
else:
return ['-w', parameters.deadline,
'-W', parameters.deadline]
IPUTILS_PING_USAGE = """
ping: invalid option -- '-'
Usage: ping [-aAbBdDfhLnOqrRUvV] [-c count] [-i interval] [-I interface]
[-m mark] [-M pmtudisc_option] [-l preload] [-p pattern] [-Q tos]
[-s packetsize] [-S sndbuf] [-t ttl] [-T timestamp_option]
[-w deadline] [-W timeout] [hop1 ...] destination
""".strip()
@ping_interface
class BsdPingInterface(PingInterface):
def match_ping_usage(self, usage):
return usage.startswith(BSD_PING_USAGE)
has_fragment_option = False
def get_deadline_option(self, parameters):
return ['-t', parameters.deadline]
BSD_PING_USAGE = """
ping: unrecognized option `--help'
usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize]
[-g sweepminsize] [-h sweepincrsize] [-i wait]
[-l preload] [-M mask | time] [-m ttl] [-p pattern]
[-S src_addr] [-s packetsize] [-t timeout][-W waittime]
[-z tos] host
ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait]
[-l preload] [-M mask | time] [-m ttl] [-p pattern] [-S src_addr]
[-s packetsize] [-T ttl] [-t timeout] [-W waittime]
[-z tos] mcast-group
""".strip()

View File

@ -292,35 +292,51 @@ def handle_ping_command_error(error):
prefix = 'ping: '
if error.startswith('ping: '):
text = error[len(prefix):]
prefix = 'bad address '
if text.startswith(prefix):
address = text[len(prefix):].replace("'", '').strip()
raise _exception.BadAddressPingError(address=address)
prefix = 'local error: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.LocalPingError(details=details)
prefix = 'sendto: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.SendToPingError(details=details)
prefix = 'unknown host'
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': Name or service not known'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': No route to host'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
handle_ping_bad_address_error(text)
handle_ping_local_error(text)
handle_ping_send_to_error(text)
handle_ping_unknow_host_error(text)
raise _exception.PingError(details=text)
def handle_ping_bad_address_error(text):
prefix = 'bad address '
if text.startswith(prefix):
address = text[len(prefix):].replace("'", '').strip()
raise _exception.BadAddressPingError(address=address)
def handle_ping_local_error(text):
prefix = 'local error: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.LocalPingError(details=details)
def handle_ping_send_to_error(text):
prefix = 'sendto: '
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.SendToPingError(details=details)
def handle_ping_unknow_host_error(text):
prefix = 'unknown host'
if text.startswith(prefix):
details = text[len(prefix):].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': Name or service not known'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': No route to host'
if text.endswith(suffix):
details = text[:-len(suffix)].strip()
raise _exception.UnknowHostError(details=details)
suffix = ': Unknown host'
if text.endswith(suffix):
details = text[:-len(suffix)].strip().split()[-1]
raise _exception.UnknowHostError(details=details)

View File

@ -21,6 +21,7 @@ import testtools
import tobiko
from tobiko import docker
from tobiko.openstack import keystone
from tobiko.openstack import topology
@ -41,6 +42,7 @@ class DockerNodeFixture(tobiko.SharedFixture):
' '.join(node.name for node in nodes))
@keystone.skip_unless_has_keystone_credentials()
class DockerClientTest(testtools.TestCase):
node = tobiko.required_setup_fixture(DockerNodeFixture)

View File

@ -20,11 +20,13 @@ import yaml
import tobiko
from tobiko.shell import sh
from tobiko.openstack import keystone
from tobiko.openstack import nova
from tobiko.openstack import stacks
from tobiko.tests.functional.openstack.stacks import test_cirros
@keystone.skip_unless_has_keystone_credentials()
class CentosServerStackTest(test_cirros.CirrosServerStackTest):
"""Tests connectivity to Nova instances via floating IPs"""

View File

@ -18,11 +18,13 @@ from __future__ import absolute_import
import testtools
import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import stacks
from tobiko.shell import ping
from tobiko.shell import sh
@keystone.skip_unless_has_keystone_credentials()
class CirrosServerStackTest(testtools.TestCase):
"""Tests connectivity to Nova instances via floating IPs"""

View File

@ -18,11 +18,13 @@ from __future__ import absolute_import
import testtools
import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import neutron
from tobiko.openstack import stacks
class NetworkTestCase(testtools.TestCase):
@keystone.skip_unless_has_keystone_credentials()
class NetworkTest(testtools.TestCase):
"""Tests network creation"""
#: Stack of resources with a network with a gateway router
@ -78,8 +80,9 @@ class NetworkTestCase(testtools.TestCase):
self.stack.ipv6_gateway_addresses)
@keystone.skip_unless_has_keystone_credentials()
@neutron.skip_if_missing_networking_extensions('net-mtu-write')
class NetworkWithNetMtuWriteTestCase(NetworkTestCase):
class NetworkWithNetMtuWriteTest(NetworkTest):
#: Stack of resources with a network with a gateway router
stack = tobiko.required_setup_fixture(
@ -89,15 +92,17 @@ class NetworkWithNetMtuWriteTestCase(NetworkTestCase):
self.assertEqual(self.stack.mtu, self.stack.outputs.mtu)
@keystone.skip_unless_has_keystone_credentials()
@neutron.skip_if_missing_networking_extensions('l3-ha')
@neutron.skip_if_missing_networking_agents(binary='neutron-l3-agent',
count=2)
class L3HaNetworkTestCase(NetworkTestCase):
class L3HaNetworkTest(NetworkTest):
#: Stack of resources with a network with a gateway router
stack = tobiko.required_setup_fixture(stacks.L3haNetworkStackFixture)
@keystone.skip_unless_has_keystone_credentials()
class FloatingNetworkStackTest(testtools.TestCase):
@stacks.skip_if_missing_floating_network

View File

@ -31,6 +31,7 @@ LOG = log.getLogger(__name__)
CIENT_CLASSSES = v2_client.Client, v3_client.Client
@keystone.skip_unless_has_keystone_credentials()
class TobikoKeystoneCredentialsCommandTest(testtools.TestCase):
def test_execute(self):
@ -41,6 +42,7 @@ class TobikoKeystoneCredentialsCommandTest(testtools.TestCase):
self.assertEqual(expected, actual)
@keystone.skip_unless_has_keystone_credentials()
class KeystoneClientAPITest(testtools.TestCase):
def test_get_keystone_client(self):

View File

@ -20,6 +20,7 @@ import testtools
import tobiko
from tobiko import config
from tobiko.openstack import keystone
from tobiko.openstack import neutron
from tobiko.openstack import nova
from tobiko.openstack import stacks
@ -29,6 +30,7 @@ from tobiko.openstack import tests
CONF = config.CONF
@keystone.skip_unless_has_keystone_credentials()
class NeutronApiTestCase(testtools.TestCase):
"""Tests network creation"""
@ -112,6 +114,7 @@ class NeutronApiTestCase(testtools.TestCase):
self.assertIn(agent['id'], {a['id'] for a in agents})
@keystone.skip_unless_has_keystone_credentials()
class PortTest(testtools.TestCase):
#: Stack of resources with a network with a gateway router
@ -159,6 +162,7 @@ class PortTest(testtools.TestCase):
self.assertIn(port_address, cidr)
@keystone.skip_unless_has_keystone_credentials()
class AgentTest(testtools.TestCase):
def test_skip_if_missing_agents(self, count=1, should_skip=False,
@ -192,9 +196,6 @@ class AgentTest(testtools.TestCase):
self.test_skip_if_missing_agents(count=1000000,
should_skip=True)
class NeutronAgentTest(testtools.TestCase):
def test_neutron_agents_are_alive(self):
agents = tests.test_neutron_agents_are_alive()
# check has agents and they are all alive

View File

@ -21,6 +21,7 @@ import netaddr
import testtools
import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import nova
from tobiko.openstack import stacks
@ -34,6 +35,7 @@ class KeyPairTest(testtools.TestCase):
self.assertTrue(os.path.isfile(self.stack.key_file + '.pub'))
@keystone.skip_unless_has_keystone_credentials()
class ClientTest(testtools.TestCase):
#: Stack of resources with a server attached to a floating IP
@ -117,6 +119,7 @@ class ClientTest(testtools.TestCase):
self.assertEqual('ACTIVE', server.status)
@keystone.skip_unless_has_keystone_credentials()
class HypervisorTest(testtools.TestCase):
def test_skip_if_missing_hypervisors(self, count=1, should_skip=False,
@ -152,6 +155,7 @@ class HypervisorTest(testtools.TestCase):
should_skip=True)
@keystone.skip_unless_has_keystone_credentials()
class ServiceTest(testtools.TestCase):
def test_wait_for_services_up(self):

View File

@ -21,6 +21,7 @@ from tobiko.openstack import keystone
from tobiko.openstack import octavia
@keystone.skip_unless_has_keystone_credentials()
@keystone.skip_if_missing_service(name='octavia')
class OctaviaClientAPITest(testtools.TestCase):

View File

@ -18,12 +18,14 @@ from __future__ import absolute_import
import testtools
import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import nova
from tobiko.openstack import topology
from tobiko.shell import ping
from tobiko.shell import sh
@keystone.skip_unless_has_keystone_credentials()
class OpenStackTopologyTest(testtools.TestCase):
topology = tobiko.required_setup_fixture(topology.OpenStackTopology)

View File

@ -19,6 +19,7 @@ import testtools
import tobiko
from tobiko.openstack import glance
from tobiko.openstack import keystone
from tobiko.openstack import nova
from tobiko.openstack import tests
@ -27,6 +28,7 @@ class MyServerStack(tests.TestServerCreationStack):
pass
@keystone.skip_unless_has_keystone_credentials()
class ServerCreationTest(testtools.TestCase):
def test_server_creation(self):

View File

@ -21,6 +21,7 @@ import testtools
import tobiko
from tobiko import podman
from tobiko.openstack import keystone
from tobiko.openstack import topology
@ -41,6 +42,7 @@ class PodmanNodeFixture(tobiko.SharedFixture):
' '.join(node.name for node in nodes))
@keystone.skip_unless_has_keystone_credentials()
class PodmanClientTest(testtools.TestCase):
node = tobiko.required_setup_fixture(PodmanNodeFixture)

View File

@ -1,10 +1,12 @@
from __future__ import absolute_import
import tobiko
from tobiko.openstack import keystone
from tobiko.openstack import topology
from tobiko.shell import ip
@keystone.skip_unless_has_keystone_credentials()
class NetworkNamespaceFixture(tobiko.SharedFixture):
network_namespace = None

View File

@ -23,9 +23,11 @@ import testtools
import tobiko
from tobiko.shell import sh
from tobiko.shell import ssh
from tobiko.openstack import keystone
from tobiko.openstack import stacks
@keystone.skip_unless_has_keystone_credentials()
class HostnameTest(testtools.TestCase):
server_stack = tobiko.required_setup_fixture(

View File

@ -22,6 +22,7 @@ import tobiko
from tobiko.shell import ifconfig
from tobiko.shell import sh
from tobiko.shell import ssh
from tobiko.openstack import keystone
from tobiko.openstack import stacks
@ -53,9 +54,11 @@ class IfconfigTest(testtools.TestCase):
def test_list_ip_addresses_with_ipv6(self):
self.test_list_ip_addresses(ip_version=6)
@keystone.skip_unless_has_keystone_credentials()
def test_list_ip_addresses_with_cirros_server(self):
self.test_list_ip_addresses(ssh_client=self.cirros_stack.ssh_client)
@keystone.skip_unless_has_keystone_credentials()
def test_list_ip_addresses_with_ubuntu_server(self):
self.test_list_ip_addresses(ssh_client=self.ubuntu_stack.ssh_client)

View File

@ -15,8 +15,9 @@
# under the License.
from __future__ import absolute_import
import os
import netaddr
import six
import testtools
import tobiko
@ -41,6 +42,8 @@ class IpTest(testtools.TestCase):
def test_list_ip_addresses(self, ip_version=None, scope=None,
**execute_params):
if not os.path.isfile('/bin/ip'):
self.skip("'bin/ip' command not found")
ips = ip.list_ip_addresses(ip_version=ip_version, scope=scope,
**execute_params)
self.assertIsInstance(ips, tobiko.Selection)
@ -125,10 +128,12 @@ class IpTest(testtools.TestCase):
**execute_params)
def test_list_namespaces(self, **execute_params):
if not os.path.isfile('/bin/ip'):
self.skip("'bin/ip' command not found")
namespaces = ip.list_network_namespaces(**execute_params)
self.assertIsInstance(namespaces, list)
for namespace in namespaces:
self.assertIsInstance(namespace, six.string_types)
self.assertIsInstance(namespace, str)
self.test_list_ip_addresses(network_namespace=namespace)
def test_list_namespaces_with_centos_server(self):

View File

@ -15,6 +15,8 @@
# under the License.
from __future__ import absolute_import
import os
import netaddr
import testtools
@ -98,6 +100,8 @@ class PingTest(testtools.TestCase):
def test_ping_hosts(self, ssh_client=None, network_namespace=None,
**params):
if not os.path.isfile('/sbin/ip'):
self.skip("'/sbin/ip' command not found")
ips = ip.list_ip_addresses(ssh_client=ssh_client,
network_namespace=network_namespace)
reachable_ips, unrecheable_ips = ping.ping_hosts(

View File

@ -51,18 +51,20 @@ def normalize_path(path):
def execute(command, *args, **kwargs):
capture_stdout = kwargs.pop('capture_stdout', True)
universal_newlines = kwargs.pop('universal_newlines', True)
check = kwargs.pop('check', True)
if args or kwargs:
command = command.format(*args, **kwargs)
command = command.strip()
if capture_stdout:
execute_func = subprocess.check_output
else:
execute_func = subprocess.check_call
stdout = capture_stdout and subprocess.PIPE or None
return execute_func(['/bin/bash', '-x', '-c', command],
shell=False, universal_newlines=universal_newlines)
result = subprocess.run(['/bin/bash', '-x', '-c', command],
stdout=stdout, shell=False,
universal_newlines=universal_newlines)
if check:
result.check_returncode()
return result.stdout
def get_posargs(args=None):

View File

@ -106,7 +106,8 @@ def log_environ():
def log_tests_results():
common.execute('stestr last --all-attachments >> "{log_file}"',
log_file=TOX_REPORT_LOG,
capture_stdout=False)
capture_stdout=False,
check=False)
def run_test_cases():

View File

@ -1,6 +1,6 @@
[tox]
envlist = bindep,linters,py3,lower-constraints
envlist = bindep,linters,py3,lower-constraints,functional
minversion = 3.8.0