Make timeouts in functional tests configurable

functional tests are often failing due to timeouts in `wait_for`
functions. It forces us to trigger a "recheck". Let's make it
configurable instead. A top level timeout can be set
with `OPENSTACKSDK_FUNC_TEST_TIMEOUT` env and defaults to 300.
Func tests for each service might override this var
(i.e. for heat `OPENSTACKSDK_FUNC_TEST_TIMEOUT_ORCHESTRATE`).
OPENSTACKSDK_FUNC_TEST_TIMEOUT_LOAD_BALANCER is set to 600 (in tox)
to respect the value previously used in the code.

Change-Id: I7bdcd67e858a1f2c43cb131ebdf549da070fbb4a
This commit is contained in:
Artem Goncharov 2018-11-23 10:21:06 +01:00
parent cdef4806ce
commit 84116d6125
11 changed files with 168 additions and 48 deletions

View File

@ -45,6 +45,15 @@ FLAVOR_NAME = _get_resource_value('flavor_name', 'm1.small')
class BaseFunctionalTest(base.TestCase):
@classmethod
def setUpClass(cls):
super(BaseFunctionalTest, cls).setUpClass()
# Defines default timeout for wait_for methods used
# in the functional tests
cls._wait_for_timeout = int(os.getenv(
'OPENSTACKSDK_FUNC_TEST_TIMEOUT',
300))
def setUp(self):
super(BaseFunctionalTest, self).setUp()
self.conn = connection.Connection(config=TEST_CLOUD_REGION)

View File

@ -0,0 +1,25 @@
# 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 os
from openstack.tests.functional import base
class BaseBlockStorageTest(base.BaseFunctionalTest):
@classmethod
def setUpClass(cls):
super(BaseBlockStorageTest, cls).setUpClass()
cls._wait_for_timeout = int(os.getenv(
'OPENSTACKSDK_FUNC_TEST_TIMEOUT_BLOCK_STORAGE',
cls._wait_for_timeout))

View File

@ -13,10 +13,10 @@
from openstack.block_storage.v2 import snapshot as _snapshot
from openstack.block_storage.v2 import volume as _volume
from openstack.tests.functional import base
from openstack.tests.functional.block_storage.v2 import base
class TestSnapshot(base.BaseFunctionalTest):
class TestSnapshot(base.BaseBlockStorageTest):
def setUp(self):
super(TestSnapshot, self).setUp()
@ -34,7 +34,7 @@ class TestSnapshot(base.BaseFunctionalTest):
status='available',
failures=['error'],
interval=2,
wait=120)
wait=self._wait_for_timeout)
assert isinstance(volume, _volume.Volume)
self.assertEqual(self.VOLUME_NAME, volume.name)
self.VOLUME_ID = volume.id
@ -46,7 +46,7 @@ class TestSnapshot(base.BaseFunctionalTest):
status='available',
failures=['error'],
interval=2,
wait=120)
wait=self._wait_for_timeout)
assert isinstance(snapshot, _snapshot.Snapshot)
self.assertEqual(self.SNAPSHOT_NAME, snapshot.name)
self.SNAPSHOT_ID = snapshot.id
@ -56,7 +56,7 @@ class TestSnapshot(base.BaseFunctionalTest):
sot = self.conn.block_storage.delete_snapshot(
snapshot, ignore_missing=False)
self.conn.block_storage.wait_for_delete(
snapshot, interval=2, wait=120)
snapshot, interval=2, wait=self._wait_for_timeout)
self.assertIsNone(sot)
sot = self.conn.block_storage.delete_volume(
self.VOLUME_ID, ignore_missing=False)

View File

@ -12,10 +12,10 @@
from openstack.block_storage.v2 import type as _type
from openstack.tests.functional import base
from openstack.tests.functional.block_storage.v2 import base
class TestType(base.BaseFunctionalTest):
class TestType(base.BaseBlockStorageTest):
def setUp(self):
super(TestType, self).setUp()

View File

@ -10,12 +10,11 @@
# License for the specific language governing permissions and limitations
# under the License.
from openstack.block_storage.v2 import volume as _volume
from openstack.tests.functional import base
from openstack.tests.functional.block_storage.v2 import base
class TestVolume(base.BaseFunctionalTest):
class TestVolume(base.BaseBlockStorageTest):
def setUp(self):
super(TestVolume, self).setUp()
@ -31,7 +30,7 @@ class TestVolume(base.BaseFunctionalTest):
status='available',
failures=['error'],
interval=2,
wait=120)
wait=self._wait_for_timeout)
assert isinstance(volume, _volume.Volume)
self.assertEqual(self.VOLUME_NAME, volume.name)
self.VOLUME_ID = volume.id

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import time
from openstack.clustering.v1 import cluster
@ -19,6 +20,13 @@ from openstack.tests.functional.network.v2 import test_network
class TestCluster(base.BaseFunctionalTest):
@classmethod
def setUpClass(cls):
super(TestCluster, cls).setUpClass()
cls._wait_for_timeout = int(os.getenv(
'OPENSTACKSDK_FUNC_TEST_TIMEOUT_CLUSTER',
cls._wait_for_timeout))
def setUp(self):
super(TestCluster, self).setUp()
self.require_service('clustering')
@ -56,12 +64,15 @@ class TestCluster(base.BaseFunctionalTest):
}
self.cluster = self.conn.clustering.create_cluster(**cluster_spec)
self.conn.clustering.wait_for_status(self.cluster, 'ACTIVE')
self.conn.clustering.wait_for_status(
self.cluster, 'ACTIVE',
wait=self._wait_for_timeout)
assert isinstance(self.cluster, cluster.Cluster)
def tearDown(self):
self.conn.clustering.delete_cluster(self.cluster.id)
self.conn.clustering.wait_for_delete(self.cluster)
self.conn.clustering.wait_for_delete(self.cluster,
wait=self._wait_for_timeout)
test_network.delete_network(self.conn, self.network, self.subnet)

View File

@ -0,0 +1,25 @@
# 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 os
from openstack.tests.functional import base
class BaseComputeTest(base.BaseFunctionalTest):
@classmethod
def setUpClass(cls):
super(BaseComputeTest, cls).setUpClass()
cls._wait_for_timeout = int(os.getenv(
'OPENSTACKSDK_FUNC_TEST_TIMEOUT_COMPUTE',
cls._wait_for_timeout))

View File

@ -12,10 +12,11 @@
from openstack.compute.v2 import server
from openstack.tests.functional import base
from openstack.tests.functional.compute import base as ft_base
from openstack.tests.functional.network.v2 import test_network
class TestServer(base.BaseFunctionalTest):
class TestServer(ft_base.BaseComputeTest):
def setUp(self):
super(TestServer, self).setUp()
@ -38,7 +39,7 @@ class TestServer(base.BaseFunctionalTest):
sot = self.conn.compute.create_server(
name=self.NAME, flavor_id=flavor.id, image_id=image.id,
networks=[{"uuid": self.network.id}])
self.conn.compute.wait_for_server(sot)
self.conn.compute.wait_for_server(sot, wait=self._wait_for_timeout)
assert isinstance(sot, server.Server)
self.assertEqual(self.NAME, sot.name)
self.server = sot
@ -47,7 +48,8 @@ class TestServer(base.BaseFunctionalTest):
sot = self.conn.compute.delete_server(self.server.id)
self.assertIsNone(sot)
# Need to wait for the stack to go away before network delete
self.conn.compute.wait_for_delete(self.server)
self.conn.compute.wait_for_delete(self.server,
wait=self._wait_for_timeout)
test_network.delete_network(self.conn, self.network, self.subnet)
super(TestServer, self).tearDown()

View File

@ -10,6 +10,8 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
from openstack.load_balancer.v2 import health_monitor
from openstack.load_balancer.v2 import l7_policy
from openstack.load_balancer.v2 import l7_rule
@ -45,6 +47,13 @@ class TestLoadBalancer(base.BaseFunctionalTest):
L7RULE_TYPE = 'HOST_NAME'
L7RULE_VALUE = 'example'
@classmethod
def setUpClass(cls):
super(TestLoadBalancer, cls).setUpClass()
cls._wait_for_timeout = int(os.getenv(
'OPENSTACKSDK_FUNC_TEST_TIMEOUT_LOAD_BALANCER',
cls._wait_for_timeout))
# TODO(shade): Creating load balancers can be slow on some hosts due to
# nova instance boot times (up to ten minutes). This used to
# use setUpClass, but that's a whole other pile of bad, so
@ -70,8 +79,9 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.assertEqual(self.LB_NAME, test_lb.name)
# Wait for the LB to go ACTIVE. On non-virtualization enabled hosts
# it can take nova up to ten minutes to boot a VM.
self.conn.load_balancer.wait_for_load_balancer(test_lb.id, interval=1,
wait=600)
self.conn.load_balancer.wait_for_load_balancer(
test_lb.id, interval=1,
wait=self._wait_for_timeout)
self.LB_ID = test_lb.id
test_listener = self.conn.load_balancer.create_listener(
@ -80,7 +90,8 @@ class TestLoadBalancer(base.BaseFunctionalTest):
assert isinstance(test_listener, listener.Listener)
self.assertEqual(self.LISTENER_NAME, test_listener.name)
self.LISTENER_ID = test_listener.id
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_pool = self.conn.load_balancer.create_pool(
name=self.POOL_NAME, protocol=self.PROTOCOL,
@ -88,7 +99,8 @@ class TestLoadBalancer(base.BaseFunctionalTest):
assert isinstance(test_pool, pool.Pool)
self.assertEqual(self.POOL_NAME, test_pool.name)
self.POOL_ID = test_pool.id
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_member = self.conn.load_balancer.create_member(
pool=self.POOL_ID, name=self.MEMBER_NAME,
@ -97,7 +109,8 @@ class TestLoadBalancer(base.BaseFunctionalTest):
assert isinstance(test_member, member.Member)
self.assertEqual(self.MEMBER_NAME, test_member.name)
self.MEMBER_ID = test_member.id
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_hm = self.conn.load_balancer.create_health_monitor(
pool_id=self.POOL_ID, name=self.HM_NAME, delay=self.DELAY,
@ -106,7 +119,8 @@ class TestLoadBalancer(base.BaseFunctionalTest):
assert isinstance(test_hm, health_monitor.HealthMonitor)
self.assertEqual(self.HM_NAME, test_hm.name)
self.HM_ID = test_hm.id
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_l7policy = self.conn.load_balancer.create_l7_policy(
listener_id=self.LISTENER_ID, name=self.L7POLICY_NAME,
@ -114,7 +128,8 @@ class TestLoadBalancer(base.BaseFunctionalTest):
assert isinstance(test_l7policy, l7_policy.L7Policy)
self.assertEqual(self.L7POLICY_NAME, test_l7policy.name)
self.L7POLICY_ID = test_l7policy.id
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_l7rule = self.conn.load_balancer.create_l7_rule(
l7_policy=self.L7POLICY_ID, compare_type=self.COMPARE_TYPE,
@ -122,34 +137,42 @@ class TestLoadBalancer(base.BaseFunctionalTest):
assert isinstance(test_l7rule, l7_rule.L7Rule)
self.assertEqual(self.COMPARE_TYPE, test_l7rule.compare_type)
self.L7RULE_ID = test_l7rule.id
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
def tearDown(self):
self.conn.load_balancer.get_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
self.conn.load_balancer.delete_l7_rule(
self.L7RULE_ID, l7_policy=self.L7POLICY_ID, ignore_missing=False)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
self.conn.load_balancer.delete_l7_policy(
self.L7POLICY_ID, ignore_missing=False)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
self.conn.load_balancer.delete_health_monitor(
self.HM_ID, ignore_missing=False)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
self.conn.load_balancer.delete_member(
self.MEMBER_ID, self.POOL_ID, ignore_missing=False)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
self.conn.load_balancer.delete_pool(self.POOL_ID, ignore_missing=False)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
self.conn.load_balancer.delete_listener(self.LISTENER_ID,
ignore_missing=False)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
self.conn.load_balancer.delete_load_balancer(
self.LB_ID, ignore_missing=False)
@ -172,13 +195,15 @@ class TestLoadBalancer(base.BaseFunctionalTest):
def test_lb_update(self):
self.conn.load_balancer.update_load_balancer(
self.LB_ID, name=self.UPDATE_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_lb = self.conn.load_balancer.get_load_balancer(self.LB_ID)
self.assertEqual(self.UPDATE_NAME, test_lb.name)
self.conn.load_balancer.update_load_balancer(
self.LB_ID, name=self.LB_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_lb = self.conn.load_balancer.get_load_balancer(self.LB_ID)
self.assertEqual(self.LB_NAME, test_lb.name)
@ -203,13 +228,15 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.conn.load_balancer.update_listener(
self.LISTENER_ID, name=self.UPDATE_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_listener = self.conn.load_balancer.get_listener(self.LISTENER_ID)
self.assertEqual(self.UPDATE_NAME, test_listener.name)
self.conn.load_balancer.update_listener(
self.LISTENER_ID, name=self.LISTENER_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_listener = self.conn.load_balancer.get_listener(self.LISTENER_ID)
self.assertEqual(self.LISTENER_NAME, test_listener.name)
@ -232,13 +259,15 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.conn.load_balancer.update_pool(self.POOL_ID,
name=self.UPDATE_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_pool = self.conn.load_balancer.get_pool(self.POOL_ID)
self.assertEqual(self.UPDATE_NAME, test_pool.name)
self.conn.load_balancer.update_pool(self.POOL_ID,
name=self.POOL_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_pool = self.conn.load_balancer.get_pool(self.POOL_ID)
self.assertEqual(self.POOL_NAME, test_pool.name)
@ -266,14 +295,16 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.conn.load_balancer.update_member(self.MEMBER_ID, self.POOL_ID,
name=self.UPDATE_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_member = self.conn.load_balancer.get_member(self.MEMBER_ID,
self.POOL_ID)
self.assertEqual(self.UPDATE_NAME, test_member.name)
self.conn.load_balancer.update_member(self.MEMBER_ID, self.POOL_ID,
name=self.MEMBER_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_member = self.conn.load_balancer.get_member(self.MEMBER_ID,
self.POOL_ID)
self.assertEqual(self.MEMBER_NAME, test_member.name)
@ -300,13 +331,15 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.conn.load_balancer.update_health_monitor(self.HM_ID,
name=self.UPDATE_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_hm = self.conn.load_balancer.get_health_monitor(self.HM_ID)
self.assertEqual(self.UPDATE_NAME, test_hm.name)
self.conn.load_balancer.update_health_monitor(self.HM_ID,
name=self.HM_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_hm = self.conn.load_balancer.get_health_monitor(self.HM_ID)
self.assertEqual(self.HM_NAME, test_hm.name)
@ -331,14 +364,16 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.conn.load_balancer.update_l7_policy(
self.L7POLICY_ID, name=self.UPDATE_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_l7_policy = self.conn.load_balancer.get_l7_policy(
self.L7POLICY_ID)
self.assertEqual(self.UPDATE_NAME, test_l7_policy.name)
self.conn.load_balancer.update_l7_policy(self.L7POLICY_ID,
name=self.L7POLICY_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_l7_policy = self.conn.load_balancer.get_l7_policy(
self.L7POLICY_ID)
self.assertEqual(self.L7POLICY_NAME, test_l7_policy.name)
@ -368,7 +403,8 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.conn.load_balancer.update_l7_rule(self.L7RULE_ID,
l7_policy=self.L7POLICY_ID,
rule_value=self.UPDATE_NAME)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_l7_rule = self.conn.load_balancer.get_l7_rule(
self.L7RULE_ID, l7_policy=self.L7POLICY_ID)
self.assertEqual(self.UPDATE_NAME, test_l7_rule.rule_value)
@ -376,7 +412,8 @@ class TestLoadBalancer(base.BaseFunctionalTest):
self.conn.load_balancer.update_l7_rule(self.L7RULE_ID,
l7_policy=self.L7POLICY_ID,
rule_value=self.L7RULE_VALUE)
self.conn.load_balancer.wait_for_load_balancer(self.LB_ID)
self.conn.load_balancer.wait_for_load_balancer(
self.LB_ID, wait=self._wait_for_timeout)
test_l7_rule = self.conn.load_balancer.get_l7_rule(
self.L7RULE_ID, l7_policy=self.L7POLICY_ID,)
self.assertEqual(self.L7RULE_VALUE, test_l7_rule.rule_value)

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
import yaml
from openstack import exceptions
@ -26,6 +27,13 @@ class TestStack(base.BaseFunctionalTest):
subnet = None
cidr = '10.99.99.0/16'
@classmethod
def setUpClass(cls):
super(TestStack, cls).setUpClass()
cls._wait_for_timeout = int(os.getenv(
'OPENSTACKSDK_FUNC_TEST_TIMEOUT_ORCHESTRATION',
cls._wait_for_timeout))
def setUp(self):
super(TestStack, self).setUp()
self.require_service('orchestration')
@ -58,7 +66,8 @@ class TestStack(base.BaseFunctionalTest):
self.stack = sot
self.assertEqual(self.NAME, sot.name)
self.conn.orchestration.wait_for_status(
sot, status='CREATE_COMPLETE', failures=['CREATE_FAILED'])
sot, status='CREATE_COMPLETE', failures=['CREATE_FAILED'],
wait=self._wait_for_timeout)
def tearDown(self):
self.conn.orchestration.delete_stack(self.stack, ignore_missing=False)
@ -66,7 +75,7 @@ class TestStack(base.BaseFunctionalTest):
# Need to wait for the stack to go away before network delete
try:
self.conn.orchestration.wait_for_status(
self.stack, 'DELETE_COMPLETE')
self.stack, 'DELETE_COMPLETE', wait=self._wait_for_timeout)
except exceptions.ResourceNotFound:
pass
test_network.delete_network(self.conn, self.network, self.subnet)

View File

@ -29,9 +29,12 @@ commands = stestr --test-path ./openstack/tests/examples run {posargs}
stestr slowest
[testenv:functional]
# Some jobs (especially heat) takes longer, therefore increase default timeout
# This timeout should not be smaller, than the longest individual timeout
setenv =
{[testenv]setenv}
OS_TEST_TIMEOUT=120
OS_TEST_TIMEOUT=600
OPENSTACKSDK_FUNC_TEST_TIMEOUT_LOAD_BALANCER=600
commands = stestr --test-path ./openstack/tests/functional/{env:OPENSTACKSDK_TESTS_SUBDIR:} run --serial {posargs}
stestr slowest