Merge "Make image metadef tests admin-only"
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index c43e420..c790c5f 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -153,6 +153,11 @@
Pre-Provisioned Credentials are also known as accounts.yaml or accounts file.
+Keystone Scopes & Roles Support in Tempest
+""""""""""""""""""""""""""""""""""""""""""
+For details on scope and roles support in Tempest,
+please refer to :doc:`this document <keystone_scopes_and_roles_support>`
+
Compute
-------
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 66e68ea..2f29cf2 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -105,6 +105,14 @@
tempest_and_plugins_compatible_version_policy
+Keystone Scopes & Roles Support in Tempest
+------------------------------------------
+
+.. toctree::
+ :maxdepth: 2
+
+ keystone_scopes_and_roles_support
+
Stable Branch Support Policy
----------------------------
diff --git a/doc/source/keystone_scopes_and_roles_support.rst b/doc/source/keystone_scopes_and_roles_support.rst
new file mode 100644
index 0000000..f446f8c
--- /dev/null
+++ b/doc/source/keystone_scopes_and_roles_support.rst
@@ -0,0 +1,286 @@
+Keystone Scopes & Roles Support in Tempest
+==========================================
+
+OpenStack Keystone supports different scopes in token, refer to the
+`Keystone doc <https://docs.openstack.org/keystone/latest/admin/tokens-overview.html#authorization-scopes>`_.
+Along with the scopes, keystone supports default roles, one of which
+is a reader role, for details refer to
+`this keystone document <https://docs.openstack.org/keystone/latest/admin/service-api-protection.html>`_.
+
+Tempest supports those scopes and roles credentials that can be used
+to test APIs under different scope and roles.
+
+Dynamic Credentials
+-------------------
+
+Dynamic credential supports all the below set of personas and allows
+you to generate credentials tailored to a specific persona that you
+can use in your test.
+
+Domain scoped personas:
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+ #. Domain Admin: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['domain_admin']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_d_admin_client = (
+ cls.os_domain_admin.availability_zone_client)
+
+ #. Domain Member: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['domain_member']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_d_member_client = (
+ cls.os_domain_member.availability_zone_client)
+
+ #. Domain Reader: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['domain_reader']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_d_reader_client = (
+ cls.os_domain_reader.availability_zone_client)
+
+ #. Domain other roles: This is supported and can be requested and used from
+ the test as below:
+
+ You need to use the ``domain`` as the prefix in credentials type, and
+ based on that, Tempest will create test users under 'domain' scope.
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = [['domain_my_role1', 'my_own_role1', 'admin']
+ ['domain_my_role2', 'my_own_role2']]
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_d_role1_client = (
+ cls.os_domain_my_role1.availability_zone_client)
+ cls.az_d_role2_client = (
+ cls.os_domain_my_role2.availability_zone_client)
+
+System scoped personas:
+^^^^^^^^^^^^^^^^^^^^^^^
+
+ #. System Admin: This is supported and can be requested and used from the
+ test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['system_admin']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_s_admin_client = (
+ cls.os_system_admin.availability_zone_client)
+
+ #. System Member: This is supported and can be requested and used from the
+ test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['system_member']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_s_member_client = (
+ cls.os_system_member.availability_zone_client)
+
+ #. System Reader: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['system_reader']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_s_reader_client = (
+ cls.os_system_reader.availability_zone_client)
+
+ #. System other roles: This is supported and can be requested and used from
+ the test as below:
+
+ You need to use the ``system`` as the prefix in credentials type, and
+ based on that, Tempest will create test users under 'project' scope.
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = [['system_my_role1', 'my_own_role1', 'admin']
+ ['system_my_role2', 'my_own_role2']]
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_s_role1_client = (
+ cls.os_system_my_role1.availability_zone_client)
+ cls.az_s_role2_client = (
+ cls.os_system_my_role2.availability_zone_client)
+
+Project scoped personas:
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+ #. Project Admin: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['project_admin']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_p_admin_client = (
+ cls.os_project_admin.availability_zone_client)
+
+ #. Project Member: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['project_member']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_p_member_client = (
+ cls.os_project_member.availability_zone_client)
+
+ #. Project Reader: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['project_reader']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_p_reader_client = (
+ cls.os_project_reader.availability_zone_client)
+
+ #. Project alternate Admin: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['project_alt_admin']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_p_alt_admin_client = (
+ cls.os_project_alt_admin.availability_zone_client)
+
+ #. Project alternate Member: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['project_alt_member']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_p_alt_member_client = (
+ cls.os_project_alt_member.availability_zone_client)
+
+ #. Project alternate Reader: This is supported and can be requested and used from
+ the test as below:
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = ['project_alt_reader']
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_p_alt_reader_client = (
+ cls.os_project_alt_reader.availability_zone_client)
+
+ #. Project other roles: This is supported and can be requested and used from
+ the test as below:
+
+ You need to use the ``project`` as the prefix in credentials type, and
+ based on that, Tempest will create test users under 'project' scope.
+
+ .. code-block:: python
+
+ class TestDummy(base.DummyBaseTest):
+
+ credentials = [['project_my_role1', 'my_own_role1', 'admin']
+ ['project_my_role2', 'my_own_role2']]
+
+ @classmethod
+ def setup_clients(cls):
+ super(TestDummy, cls).setup_clients()
+ cls.az_role1_client = (
+ cls.os_project_my_role1.availability_zone_client)
+ cls.az_role2_client = (
+ cls.os_project_my_role2.availability_zone_client)
+
+Pre-Provisioned Credentials
+---------------------------
+
+Pre-Provisioned credentials support the below set of personas and can be
+used in the test as shown above in the ``Dynamic Credentials`` Section.
+
+* Domain Admin
+* Domain Member
+* Domain Reader
+* System Admin
+* System Member
+* System Reader
+* Project Admin
+* Project Member
+* Project Reader
diff --git a/releasenotes/notes/add-compute-feature-ide-bus-b63802502c378083.yaml b/releasenotes/notes/add-compute-feature-ide-bus-b63802502c378083.yaml
new file mode 100644
index 0000000..43a0e8c
--- /dev/null
+++ b/releasenotes/notes/add-compute-feature-ide-bus-b63802502c378083.yaml
@@ -0,0 +1,10 @@
+---
+other:
+ - |
+ A new ``[compute-feature-enabled]ide_bus`` config option has been
+ introduced to indicate if the environment supports attaching disks to an
+ instance using an ``IDE`` bus.
+
+ This currently defaults to ``True`` but should be set to ``False`` when
+ using the libvirt OpenStack Nova virt driver *and* the ``q35`` machine type
+ as support for this bus is no longer provided.
diff --git a/releasenotes/notes/remove-old-data-utils-e0966f882f7fe23a.yaml b/releasenotes/notes/remove-old-data-utils-e0966f882f7fe23a.yaml
new file mode 100644
index 0000000..ac20340
--- /dev/null
+++ b/releasenotes/notes/remove-old-data-utils-e0966f882f7fe23a.yaml
@@ -0,0 +1,6 @@
+---
+upgrade:
+ - |
+ The old deprecated ``data-ultis`` from ``tempest.common.utils`` has been
+ removed. If you are still using this, use the stable version
+ of ``data-utils`` from new location ``tempest.lib.common.utils``.
diff --git a/requirements.txt b/requirements.txt
index abc0bce..d84116b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -18,7 +18,7 @@
PyYAML>=3.12 # MIT
python-subunit>=1.0.0 # Apache-2.0/BSD
stevedore>=1.20.0 # Apache-2.0
-PrettyTable<0.8,>=0.7.1 # BSD
+PrettyTable>=0.7.1 # BSD
urllib3>=1.21.1 # MIT
debtcollector>=1.2.0 # Apache-2.0
unittest2>=1.1.0 # BSD
diff --git a/roles/run-tempest/defaults/main.yaml b/roles/run-tempest/defaults/main.yaml
index 52713be..5f13883 100644
--- a/roles/run-tempest/defaults/main.yaml
+++ b/roles/run-tempest/defaults/main.yaml
@@ -6,3 +6,6 @@
stable_constraints_file: "{{ devstack_base_dir }}/requirements/upper-constraints.txt"
target_branch: "{{ zuul.branch }}"
tempest_tox_environment: {}
+# NOTE(gmann): external_bridge_mtu shows as undefined for run-tempest role
+# defining default value here to avoid that error.
+external_bridge_mtu: 0
diff --git a/roles/run-tempest/tasks/main.yaml b/roles/run-tempest/tasks/main.yaml
index 5b00de3..37026e4 100644
--- a/roles/run-tempest/tasks/main.yaml
+++ b/roles/run-tempest/tasks/main.yaml
@@ -31,6 +31,17 @@
tempest_tox_environment: "{{ tempest_tox_environment | combine({'UPPER_CONSTRAINTS_FILE': stable_constraints_file}) | combine({'TOX_CONSTRAINTS_FILE': stable_constraints_file}) }}"
when: target_branch in ["stable/ocata", "stable/pike", "stable/queens", "stable/rocky", "stable/stein"]
+- name: Use Configured upper-constraints for non-master Tempest
+ set_fact:
+ # TOX_CONSTRAINTS_FILE is new name, UPPER_CONSTRAINTS_FILE is old one, best to set both
+ tempest_tox_environment: "{{ tempest_tox_environment | combine({'UPPER_CONSTRAINTS_FILE': devstack_localrc['TEMPEST_VENV_UPPER_CONSTRAINTS']}) | combine({'TOX_CONSTRAINTS_FILE': devstack_localrc['TEMPEST_VENV_UPPER_CONSTRAINTS']}) }}"
+ when:
+ - devstack_localrc is defined
+ - "'TEMPEST_BRANCH' in devstack_localrc"
+ - "'TEMPEST_VENV_UPPER_CONSTRAINTS' in devstack_localrc"
+ - devstack_localrc['TEMPEST_BRANCH'] != 'master'
+ - devstack_localrc['TEMPEST_VENV_UPPER_CONSTRAINTS'] != 'default'
+
- name: Set OS_TEST_TIMEOUT if requested
set_fact:
tempest_tox_environment: "{{ tempest_tox_environment | combine({'OS_TEST_TIMEOUT': tempest_test_timeout}) }}"
diff --git a/tempest/api/compute/servers/test_server_rescue.py b/tempest/api/compute/servers/test_server_rescue.py
index c222893..a9f8c09 100644
--- a/tempest/api/compute/servers/test_server_rescue.py
+++ b/tempest/api/compute/servers/test_server_rescue.py
@@ -158,8 +158,14 @@
self.servers_client, server_id, 'ACTIVE')
-class ServerStableDeviceRescueTest(BaseServerStableDeviceRescueTest):
- """Test rescuing server specifying type of device for the rescue disk"""
+class ServerStableDeviceRescueTestIDE(BaseServerStableDeviceRescueTest):
+ """Test rescuing server using an IDE device for the rescue disk"""
+
+ @classmethod
+ def skip_checks(cls):
+ super().skip_checks()
+ if not CONF.compute_feature_enabled.ide_bus:
+ raise cls.skipException("IDE bus not available.")
@decorators.idempotent_id('947004c3-e8ef-47d9-9f00-97b74f9eaf96')
def test_stable_device_rescue_cdrom_ide(self):
@@ -168,6 +174,10 @@
hw_rescue_device='cdrom', hw_rescue_bus='ide')
self._test_stable_device_rescue(server_id, rescue_image_id)
+
+class ServerStableDeviceRescueTest(BaseServerStableDeviceRescueTest):
+ """Test rescuing server specifying type of device for the rescue disk"""
+
@decorators.idempotent_id('16865750-1417-4854-bcf7-496e6753c01e')
def test_stable_device_rescue_disk_virtio(self):
"""Test rescuing server with disk and virtio as the rescue disk"""
diff --git a/tempest/api/image/v2/test_images_negative.py b/tempest/api/image/v2/test_images_negative.py
index 810c37c..a3802a9 100644
--- a/tempest/api/image/v2/test_images_negative.py
+++ b/tempest/api/image/v2/test_images_negative.py
@@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import time
+
from tempest.api.image import base
from tempest import config
from tempest.lib.common.utils import data_utils
@@ -156,3 +158,63 @@
container_format='bare',
disk_format='raw',
os_glance_foo='bar')
+
+
+class ImportImagesNegativeTest(base.BaseV2ImageTest):
+ """Here we test the import operations for image"""
+
+ @classmethod
+ def skip_checks(cls):
+ super(ImportImagesNegativeTest, cls).skip_checks()
+ if not CONF.image_feature_enabled.import_image:
+ skip_msg = (
+ "%s skipped as image import is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ @classmethod
+ def resource_setup(cls):
+ super(ImportImagesNegativeTest, cls).resource_setup()
+ cls.available_import_methods = cls.client.info_import()[
+ 'import-methods']['value']
+ if not cls.available_import_methods:
+ raise cls.skipException('Server does not support '
+ 'any import method')
+
+ cls.available_stores = cls.get_available_stores()
+ if not len(cls.available_stores) > 0:
+ raise cls.skipException(
+ 'No stores configured %s' % cls.available_stores)
+
+ @decorators.attr(type=['negative'])
+ @decorators.idempotent_id('c52f6a77-f522-4411-8dbe-9d14f2b1ba6b')
+ def test_image_web_download_import_with_bad_url(self):
+ """Test 'web-download' import functionalities
+
+ Make sure that web-download with invalid URL fails properly.
+ """
+ if 'web-download' not in self.available_import_methods:
+ raise self.skipException('Server does not support '
+ 'web-download import method')
+ image = self.client.create_image(name='test',
+ container_format='bare',
+ disk_format='raw')
+ # Now try to get image details
+ body = self.client.show_image(image['id'])
+ self.assertEqual(image['id'], body['id'])
+ self.assertEqual('queued', body['status'])
+ stores = self.get_available_stores()
+ # import image from web to backend
+ image_uri = 'http://does-not.exist/no/possible/way'
+ self.client.image_import(image['id'], method='web-download',
+ image_uri=image_uri,
+ stores=[stores[0]['id']])
+
+ start_time = int(time.time())
+ while int(time.time()) - start_time < self.client.build_timeout:
+ body = self.client.show_image(image['id'])
+ if body.get('os_glance_failed_import'):
+ # Store ended up in failed list, which is good
+ return
+ time.sleep(self.client.build_interval)
+
+ self.fail('Image never reported failed store')
diff --git a/tempest/api/network/test_floating_ips.py b/tempest/api/network/test_floating_ips.py
index eb31d24..64f6e80 100644
--- a/tempest/api/network/test_floating_ips.py
+++ b/tempest/api/network/test_floating_ips.py
@@ -15,9 +15,9 @@
from tempest.api.network import base
from tempest.common import utils
-from tempest.common.utils import data_utils
from tempest.common.utils import net_utils
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
diff --git a/tempest/api/object_storage/test_object_services.py b/tempest/api/object_storage/test_object_services.py
index fc9b1a2..93f6fdb 100644
--- a/tempest/api/object_storage/test_object_services.py
+++ b/tempest/api/object_storage/test_object_services.py
@@ -13,12 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
import random
import re
import time
import zlib
+from oslo_utils.secretutils import md5
from tempest.api.object_storage import base
from tempest.common import custom_matchers
from tempest import config
@@ -151,8 +151,8 @@
"""Test creating object with Etag"""
object_name = data_utils.rand_name(name='TestObject')
data = data_utils.random_bytes()
- md5 = hashlib.md5(data).hexdigest()
- metadata = {'Etag': md5}
+ create_md5 = md5(data, usedforsecurity=False).hexdigest()
+ metadata = {'Etag': create_md5}
resp, _ = self.object_client.create_object(
self.container_name,
object_name,
@@ -641,7 +641,7 @@
"""Test getting object with if_match"""
object_name = data_utils.rand_name(name='TestObject')
data = data_utils.random_bytes(10)
- create_md5 = hashlib.md5(data).hexdigest()
+ create_md5 = md5(data, usedforsecurity=False).hexdigest()
create_metadata = {'Etag': create_md5}
self.object_client.create_object(self.container_name,
object_name,
@@ -681,7 +681,7 @@
"""Test getting object with if_none_match"""
object_name = data_utils.rand_name(name='TestObject')
data = data_utils.random_bytes()
- create_md5 = hashlib.md5(data).hexdigest()
+ create_md5 = md5(data, usedforsecurity=False).hexdigest()
create_metadata = {'Etag': create_md5}
self.object_client.create_object(self.container_name,
object_name,
@@ -689,7 +689,7 @@
metadata=create_metadata)
list_data = data_utils.random_bytes()
- list_md5 = hashlib.md5(list_data).hexdigest()
+ list_md5 = md5(list_data, usedforsecurity=False).hexdigest()
list_metadata = {'If-None-Match': list_md5}
resp, body = self.object_client.get_object(
self.container_name,
@@ -978,8 +978,8 @@
"""
object_name, data = self.create_object(self.container_name)
# local copy is identical, no download
- md5 = hashlib.md5(data).hexdigest()
- headers = {'If-None-Match': md5}
+ object_md5 = md5(data, usedforsecurity=False).hexdigest()
+ headers = {'If-None-Match': object_md5}
url = "%s/%s" % (self.container_name, object_name)
resp, _ = self.object_client.get(url, headers=headers)
self.assertEqual(resp['status'], '304')
@@ -993,8 +993,8 @@
# local copy is different, download
local_data = "something different"
- md5 = hashlib.md5(local_data.encode()).hexdigest()
- headers = {'If-None-Match': md5}
+ other_md5 = md5(local_data.encode(), usedforsecurity=False).hexdigest()
+ headers = {'If-None-Match': other_md5}
resp, _ = self.object_client.get(url, headers=headers)
self.assertHeaders(resp, 'Object', 'GET')
diff --git a/tempest/api/object_storage/test_object_slo.py b/tempest/api/object_storage/test_object_slo.py
index 664bbc8..0c84357 100644
--- a/tempest/api/object_storage/test_object_slo.py
+++ b/tempest/api/object_storage/test_object_slo.py
@@ -12,10 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
-
from oslo_serialization import jsonutils as json
+from oslo_utils.secretutils import md5
from tempest.api.object_storage import base
from tempest.common import utils
from tempest.lib.common.utils import data_utils
@@ -70,10 +69,12 @@
path_object_2 = '/%s/%s' % (self.container_name,
object_name_base_2)
data_manifest = [{'path': path_object_1,
- 'etag': hashlib.md5(self.content).hexdigest(),
+ 'etag': md5(self.content,
+ usedforsecurity=False).hexdigest(),
'size_bytes': data_size},
{'path': path_object_2,
- 'etag': hashlib.md5(self.content).hexdigest(),
+ 'etag': md5(self.content,
+ usedforsecurity=False).hexdigest(),
'size_bytes': data_size}]
return json.dumps(data_manifest)
diff --git a/tempest/clients.py b/tempest/clients.py
index d2fb3eb..6db43db 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -94,7 +94,8 @@
# config option to see if the alternate_image_endpoint is set.
self.image_client_remote = self.image_v2.ImagesClient(
service=CONF.image.alternate_image_endpoint,
- endpoint_type=CONF.image.alternate_image_endpoint_type)
+ endpoint_type=CONF.image.alternate_image_endpoint_type,
+ region=CONF.image.region)
def _set_compute_clients(self):
self.agents_client = self.compute.AgentsClient()
diff --git a/tempest/common/utils/__init__.py b/tempest/common/utils/__init__.py
index 38881ee..88a16b7 100644
--- a/tempest/common/utils/__init__.py
+++ b/tempest/common/utils/__init__.py
@@ -13,37 +13,17 @@
# under the License.
import functools
-from functools import partial
import testtools
from tempest import config
from tempest.exceptions import InvalidServiceTag
-from tempest.lib.common.utils import data_utils as lib_data_utils
from tempest.lib import decorators
CONF = config.CONF
-class DataUtils(object):
- def __getattr__(self, attr):
-
- if attr == 'rand_name':
- # NOTE(flwang): This is a proxy to generate a random name that
- # includes a random number and a prefix 'tempest'
- attr_obj = partial(lib_data_utils.rand_name,
- prefix='tempest')
- else:
- attr_obj = getattr(lib_data_utils, attr)
-
- self.__dict__[attr] = attr_obj
- return attr_obj
-
-
-data_utils = DataUtils()
-
-
def get_service_list():
service_list = {
'compute': CONF.service_available.nova,
diff --git a/tempest/config.py b/tempest/config.py
index e7dca38..46aae23 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -636,6 +636,10 @@
"APIs that only worked with that driver "
"have been removed and there's nothing to "
"test after Ussuri."),
+ cfg.BoolOpt('ide_bus',
+ default=True,
+ help='Does the test environment support attaching devices '
+ 'using an IDE bus to the instance?'),
]
diff --git a/tempest/lib/common/preprov_creds.py b/tempest/lib/common/preprov_creds.py
index df0f4d6..6d948cf 100644
--- a/tempest/lib/common/preprov_creds.py
+++ b/tempest/lib/common/preprov_creds.py
@@ -12,11 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
import os
from oslo_concurrency import lockutils
from oslo_log import log as logging
+from oslo_utils.secretutils import md5
import yaml
from tempest.lib import auth
@@ -134,7 +134,7 @@
scope = 'domain'
elif 'system' in account:
scope = 'system'
- temp_hash = hashlib.md5()
+ temp_hash = md5(usedforsecurity=False)
account_for_hash = dict((k, v) for (k, v) in account.items()
if k in cls.HASH_CRED_FIELDS)
temp_hash.update(str(account_for_hash).encode('utf-8'))
diff --git a/tempest/tests/cmd/test_verify_tempest_config.py b/tempest/tests/cmd/test_verify_tempest_config.py
index e19efb7..a8a4c0f 100644
--- a/tempest/tests/cmd/test_verify_tempest_config.py
+++ b/tempest/tests/cmd/test_verify_tempest_config.py
@@ -18,12 +18,9 @@
import fixtures
from oslo_serialization import jsonutils as json
-from tempest import clients
from tempest.cmd import init
from tempest.cmd import verify_tempest_config
-from tempest.common import credentials_factory
from tempest import config
-from tempest.lib.common import rest_client
from tempest.lib.common.utils import data_utils
from tempest.lib import exceptions as lib_exc
from tempest.tests import base
@@ -514,23 +511,24 @@
self.assertEqual([], results['swift']['extensions'])
def test_get_extension_client(self):
- creds = credentials_factory.get_credentials(
- fill_in=False, username='fake_user', project_name='fake_project',
- password='fake_password')
- os = clients.Manager(creds)
- for service in ['nova', 'neutron', 'swift', 'cinder']:
+ fake_os = mock.MagicMock()
+ services = {
+ 'nova': fake_os.compute.ExtensionsClient(),
+ 'neutron': fake_os.network.ExtensionsClient(),
+ 'swift': fake_os.object_storage.CapabilitiesClient(),
+ 'cinder': fake_os.volume_v2.ExtensionsClient(),
+ }
+ for service in services.keys():
extensions_client = verify_tempest_config.get_extension_client(
- os, service)
- self.assertIsInstance(extensions_client, rest_client.RestClient)
+ fake_os, service)
+ self.assertIsInstance(extensions_client, mock.MagicMock)
+ self.assertEqual(extensions_client, services[service])
def test_get_extension_client_sysexit(self):
- creds = credentials_factory.get_credentials(
- fill_in=False, username='fake_user', project_name='fake_project',
- password='fake_password')
- os = clients.Manager(creds)
+ fake_os = mock.MagicMock()
self.assertRaises(SystemExit,
verify_tempest_config.get_extension_client,
- os, 'fakeservice')
+ fake_os, 'fakeservice')
def test_get_config_file(self):
conf_dir = os.path.join(os.getcwd(), 'etc')
diff --git a/tempest/tests/lib/cmd/test_check_uuid.py b/tempest/tests/lib/cmd/test_check_uuid.py
index a621a75..5d63dec 100644
--- a/tempest/tests/lib/cmd/test_check_uuid.py
+++ b/tempest/tests/lib/cmd/test_check_uuid.py
@@ -19,6 +19,7 @@
from unittest import mock
from tempest.lib.cmd import check_uuid
+from tempest.lib import decorators
from tempest.tests import base
@@ -49,6 +50,7 @@
with open(tests_file, "r") as f:
self.assertTrue(TestCLInterface.CODE == f.read())
+ @decorators.skip_because(bug='1918316')
def test_fix_argument_yes(self):
temp_dir = tempfile.mkdtemp(prefix='check-uuid-yes', dir=".")
self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
diff --git a/tempest/tests/lib/common/test_preprov_creds.py b/tempest/tests/lib/common/test_preprov_creds.py
index 499b6fe..fe7fcd2 100644
--- a/tempest/tests/lib/common/test_preprov_creds.py
+++ b/tempest/tests/lib/common/test_preprov_creds.py
@@ -12,7 +12,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import hashlib
import os
import shutil
from unittest import mock
@@ -22,6 +21,7 @@
import fixtures
from oslo_concurrency.fixture import lockutils as lockutils_fixtures
from oslo_config import cfg
+from oslo_utils.secretutils import md5
from tempest import config
from tempest.lib import auth
@@ -105,7 +105,7 @@
hash_fields = (
preprov_creds.PreProvisionedCredentialProvider.HASH_CRED_FIELDS)
for account in accounts_list:
- hash = hashlib.md5()
+ hash = md5(usedforsecurity=False)
account_for_hash = dict((k, v) for (k, v) in account.items()
if k in hash_fields)
hash.update(str(account_for_hash).encode('utf-8'))