Merge "Add list resource provider usage"
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
index 9b1719f..ed0a09f 100644
--- a/releasenotes/source/index.rst
+++ b/releasenotes/source/index.rst
@@ -6,6 +6,7 @@
:maxdepth: 1
unreleased
+ v27.0.0
v26.1.0
v26.0.0
v24.0.0
diff --git a/releasenotes/source/v27.0.0.rst b/releasenotes/source/v27.0.0.rst
new file mode 100644
index 0000000..0009124
--- /dev/null
+++ b/releasenotes/source/v27.0.0.rst
@@ -0,0 +1,5 @@
+=====================
+v27.0.0 Release Notes
+=====================
+.. release-notes:: 27.0.0 Release Notes
+ :version: 27.0.0
diff --git a/requirements.txt b/requirements.txt
index eae5427..c71cabe 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -13,7 +13,6 @@
stestr>=1.0.0 # Apache-2.0
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
oslo.utils>=4.7.0 # Apache-2.0
-six>=1.10.0 # MIT
fixtures>=3.0.0 # Apache-2.0/BSD
PyYAML>=3.12 # MIT
python-subunit>=1.0.0 # Apache-2.0/BSD
diff --git a/roles/run-tempest/tasks/main.yaml b/roles/run-tempest/tasks/main.yaml
index 37026e4..a8b3ede 100644
--- a/roles/run-tempest/tasks/main.yaml
+++ b/roles/run-tempest/tasks/main.yaml
@@ -40,7 +40,7 @@
- "'TEMPEST_BRANCH' in devstack_localrc"
- "'TEMPEST_VENV_UPPER_CONSTRAINTS' in devstack_localrc"
- devstack_localrc['TEMPEST_BRANCH'] != 'master'
- - devstack_localrc['TEMPEST_VENV_UPPER_CONSTRAINTS'] != 'default'
+ - devstack_localrc['TEMPEST_VENV_UPPER_CONSTRAINTS'] != 'master'
- name: Set OS_TEST_TIMEOUT if requested
set_fact:
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 52ccea7..c91b557 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -23,6 +23,8 @@
from tempest.common import utils
from tempest.common import waiters
from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib.common.utils import test_utils
from tempest.lib import decorators
CONF = config.CONF
@@ -55,6 +57,10 @@
def setup_clients(cls):
super(LiveMigrationTestBase, cls).setup_clients()
cls.admin_migration_client = cls.os_admin.migrations_client
+ cls.networks_client = cls.os_primary.networks_client
+ cls.subnets_client = cls.os_primary.subnets_client
+ cls.ports_client = cls.os_primary.ports_client
+ cls.trunks_client = cls.os_primary.trunks_client
def _migrate_server_to(self, server_id, dest_host, volume_backed=False):
kwargs = dict()
@@ -197,6 +203,90 @@
self.assertEqual(volume_id1, volume_id2)
+ def _create_net_subnet(self, name, cidr):
+ net_name = data_utils.rand_name(name=name)
+ net = self.networks_client.create_network(name=net_name)['network']
+ self.addClassResourceCleanup(
+ self.networks_client.delete_network, net['id'])
+
+ subnet = self.subnets_client.create_subnet(
+ network_id=net['id'],
+ cidr=cidr,
+ ip_version=4)
+ self.addClassResourceCleanup(self.subnets_client.delete_subnet,
+ subnet['subnet']['id'])
+ return net
+
+ def _create_port(self, network_id, name):
+ name = data_utils.rand_name(name=name)
+ port = self.ports_client.create_port(name=name,
+ network_id=network_id)['port']
+ self.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.ports_client.delete_port,
+ port_id=port['id'])
+ return port
+
+ def _create_trunk_with_subport(self):
+ tenant_network = self.get_tenant_network()
+ parent = self._create_port(network_id=tenant_network['id'],
+ name='parent')
+ net = self._create_net_subnet(name='subport_net', cidr='19.80.0.0/24')
+ subport = self._create_port(network_id=net['id'], name='subport')
+
+ trunk = self.trunks_client.create_trunk(
+ name=data_utils.rand_name('trunk'),
+ port_id=parent['id'],
+ sub_ports=[{"segmentation_id": 42, "port_id": subport['id'],
+ "segmentation_type": "vlan"}]
+ )['trunk']
+ self.addClassResourceCleanup(test_utils.call_and_ignore_notfound_exc,
+ self.trunks_client.delete_trunk,
+ trunk['id'])
+ return trunk, parent, subport
+
+ def _is_port_status_active(self, port_id):
+ port = self.ports_client.show_port(port_id)['port']
+ return port['status'] == 'ACTIVE'
+
+ @decorators.idempotent_id('0022c12e-a482-42b0-be2d-396b5f0cffe3')
+ @utils.requires_ext(service='network', extension='trunk')
+ @utils.services('network')
+ def test_live_migration_with_trunk(self):
+ """Test live migration with trunk and subport"""
+ trunk, parent, subport = self._create_trunk_with_subport()
+
+ server = self.create_test_server(
+ wait_until="ACTIVE", networks=[{'port': parent['id']}])
+
+ # Wait till subport status is ACTIVE
+ self.assertTrue(
+ test_utils.call_until_true(
+ self._is_port_status_active, CONF.validation.connect_timeout,
+ 5, subport['id']))
+ self.assertTrue(
+ test_utils.call_until_true(
+ self._is_port_status_active, CONF.validation.connect_timeout,
+ 5, parent['id']))
+ subport = self.ports_client.show_port(subport['id'])['port']
+
+ if not CONF.compute_feature_enabled.can_migrate_between_any_hosts:
+ # not to specify a host so that the scheduler will pick one
+ target_host = None
+ else:
+ target_host = self.get_host_other_than(server['id'])
+
+ self._live_migrate(server['id'], target_host, 'ACTIVE')
+
+ # Wait till subport status is ACTIVE
+ self.assertTrue(
+ test_utils.call_until_true(
+ self._is_port_status_active, CONF.validation.connect_timeout,
+ 5, subport['id']))
+ self.assertTrue(
+ test_utils.call_until_true(
+ self._is_port_status_active, CONF.validation.connect_timeout,
+ 5, parent['id']))
+
class LiveMigrationRemoteConsolesV26Test(LiveMigrationTestBase):
min_microversion = '2.6'
diff --git a/tempest/api/compute/servers/test_novnc.py b/tempest/api/compute/servers/test_novnc.py
index a9c0e56..1308b19 100644
--- a/tempest/api/compute/servers/test_novnc.py
+++ b/tempest/api/compute/servers/test_novnc.py
@@ -15,8 +15,6 @@
import struct
import urllib.parse as urlparse
-
-import six
import urllib3
from tempest.api.compute import base
@@ -122,7 +120,7 @@
'Expected authentication type None.')
# Send to the server that we only support authentication
# type None
- self._websocket.send_frame(six.int2byte(1))
+ self._websocket.send_frame(bytes((1,)))
# The server should send 4 bytes of 0's if security
# handshake succeeded
@@ -135,7 +133,7 @@
'Server did not think security was successful.')
# Say to leave the desktop as shared as part of client initialization
- self._websocket.send_frame(six.int2byte(1))
+ self._websocket.send_frame(bytes((1,)))
# Get the server initialization packet back and make sure it is the
# right structure where bytes 20-24 is the name length and
# 24-N is the name
diff --git a/tempest/api/compute/servers/test_server_tags.py b/tempest/api/compute/servers/test_server_tags.py
index 619f480..c988788 100644
--- a/tempest/api/compute/servers/test_server_tags.py
+++ b/tempest/api/compute/servers/test_server_tags.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
-
from tempest.api.compute import base
from tempest.common import utils
from tempest.lib.common.utils import data_utils
@@ -84,11 +82,11 @@
new_tags = [data_utils.rand_name('tag'), data_utils.rand_name('tag')]
replaced_tags = self.client.update_all_tags(
self.server['id'], new_tags)['tags']
- six.assertCountEqual(self, new_tags, replaced_tags)
+ self.assertCountEqual(new_tags, replaced_tags)
# List the tags and check that the tags were replaced.
fetched_tags = self.client.list_tags(self.server['id'])['tags']
- six.assertCountEqual(self, new_tags, fetched_tags)
+ self.assertCountEqual(new_tags, fetched_tags)
@decorators.idempotent_id('a63b2a74-e918-4b7c-bcab-10c855f3a57e')
def test_delete_all_tags(self):
diff --git a/tempest/api/identity/v2/test_tokens.py b/tempest/api/identity/v2/test_tokens.py
index a928ad9..d3776b8 100644
--- a/tempest/api/identity/v2/test_tokens.py
+++ b/tempest/api/identity/v2/test_tokens.py
@@ -14,7 +14,6 @@
# under the License.
from oslo_utils import timeutils
-import six
from tempest.api.identity import base
from tempest.lib import decorators
@@ -36,7 +35,7 @@
body = token_client.auth(username, password, tenant_name)
self.assertNotEmpty(body['token']['id'])
- self.assertIsInstance(body['token']['id'], six.string_types)
+ self.assertIsInstance(body['token']['id'], str)
now = timeutils.utcnow()
expires_at = timeutils.normalize_time(
diff --git a/tempest/api/identity/v3/test_tokens.py b/tempest/api/identity/v3/test_tokens.py
index b201285..55fcead 100644
--- a/tempest/api/identity/v3/test_tokens.py
+++ b/tempest/api/identity/v3/test_tokens.py
@@ -16,7 +16,6 @@
import operator
from oslo_utils import timeutils
-import six
from tempest.api.identity import base
from tempest.lib import decorators
@@ -88,7 +87,7 @@
auth_data=True)
self.assertNotEmpty(token_id)
- self.assertIsInstance(token_id, six.string_types)
+ self.assertIsInstance(token_id, str)
now = timeutils.utcnow()
expires_at = timeutils.normalize_time(
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index efa23bb..d283ab3 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -105,12 +105,10 @@
'validate the image/tasks API.')
return
- # Make sure we can access the task and that some of the key
- # fields look legit.
- tasks = self.client.show_image_tasks(image_id)
- self.assertEqual(1, len(tasks['tasks']))
- task = tasks['tasks'][0]
- self.assertEqual('success', task['status'])
+ tasks = waiters.wait_for_image_tasks_status(
+ self.client, image_id, 'success')
+ self.assertEqual(1, len(tasks))
+ task = tasks[0]
self.assertEqual(resp.response['x-openstack-request-id'],
task['request_id'])
self.assertEqual('glance-direct',
diff --git a/tempest/api/network/test_allowed_address_pair.py b/tempest/api/network/test_allowed_address_pair.py
index 0b9d381..905bf13 100644
--- a/tempest/api/network/test_allowed_address_pair.py
+++ b/tempest/api/network/test_allowed_address_pair.py
@@ -13,8 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
-
from tempest.api.network import base
from tempest.common import utils
from tempest.lib.common.utils import data_utils
@@ -99,8 +97,7 @@
body = self.ports_client.update_port(
port_id, allowed_address_pairs=allowed_address_pairs)
allowed_address_pair = body['port']['allowed_address_pairs']
- six.assertCountEqual(self, allowed_address_pair,
- allowed_address_pairs)
+ self.assertCountEqual(allowed_address_pair, allowed_address_pairs)
@decorators.idempotent_id('9599b337-272c-47fd-b3cf-509414414ac4')
def test_update_port_with_address_pair(self):
diff --git a/tempest/api/network/test_networks.py b/tempest/api/network/test_networks.py
index 7646b63..caaf964 100644
--- a/tempest/api/network/test_networks.py
+++ b/tempest/api/network/test_networks.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
import netaddr
-import six
import testtools
from tempest.api.network import base
@@ -595,9 +594,9 @@
subnets = [sub['id'] for sub in body['subnets']
if sub['network_id'] == network['id']]
test_subnet_ids = [sub['id'] for sub in (subnet1, subnet2)]
- six.assertCountEqual(self, subnets,
- test_subnet_ids,
- 'Subnet are not in the same network')
+ self.assertCountEqual(subnets,
+ test_subnet_ids,
+ 'Subnet are not in the same network')
class NetworksIpV6TestAttrs(BaseNetworkTestResources):
diff --git a/tempest/api/object_storage/test_account_services.py b/tempest/api/object_storage/test_account_services.py
index ffea6f6..4966ec4 100644
--- a/tempest/api/object_storage/test_account_services.py
+++ b/tempest/api/object_storage/test_account_services.py
@@ -14,8 +14,6 @@
# under the License.
import random
-
-import six
import testtools
from tempest.api.object_storage import base
@@ -43,7 +41,7 @@
def resource_setup(cls):
super(AccountTest, cls).resource_setup()
for i in range(ord('a'), ord('f') + 1):
- name = data_utils.rand_name(name='%s-' % six.int2byte(i))
+ name = data_utils.rand_name(name='%s-' % bytes((i,)))
cls.container_client.update_container(name)
cls.addClassResourceCleanup(base.delete_containers,
[name],
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index a5de987..83733bd 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -10,7 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
from tempest.api.volume import base
from tempest.common import waiters
from tempest import config
@@ -149,4 +148,4 @@
# assert that volumes are each created on separate hosts:
msg = ("volumes %s were created in the same backend" % ", "
.join(volume_hosts))
- six.assertCountEqual(self, volume_hosts, set(volume_hosts), msg)
+ self.assertCountEqual(volume_hosts, set(volume_hosts), msg)
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index 9f9fc3b..d5c6fd9 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -155,6 +155,10 @@
backup = backup_client.create_backup(
volume_id=volume_id, **kwargs)['backup']
+ # addCleanup uses list pop to cleanup. Wait should be added before
+ # the backup is deleted
+ self.addCleanup(backup_client.wait_for_resource_deletion,
+ backup['id'])
self.addCleanup(backup_client.delete_backup, backup['id'])
waiters.wait_for_volume_resource_status(backup_client, backup['id'],
'available')
diff --git a/tempest/clients.py b/tempest/clients.py
index c4e00fe..6807fc4 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -72,6 +72,7 @@
self.qos_client = self.network.QosClient()
self.qos_min_bw_client = self.network.QosMinimumBandwidthRulesClient()
self.segments_client = self.network.SegmentsClient()
+ self.trunks_client = self.network.TrunksClient()
def _set_image_clients(self):
if CONF.service_available.glance:
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index eaac05e..3750b11 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -193,6 +193,30 @@
raise lib_exc.TimeoutException(message)
+def wait_for_image_tasks_status(client, image_id, status):
+ """Waits for an image tasks to reach a given status."""
+ pending_tasks = []
+ start = int(time.time())
+ while int(time.time()) - start < client.build_timeout:
+ tasks = client.show_image_tasks(image_id)['tasks']
+
+ pending_tasks = [task for task in tasks if task['status'] != status]
+ if not pending_tasks:
+ return tasks
+ time.sleep(client.build_interval)
+
+ message = ('Image %(image_id)s tasks: %(pending_tasks)s '
+ 'failed to reach %(status)s state within the required '
+ 'time (%(timeout)s s).' % {'image_id': image_id,
+ 'pending_tasks': pending_tasks,
+ 'status': status,
+ 'timeout': client.build_timeout})
+ caller = test_utils.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
+ raise lib_exc.TimeoutException(message)
+
+
def wait_for_image_imported_to_stores(client, image_id, stores=None):
"""Waits for an image to be imported to all requested stores.
diff --git a/tempest/hacking/checks.py b/tempest/hacking/checks.py
index 6a97a00..c1e6b2d 100644
--- a/tempest/hacking/checks.py
+++ b/tempest/hacking/checks.py
@@ -140,20 +140,10 @@
"decorators.skip_because from tempest.lib")
-def _common_service_clients_check(logical_line, physical_line, filename,
- ignored_list_file=None):
+def _common_service_clients_check(logical_line, physical_line, filename):
if not re.match('tempest/(lib/)?services/.*', filename):
return False
- if ignored_list_file is not None:
- ignored_list = []
- with open('tempest/hacking/' + ignored_list_file) as f:
- for line in f:
- ignored_list.append(line.strip())
-
- if filename in ignored_list:
- return False
-
if not METHOD.match(physical_line):
return False
@@ -171,7 +161,7 @@
T110
"""
if not _common_service_clients_check(logical_line, physical_line,
- filename, 'ignored_list_T110.txt'):
+ filename):
return
for line in lines[line_number:]:
@@ -199,7 +189,7 @@
T111
"""
if not _common_service_clients_check(logical_line, physical_line,
- filename, 'ignored_list_T111.txt'):
+ filename):
return
for line in lines[line_number:]:
diff --git a/tempest/lib/common/api_version_utils.py b/tempest/lib/common/api_version_utils.py
index 80dbc1d..db5c8c3 100644
--- a/tempest/lib/common/api_version_utils.py
+++ b/tempest/lib/common/api_version_utils.py
@@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
import testtools
from tempest.lib.common import api_version_request
@@ -117,7 +116,7 @@
:param response_header: Response header where microversion is
expected to be present.
"""
- if not isinstance(api_microversion, six.string_types):
+ if not isinstance(api_microversion, str):
raise TypeError('api_microversion must be a string')
api_microversion_header_name = api_microversion_header_name.lower()
if (api_microversion_header_name not in response_header or
diff --git a/tempest/lib/common/dynamic_creds.py b/tempest/lib/common/dynamic_creds.py
index f334c36..d86522a 100644
--- a/tempest/lib/common/dynamic_creds.py
+++ b/tempest/lib/common/dynamic_creds.py
@@ -16,7 +16,6 @@
import netaddr
from oslo_log import log as logging
-import six
from tempest.lib.common import cred_client
from tempest.lib.common import cred_provider
@@ -556,7 +555,7 @@
if not self._creds:
return
self._clear_isolated_net_resources()
- for creds in six.itervalues(self._creds):
+ for creds in self._creds.values():
try:
self.creds_client.delete_user(creds.user_id)
except lib_exc.NotFound:
diff --git a/tempest/lib/common/http.py b/tempest/lib/common/http.py
index 8c1a802..33f871b 100644
--- a/tempest/lib/common/http.py
+++ b/tempest/lib/common/http.py
@@ -13,7 +13,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import six
import urllib3
@@ -89,7 +88,7 @@
for key, value in info.getheaders().items():
# We assume HTTP header name to be string, not random
# bytes, thus ensure we have string keys.
- self[six.u(key).lower()] = value
+ self[str(key).lower()] = value
self.status = info.status
self['status'] = str(self.status)
self.reason = info.reason
diff --git a/tempest/lib/common/rest_client.py b/tempest/lib/common/rest_client.py
index 00f2aeb..573d64e 100644
--- a/tempest/lib/common/rest_client.py
+++ b/tempest/lib/common/rest_client.py
@@ -24,7 +24,6 @@
from oslo_log import log as logging
from oslo_log import versionutils
from oslo_serialization import jsonutils as json
-import six
from tempest.lib.common import http
from tempest.lib.common import jsonschema_validator
@@ -509,7 +508,7 @@
if not hasattr(body, "keys") or len(body.keys()) != 1:
return body
# Just return the "wrapped" element
- _, first_item = six.next(six.iteritems(body))
+ _, first_item = tuple(body.items())[0]
if isinstance(first_item, (dict, list)):
return first_item
except (ValueError, IndexError):
@@ -907,9 +906,14 @@
return
if int(time.time()) - start_time >= self.build_timeout:
message = ('Failed to delete %(resource_type)s %(id)s within '
- 'the required time (%(timeout)s s).' %
+ 'the required time (%(timeout)s s). Timer started '
+ 'at %(start_time)s. Timer ended at %(end_time)s'
+ 'waited for %(wait_time)s' %
{'resource_type': self.resource_type, 'id': id,
- 'timeout': self.build_timeout})
+ 'timeout': self.build_timeout,
+ 'start_time': start_time,
+ 'end_time': int(time.time()),
+ 'wait_time': int(time.time()) - start_time})
caller = test_utils.find_test_caller()
if caller:
message = '(%s) %s' % (caller, message)
diff --git a/tempest/lib/common/ssh.py b/tempest/lib/common/ssh.py
index 60107d7..ee15375 100644
--- a/tempest/lib/common/ssh.py
+++ b/tempest/lib/common/ssh.py
@@ -21,7 +21,6 @@
import warnings
from oslo_log import log as logging
-import six
from tempest.lib import exceptions
@@ -66,7 +65,7 @@
self.username = username
self.port = port
self.password = password
- if isinstance(pkey, six.string_types):
+ if isinstance(pkey, str):
pkey = paramiko.RSAKey.from_private_key(
io.StringIO(str(pkey)))
self.pkey = pkey
diff --git a/tempest/lib/common/utils/data_utils.py b/tempest/lib/common/utils/data_utils.py
index b6671b5..1e94f86 100644
--- a/tempest/lib/common/utils/data_utils.py
+++ b/tempest/lib/common/utils/data_utils.py
@@ -19,7 +19,6 @@
import uuid
from oslo_utils import uuidutils
-import six.moves
def rand_uuid():
@@ -171,7 +170,7 @@
"""
if size > 1 << 20:
raise RuntimeError('Size should be less than 1MiB')
- return b''.join([six.int2byte(random.randint(0, 255))
+ return b''.join([bytes((random.randint(0, 255),))
for i in range(size)])
diff --git a/tempest/lib/common/utils/linux/remote_client.py b/tempest/lib/common/utils/linux/remote_client.py
index 71fed02..d84dd28 100644
--- a/tempest/lib/common/utils/linux/remote_client.py
+++ b/tempest/lib/common/utils/linux/remote_client.py
@@ -15,7 +15,6 @@
import netaddr
from oslo_log import log as logging
-import six
from tempest.lib.common import ssh
from tempest.lib.common.utils import test_utils
@@ -55,8 +54,8 @@
except Exception:
msg = 'Could not get console_log for server %s'
LOG.debug(msg, self.server['id'])
- # re-raise the original ssh timeout exception
- six.reraise(*original_exception)
+ # raise the original ssh timeout exception
+ raise
finally:
# Delete the traceback to avoid circular references
_, _, trace = original_exception
diff --git a/tempest/lib/decorators.py b/tempest/lib/decorators.py
index 25ff473..a4633ca 100644
--- a/tempest/lib/decorators.py
+++ b/tempest/lib/decorators.py
@@ -16,7 +16,6 @@
import uuid
from oslo_log import log as logging
-import six
import testtools
from tempest.lib import exceptions as lib_exc
@@ -110,7 +109,7 @@
def idempotent_id(id):
"""Stub for metadata decorator"""
- if not isinstance(id, six.string_types):
+ if not isinstance(id, str):
raise TypeError('Test idempotent_id must be string not %s'
'' % type(id).__name__)
uuid.UUID(id)
@@ -140,7 +139,7 @@
# Check to see if the attr should be conditional applied.
if 'condition' in kwargs and not kwargs.get('condition'):
return f
- if 'type' in kwargs and isinstance(kwargs['type'], six.string_types):
+ if 'type' in kwargs and isinstance(kwargs['type'], str):
f = testtools.testcase.attr(kwargs['type'])(f)
elif 'type' in kwargs and isinstance(kwargs['type'], list):
for attr in kwargs['type']:
diff --git a/tempest/lib/services/compute/assisted_volume_snapshots_client.py b/tempest/lib/services/compute/assisted_volume_snapshots_client.py
index 8b67491..7a949df 100644
--- a/tempest/lib/services/compute/assisted_volume_snapshots_client.py
+++ b/tempest/lib/services/compute/assisted_volume_snapshots_client.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations
# under the License.
+from urllib import parse as urllib
+
from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
from tempest.lib.services.compute import base_compute_client
diff --git a/tempest/lib/services/identity/v3/identity_providers_client.py b/tempest/lib/services/identity/v3/identity_providers_client.py
index af6a245..002bc8c 100644
--- a/tempest/lib/services/identity/v3/identity_providers_client.py
+++ b/tempest/lib/services/identity/v3/identity_providers_client.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations under
# the License.
+from urllib import parse as urllib
+
from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
diff --git a/tempest/lib/services/identity/v3/mappings_client.py b/tempest/lib/services/identity/v3/mappings_client.py
index 9ec5384..a924b33 100644
--- a/tempest/lib/services/identity/v3/mappings_client.py
+++ b/tempest/lib/services/identity/v3/mappings_client.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations under
# the License.
+from urllib import parse as urllib
+
from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
diff --git a/tempest/lib/services/identity/v3/oauth_token_client.py b/tempest/lib/services/identity/v3/oauth_token_client.py
index 236b224..564d6d6 100644
--- a/tempest/lib/services/identity/v3/oauth_token_client.py
+++ b/tempest/lib/services/identity/v3/oauth_token_client.py
@@ -20,8 +20,6 @@
import time
from urllib import parse as urlparse
-import six
-
from oslo_serialization import jsonutils as json
from tempest.lib.common import rest_client
@@ -35,7 +33,7 @@
safe = b'~'
s = s.encode('utf-8') if isinstance(s, str) else s
s = urlparse.quote(s, safe)
- if isinstance(s, six.binary_type):
+ if isinstance(s, bytes):
s = s.decode('utf-8')
return s
diff --git a/tempest/lib/services/identity/v3/protocols_client.py b/tempest/lib/services/identity/v3/protocols_client.py
index 2e0221b..19aa426 100644
--- a/tempest/lib/services/identity/v3/protocols_client.py
+++ b/tempest/lib/services/identity/v3/protocols_client.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations under
# the License.
+from urllib import parse as urllib
+
from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
diff --git a/tempest/lib/services/identity/v3/service_providers_client.py b/tempest/lib/services/identity/v3/service_providers_client.py
index b84cf43..5d4f014 100644
--- a/tempest/lib/services/identity/v3/service_providers_client.py
+++ b/tempest/lib/services/identity/v3/service_providers_client.py
@@ -13,8 +13,9 @@
# License for the specific language governing permissions and limitations under
# the License.
+from urllib import parse as urllib
+
from oslo_serialization import jsonutils as json
-from six.moves.urllib import parse as urllib
from tempest.lib.common import rest_client
diff --git a/tempest/lib/services/network/__init__.py b/tempest/lib/services/network/__init__.py
index f7ac046..7e57499 100644
--- a/tempest/lib/services/network/__init__.py
+++ b/tempest/lib/services/network/__init__.py
@@ -36,6 +36,7 @@
from tempest.lib.services.network.subnetpools_client import SubnetpoolsClient
from tempest.lib.services.network.subnets_client import SubnetsClient
from tempest.lib.services.network.tags_client import TagsClient
+from tempest.lib.services.network.trunks_client import TrunksClient
from tempest.lib.services.network.versions_client import NetworkVersionsClient
__all__ = ['AgentsClient', 'ExtensionsClient', 'FloatingIPsClient',
@@ -44,4 +45,4 @@
'QosClient', 'QosMinimumBandwidthRulesClient', 'QuotasClient',
'RoutersClient', 'SecurityGroupRulesClient', 'SecurityGroupsClient',
'SegmentsClient', 'ServiceProvidersClient', 'SubnetpoolsClient',
- 'SubnetsClient', 'TagsClient']
+ 'SubnetsClient', 'TagsClient', 'TrunksClient']
diff --git a/tempest/lib/services/network/trunks_client.py b/tempest/lib/services/network/trunks_client.py
new file mode 100644
index 0000000..2fd9e01
--- /dev/null
+++ b/tempest/lib/services/network/trunks_client.py
@@ -0,0 +1,100 @@
+# 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 tempest.lib.services.network import base
+
+
+class TrunksClient(base.BaseNetworkClient):
+
+ def create_trunk(self, **kwargs):
+ """Creates a trunk.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#create-trunk
+ """
+ uri = '/trunks'
+ post_data = {'trunk': kwargs}
+ return self.create_resource(uri, post_data)
+
+ def update_trunk(self, trunk_id, **kwargs):
+ """Updates a trunk.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#update-trunk
+ """
+ uri = '/trunks/%s' % trunk_id
+ put_data = {'trunk': kwargs}
+ return self.update_resource(uri, put_data)
+
+ def show_trunk(self, trunk_id):
+ """Shows details for a trunk.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#show-trunk
+ """
+ uri = '/trunks/%s' % trunk_id
+ return self.show_resource(uri)
+
+ def delete_trunk(self, trunk_id):
+ """Deletes a trunk.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#delete-trunk
+ """
+ uri = '/trunks/%s' % trunk_id
+ return self.delete_resource(uri)
+
+ def list_trunks(self, **filters):
+ """Lists trunks to which the tenant has access.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#list-trunks
+ """
+ uri = '/trunks'
+ return self.list_resources(uri, **filters)
+
+ def add_subports_to_trunk(self, trunk_id, sub_ports):
+ """Add subports to a trunk.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#add-subports-to-trunk
+ """
+ uri = '/trunks/%s/add_subports' % trunk_id
+ put_data = {'sub_ports': sub_ports}
+ return self.update_resource(uri, put_data)
+
+ def delete_subports_from_trunk(self, trunk_id, sub_ports):
+ """Deletes subports from a trunk.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#delete-subports-from-trunk
+ """
+ uri = '/trunks/%s/remove_subports' % trunk_id
+ put_data = {'sub_ports': sub_ports}
+ return self.update_resource(uri, put_data)
+
+ def list_subports_of_trunk(self, trunk_id):
+ """List subports of a trunk.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/network/v2/index.html#list-subports-for-trunk
+ """
+ uri = '/trunks/%s/get_subports' % trunk_id
+ return self.list_resources(uri)
diff --git a/tempest/lib/services/volume/v1/volumes_client.py b/tempest/lib/services/volume/v1/volumes_client.py
index 9fca800..5d8d73b 100644
--- a/tempest/lib/services/volume/v1/volumes_client.py
+++ b/tempest/lib/services/volume/v1/volumes_client.py
@@ -16,7 +16,6 @@
from urllib import parse as urllib
from oslo_serialization import jsonutils as json
-import six
from tempest.lib.common import rest_client
from tempest.lib import exceptions as lib_exc
@@ -31,7 +30,7 @@
If params is a string it will be left as it is, but if it's not it will
be urlencoded.
"""
- if isinstance(params, six.string_types):
+ if isinstance(params, str):
return params
return urllib.urlencode(params)
diff --git a/tempest/lib/services/volume/v3/volumes_client.py b/tempest/lib/services/volume/v3/volumes_client.py
index 147a79b..9c6fe68 100644
--- a/tempest/lib/services/volume/v3/volumes_client.py
+++ b/tempest/lib/services/volume/v3/volumes_client.py
@@ -16,7 +16,6 @@
from urllib import parse as urllib
from oslo_serialization import jsonutils as json
-import six
from tempest.lib.api_schema.response.volume import volumes as schema
from tempest.lib.common import rest_client
@@ -33,7 +32,7 @@
If params is a string it will be left as it is, but if it's not it will
be urlencoded.
"""
- if isinstance(params, six.string_types):
+ if isinstance(params, str):
return params
return urllib.urlencode(params)
diff --git a/tempest/test.py b/tempest/test.py
index 655b9a4..8ea3b16 100644
--- a/tempest/test.py
+++ b/tempest/test.py
@@ -20,7 +20,6 @@
import debtcollector.moves
import fixtures
from oslo_log import log as logging
-import six
import testtools
from tempest import clients
@@ -179,7 +178,7 @@
etype, cls.__name__)
cls.tearDownClass()
try:
- six.reraise(etype, value, trace)
+ raise value.with_traceback(trace)
finally:
del trace # to avoid circular refs
finally:
@@ -233,7 +232,7 @@
# the first one
if re_raise and etype is not None:
try:
- six.reraise(etype, value, trace)
+ raise value.with_traceback(trace)
finally:
del trace # to avoid circular refs
@@ -384,7 +383,7 @@
# This may raise an exception in case credentials are not available
# In that case we want to let the exception through and the test
# fail accordingly
- if isinstance(credentials_type, six.string_types):
+ if isinstance(credentials_type, str):
manager = cls.get_client_manager(
credential_type=credentials_type)
setattr(cls, 'os_%s' % credentials_type, manager)
@@ -859,7 +858,7 @@
"""
# Get a manager for the given credentials_type, but at least
# always fall back on getting the manager for primary credentials
- if isinstance(credentials_type, six.string_types):
+ if isinstance(credentials_type, str):
manager = cls.get_client_manager(credential_type=credentials_type)
elif isinstance(credentials_type, list):
scope = 'project'
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index d64d7b0..f801243 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -120,6 +120,29 @@
waiters.wait_for_image_copied_to_stores,
self.client, 'fake_image_id')
+ def test_wait_for_image_tasks_status(self):
+ self.client.show_image_tasks.return_value = ({
+ 'tasks': [{'status': 'success'}]})
+ start_time = int(time.time())
+ waiters.wait_for_image_tasks_status(
+ self.client, 'fake_image_id', 'success')
+ end_time = int(time.time())
+ # Ensure waiter returns before build_timeout
+ self.assertLess((end_time - start_time), 10)
+
+ def test_wait_for_image_tasks_status_timeout(self):
+ time_mock = self.patch('time.time')
+ self.patch('time.time', side_effect=[0., 1.])
+ time_mock.side_effect = utils.generate_timeout_series(1)
+
+ self.client.show_image_tasks.return_value = ({
+ 'tasks': [
+ {'status': 'success'},
+ {'status': 'processing'}]})
+ self.assertRaises(lib_exc.TimeoutException,
+ waiters.wait_for_image_tasks_status,
+ self.client, 'fake_image_id', 'success')
+
class TestInterfaceWaiters(base.TestCase):
diff --git a/tempest/tests/lib/common/test_preprov_creds.py b/tempest/tests/lib/common/test_preprov_creds.py
index fe7fcd2..f2131dc 100644
--- a/tempest/tests/lib/common/test_preprov_creds.py
+++ b/tempest/tests/lib/common/test_preprov_creds.py
@@ -144,8 +144,7 @@
# Emulate the lock existing on the filesystem
self.useFixture(fixtures.MockPatch(
'os.path.isfile', return_value=True))
- with mock.patch('six.moves.builtins.open', mock.mock_open(),
- create=True):
+ with mock.patch('builtins.open', mock.mock_open(), create=True):
test_account_class = (
preprov_creds.PreProvisionedCredentialProvider(
**self.fixed_params))
@@ -157,8 +156,7 @@
# Emulate the lock not existing on the filesystem
self.useFixture(fixtures.MockPatch(
'os.path.isfile', return_value=False))
- with mock.patch('six.moves.builtins.open', mock.mock_open(),
- create=True):
+ with mock.patch('builtins.open', mock.mock_open(), create=True):
test_account_class = (
preprov_creds.PreProvisionedCredentialProvider(
**self.fixed_params))
@@ -177,7 +175,7 @@
'os.path.isfile', return_value=False))
test_account_class = preprov_creds.PreProvisionedCredentialProvider(
**self.fixed_params)
- with mock.patch('six.moves.builtins.open', mock.mock_open(),
+ with mock.patch('builtins.open', mock.mock_open(),
create=True) as open_mock:
test_account_class._get_free_hash(hash_list)
lock_path = os.path.join(self.fixed_params['accounts_lock_dir'],
@@ -196,8 +194,7 @@
'os.path.isfile', return_value=True))
test_account_class = preprov_creds.PreProvisionedCredentialProvider(
**self.fixed_params)
- with mock.patch('six.moves.builtins.open', mock.mock_open(),
- create=True):
+ with mock.patch('builtins.open', mock.mock_open(), create=True):
self.assertRaises(lib_exc.InvalidCredentials,
test_account_class._get_free_hash, hash_list)
@@ -217,7 +214,7 @@
return True
self.patchobject(os.path, 'isfile', _fake_is_file)
- with mock.patch('six.moves.builtins.open', mock.mock_open(),
+ with mock.patch('builtins.open', mock.mock_open(),
create=True) as open_mock:
test_account_class._get_free_hash(hash_list)
lock_path = os.path.join(self.fixed_params['accounts_lock_dir'],
diff --git a/tempest/tests/lib/common/test_rest_client.py b/tempest/tests/lib/common/test_rest_client.py
index b861582..c5f6d7a 100644
--- a/tempest/tests/lib/common/test_rest_client.py
+++ b/tempest/tests/lib/common/test_rest_client.py
@@ -17,7 +17,6 @@
import fixtures
import jsonschema
from oslo_serialization import jsonutils as json
-import six
from tempest.lib.common import http
from tempest.lib.common import rest_client
@@ -93,7 +92,7 @@
class TestRestClientHeadersJSON(TestRestClientHTTPMethods):
def _verify_headers(self, resp):
- resp = dict((k.lower(), v) for k, v in six.iteritems(resp))
+ resp = dict((k.lower(), v) for k, v in resp.items())
self.assertEqual(self.header_value, resp['accept'])
self.assertEqual(self.header_value, resp['content-type'])
@@ -526,9 +525,11 @@
self.rest_client.wait_for_resource_deletion,
'1234')
- # time.time() should be called twice, first to start the timer
- # and then to compute the timedelta
- self.assertEqual(2, time_mock.call_count)
+ # time.time() should be called 4 times,
+ # 1. Start timer
+ # 2. End timer
+ # 3 & 4. To generate timeout exception message
+ self.assertEqual(4, time_mock.call_count)
def test_wait_for_deletion_with_unimplemented_deleted_method(self):
self.rest_client.is_resource_deleted = self.original_deleted_method
diff --git a/tempest/tests/lib/services/network/test_trunks_client.py b/tempest/tests/lib/services/network/test_trunks_client.py
new file mode 100644
index 0000000..b637d5e
--- /dev/null
+++ b/tempest/tests/lib/services/network/test_trunks_client.py
@@ -0,0 +1,201 @@
+# 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 copy
+
+from tempest.lib.services.network import trunks_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestTrunksClient(base.BaseServiceTest):
+
+ FAKE_TRUNK_ID = "dfbc2103-93cf-4edf-952a-ef6deb32ddc6"
+ FAKE_PORT_ID = "1f04eb36-6c84-11eb-b0ab-4fc62961629d"
+ FAKE_TRUNKS = {
+ "trunks": [
+ {
+ "admin_state_up": True,
+ "description": "",
+ "id": "dfbc2103-93cf-4edf-952a-ef6deb32ddc6",
+ "name": "trunk0",
+ "port_id": "00130aab-bb51-42a1-a7c4-6703a3a43aa5",
+ "project_id": "",
+ "revision_number": 2,
+ "status": "DOWN",
+ "sub_ports": [
+ {
+ "port_id": "87d2483d-e5e6-483d-b5f0-81b9ed1d1a91",
+ "segmentation_id": 101,
+ "segmentation_type": "vlan"
+ }
+ ],
+ "tags": [],
+ },
+ {
+ "admin_state_up": True,
+ "description": "",
+ "id": "9eb0e72e-11d3-4295-bcaf-6c89008d9f0a",
+ "name": "trunk1",
+ "port_id": "035a12bf-2ae3-42ae-8ad6-9f70640cddde",
+ "project_id": "",
+ "revision_number": 2,
+ "status": "DOWN",
+ "sub_ports": [
+ {
+ "port_id": "cba839d5-02e2-4e09-b964-81356da78165",
+ "segmentation_id": 102,
+ "segmentation_type": "vlan"
+ }
+ ],
+ "tags": [],
+ },
+ ]
+ }
+
+ FAKE_TRUNK_1 = {
+ "name": "trunk0",
+ "port_id": "00130aab-bb51-42a1-a7c4-6703a3a43aa5"
+ }
+
+ def setUp(self):
+ super(TestTrunksClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.trunks_client = trunks_client.TrunksClient(
+ fake_auth, "network", "regionOne")
+
+ def _test_create_trunk(self, bytes_body=False):
+ self.check_service_client_function(
+ self.trunks_client.create_trunk,
+ "tempest.lib.common.rest_client.RestClient.post",
+ {"trunk": self.FAKE_TRUNKS["trunks"][0]},
+ bytes_body,
+ 201,
+ **self.FAKE_TRUNK_1)
+
+ def _test_list_trunks(self, bytes_body=False):
+ self.check_service_client_function(
+ self.trunks_client.list_trunks,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_TRUNKS,
+ bytes_body,
+ 200)
+
+ def _test_show_trunk(self, bytes_body=False):
+ self.check_service_client_function(
+ self.trunks_client.show_trunk,
+ "tempest.lib.common.rest_client.RestClient.get",
+ {"trunk": self.FAKE_TRUNKS["trunks"][0]},
+ bytes_body,
+ 200,
+ trunk_id=self.FAKE_TRUNK_ID)
+
+ def _test_update_trunk(self, bytes_body=False):
+ update_kwargs = {
+ "admin_state_up": True,
+ "name": "new_trunk"
+ }
+
+ resp_body = {
+ "trunk": copy.deepcopy(
+ self.FAKE_TRUNKS["trunks"][0]
+ )
+ }
+ resp_body["trunk"].update(update_kwargs)
+
+ self.check_service_client_function(
+ self.trunks_client.update_trunk,
+ "tempest.lib.common.rest_client.RestClient.put",
+ resp_body,
+ bytes_body,
+ 200,
+ trunk_id=self.FAKE_TRUNK_ID,
+ **update_kwargs)
+
+ def _test_add_subports_to_trunk(self, bytes_body=False):
+ sub_ports = [{
+ "port_id": "f04eb36-6c84-11eb-b0ab-4fc62961629d",
+ "segmentation_type": "vlan",
+ "segmentation_id": "1001"
+ }]
+ resp_body = copy.deepcopy(self.FAKE_TRUNKS["trunks"][0])
+
+ resp_body["sub_ports"].append(sub_ports)
+ self.check_service_client_function(
+ self.trunks_client.add_subports_to_trunk,
+ "tempest.lib.common.rest_client.RestClient.put",
+ resp_body,
+ bytes_body,
+ 200,
+ trunk_id=self.FAKE_TRUNK_ID,
+ sub_ports=sub_ports)
+
+ def _test_delete_subports_from_trunk(self, bytes_body=False):
+ fake_sub_ports = self.FAKE_TRUNKS['trunks'][0]['sub_ports']
+ sub_ports = [
+ {"port_id": fake_sub_ports[0]['port_id']}
+ ]
+ resp_body = copy.deepcopy(self.FAKE_TRUNKS["trunks"][0])
+
+ resp_body['sub_ports'] = []
+ self.check_service_client_function(
+ self.trunks_client.delete_subports_from_trunk,
+ "tempest.lib.common.rest_client.RestClient.put",
+ resp_body,
+ bytes_body,
+ 200,
+ trunk_id=self.FAKE_TRUNK_ID,
+ sub_ports=sub_ports)
+
+ def test_create_trunk_with_str_body(self):
+ self._test_create_trunk()
+
+ def test_create_trunk_with_bytes_body(self):
+ self._test_create_trunk(bytes_body=True)
+
+ def test_list_trunks_with_str_body(self):
+ self._test_list_trunks()
+
+ def test_list_trunks_with_bytes_body(self):
+ self._test_list_trunks(bytes_body=True)
+
+ def test_show_trunk_with_str_body(self):
+ self._test_show_trunk()
+
+ def test_show_trunk_with_bytes_body(self):
+ self._test_show_trunk(bytes_body=True)
+
+ def test_update_trunk_with_str_body(self):
+ self._test_update_trunk()
+
+ def test_update_trunk_with_bytes_body(self):
+ self._test_update_trunk(bytes_body=True)
+
+ def test_add_subports_to_trunk_str_body(self):
+ self._test_add_subports_to_trunk()
+
+ def test_add_subports_to_trunk_bytes_body(self):
+ self._test_add_subports_to_trunk(bytes_body=True)
+
+ def test_delete_subports_from_trunk_str_body(self):
+ self._test_delete_subports_from_trunk()
+
+ def test_delete_subports_from_trunk_bytes_body(self):
+ self._test_delete_subports_from_trunk(bytes_body=True)
+
+ def test_delete_trunk(self):
+ self.check_service_client_function(
+ self.trunks_client.delete_trunk,
+ "tempest.lib.common.rest_client.RestClient.delete",
+ {},
+ status=204,
+ trunk_id=self.FAKE_TRUNK_ID)
diff --git a/tempest/tests/lib/services/test_clients.py b/tempest/tests/lib/services/test_clients.py
index f83064a..6c79db6 100644
--- a/tempest/tests/lib/services/test_clients.py
+++ b/tempest/tests/lib/services/test_clients.py
@@ -16,7 +16,6 @@
from unittest import mock
import fixtures
-import six
import testtools
from tempest.lib import auth
@@ -270,8 +269,7 @@
'module_path': 'This neither',
'client_names': ['SomeClient1']}]}
msg = "(?=.*{0})(?=.*{1})".format(
- *[x[1][0]['module_path'] for x in six.iteritems(
- fake_service_clients)])
+ *[x[1][0]['module_path'] for x in fake_service_clients.items()])
self.useFixture(fixtures.MockPatchObject(
clients.ClientsRegistry(), 'get_service_clients',
return_value=fake_service_clients))
@@ -300,8 +298,8 @@
'module_path': 'fake_path_2',
'client_names': ['SomeClient2']}]}
msg = "(?=.*{0})(?=.*{1})".format(
- *[x[1][0]['service_version'] for x in six.iteritems(
- fake_service_clients)])
+ *[x[1][0]['service_version'] for x in
+ fake_service_clients.items()])
self.useFixture(fixtures.MockPatchObject(
clients.ClientsRegistry(), 'get_service_clients',
return_value=fake_service_clients))
diff --git a/tempest/tests/lib/test_ssh.py b/tempest/tests/lib/test_ssh.py
index 035bdb0..886d99c 100644
--- a/tempest/tests/lib/test_ssh.py
+++ b/tempest/tests/lib/test_ssh.py
@@ -16,7 +16,6 @@
import socket
from unittest import mock
-import six
import testtools
from tempest.lib.common import ssh
@@ -240,7 +239,7 @@
return chan_mock, poll_mock, select_mock, client_mock
- _utf8_string = six.unichr(1071)
+ _utf8_string = chr(1071)
_utf8_bytes = _utf8_string.encode("utf-8")
@mock.patch('select.POLLIN', SELECT_POLLIN, create=True)
diff --git a/tools/check_logs.py b/tools/check_logs.py
index cc74b17..8ab3af2 100755
--- a/tools/check_logs.py
+++ b/tools/check_logs.py
@@ -23,7 +23,6 @@
import sys
import urllib.request as urlreq
-import six
import yaml
# DEVSTACK_GATE_GRENADE is either unset if grenade is not running
@@ -137,7 +136,7 @@
with open(ALLOW_LIST_FILE) as stream:
loaded = yaml.safe_load(stream)
if loaded:
- for (name, l) in six.iteritems(loaded):
+ for (name, l) in loaded.values():
for w in l:
assert 'module' in w, 'no module in %s' % name
assert 'message' in w, 'no message in %s' % name
diff --git a/tox.ini b/tox.ini
index 2315163..cd32174 100644
--- a/tox.ini
+++ b/tox.ini
@@ -409,3 +409,15 @@
allowlist_externals = bash
commands =
bash tools/tempest-plugin-sanity.sh
+
+[testenv:stestr-master]
+envdir = .tox/tempest
+sitepackages = {[tempestenv]sitepackages}
+basepython = {[tempestenv]basepython}
+setenv = {[tempestenv]setenv}
+deps = {[tempestenv]deps}
+# The below command install stestr master version and run smoke tests
+commands =
+ find . -type f -name "*.pyc" -delete
+ pip install -U git+https://github.com/mtreinish/stestr
+ tempest run --regex '\[.*\bsmoke\b.*\]' {posargs}
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index 5a14430..b83eb34 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -302,6 +302,7 @@
devstack_services:
neutron-placement: true
neutron-qos: true
+ neutron-trunk: true
group-vars:
subnode:
devstack_localrc:
diff --git a/zuul.d/project.yaml b/zuul.d/project.yaml
index d5b2787..698df53 100644
--- a/zuul.d/project.yaml
+++ b/zuul.d/project.yaml
@@ -3,7 +3,7 @@
- check-requirements
- integrated-gate-py3
- openstack-cover-jobs
- - openstack-python3-victoria-jobs
+ - openstack-python3-xena-jobs
- publish-openstack-docs-pti
- release-notes-jobs-python3
check:
@@ -31,6 +31,8 @@
- glance-multistore-cinder-import:
voting: false
irrelevant-files: *tempest-irrelevant-files
+ - tempest-full-wallaby-py3:
+ irrelevant-files: *tempest-irrelevant-files
- tempest-full-victoria-py3:
irrelevant-files: *tempest-irrelevant-files
- tempest-full-ussuri-py3:
@@ -107,6 +109,7 @@
irrelevant-files: *tempest-irrelevant-files
experimental:
jobs:
+ - tempest-stestr-master
- tempest-cinder-v2-api:
irrelevant-files: *tempest-irrelevant-files
- tempest-all:
@@ -123,6 +126,7 @@
irrelevant-files: *tempest-irrelevant-files
periodic-stable:
jobs:
+ - tempest-full-wallaby-py3
- tempest-full-victoria-py3
- tempest-full-ussuri-py3
- tempest-full-train-py3
@@ -130,3 +134,4 @@
jobs:
- tempest-all
- tempest-full-oslo-master
+ - tempest-stestr-master
diff --git a/zuul.d/stable-jobs.yaml b/zuul.d/stable-jobs.yaml
index 769b280..2f0df66 100644
--- a/zuul.d/stable-jobs.yaml
+++ b/zuul.d/stable-jobs.yaml
@@ -1,5 +1,10 @@
# NOTE(gmann): This file includes all stable release jobs definition.
- job:
+ name: tempest-full-wallaby-py3
+ parent: tempest-full-py3
+ override-checkout: stable/wallaby
+
+- job:
name: tempest-full-victoria-py3
parent: tempest-full-py3
override-checkout: stable/victoria
diff --git a/zuul.d/tempest-specific.yaml b/zuul.d/tempest-specific.yaml
index fd348cc..5063d89 100644
--- a/zuul.d/tempest-specific.yaml
+++ b/zuul.d/tempest-specific.yaml
@@ -113,3 +113,19 @@
vars:
devstack_localrc:
TEMPEST_HAS_ADMIN: False
+
+- job:
+ name: tempest-stestr-master
+ parent: devstack-tempest
+ description: |
+ Smoke integration test with stestr master.
+ This ensures that new stestr release does
+ not break Temepst.
+ vars:
+ tox_envlist: stestr-master
+ devstack_services:
+ s-account: false
+ s-container: false
+ s-object: false
+ s-proxy: false
+ c-bak: false