Merge "Remove indentation for bullet list"
diff --git a/.zuul.yaml b/.zuul.yaml
index 0035f7c..02570a6 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -100,6 +100,7 @@
devstack_localrc:
ENABLE_FILE_INJECTION: true
ENABLE_VOLUME_MULTIATTACH: true
+ USE_PYTHON3: False
devstack_services:
# NOTE(mriedem): Disable the cinder-backup service from tempest-full
# since tempest-full is in the integrated-gate project template but
@@ -138,6 +139,9 @@
- opendev.org/openstack/oslo.utils
- opendev.org/openstack/oslo.versionedobjects
- opendev.org/openstack/oslo.vmware
+ vars:
+ devstack_localrc:
+ USE_PYTHON3: True
- job:
name: tempest-full-parallel
@@ -146,11 +150,13 @@
branches:
- master
description: |
- Base integration test with Neutron networking and py27.
+ Base integration test with Neutron networking.
It includes all scenarios as it was in the past.
This job runs all scenario tests in parallel!
vars:
tox_envlist: full-parallel
+ devstack_localrc:
+ USE_PYTHON3: True
- job:
name: tempest-full-py3
@@ -345,6 +351,13 @@
- stable/pike
- stable/queens
- stable/rocky
+ vars:
+ devstack_localrc:
+ USE_PYTHON3: False
+ group-vars:
+ subnode:
+ devstack_localrc:
+ USE_PYTHON3: False
- job:
name: tempest-multinode-full-py3
@@ -426,32 +439,16 @@
USE_PYTHON3: true
- job:
- name: tempest-full-train
- parent: tempest-full
- override-checkout: stable/train
-
-- job:
name: tempest-full-train-py3
parent: tempest-full-py3
override-checkout: stable/train
- job:
- name: tempest-full-stein
- parent: tempest-full
- override-checkout: stable/stein
-
-- job:
name: tempest-full-stein-py3
parent: tempest-full-py3
override-checkout: stable/stein
- job:
- name: tempest-full-rocky
- parent: tempest-full
- nodeset: openstack-single-node-xenial
- override-checkout: stable/rocky
-
-- job:
name: tempest-full-rocky-py3
parent: tempest-full-py3
nodeset: openstack-single-node-xenial
@@ -511,12 +508,13 @@
name: tempest-pg-full
parent: tempest-full
description: |
- Base integration test with Neutron networking and py27 and PostgreSQL.
+ Base integration test with Neutron networking and PostgreSQL.
Former name for this job was legacy-tempest-dsvm-neutron-pg-full.
vars:
devstack_localrc:
ENABLE_FILE_INJECTION: true
DATABASE_TYPE: postgresql
+ USE_PYTHON3: True
- project-template:
name: integrated-gate-networking
@@ -600,12 +598,9 @@
- project:
templates:
- check-requirements
- - integrated-gate
- integrated-gate-py3
- openstack-cover-jobs
- - openstack-python-jobs
- - openstack-python35-jobs
- - openstack-python3-train-jobs
+ - openstack-python3-ussuri-jobs
- publish-openstack-docs-pti
- release-notes-jobs-python3
check:
@@ -641,20 +636,12 @@
- tempest-full-py3-ipv6:
voting: false
irrelevant-files: *tempest-irrelevant-files
- - tempest-full-train:
- irrelevant-files: *tempest-irrelevant-files
- tempest-full-train-py3:
irrelevant-files: *tempest-irrelevant-files
- - tempest-full-stein:
- irrelevant-files: *tempest-irrelevant-files
- tempest-full-stein-py3:
irrelevant-files: *tempest-irrelevant-files
- - tempest-full-rocky:
- irrelevant-files: *tempest-irrelevant-files
- tempest-full-rocky-py3:
irrelevant-files: *tempest-irrelevant-files
- - tempest-multinode-full:
- irrelevant-files: *tempest-irrelevant-files
- tempest-multinode-full-py3:
irrelevant-files: *tempest-irrelevant-files
- tempest-tox-plugin-sanity-check:
@@ -673,8 +660,6 @@
# tools/ is not here since this relies on a script in tools/.
- tempest-ipv6-only:
irrelevant-files: *tempest-irrelevant-files-2
- - tempest-slow:
- irrelevant-files: *tempest-irrelevant-files
- tempest-slow-py3:
irrelevant-files: *tempest-irrelevant-files
- nova-live-migration:
@@ -701,8 +686,6 @@
irrelevant-files: *tempest-irrelevant-files
- neutron-tempest-dvr:
irrelevant-files: *tempest-irrelevant-files
- - tempest-full:
- irrelevant-files: *tempest-irrelevant-files
- interop-tempest-consistency:
irrelevant-files: *tempest-irrelevant-files
- tempest-full-test-account-py3:
@@ -719,7 +702,7 @@
irrelevant-files: *tempest-irrelevant-files
- neutron-grenade-multinode:
irrelevant-files: *tempest-irrelevant-files
- - tempest-full:
+ - tempest-full-py3:
irrelevant-files: *tempest-irrelevant-files
- grenade-py3:
irrelevant-files: *tempest-irrelevant-files
@@ -747,11 +730,8 @@
irrelevant-files: *tempest-irrelevant-files
periodic-stable:
jobs:
- - tempest-full-train
- tempest-full-train-py3
- - tempest-full-stein
- tempest-full-stein-py3
- - tempest-full-rocky
- tempest-full-rocky-py3
periodic:
jobs:
diff --git a/doc/requirements.txt b/doc/requirements.txt
index 2194dc4..9f38ada 100644
--- a/doc/requirements.txt
+++ b/doc/requirements.txt
@@ -3,6 +3,5 @@
# process, which may cause wedges in the gate later.
openstackdocstheme>=1.20.0 # Apache-2.0
reno>=2.5.0 # Apache-2.0
-sphinx!=1.6.6,!=1.6.7,>=1.6.2,<2.0.0;python_version=='2.7' # BSD
-sphinx!=1.6.6,!=1.6.7,!=2.1.0,>=1.6.2;python_version>='3.4' # BSD
+sphinx!=1.6.6,!=1.6.7,!=2.1.0,>=1.6.2 # BSD
sphinxcontrib-svg2pdfconverter>=0.1.0 # BSD
diff --git a/doc/source/supported_version.rst b/doc/source/supported_version.rst
index 60e7b97..4f65fd4 100644
--- a/doc/source/supported_version.rst
+++ b/doc/source/supported_version.rst
@@ -1,7 +1,7 @@
Supported OpenStack Releases and Python Versions
================================================
-This Document list the officially supported OpenStack releases
+This document lists the officially supported OpenStack releases
and python versions by Tempest.
Compatible OpenStack Releases
@@ -24,14 +24,13 @@
* https://releases.openstack.org/stein/index.html#stein-tempest
How to use Tempest tag on Extended Maintenance stable branch:
-* https://review.opendev.org/#/c/681950/
+
+* https://review.opendev.org/#/c/705098/
Supported Python Versions
-------------------------
Tempest master supports the below python versions:
-* Python 2.7
-* Python 3.5
* Python 3.6
* Python 3.7
diff --git a/releasenotes/notes/add-consistency-group-exceptions-01cbb792cd710231.yaml b/releasenotes/notes/add-consistency-group-exceptions-01cbb792cd710231.yaml
new file mode 100644
index 0000000..e879c2c
--- /dev/null
+++ b/releasenotes/notes/add-consistency-group-exceptions-01cbb792cd710231.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ Fixed bug #1858417. Adding consistency group exceptions
+ ``ConsistencyGroupException`` and ``ConsistencyGroupSnapshotException``
+ that didn't exist before and caused failure in cinder-tempest-plugin.
diff --git a/releasenotes/notes/change-default-region-for-placement-to-empty-string-394f1132c28345bb.yaml b/releasenotes/notes/change-default-region-for-placement-to-empty-string-394f1132c28345bb.yaml
new file mode 100644
index 0000000..a28e4e2
--- /dev/null
+++ b/releasenotes/notes/change-default-region-for-placement-to-empty-string-394f1132c28345bb.yaml
@@ -0,0 +1,13 @@
+---
+upgrade:
+ - |
+ Default value of config option ``CONF.placement.region`` is updated
+ from ``RegionOne`` to empty string.
+
+ As per tempest design, if tempest conf is not having any region for
+ a service then identity region should be used. In case of placement
+ the default value is "RegionOne" which is considered as placement
+ region if region missing in tempest conf. In order to have identity
+ region to be used as default we need to change to empty string for
+ placement service. Empty string can be seen being used in other
+ services like volume, image etc.
diff --git a/releasenotes/notes/deprecate-compute-feature-enabled-block-migrate-cinder-iscsi-fcda802d774dfeec.yaml b/releasenotes/notes/deprecate-compute-feature-enabled-block-migrate-cinder-iscsi-fcda802d774dfeec.yaml
new file mode 100644
index 0000000..6bbb381
--- /dev/null
+++ b/releasenotes/notes/deprecate-compute-feature-enabled-block-migrate-cinder-iscsi-fcda802d774dfeec.yaml
@@ -0,0 +1,8 @@
+---
+deprecations:
+ - |
+ The ``[compute-feature-enabled]/block_migrate_cinder_iscsi`` is deprecated
+ ahead of removal in a future release. Once removed the
+ ``[compute-feature-enabled]/block_migration_for_live_migration``
+ configurable will then be used to determine when to run block migration
+ based tests during live migration.
diff --git a/releasenotes/notes/drop-py-2-7-730baf411876d5d8.yaml b/releasenotes/notes/drop-py-2-7-730baf411876d5d8.yaml
new file mode 100644
index 0000000..a0ac244
--- /dev/null
+++ b/releasenotes/notes/drop-py-2-7-730baf411876d5d8.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+ - |
+ Python 2.7 support has been dropped. Last release of Tempest
+ to support python 2.7 is Temepst 23.0.0. The minimum version of Python now
+ supported by Tempest is Python 3.6.
diff --git a/releasenotes/notes/drop-py-3-5-support-76ca78f1a650fcad.yaml b/releasenotes/notes/drop-py-3-5-support-76ca78f1a650fcad.yaml
new file mode 100644
index 0000000..99ef31e
--- /dev/null
+++ b/releasenotes/notes/drop-py-3-5-support-76ca78f1a650fcad.yaml
@@ -0,0 +1,8 @@
+---
+prelude: >
+ Remove the support of python3.5.
+ Tempest, its plugins dependencies in ussuri cycle
+ are python-requires>=py3.6 which makes distro not
+ having python 3.6 to do hack to install py3.6 etc.
+ It time to drop the py3.5 from Tempest. Last supported
+ version of Tempest for py3.5 is 23.0.0.
diff --git a/releasenotes/notes/os_tenant_name-3ee175763bff455b.yaml b/releasenotes/notes/os_tenant_name-3ee175763bff455b.yaml
new file mode 100644
index 0000000..936bf1f
--- /dev/null
+++ b/releasenotes/notes/os_tenant_name-3ee175763bff455b.yaml
@@ -0,0 +1,5 @@
+---
+upgrade:
+ - |
+ Remove the deprecated argument ``os-tenant-name`` or ``OS_TENANT_NAME`` in favour of
+ ``os-project-name`` argument.
diff --git a/releasenotes/notes/verify-tempest-command-8e88452c7a08dd77.yaml b/releasenotes/notes/verify-tempest-command-8e88452c7a08dd77.yaml
new file mode 100644
index 0000000..ce401ff
--- /dev/null
+++ b/releasenotes/notes/verify-tempest-command-8e88452c7a08dd77.yaml
@@ -0,0 +1,7 @@
+---
+upgrade:
+ - |
+ Remove the deprecated CLI ``verify-tempest-config`` in favour of
+ ``tempest verify-config`` command.
+ You can use ``tempest verify-config`` CLI to verify the tempest
+ conf file.
diff --git a/roles/run-tempest/README.rst b/roles/run-tempest/README.rst
index d4b253a..1f7fb70 100644
--- a/roles/run-tempest/README.rst
+++ b/roles/run-tempest/README.rst
@@ -72,3 +72,16 @@
:default: ''
The timeout (in seconds) for each test.
+
+.. zuul:rolevar:: stable_constraints_file
+ :default: ''
+
+ Upper constraints file to be used for stable branch till stable/rocky.
+
+.. zuul:rolevar:: tempest_tox_environment
+ :default: ''
+
+ Environment variable to set for run-tempst task.
+
+ Env variables set in this variable will be combined with some more
+ defaults env variable set at runtime.
diff --git a/roles/run-tempest/defaults/main.yaml b/roles/run-tempest/defaults/main.yaml
index 79df3e1..5867b6c 100644
--- a/roles/run-tempest/defaults/main.yaml
+++ b/roles/run-tempest/defaults/main.yaml
@@ -4,3 +4,6 @@
tempest_black_regex: ''
tox_extra_args: ''
tempest_test_timeout: ''
+stable_constraints_file: "{{ devstack_base_dir }}/requirements/upper-constraints.txt"
+target_branch: "{{ zuul.branch }}"
+tempest_tox_environment: {}
diff --git a/roles/run-tempest/tasks/main.yaml b/roles/run-tempest/tasks/main.yaml
index 24bd4db..8686f9a 100644
--- a/roles/run-tempest/tasks/main.yaml
+++ b/roles/run-tempest/tasks/main.yaml
@@ -20,6 +20,21 @@
default_concurrency: "{{ num_cores|int // 2 }}"
when: num_cores|int > 3
+- name: Override target branch
+ set_fact:
+ target_branch: "{{ zuul.override_checkout }}"
+ when: zuul.override_checkout is defined
+
+- name: Use stable branch upper-constraints till stable/rocky
+ set_fact:
+ tempest_tox_environment: "{{ tempest_tox_environment | combine({'UPPER_CONSTRAINTS_FILE': stable_constraints_file}) }}"
+ when: target_branch in ["stable/ocata", "stable/pike", "stable/queens", "stable/rocky"]
+
+- name: Set OS_TEST_TIMEOUT if requested
+ set_fact:
+ tempest_tox_environment: "{{ tempest_tox_environment | combine({'OS_TEST_TIMEOUT': tempest_test_timeout}) }}"
+ when: tempest_test_timeout != ''
+
- when:
- tempest_test_blacklist is defined
block:
@@ -42,4 +57,4 @@
chdir: "{{devstack_base_dir}}/tempest"
become: true
become_user: tempest
- environment: '{{ {"OS_TEST_TIMEOUT": tempest_test_timeout} if tempest_test_timeout else {} }}'
+ environment: "{{ tempest_tox_environment }}"
diff --git a/setup.cfg b/setup.cfg
index 1e9b8e9..d246c68 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -6,6 +6,7 @@
author = OpenStack
author-email = openstack-discuss@lists.openstack.org
home-page = https://docs.openstack.org/tempest/latest/
+requires-python = >=3.6
classifier =
Intended Audience :: Information Technology
Intended Audience :: System Administrators
@@ -13,12 +14,11 @@
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
- Programming Language :: Python :: 2
- Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
- Programming Language :: Python :: 3.5
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
+ Programming Language :: Python :: 3 :: Only
+ Programming Language :: Python :: Implementation :: CPython
[files]
packages =
@@ -28,7 +28,6 @@
[entry_points]
console_scripts =
- verify-tempest-config = tempest.cmd.verify_tempest_config:main
tempest-account-generator = tempest.cmd.account_generator:main
tempest = tempest.cmd.main:main
skip-tracker = tempest.lib.cmd.skip_tracker:main
diff --git a/setup.py b/setup.py
index 566d844..f63cc23 100644
--- a/setup.py
+++ b/setup.py
@@ -16,14 +16,6 @@
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
-# In python < 2.7.4, a lazy loading of package `pbr` will break
-# setuptools if some other modules registered functions in `atexit`.
-# solution from: http://bugs.python.org/issue15881#msg170215
-try:
- import multiprocessing # noqa
-except ImportError:
- pass
-
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
pbr=True)
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index 7c2d9d2..d7ee39c 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -52,12 +52,15 @@
super(BaseV2ComputeTest, cls).skip_checks()
if not CONF.service_available.nova:
raise cls.skipException("Nova is not available")
- cfg_min_version = CONF.compute.min_microversion
- cfg_max_version = CONF.compute.max_microversion
- api_version_utils.check_skip_with_microversion(cls.min_microversion,
- cls.max_microversion,
- cfg_min_version,
- cfg_max_version)
+ api_version_utils.check_skip_with_microversion(
+ cls.min_microversion, cls.max_microversion,
+ CONF.compute.min_microversion, CONF.compute.max_microversion)
+ api_version_utils.check_skip_with_microversion(
+ cls.volume_min_microversion, cls.volume_max_microversion,
+ CONF.volume.min_microversion, CONF.volume.max_microversion)
+ api_version_utils.check_skip_with_microversion(
+ cls.placement_min_microversion, cls.placement_max_microversion,
+ CONF.placement.min_microversion, CONF.placement.max_microversion)
@classmethod
def setup_credentials(cls):
@@ -151,6 +154,14 @@
api_version_utils.select_request_microversion(
cls.min_microversion,
CONF.compute.min_microversion))
+ cls.volume_request_microversion = (
+ api_version_utils.select_request_microversion(
+ cls.volume_min_microversion,
+ CONF.volume.min_microversion))
+ cls.placement_request_microversion = (
+ api_version_utils.select_request_microversion(
+ cls.placement_min_microversion,
+ CONF.placement.min_microversion))
cls.build_interval = CONF.compute.build_interval
cls.build_timeout = CONF.compute.build_timeout
cls.image_ref = CONF.compute.image_ref
@@ -476,7 +487,9 @@
def setUp(self):
super(BaseV2ComputeTest, self).setUp()
self.useFixture(api_microversion_fixture.APIMicroversionFixture(
- compute_microversion=self.request_microversion))
+ compute_microversion=self.request_microversion,
+ volume_microversion=self.volume_request_microversion,
+ placement_microversion=self.placement_request_microversion))
@classmethod
def create_volume(cls, image_ref=None, **kwargs):
@@ -542,11 +555,17 @@
attachment = self.servers_client.attach_volume(
server['id'], **attach_kwargs)['volumeAttachment']
- # On teardown detach the volume and wait for it to be available. This
- # is so we don't error out when trying to delete the volume during
- # teardown.
- self.addCleanup(waiters.wait_for_volume_resource_status,
- self.volumes_client, volume['id'], 'available')
+ # On teardown detach the volume and for multiattach volumes wait for
+ # the attachment to be removed. For non-multiattach volumes wait for
+ # the state of the volume to change to available. This is so we don't
+ # error out when trying to delete the volume during teardown.
+ if volume['multiattach']:
+ self.addCleanup(waiters.wait_for_volume_attachment_remove,
+ self.volumes_client, volume['id'],
+ attachment['id'])
+ else:
+ self.addCleanup(waiters.wait_for_volume_resource_status,
+ self.volumes_client, volume['id'], 'available')
# Ignore 404s on detach in case the server is deleted or the volume
# is already detached.
self.addCleanup(self._detach_volume, server, volume)
diff --git a/tempest/api/compute/servers/test_device_tagging.py b/tempest/api/compute/servers/test_device_tagging.py
index 8aab574..1f7eb7b 100644
--- a/tempest/api/compute/servers/test_device_tagging.py
+++ b/tempest/api/compute/servers/test_device_tagging.py
@@ -358,7 +358,8 @@
validation_resources=validation_resources,
config_drive=config_drive_enabled,
name=data_utils.rand_name('device-tagging-server'),
- networks=[{'uuid': self.get_tenant_network()['id']}])
+ networks=[{'uuid': self.get_tenant_network()['id']}],
+ wait_until='ACTIVE')
self.addCleanup(self.delete_server, server['id'])
# NOTE(mgoddard): Get detailed server to ensure addresses are present
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index ff50836..d477be0 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -343,20 +343,27 @@
def test_resize_volume_backed_server_confirm(self):
# We have to create a new server that is volume-backed since the one
# from setUp is not volume-backed.
- server = self.create_test_server(
- volume_backed=True, wait_until='ACTIVE')
+ kwargs = {'volume_backed': True,
+ 'wait_until': 'ACTIVE'}
+ if CONF.validation.run_validation:
+ validation_resources = self.get_test_validation_resources(
+ self.os_primary)
+ kwargs.update({'validatable': True,
+ 'validation_resources': validation_resources})
+ server = self.create_test_server(**kwargs)
+
# NOTE(mgoddard): Get detailed server to ensure addresses are present
# in fixed IP case.
server = self.servers_client.show_server(server['id'])['server']
+
self._test_resize_server_confirm(server['id'])
+
if CONF.compute_feature_enabled.console_output:
# Now do something interactive with the guest like get its console
# output; we don't actually care about the output,
# just that it doesn't raise an error.
self.client.get_console_output(server['id'])
if CONF.validation.run_validation:
- validation_resources = self.get_class_validation_resources(
- self.os_primary)
linux_client = remote_client.RemoteClient(
self.get_server_ip(server, validation_resources),
self.ssh_user,
diff --git a/tempest/api/compute/servers/test_servers_negative.py b/tempest/api/compute/servers/test_servers_negative.py
index f42bb9c..7fa30b0 100644
--- a/tempest/api/compute/servers/test_servers_negative.py
+++ b/tempest/api/compute/servers/test_servers_negative.py
@@ -555,6 +555,7 @@
class ServersNegativeTestMultiTenantJSON(base.BaseV2ComputeTest):
+ create_default_network = True
credentials = ['primary', 'alt']
diff --git a/tempest/api/compute/volumes/test_attach_volume.py b/tempest/api/compute/volumes/test_attach_volume.py
index bee2b7b..97813a5 100644
--- a/tempest/api/compute/volumes/test_attach_volume.py
+++ b/tempest/api/compute/volumes/test_attach_volume.py
@@ -80,7 +80,7 @@
# NOTE(andreaf) We need to ensure the ssh key has been
# injected in the guest before we power cycle
linux_client.validate_authentication()
- disks_before_attach = linux_client.count_disks()
+ disks_before_attach = linux_client.list_disks()
volume = self.create_volume()
@@ -102,8 +102,10 @@
'ACTIVE')
if CONF.validation.run_validation:
- disks_after_attach = linux_client.count_disks()
- self.assertGreater(disks_after_attach, disks_before_attach)
+ disks_after_attach = linux_client.list_disks()
+ self.assertGreater(
+ len(disks_after_attach),
+ len(disks_before_attach))
self.servers_client.detach_volume(server['id'], attachment['volumeId'])
waiters.wait_for_volume_resource_status(
@@ -118,8 +120,8 @@
'ACTIVE')
if CONF.validation.run_validation:
- disks_after_detach = linux_client.count_disks()
- self.assertEqual(disks_before_attach, disks_after_detach)
+ disks_after_detach = linux_client.list_disks()
+ self.assertEqual(len(disks_before_attach), len(disks_after_detach))
@decorators.idempotent_id('7fa563fe-f0f7-43eb-9e22-a1ece036b513')
def test_list_get_volume_attachments(self):
diff --git a/tempest/api/object_storage/test_crossdomain.py b/tempest/api/object_storage/test_crossdomain.py
index f61d9f8..1567e06 100644
--- a/tempest/api/object_storage/test_crossdomain.py
+++ b/tempest/api/object_storage/test_crossdomain.py
@@ -34,13 +34,12 @@
def setUp(self):
super(CrossdomainTest, self).setUp()
- # Turning http://.../v1/foobar into http://.../
- self.account_client.skip_path()
-
@decorators.idempotent_id('d1b8b031-b622-4010-82f9-ff78a9e915c7')
@utils.requires_ext(extension='crossdomain', service='object')
def test_get_crossdomain_policy(self):
- resp, body = self.account_client.get("crossdomain.xml", {})
+ url = self.account_client._get_base_version_url() + "crossdomain.xml"
+ resp, body = self.account_client.raw_request(url, "GET")
+ self.account_client._error_checker(resp, body)
body = body.decode()
self.assertTrue(body.startswith(self.xml_start) and
diff --git a/tempest/api/object_storage/test_healthcheck.py b/tempest/api/object_storage/test_healthcheck.py
index a186f9e..8e9e406 100644
--- a/tempest/api/object_storage/test_healthcheck.py
+++ b/tempest/api/object_storage/test_healthcheck.py
@@ -22,13 +22,12 @@
def setUp(self):
super(HealthcheckTest, self).setUp()
- # Turning http://.../v1/foobar into http://.../
- self.account_client.skip_path()
@decorators.idempotent_id('db5723b1-f25c-49a9-bfeb-7b5640caf337')
def test_get_healthcheck(self):
-
- resp, _ = self.account_client.get("healthcheck", {})
+ url = self.account_client._get_base_version_url() + "healthcheck"
+ resp, body = self.account_client.raw_request(url, "GET")
+ self.account_client._error_checker(resp, body)
# The target of the request is not any Swift resource. Therefore, the
# existence of response header is checked without a custom matcher.
diff --git a/tempest/cmd/account_generator.py b/tempest/cmd/account_generator.py
index 7ea0099..1535786 100755
--- a/tempest/cmd/account_generator.py
+++ b/tempest/cmd/account_generator.py
@@ -46,7 +46,6 @@
Username ``--os-username`` OS_USERNAME
Password ``--os-password`` OS_PASSWORD
Project ``--os-project-name`` OS_PROJECT_NAME
-Tenant ``--os-tenant-name`` (depr.) OS_TENANT_NAME
Domain ``--os-domain-name`` OS_DOMAIN_NAME
======== ============================ ====================
@@ -75,9 +74,6 @@
* ``--os-project-name <auth-project-name>`` (Optional) Project to request
authorization on. Defaults to env[OS_PROJECT_NAME].
-* ``--os-tenant-name <auth-tenant-name>`` (Optional, deprecated) Tenant to
- request authorization on. Defaults to env[OS_TENANT_NAME].
-
* ``--os-domain-name <auth-domain-name>`` (Optional) Domain the user and
project belong to. Defaults to env[OS_DOMAIN_NAME].
@@ -139,7 +135,7 @@
'dhcp': True}
admin_creds_dict = {'username': opts.os_username,
'password': opts.os_password}
- _project_name = opts.os_project_name or opts.os_tenant_name
+ _project_name = opts.os_project_name
if opts.identity_version == 3:
admin_creds_dict['project_name'] = _project_name
admin_creds_dict['domain_name'] = opts.os_domain_name or 'Default'
@@ -221,10 +217,6 @@
metavar='<auth-project-name>',
default=os.environ.get('OS_PROJECT_NAME'),
help='Defaults to env[OS_PROJECT_NAME].')
- parser.add_argument('--os-tenant-name',
- metavar='<auth-tenant-name>',
- default=os.environ.get('OS_TENANT_NAME'),
- help='Defaults to env[OS_TENANT_NAME].')
parser.add_argument('--os-domain-name',
metavar='<auth-domain-name>',
default=os.environ.get('OS_DOMAIN_NAME'),
@@ -301,10 +293,6 @@
if log_warning:
LOG.warning("Use of: 'tempest-account-generator' is deprecated, "
"please use: 'tempest account-generator'")
- if opts.os_tenant_name:
- LOG.warning("'os-tenant-name' and 'OS_TENANT_NAME' are both "
- "deprecated, please use 'os-project-name' or "
- "'OS_PROJECT_NAME' instead")
resources = []
for count in range(opts.concurrency):
# Use N different cred_providers to obtain different sets of creds
diff --git a/tempest/cmd/verify_tempest_config.py b/tempest/cmd/verify_tempest_config.py
index d25d3ca..8d5bdbd 100644
--- a/tempest/cmd/verify_tempest_config.py
+++ b/tempest/cmd/verify_tempest_config.py
@@ -433,11 +433,6 @@
def main(opts=None):
- print('Running config verification...')
- if opts is None:
- print("Use of: 'verify-tempest-config' is deprecated, "
- "please use: 'tempest verify-config'")
- opts = parse_args()
update = opts.update
replace = opts.replace_ext
global CONF_PARSER
@@ -497,7 +492,3 @@
LOG.exception("Failure verifying configuration.")
traceback.print_exc()
raise
-
-
-if __name__ == "__main__":
- main()
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 5875da3..b68a879 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -73,12 +73,12 @@
msg = "'TYPE' column is required but the output doesn't have it: "
raise tempest.lib.exceptions.TempestException(msg + output)
- def count_disks(self):
+ def list_disks(self):
disks_list = self.get_disks()
disks_list = [line[0] for line in
[device_name.split()
for device_name in disks_list.splitlines()][1:]]
- return len(disks_list)
+ return disks_list
def get_boot_time(self):
cmd = 'cut -f1 -d. /proc/uptime'
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index 11f3bf9..b547cc6 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -217,6 +217,22 @@
resource_name, resource_id, status, time.time() - start)
+def wait_for_volume_attachment_remove(client, volume_id, attachment_id):
+ """Waits for a volume attachment to be removed from a given volume."""
+ start = int(time.time())
+ attachments = client.show_volume(volume_id)['volume']['attachments']
+ while any(attachment_id == a['attachment_id'] for a in attachments):
+ time.sleep(client.build_interval)
+ if int(time.time()) - start >= client.build_timeout:
+ message = ('Failed to remove attachment %s from volume %s'
+ 'within the required time (%s s).' %
+ (attachment_id, volume_id, client.build_timeout))
+ raise lib_exc.TimeoutException(message)
+ attachments = client.show_volume(volume_id)['volume']['attachments']
+ LOG.info('Attachment %s removed from volume %s after waiting for %f '
+ 'seconds', attachment_id, volume_id, time.time() - start)
+
+
def wait_for_volume_migration(client, volume_id, new_host):
"""Waits for a Volume to move to a new host."""
body = client.show_volume(volume_id)['volume']
diff --git a/tempest/config.py b/tempest/config.py
index 32cebc5..0f888d6 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -390,7 +390,7 @@
default='placement',
help="Catalog type of the Placement service."),
cfg.StrOpt('region',
- default='RegionOne',
+ default='',
help="The placement region name to use. If empty, the value "
"of [identity]/region is used instead. If no such region "
"is found in the service catalog, the first region found "
@@ -475,7 +475,14 @@
default=False,
help="Does the test environment support block migration with "
"Cinder iSCSI volumes. Note: libvirt >= 1.2.17 is required "
- "to support this if using the libvirt compute driver."),
+ "to support this if using the libvirt compute driver.",
+ deprecated_for_removal=True,
+ deprecated_reason='This option duplicates the more generic '
+ '[compute-feature-enabled]/block_migration '
+ '_for_live_migration now that '
+ 'MIN_LIBVIRT_VERSION is >= 1.2.17 on all '
+ 'branches from stable/rocky and will be '
+ 'removed in a future release.'),
cfg.BoolOpt('vnc_console',
default=False,
help='Enable VNC console. This configuration value should '
diff --git a/tempest/lib/common/api_version_utils.py b/tempest/lib/common/api_version_utils.py
index d29362d..80dbc1d 100644
--- a/tempest/lib/common/api_version_utils.py
+++ b/tempest/lib/common/api_version_utils.py
@@ -32,6 +32,10 @@
# (min_microversion, max_microversion) on each test class if necessary.
min_microversion = None
max_microversion = LATEST_MICROVERSION
+ volume_min_microversion = None
+ volume_max_microversion = LATEST_MICROVERSION
+ placement_min_microversion = None
+ placement_max_microversion = LATEST_MICROVERSION
def check_skip_with_microversion(test_min_version, test_max_version,
diff --git a/tempest/lib/exceptions.py b/tempest/lib/exceptions.py
index 13af890..b25b4b2 100644
--- a/tempest/lib/exceptions.py
+++ b/tempest/lib/exceptions.py
@@ -280,3 +280,12 @@
class InvalidParam(TempestException):
message = ("Invalid Parameter passed: %(invalid_param)s")
+
+
+class ConsistencyGroupException(TempestException):
+ message = "Consistency group %(cg_id)s failed and is in ERROR status"
+
+
+class ConsistencyGroupSnapshotException(TempestException):
+ message = ("Consistency group snapshot %(cgsnapshot_id)s failed and is "
+ "in ERROR status")
diff --git a/tempest/lib/services/object_storage/capabilities_client.py b/tempest/lib/services/object_storage/capabilities_client.py
index d31bbc2..f08bd9a 100644
--- a/tempest/lib/services/object_storage/capabilities_client.py
+++ b/tempest/lib/services/object_storage/capabilities_client.py
@@ -21,9 +21,10 @@
class CapabilitiesClient(rest_client.RestClient):
def list_capabilities(self):
- self.skip_path()
try:
- resp, body = self.get('info')
+ url = self._get_base_version_url() + 'info'
+ resp, body = self.raw_request(url, 'GET')
+ self._error_checker(resp, body)
finally:
self.reset_path()
body = json.loads(body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 1252f09..cb7acbf 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -634,8 +634,7 @@
def nova_volume_attach(self, server, volume_to_attach):
volume = self.servers_client.attach_volume(
- server['id'], volumeId=volume_to_attach['id'], device='/dev/%s'
- % CONF.compute.volume_device_name)['volumeAttachment']
+ server['id'], volumeId=volume_to_attach['id'])['volumeAttachment']
self.assertEqual(volume_to_attach['id'], volume['id'])
waiters.wait_for_volume_resource_status(self.volumes_client,
volume['id'], 'in-use')
@@ -811,6 +810,42 @@
server_details = cls.os_admin.servers_client.show_server(server_id)
return server_details['server']['OS-EXT-SRV-ATTR:host']
+ def _get_bdm(self, source_id, source_type, delete_on_termination=False):
+ bd_map_v2 = [{
+ 'uuid': source_id,
+ 'source_type': source_type,
+ 'destination_type': 'volume',
+ 'boot_index': 0,
+ 'delete_on_termination': delete_on_termination}]
+ return {'block_device_mapping_v2': bd_map_v2}
+
+ def boot_instance_from_resource(self, source_id,
+ source_type,
+ keypair=None,
+ security_group=None,
+ delete_on_termination=False,
+ name=None):
+ create_kwargs = dict()
+ if keypair:
+ create_kwargs['key_name'] = keypair['name']
+ if security_group:
+ create_kwargs['security_groups'] = [
+ {'name': security_group['name']}]
+ create_kwargs.update(self._get_bdm(
+ source_id,
+ source_type,
+ delete_on_termination=delete_on_termination))
+ if name:
+ create_kwargs['name'] = name
+
+ return self.create_server(image_id='', **create_kwargs)
+
+ def create_volume_from_image(self):
+ img_uuid = CONF.compute.image_ref
+ vol_name = data_utils.rand_name(
+ self.__class__.__name__ + '-volume-origin')
+ return self.create_volume(name=vol_name, imageRef=img_uuid)
+
class NetworkScenarioTest(ScenarioTest):
"""Base class for network scenario tests.
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index cee543b..4cd860d 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -61,7 +61,11 @@
def cinder_show(self, volume):
got_volume = self.volumes_client.show_volume(volume['id'])['volume']
- self.assertEqual(volume, got_volume)
+ # Exclude updated_at because of bug 1838202.
+ excluded_keys = ['updated_at']
+ self.assertThat(
+ volume, custom_matchers.MatchesDictExceptForKeys(
+ got_volume, excluded_keys=excluded_keys))
def nova_reboot(self, server):
self.servers_client.reboot_server(server['id'], type='SOFT')
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index af79ea0..c3b3670 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -55,20 +55,24 @@
if not CONF.volume_feature_enabled.snapshot:
raise cls.skipException("Cinder volume snapshots are disabled")
- def _wait_for_volume_available_on_the_system(self, ip_address,
- private_key):
+ def _attached_volume_name(
+ self, disks_list_before_attach, ip_address, private_key):
ssh = self.get_remote_client(ip_address, private_key=private_key)
- def _func():
- disks = ssh.get_disks()
- LOG.debug("Disks: %s", disks)
- return CONF.compute.volume_device_name in disks
+ def _wait_for_volume_available_on_system():
+ disks_list_after_attach = ssh.list_disks()
+ return len(disks_list_after_attach) > len(disks_list_before_attach)
- if not test_utils.call_until_true(_func,
+ if not test_utils.call_until_true(_wait_for_volume_available_on_system,
CONF.compute.build_timeout,
CONF.compute.build_interval):
raise lib_exc.TimeoutException
+ disks_list_after_attach = ssh.list_disks()
+ volume_name = [item for item in disks_list_after_attach
+ if item not in disks_list_before_attach][0]
+ return volume_name
+
@decorators.attr(type='slow')
@decorators.idempotent_id('10fd234a-515c-41e5-b092-8323060598c5')
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
@@ -91,15 +95,16 @@
ip_for_server = self.get_server_ip(server)
# Make sure the machine ssh-able before attaching the volume
- self.get_remote_client(ip_for_server,
- private_key=keypair['private_key'],
- server=server)
-
+ linux_client = self.get_remote_client(
+ ip_for_server, private_key=keypair['private_key'],
+ server=server)
+ disks_list_before_attach = linux_client.list_disks()
self.nova_volume_attach(server, volume)
- self._wait_for_volume_available_on_the_system(ip_for_server,
- keypair['private_key'])
+ volume_device_name = self._attached_volume_name(
+ disks_list_before_attach, ip_for_server, keypair['private_key'])
+
timestamp = self.create_timestamp(ip_for_server,
- CONF.compute.volume_device_name,
+ volume_device_name,
private_key=keypair['private_key'],
server=server)
self.nova_volume_detach(server, volume)
@@ -126,18 +131,19 @@
# Make sure the machine ssh-able before attaching the volume
# Just a live machine is responding
# for device attache/detach as expected
- self.get_remote_client(ip_for_snapshot,
- private_key=keypair['private_key'],
- server=server_from_snapshot)
+ linux_client = self.get_remote_client(
+ ip_for_snapshot, private_key=keypair['private_key'],
+ server=server_from_snapshot)
+ disks_list_before_attach = linux_client.list_disks()
# attach volume2 to instance2
self.nova_volume_attach(server_from_snapshot, volume_from_snapshot)
- self._wait_for_volume_available_on_the_system(ip_for_snapshot,
- keypair['private_key'])
+ volume_device_name = self._attached_volume_name(
+ disks_list_before_attach, ip_for_snapshot, keypair['private_key'])
# check the existence of the timestamp file in the volume2
timestamp2 = self.get_timestamp(ip_for_snapshot,
- CONF.compute.volume_device_name,
+ volume_device_name,
private_key=keypair['private_key'],
server=server_from_snapshot)
self.assertEqual(timestamp, timestamp2)
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 6ed7e30..ec44b13 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -31,42 +31,6 @@
# breathing room to get through deletes in the time allotted.
TIMEOUT_SCALING_FACTOR = 2
- def _create_volume_from_image(self):
- img_uuid = CONF.compute.image_ref
- vol_name = data_utils.rand_name(
- self.__class__.__name__ + '-volume-origin')
- return self.create_volume(name=vol_name, imageRef=img_uuid)
-
- def _get_bdm(self, source_id, source_type, delete_on_termination=False):
- bd_map_v2 = [{
- 'uuid': source_id,
- 'source_type': source_type,
- 'destination_type': 'volume',
- 'boot_index': 0,
- 'delete_on_termination': delete_on_termination}]
- return {'block_device_mapping_v2': bd_map_v2}
-
- def _boot_instance_from_resource(self, source_id,
- source_type,
- keypair=None,
- security_group=None,
- delete_on_termination=False,
- name=None):
- create_kwargs = dict()
- if keypair:
- create_kwargs['key_name'] = keypair['name']
- if security_group:
- create_kwargs['security_groups'] = [
- {'name': security_group['name']}]
- create_kwargs.update(self._get_bdm(
- source_id,
- source_type,
- delete_on_termination=delete_on_termination))
- if name:
- create_kwargs['name'] = name
-
- return self.create_server(image_id='', **create_kwargs)
-
def _delete_server(self, server):
self.servers_client.delete_server(server['id'])
waiters.wait_for_server_termination(self.servers_client, server['id'])
@@ -104,8 +68,8 @@
# create an instance from volume
LOG.info("Booting instance 1 from volume")
- volume_origin = self._create_volume_from_image()
- instance_1st = self._boot_instance_from_resource(
+ volume_origin = self.create_volume_from_image()
+ instance_1st = self.boot_instance_from_resource(
source_id=volume_origin['id'],
source_type='volume',
keypair=keypair,
@@ -124,7 +88,7 @@
self._delete_server(instance_1st)
# create a 2nd instance from volume
- instance_2nd = self._boot_instance_from_resource(
+ instance_2nd = self.boot_instance_from_resource(
source_id=volume_origin['id'],
source_type='volume',
keypair=keypair,
@@ -149,10 +113,10 @@
size=snapshot['size'])
LOG.info("Booting third instance from snapshot")
server_from_snapshot = (
- self._boot_instance_from_resource(source_id=volume['id'],
- source_type='volume',
- keypair=keypair,
- security_group=security_group))
+ self.boot_instance_from_resource(source_id=volume['id'],
+ source_type='volume',
+ keypair=keypair,
+ security_group=security_group))
LOG.info("Booted third instance %s", server_from_snapshot)
# check the content of written file
@@ -171,13 +135,13 @@
@utils.services('compute', 'image', 'volume')
def test_create_server_from_volume_snapshot(self):
# Create a volume from an image
- boot_volume = self._create_volume_from_image()
+ boot_volume = self.create_volume_from_image()
# Create a snapshot
boot_snapshot = self.create_volume_snapshot(boot_volume['id'])
# Create a server from a volume snapshot
- server = self._boot_instance_from_resource(
+ server = self.boot_instance_from_resource(
source_id=boot_snapshot['id'],
source_type='snapshot',
delete_on_termination=True)
@@ -209,10 +173,10 @@
@utils.services('compute', 'volume', 'image')
def test_image_defined_boot_from_volume(self):
# create an instance from image-backed volume
- volume_origin = self._create_volume_from_image()
+ volume_origin = self.create_volume_from_image()
name = data_utils.rand_name(self.__class__.__name__ +
'-volume-backed-server')
- instance1 = self._boot_instance_from_resource(
+ instance1 = self.boot_instance_from_resource(
source_id=volume_origin['id'],
source_type='volume',
delete_on_termination=True,
@@ -288,7 +252,7 @@
self.volumes_client.set_bootable_volume(volume['id'], bootable=True)
# Boot a server from the encrypted volume
- server = self._boot_instance_from_resource(
+ server = self.boot_instance_from_resource(
source_id=volume['id'],
source_type='volume',
delete_on_termination=False)
diff --git a/tempest/tests/cmd/test_account_generator.py b/tempest/tests/cmd/test_account_generator.py
index b349bba..a962e37 100644
--- a/tempest/tests/cmd/test_account_generator.py
+++ b/tempest/tests/cmd/test_account_generator.py
@@ -28,7 +28,6 @@
self.os_username = 'fake_user'
self.os_password = 'fake_password'
self.os_project_name = 'fake_project_name'
- self.os_tenant_name = None
self.os_domain_name = 'fake_domain'
self.tag = 'fake'
self.concurrency = 2
@@ -100,15 +99,6 @@
self.assertEqual(self.opts.os_password, admin_creds.password)
self.assertFalse(hasattr(admin_creds, 'domain_name'))
- def test_get_credential_provider_with_tenant(self):
- self.opts.os_project_name = None
- self.opts.os_tenant_name = 'fake_tenant'
- cp = account_generator.get_credential_provider(self.opts)
- admin_creds = cp.default_admin_creds
- self.assertEqual(self.opts.os_tenant_name, admin_creds.tenant_name)
- self.assertEqual(self.opts.os_username, admin_creds.username)
- self.assertEqual(self.opts.os_password, admin_creds.password)
-
class TestAccountGeneratorV3(TestAccountGeneratorV2):
diff --git a/tempest/tests/common/test_waiters.py b/tempest/tests/common/test_waiters.py
index 6275f22..e3bb836 100755
--- a/tempest/tests/common/test_waiters.py
+++ b/tempest/tests/common/test_waiters.py
@@ -15,6 +15,7 @@
import time
import mock
+from oslo_utils.fixture import uuidsentinel as uuids
from tempest.common import waiters
from tempest import exceptions
@@ -232,3 +233,51 @@
mock_show.assert_has_calls([mock.call(volume_id),
mock.call(volume_id)])
mock_sleep.assert_called_once_with(1)
+
+ def test_wait_for_volume_attachment(self):
+ vol_detached = {'volume': {'attachments': []}}
+ vol_attached = {'volume': {'attachments': [
+ {'attachment_id': uuids.attachment_id}]}}
+ show_volume = mock.MagicMock(side_effect=[
+ vol_attached, vol_attached, vol_detached])
+ client = mock.Mock(spec=volumes_client.VolumesClient,
+ build_interval=1,
+ build_timeout=5,
+ show_volume=show_volume)
+ self.patch('time.time')
+ self.patch('time.sleep')
+ waiters.wait_for_volume_attachment_remove(client, uuids.volume_id,
+ uuids.attachment_id)
+ # Assert that show volume is called until the attachment is removed.
+ show_volume.assert_has_calls = [mock.call(uuids.volume_id),
+ mock.call(uuids.volume_id),
+ mock.call(uuids.volume_id)]
+
+ def test_wait_for_volume_attachment_timeout(self):
+ show_volume = mock.MagicMock(return_value={
+ 'volume': {'attachments': [
+ {'attachment_id': uuids.attachment_id}]}})
+ client = mock.Mock(spec=volumes_client.VolumesClient,
+ build_interval=1,
+ build_timeout=1,
+ show_volume=show_volume)
+ self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
+ self.patch('time.sleep')
+ # Assert that a timeout is raised if the attachment remains.
+ self.assertRaises(lib_exc.TimeoutException,
+ waiters.wait_for_volume_attachment_remove,
+ client, uuids.volume_id, uuids.attachment_id)
+
+ def test_wait_for_volume_attachment_not_present(self):
+ show_volume = mock.MagicMock(return_value={
+ 'volume': {'attachments': []}})
+ client = mock.Mock(spec=volumes_client.VolumesClient,
+ build_interval=1,
+ build_timeout=1,
+ show_volume=show_volume)
+ self.patch('time.time', side_effect=[0., client.build_timeout + 1.])
+ self.patch('time.sleep')
+ waiters.wait_for_volume_attachment_remove(client, uuids.volume_id,
+ uuids.attachment_id)
+ # Assert that show volume is only called once before we return
+ show_volume.assert_called_once_with(uuids.volume_id)
diff --git a/tempest/tests/common/utils/linux/test_remote_client.py b/tempest/tests/common/utils/linux/test_remote_client.py
index caad41c..937f93a 100644
--- a/tempest/tests/common/utils/linux/test_remote_client.py
+++ b/tempest/tests/common/utils/linux/test_remote_client.py
@@ -106,14 +106,15 @@
self.assertEqual(self.conn.get_disks(), result)
self._assert_exec_called_with('lsblk -lb --nodeps')
- def test_count_disk(self):
+ def test_list_disks(self):
output_lsblk = """\
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 128035676160 0 disk
sdb 8:16 0 1000204886016 0 disk
sr0 11:0 1 1073741312 0 rom"""
+ disk_list = ['sda', 'sdb']
self.ssh_mock.mock.exec_command.return_value = output_lsblk
- self.assertEqual(self.conn.count_disks(), 2)
+ self.assertEqual(self.conn.list_disks(), disk_list)
def test_get_boot_time(self):
booted_at = 10000
diff --git a/tempest/tests/lib/services/network/test_agents_client.py b/tempest/tests/lib/services/network/test_agents_client.py
index aabc6ce..8904882 100644
--- a/tempest/tests/lib/services/network/test_agents_client.py
+++ b/tempest/tests/lib/services/network/test_agents_client.py
@@ -22,12 +22,145 @@
FAKE_AGENT_ID = "d32019d3-bc6e-4319-9c1d-6123f4135a88"
+ FAKE_LIST_DATA = {
+ "agents": [
+ {
+ "binary": "neutron-dhcp-agent",
+ "description": None,
+ "availability_zone": "nova",
+ "heartbeat_timestamp": "2017-09-12 19:39:56",
+ "admin_state_up": True,
+ "alive": True,
+ "id": "840d5d68-5759-4e9e-812f",
+ "topic": "dhcp_agent",
+ "host": "agenthost1",
+ "agent_type": "DHCP agent",
+ "started_at": "2017-09-12 19:35:36",
+ "created_at": "2017-09-12 19:35:36",
+ "resources_synced": None,
+ "configurations": {
+ "subnets": 2,
+ "dhcp_lease_duration": 86400,
+ "dhcp_driver": "neutron.agent",
+ "networks": 1,
+ "log_agent_heartbeats": False,
+ "ports": 3
+ }
+ }
+ ]
+ }
+
+ FAKE_SHOW_DATA = {
+ "agent": {
+ "binary": "neutron-openvswitch-agent",
+ "description": None,
+ "availability_zone": None,
+ "heartbeat_timestamp": "2017-09-12 19:40:38",
+ "admin_state_up": True,
+ "alive": True,
+ "id": "04c62b91-b799-48b7-9cd5-2982db6df9c6",
+ "topic": "N/A",
+ "host": "agenthost1",
+ "agent_type": "Open vSwitch agent",
+ "started_at": "2017-09-12 19:35:38",
+ "created_at": "2017-09-12 19:35:38",
+ "resources_synced": True,
+ "configurations": {
+ "ovs_hybrid_plug": True,
+ "in_distributed_mode": False,
+ "datapath_type": "system",
+ "vhostuser_socket_dir": "/var/run/openvswitch",
+ "tunneling_ip": "172.16.78.191",
+ "arp_responder_enabled": False,
+ "devices": 0,
+ "ovs_capabilities": {
+ "datapath_types": [
+ "netdev",
+ "system"
+ ],
+ "iface_types": [
+ "geneve",
+ "gre",
+ "internal",
+ "ipsec_gre",
+ "lisp",
+ "patch",
+ "stt",
+ "system",
+ "tap",
+ "vxlan"
+ ]
+ },
+ "log_agent_heartbeats": False,
+ "l2_population": False,
+ "tunnel_types": [
+ "vxlan"
+ ],
+ "extensions": [],
+ "enable_distributed_routing": False,
+ "bridge_mappings": {
+ "public": "br-ex"
+ }
+ }
+ }
+ }
+
+ FAKE_UPDATE_DATA = {
+ "agent": {
+ "description": "My OVS agent for OpenStack"
+ }
+ }
+
def setUp(self):
super(TestAgentsClient, self).setUp()
fake_auth = fake_auth_provider.FakeAuthProvider()
self.agents_client = agents_client.AgentsClient(
fake_auth, "network", "regionOne")
+ def _test_show_agent(self, bytes_body=False):
+ self.check_service_client_function(
+ self.agents_client.show_agent,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_SHOW_DATA,
+ bytes_body,
+ status=200,
+ agent_id=self.FAKE_AGENT_ID)
+
+ def _test_update_agent(self, bytes_body=False):
+ self.check_service_client_function(
+ self.agents_client.update_agent,
+ "tempest.lib.common.rest_client.RestClient.put",
+ self.FAKE_UPDATE_DATA,
+ bytes_body,
+ status=200,
+ agent_id=self.FAKE_AGENT_ID)
+
+ def _test_list_agents(self, bytes_body=False):
+ self.check_service_client_function(
+ self.agents_client.list_agents,
+ "tempest.lib.common.rest_client.RestClient.get",
+ self.FAKE_LIST_DATA,
+ bytes_body,
+ status=200)
+
+ def test_show_agent_with_str_body(self):
+ self._test_show_agent()
+
+ def test_show_agent_with_bytes_body(self):
+ self._test_show_agent(bytes_body=True)
+
+ def test_update_agent_with_str_body(self):
+ self._test_update_agent()
+
+ def test_update_agent_with_bytes_body(self):
+ self._test_update_agent(bytes_body=True)
+
+ def test_list_agent_with_str_body(self):
+ self._test_list_agents()
+
+ def test_list_agent_with_bytes_body(self):
+ self._test_list_agents(bytes_body=True)
+
def test_delete_agent(self):
self.check_service_client_function(
self.agents_client.delete_agent,
diff --git a/tempest/tests/lib/services/object_storage/test_capabilities_client.py b/tempest/tests/lib/services/object_storage/test_capabilities_client.py
index b7f972a..9df7c7c 100644
--- a/tempest/tests/lib/services/object_storage/test_capabilities_client.py
+++ b/tempest/tests/lib/services/object_storage/test_capabilities_client.py
@@ -43,7 +43,7 @@
}
self.check_service_client_function(
self.client.list_capabilities,
- 'tempest.lib.common.rest_client.RestClient.get',
+ 'tempest.lib.common.rest_client.RestClient.raw_request',
resp,
bytes_body)
diff --git a/tempest/tests/lib/services/volume/v3/test_snapshots_client.py b/tempest/tests/lib/services/volume/v3/test_snapshots_client.py
index 2efd2e6..1ea4c65 100644
--- a/tempest/tests/lib/services/volume/v3/test_snapshots_client.py
+++ b/tempest/tests/lib/services/volume/v3/test_snapshots_client.py
@@ -20,61 +20,85 @@
class TestSnapshotsClient(base.BaseServiceTest):
FAKE_CREATE_SNAPSHOT = {
"snapshot": {
- "display_name": "snap-001",
- "display_description": "Daily backup",
- "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
- "force": True
+ "created_at": "2019-03-11T16:24:34.469003",
+ "description": "Daily backup",
+ "id": "b36476e5-d18b-47f9-ac69-4818cb43ee21",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "size": 10,
+ "status": "creating",
+ "updated_at": None,
+ "volume_id": "d291b81c-6e40-4525-8231-90aa1588121e"
}
}
- FAKE_UPDATE_SNAPSHOT_REQUEST = {
- "metadata": {
- "key": "v1"
+ FAKE_UPDATE_SNAPSHOT_RESPONSE = {
+ "snapshot": {
+ "created_at": "2019-03-12T04:53:53.426591",
+ "description": "This is yet, another snapshot.",
+ "id": "4a584cae-e4ce-429b-9154-d4c9eb8fda4c",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-002",
+ "size": 10,
+ "status": "creating",
+ "updated_at": None,
+ "volume_id": "070c942d-9909-42e9-a467-7a781f150c58"
}
}
FAKE_INFO_SNAPSHOT = {
"snapshot": {
- "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
- "display_name": "snap-001",
- "display_description": "Daily backup",
- "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
- "status": "available",
- "size": 30,
- "created_at": "2012-02-29T03:50:07Z"
+ "created_at": "2019-03-12T04:42:00.809352",
+ "description": "Daily backup",
+ "id": "4a584cae-e4ce-429b-9154-d4c9eb8fda4c",
+ "metadata": {
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "os-extended-snapshot-attributes:progress": "0%",
+ "os-extended-snapshot-attributes:project_id":
+ "89afd400-b646-4bbc-b12b-c0a4d63e5bd3",
+ "size": 10,
+ "status": "creating",
+ "updated_at": None,
+ "volume_id": "b72c48f1-64b7-4cd8-9745-b12e0be82d37"
}
}
FAKE_LIST_SNAPSHOTS = {
"snapshots": [
{
- "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
- "display_name": "snap-001",
- "display_description": "Daily backup",
- "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
- "status": "available",
- "size": 30,
- "created_at": "2012-02-29T03:50:07Z",
+ "created_at": "2019-03-11T16:24:36.464445",
+ "description": "Daily backup",
+ "id": "d0083dc5-8795-4c1a-bc9c-74f70006c205",
"metadata": {
- "contents": "junk"
- }
- },
- {
- "id": "e479997c-650b-40a4-9dfe-77655818b0d2",
- "display_name": "snap-002",
- "display_description": "Weekly backup",
- "volume_id": "76b8950a-8594-4e5b-8dce-0dfa9c696358",
- "status": "available",
- "size": 25,
- "created_at": "2012-03-19T01:52:47Z",
- "metadata": {}
+ "key": "v3"
+ },
+ "name": "snap-001",
+ "os-extended-snapshot-attributes:progress": "0%",
+ "os-extended-snapshot-attributes:project_id":
+ "89afd400-b646-4bbc-b12b-c0a4d63e5bd3",
+ "size": 10,
+ "status": "creating",
+ "updated_at": None,
+ "volume_id": "7acd675e-4e06-4653-af9f-2ecd546342d6"
}
]
}
FAKE_SNAPSHOT_METADATA_ITEM = {
+ "metadata": {
+ "key": "value"
+ }
+ }
+
+ FAKE_SNAPSHOT_KEY = {
"meta": {
- "key1": "value1"
+ "key": "new_value"
}
}
@@ -99,7 +123,7 @@
'tempest.lib.common.rest_client.RestClient.get',
self.FAKE_INFO_SNAPSHOT,
bytes_body,
- snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+ snapshot_id="4a584cae-e4ce-429b-9154-d4c9eb8fda4c")
def _test_list_snapshots(self, bytes_body=False):
self.check_service_client_function(
@@ -113,48 +137,48 @@
self.check_service_client_function(
self.client.create_snapshot_metadata,
'tempest.lib.common.rest_client.RestClient.post',
- self.FAKE_INFO_SNAPSHOT,
+ self.FAKE_SNAPSHOT_METADATA_ITEM,
bytes_body,
- snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5",
- metadata={"key": "v1"})
+ snapshot_id="4a584cae-e4ce-429b-9154-d4c9eb8fda4c",
+ metadata={"key": "value"})
def _test_update_snapshot(self, bytes_body=False):
self.check_service_client_function(
self.client.update_snapshot,
'tempest.lib.common.rest_client.RestClient.put',
- self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+ self.FAKE_UPDATE_SNAPSHOT_RESPONSE,
bytes_body,
- snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+ snapshot_id="4a584cae-e4ce-429b-9154-d4c9eb8fda4c")
def _test_show_snapshot_metadata(self, bytes_body=False):
self.check_service_client_function(
self.client.show_snapshot_metadata,
'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_UPDATE_SNAPSHOT_REQUEST,
+ self.FAKE_SNAPSHOT_METADATA_ITEM,
bytes_body,
- snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5")
+ snapshot_id="4a584cae-e4ce-429b-9154-d4c9eb8fda4c")
def _test_update_snapshot_metadata(self, bytes_body=False):
self.check_service_client_function(
self.client.update_snapshot_metadata,
'tempest.lib.common.rest_client.RestClient.put',
- self.FAKE_UPDATE_SNAPSHOT_REQUEST,
- bytes_body, snapshot_id="cbc36478b0bd8e67e89")
+ self.FAKE_SNAPSHOT_METADATA_ITEM,
+ bytes_body, snapshot_id="4a584cae-e4ce-429b-9154-d4c9eb8fda4c")
def _test_update_snapshot_metadata_item(self, bytes_body=False):
self.check_service_client_function(
self.client.update_snapshot_metadata_item,
'tempest.lib.common.rest_client.RestClient.put',
- self.FAKE_INFO_SNAPSHOT,
+ self.FAKE_SNAPSHOT_KEY,
bytes_body, volume_type_id="cbc36478b0bd8e67e89")
def _test_show_snapshot_metadata_item(self, bytes_body=False):
self.check_service_client_function(
self.client.show_snapshot_metadata_item,
'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_SNAPSHOT_METADATA_ITEM,
+ self.FAKE_SNAPSHOT_KEY,
bytes_body,
- snapshot_id="3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+ snapshot_id="4a584cae-e4ce-429b-9154-d4c9eb8fda4c",
id="key1")
def test_create_snapshot_with_str_body(self):
diff --git a/tox.ini b/tox.ini
index ff31fe8..64921ef 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,11 +1,11 @@
[tox]
-envlist = pep8,py36,py37,py27,bashate,pip-check-reqs
+envlist = pep8,py36,py37,bashate,pip-check-reqs
minversion = 3.1.1
skipsdist = True
ignore_basepython_conflict = True
[tempestenv]
-basepython = python3.6
+basepython = python3
sitepackages = False
setenv =
VIRTUAL_ENV={envdir}