Merge "Fix unstability in test_subnet_details"
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 59a2f64..b738fde 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -86,7 +86,7 @@
master_doc = 'index'
# General information about the project.
-copyright = u'2013, OpenStack QA Team'
+copyright = '2013, OpenStack QA Team'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -206,8 +206,8 @@
# (source start file, target name, title, author, documentclass
# [howto/manual]).
latex_documents = [
- ('index', 'doc-tempest.tex', u'Tempest Testing Project',
- u'OpenStack Foundation', 'manual'),
+ ('index', 'doc-tempest.tex', 'Tempest Testing Project',
+ 'OpenStack Foundation', 'manual'),
]
latex_use_xindy = False
diff --git a/releasenotes/notes/add-placement-usage-client-method-8b6015cbd8a5e0f6.yaml b/releasenotes/notes/add-placement-usage-client-method-8b6015cbd8a5e0f6.yaml
new file mode 100644
index 0000000..d31a33c
--- /dev/null
+++ b/releasenotes/notes/add-placement-usage-client-method-8b6015cbd8a5e0f6.yaml
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ Add ``placement`` API usage method for evaluating resource class
+ utilization of the resource provider. The following API call is available
+ for tempest from now in the resource_providers_client:
+
+ * GET /resource_providers/{uuid}/usages
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
index 9a9de43..b353a18 100644
--- a/releasenotes/source/conf.py
+++ b/releasenotes/source/conf.py
@@ -59,7 +59,7 @@
master_doc = 'index'
# General information about the project.
-copyright = u'2016, tempest Developers'
+copyright = '2016, tempest Developers'
# Release do not need a version number in the title, they
# cover multiple versions.
@@ -194,8 +194,8 @@
# author, documentclass [howto, manual, or own class]).
latex_documents = [
('index', 'olso.configReleaseNotes.tex',
- u'olso.config Release Notes Documentation',
- u'tempest Developers', 'manual'),
+ 'olso.config Release Notes Documentation',
+ 'tempest Developers', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
@@ -225,8 +225,8 @@
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'olso.configreleasenotes',
- u'tempest Release Notes Documentation',
- [u'tempest Developers'], 1)
+ 'tempest Release Notes Documentation',
+ ['tempest Developers'], 1)
]
# If true, show URL addresses after external links.
@@ -240,8 +240,8 @@
# dir menu entry, description, category)
texinfo_documents = [
('index', 'tempestReleaseNotes',
- u'tempest Release Notes Documentation',
- u'tempest Developers', 'olso.configReleaseNotes',
+ 'tempest Release Notes Documentation',
+ 'tempest Developers', 'olso.configReleaseNotes',
'An OpenStack library for parsing configuration options from the command'
' line and configuration files.',
'Miscellaneous'),
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/compute/servers/test_servers.py b/tempest/api/compute/servers/test_servers.py
index cc013e3..1c839eb 100644
--- a/tempest/api/compute/servers/test_servers.py
+++ b/tempest/api/compute/servers/test_servers.py
@@ -103,7 +103,7 @@
server = self.create_test_server(wait_until='ACTIVE')
self.addCleanup(self.delete_server, server['id'])
# Update instance name with non-ASCII characters
- prefix_name = u'\u00CD\u00F1st\u00E1\u00F1c\u00E9'
+ prefix_name = '\u00CD\u00F1st\u00E1\u00F1c\u00E9'
self._update_server_name(server['id'], 'ACTIVE', prefix_name)
# stop server and check server name update again
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/placement/resource_providers_client.py b/tempest/lib/services/placement/resource_providers_client.py
index e6fbcb2..3214053 100644
--- a/tempest/lib/services/placement/resource_providers_client.py
+++ b/tempest/lib/services/placement/resource_providers_client.py
@@ -26,6 +26,7 @@
* resource providers
* resource provider inventories
* resource provider aggregates
+ * resource provider usages
"""
def list_resource_providers(self, **params):
@@ -69,6 +70,19 @@
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
+ def list_resource_provider_usages(self, rp_uuid):
+ """List resource provider usages.
+
+ For full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/placement/#list-resource-provider-usages
+ """
+ url = '/resource_providers/%s/usages' % rp_uuid
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
def list_resource_provider_aggregates(self, rp_uuid):
"""List resource provider aggregates.
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/cmd/test_cleanup_services.py b/tempest/tests/cmd/test_cleanup_services.py
index fc44793..2301be6 100644
--- a/tempest/tests/cmd/test_cleanup_services.py
+++ b/tempest/tests/cmd/test_cleanup_services.py
@@ -143,40 +143,40 @@
saved_state = {
# Static list to ensure global service saved items are not deleted
- "users": {u'32rwef64245tgr20121qw324bgg': u'Lightning'},
- "flavors": {u'42': u'm1.tiny'},
- "images": {u'34yhwr-4t3q': u'stratus-0.3.2-x86_64-disk'},
- "roles": {u'3efrt74r45hn': u'president'},
- "projects": {u'f38ohgp93jj032': u'manhattan'},
- "domains": {u'default': u'Default'},
+ "users": {'32rwef64245tgr20121qw324bgg': 'Lightning'},
+ "flavors": {'42': 'm1.tiny'},
+ "images": {'34yhwr-4t3q': 'stratus-0.3.2-x86_64-disk'},
+ "roles": {'3efrt74r45hn': 'president'},
+ "projects": {'f38ohgp93jj032': 'manhattan'},
+ "domains": {'default': 'Default'},
# Static list to ensure project service saved items are not deleted
- "snapshots": {u'1ad4c789-7e8w-4dwg-afc5': u'saved-snapshot'},
- "servers": {u'7a6d4v7w-36ds-4216': u'saved-server'},
- "server_groups": {u'as6d5f7g-46ca-475e': u'saved-server-group'},
- "keypairs": {u'saved-key-pair': {
- u'fingerprint': u'7e:eb:ab:24',
- u'name': u'saved-key-pair'
+ "snapshots": {'1ad4c789-7e8w-4dwg-afc5': 'saved-snapshot'},
+ "servers": {'7a6d4v7w-36ds-4216': 'saved-server'},
+ "server_groups": {'as6d5f7g-46ca-475e': 'saved-server-group'},
+ "keypairs": {'saved-key-pair': {
+ 'fingerprint': '7e:eb:ab:24',
+ 'name': 'saved-key-pair'
}},
- "volumes": {u'aa77asdf-1234': u'saved-volume'},
- "networks": {u'6722fc13-4319': {
- u'id': u'6722fc13-4319',
- u'name': u'saved-network'
+ "volumes": {'aa77asdf-1234': 'saved-volume'},
+ "networks": {'6722fc13-4319': {
+ 'id': '6722fc13-4319',
+ 'name': 'saved-network'
}},
- "floatingips": {u'9e82d248-408a': {
- u'id': u'9e82d248-408a',
- u'status': u'ACTIVE'
+ "floatingips": {'9e82d248-408a': {
+ 'id': '9e82d248-408a',
+ 'status': 'ACTIVE'
}},
- "routers": {u'4s5w34hj-id44': u'saved-router'},
- "metering_label_rules": {u'93a973ce-4dc5': {
- u'direction': u'ingress',
- u'id': u'93a973ce-4dc5'
+ "routers": {'4s5w34hj-id44': 'saved-router'},
+ "metering_label_rules": {'93a973ce-4dc5': {
+ 'direction': 'ingress',
+ 'id': '93a973ce-4dc5'
}},
- "metering_labels": {u'723b346ce866-4c7q': u'saved-label'},
- "ports": {u'aa74aa4v-741a': u'saved-port'},
- "security_groups": {u'7q844add-3697': u'saved-sec-group'},
- "subnets": {u'55ttda4a-2584': u'saved-subnet'},
- "subnetpools": {u'8acf64c1-43fc': u'saved-subnet-pool'},
- "regions": {u'RegionOne': {}}
+ "metering_labels": {'723b346ce866-4c7q': 'saved-label'},
+ "ports": {'aa74aa4v-741a': 'saved-port'},
+ "security_groups": {'7q844add-3697': 'saved-sec-group'},
+ "subnets": {'55ttda4a-2584': 'saved-subnet'},
+ "subnetpools": {'8acf64c1-43fc': 'saved-subnet-pool'},
+ "regions": {'RegionOne': {}}
}
# Mocked methods
get_method = 'tempest.lib.common.rest_client.RestClient.get'
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/compute/test_aggregates_client.py b/tempest/tests/lib/services/compute/test_aggregates_client.py
index 674d92a..1448a4d 100644
--- a/tempest/tests/lib/services/compute/test_aggregates_client.py
+++ b/tempest/tests/lib/services/compute/test_aggregates_client.py
@@ -37,7 +37,7 @@
FAKE_CREATE_AGGREGATE = {
"aggregate":
{
- "name": u'\xf4',
+ "name": '\xf4',
"availability_zone": None,
"deleted": False,
"created_at": "2015-07-21T04:11:18.000000",
@@ -50,7 +50,7 @@
FAKE_UPDATE_AGGREGATE = {
"aggregate":
{
- "name": u'\xe9',
+ "name": '\xe9',
"availability_zone": None,
"deleted": False,
"created_at": "2015-07-16T03:07:32.000000",
@@ -74,7 +74,7 @@
"metadata": {
"availability_zone": "nova"
},
- "name": u'\xe9',
+ "name": '\xe9',
"updated_at": None
}
diff --git a/tempest/tests/lib/services/compute/test_availability_zone_client.py b/tempest/tests/lib/services/compute/test_availability_zone_client.py
index 6608592..aef98fc 100644
--- a/tempest/tests/lib/services/compute/test_availability_zone_client.py
+++ b/tempest/tests/lib/services/compute/test_availability_zone_client.py
@@ -27,7 +27,7 @@
"available": True
},
"hosts": None,
- "zoneName": u'\xf4'
+ "zoneName": '\xf4'
}
]
}
diff --git a/tempest/tests/lib/services/compute/test_extensions_client.py b/tempest/tests/lib/services/compute/test_extensions_client.py
index d7e217e..053b84c 100644
--- a/tempest/tests/lib/services/compute/test_extensions_client.py
+++ b/tempest/tests/lib/services/compute/test_extensions_client.py
@@ -27,7 +27,7 @@
"namespace":
"http://docs.openstack.org/compute/ext/multinic/api/v1.1",
"alias": "NMN",
- "description": u'\u2740(*\xb4\u25e1`*)\u2740'
+ "description": '\u2740(*\xb4\u25e1`*)\u2740'
}
}
diff --git a/tempest/tests/lib/services/compute/test_floating_ip_pools_client.py b/tempest/tests/lib/services/compute/test_floating_ip_pools_client.py
index b0c00f0..6278df4 100644
--- a/tempest/tests/lib/services/compute/test_floating_ip_pools_client.py
+++ b/tempest/tests/lib/services/compute/test_floating_ip_pools_client.py
@@ -22,8 +22,8 @@
FAKE_FLOATING_IP_POOLS = {
"floating_ip_pools":
[
- {"name": u'\u3042'},
- {"name": u'\u3044'}
+ {"name": '\u3042'},
+ {"name": '\u3044'}
]
}
diff --git a/tempest/tests/lib/services/compute/test_keypairs_client.py b/tempest/tests/lib/services/compute/test_keypairs_client.py
index ed3b9dd..214d0e5 100644
--- a/tempest/tests/lib/services/compute/test_keypairs_client.py
+++ b/tempest/tests/lib/services/compute/test_keypairs_client.py
@@ -23,7 +23,7 @@
FAKE_KEYPAIR = {"keypair": {
"public_key": "ssh-rsa foo Generated-by-Nova",
- "name": u'\u2740(*\xb4\u25e1`*)\u2740',
+ "name": '\u2740(*\xb4\u25e1`*)\u2740',
"user_id": "525d55f98980415ba98e634972fa4a10",
"fingerprint": "76:24:66:49:d7:ca:6e:5c:77:ea:8e:bb:9c:15:5f:98"
}}
diff --git a/tempest/tests/lib/services/compute/test_networks_client.py b/tempest/tests/lib/services/compute/test_networks_client.py
index 1908b57..5a88671 100644
--- a/tempest/tests/lib/services/compute/test_networks_client.py
+++ b/tempest/tests/lib/services/compute/test_networks_client.py
@@ -31,7 +31,7 @@
"deleted_at": None,
"gateway": None,
"rxtx_base": None,
- "label": u'30d7',
+ "label": '30d7',
"priority": None,
"project_id": None,
"vpn_private_address": None,
diff --git a/tempest/tests/lib/services/compute/test_quota_classes_client.py b/tempest/tests/lib/services/compute/test_quota_classes_client.py
index 22d8b91..6921365 100644
--- a/tempest/tests/lib/services/compute/test_quota_classes_client.py
+++ b/tempest/tests/lib/services/compute/test_quota_classes_client.py
@@ -29,7 +29,7 @@
"ram": 51200,
"floating_ips": 10,
"key_pairs": 100,
- "id": u'\u2740(*\xb4\u25e1`*)\u2740',
+ "id": '\u2740(*\xb4\u25e1`*)\u2740',
"instances": 10,
"security_group_rules": 20,
"security_groups": 10,
diff --git a/tempest/tests/lib/services/compute/test_tenant_networks_client.py b/tempest/tests/lib/services/compute/test_tenant_networks_client.py
index f71aad9..a042a1a 100644
--- a/tempest/tests/lib/services/compute/test_tenant_networks_client.py
+++ b/tempest/tests/lib/services/compute/test_tenant_networks_client.py
@@ -22,7 +22,7 @@
FAKE_NETWORK = {
"cidr": "None",
"id": "c2329eb4-cc8e-4439-ac4c-932369309e36",
- "label": u'\u30d7'
+ "label": '\u30d7'
}
FAKE_NETWORKS = [FAKE_NETWORK]
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/placement/test_resource_providers_client.py b/tempest/tests/lib/services/placement/test_resource_providers_client.py
index 485f584..2871395 100644
--- a/tempest/tests/lib/services/placement/test_resource_providers_client.py
+++ b/tempest/tests/lib/services/placement/test_resource_providers_client.py
@@ -85,6 +85,14 @@
},
"resource_provider_generation": 1
}
+ FAKE_RESOURCE_PROVIDER_USAGES = {
+ "usages": {
+ "VCPU": 2,
+ "MEMORY_MB": 1024,
+ "DISK_GB": 10
+ },
+ "resource_provider_generation": 3
+ }
def setUp(self):
super(TestResourceProvidersClient, self).setUp()
@@ -180,3 +188,19 @@
def test_list_resource_provider_aggregates_with_bytes_body(self):
self._test_list_resource_provider_aggregates(bytes_body=True)
+
+ def _test_list_resource_provider_usages(self, bytes_body=False):
+ self.check_service_client_function(
+ self.client.list_resource_provider_usages,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_RESOURCE_PROVIDER_USAGES,
+ to_utf=bytes_body,
+ status=200,
+ rp_uuid=self.FAKE_RESOURCE_PROVIDER_UUID
+ )
+
+ def test_show_resource_provider_usages_with_str_body(self):
+ self._test_list_resource_provider_inventories()
+
+ def test_show_resource_provider_usages_with_with_bytes_body(self):
+ self._test_list_resource_provider_inventories(bytes_body=True)
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 d4789a5..cd32174 100644
--- a/tox.ini
+++ b/tox.ini
@@ -11,7 +11,7 @@
VIRTUAL_ENV={envdir}
OS_TEST_PATH=./tempest/test_discover
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
[testenv]
@@ -28,7 +28,7 @@
install_command = pip install {opts} {packages}
allowlist_externals = *
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands =
@@ -263,7 +263,7 @@
[testenv:venv]
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt
-r{toxinidir}/doc/requirements.txt
commands = {posargs}
@@ -278,7 +278,7 @@
[testenv:docs]
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/doc/requirements.txt
commands =
sphinx-apidoc -f -o doc/source/tests/compute tempest/api/compute
@@ -363,7 +363,7 @@
[testenv:releasenotes]
deps =
- -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/wallaby}
+ -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/doc/requirements.txt
commands =
rm -rf releasenotes/build
@@ -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