Merge "Negative test for web-download import"
diff --git a/releasenotes/notes/image-client-add-versions-and-tasks-ac289dbfe1c899cc.yaml b/releasenotes/notes/image-client-add-versions-and-tasks-ac289dbfe1c899cc.yaml
new file mode 100644
index 0000000..fde6193
--- /dev/null
+++ b/releasenotes/notes/image-client-add-versions-and-tasks-ac289dbfe1c899cc.yaml
@@ -0,0 +1,6 @@
+---
+features:
+ - |
+ Adds a method to images_client to get tasks relevant to a given image. Also adds
+ has_version() method to image versions_client to probe for availability of a given
+ API version.
diff --git a/tempest/api/image/v2/test_images.py b/tempest/api/image/v2/test_images.py
index 59067d1..efa23bb 100644
--- a/tempest/api/image/v2/test_images.py
+++ b/tempest/api/image/v2/test_images.py
@@ -68,16 +68,12 @@
self.assertEqual('queued', image['status'])
return image
- @decorators.idempotent_id('32ca0c20-e16f-44ac-8590-07869c9b4cc2')
- def test_image_glance_direct_import(self):
- """Test 'glance-direct' import functionalities
-
- Create image, stage image data, import image and verify
- that import succeeded.
- """
- if 'glance-direct' not in self.available_import_methods:
+ def _require_import_method(self, method):
+ if method not in self.available_import_methods:
raise self.skipException('Server does not support '
- 'glance-direct import method')
+ '%s import method' % method)
+
+ def _stage_and_check(self):
image = self._create_image()
# Stage image data
file_content = data_utils.random_bytes()
@@ -87,9 +83,38 @@
body = self.client.show_image(image['id'])
self.assertEqual(image['id'], body['id'])
self.assertEqual('uploading', body['status'])
+ return image['id']
+
+ @decorators.idempotent_id('32ca0c20-e16f-44ac-8590-07869c9b4cc2')
+ def test_image_glance_direct_import(self):
+ """Test 'glance-direct' import functionalities
+
+ Create image, stage image data, import image and verify
+ that import succeeded.
+ """
+ self._require_import_method('glance-direct')
+
+ image_id = self._stage_and_check()
# import image from staging to backend
- self.client.image_import(image['id'], method='glance-direct')
- waiters.wait_for_image_imported_to_stores(self.client, image['id'])
+ resp = self.client.image_import(image_id, method='glance-direct')
+ waiters.wait_for_image_imported_to_stores(self.client, image_id)
+
+ if not self.versions_client.has_version('2.12'):
+ # API is not new enough to support image/tasks API
+ LOG.info('Glance does not support v2.12, so I am unable to '
+ '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'])
+ self.assertEqual(resp.response['x-openstack-request-id'],
+ task['request_id'])
+ self.assertEqual('glance-direct',
+ task['input']['import_req']['method']['name'])
@decorators.idempotent_id('f6feb7a4-b04f-4706-a011-206129f83e62')
def test_image_web_download_import(self):
@@ -98,9 +123,8 @@
Create image, import image and verify that import
succeeded.
"""
- if 'web-download' not in self.available_import_methods:
- raise self.skipException('Server does not support '
- 'web-download import method')
+ self._require_import_method('web-download')
+
image = self._create_image()
# Now try to get image details
body = self.client.show_image(image['id'])
@@ -112,6 +136,47 @@
image_uri=image_uri)
waiters.wait_for_image_imported_to_stores(self.client, image['id'])
+ @decorators.idempotent_id('e04761a1-22af-42c2-b8bc-a34a3f12b585')
+ def test_remote_import(self):
+ """Test image import against a different worker than stage.
+
+ This creates and stages an image against the primary API worker,
+ but then calls import on a secondary worker (if available) to
+ test that distributed image import works (i.e. proxies the import
+ request to the proper worker).
+ """
+ self._require_import_method('glance-direct')
+
+ if not CONF.image.alternate_image_endpoint:
+ raise self.skipException('No image_remote service to test '
+ 'against')
+
+ image_id = self._stage_and_check()
+ # import image from staging to backend, but on the alternate worker
+ self.os_primary.image_client_remote.image_import(
+ image_id, method='glance-direct')
+ waiters.wait_for_image_imported_to_stores(self.client, image_id)
+
+ @decorators.idempotent_id('44d60544-1524-42f7-8899-315301105dd8')
+ def test_remote_delete(self):
+ """Test image delete against a different worker than stage.
+
+ This creates and stages an image against the primary API worker,
+ but then calls delete on a secondary worker (if available) to
+ test that distributed image import works (i.e. proxies the delete
+ request to the proper worker).
+ """
+ self._require_import_method('glance-direct')
+
+ if not CONF.image.alternate_image_endpoint:
+ raise self.skipException('No image_remote service to test '
+ 'against')
+
+ image_id = self._stage_and_check()
+ # delete image from staging to backend, but on the alternate worker
+ self.os_primary.image_client_remote.delete_image(image_id)
+ self.client.wait_for_resource_deletion(image_id)
+
class MultiStoresImportImagesTest(base.BaseV2ImageTest):
"""Test importing image in multiple stores"""
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/api/volume/admin/test_group_snapshots.py b/tempest/api/volume/admin/test_group_snapshots.py
index 0a8b56d..659e2c4 100644
--- a/tempest/api/volume/admin/test_group_snapshots.py
+++ b/tempest/api/volume/admin/test_group_snapshots.py
@@ -64,7 +64,6 @@
class GroupSnapshotsTest(BaseGroupSnapshotsTest):
"""Test group snapshot"""
- _api_version = 3
min_microversion = '3.14'
max_microversion = 'latest'
@@ -253,7 +252,6 @@
class GroupSnapshotsV319Test(BaseGroupSnapshotsTest):
"""Test group snapshot with volume microversion greater than 3.18"""
- _api_version = 3
min_microversion = '3.19'
max_microversion = 'latest'
diff --git a/tempest/api/volume/admin/test_group_type_specs.py b/tempest/api/volume/admin/test_group_type_specs.py
index 159c6fb..5c5913e 100644
--- a/tempest/api/volume/admin/test_group_type_specs.py
+++ b/tempest/api/volume/admin/test_group_type_specs.py
@@ -21,7 +21,6 @@
class GroupTypeSpecsTest(base.BaseVolumeAdminTest):
"""Test group type specs"""
- _api_version = 3
min_microversion = '3.11'
max_microversion = 'latest'
diff --git a/tempest/api/volume/admin/test_group_types.py b/tempest/api/volume/admin/test_group_types.py
index 3993020..a7a5d6f 100644
--- a/tempest/api/volume/admin/test_group_types.py
+++ b/tempest/api/volume/admin/test_group_types.py
@@ -21,7 +21,6 @@
class GroupTypesTest(base.BaseVolumeAdminTest):
"""Test group types"""
- _api_version = 3
min_microversion = '3.11'
max_microversion = 'latest'
diff --git a/tempest/api/volume/admin/test_groups.py b/tempest/api/volume/admin/test_groups.py
index e67b985..747a194 100644
--- a/tempest/api/volume/admin/test_groups.py
+++ b/tempest/api/volume/admin/test_groups.py
@@ -25,7 +25,6 @@
class GroupsTest(base.BaseVolumeAdminTest):
"""Tests of volume groups with microversion greater than 3.12"""
- _api_version = 3
min_microversion = '3.13'
max_microversion = 'latest'
@@ -156,7 +155,6 @@
class GroupsV314Test(base.BaseVolumeAdminTest):
"""Tests of volume groups with microversion greater than 3.13"""
- _api_version = 3
min_microversion = '3.14'
max_microversion = 'latest'
@@ -194,7 +192,6 @@
class GroupsV320Test(base.BaseVolumeAdminTest):
"""Tests of volume groups with microversion greater than 3.19"""
- _api_version = 3
min_microversion = '3.20'
max_microversion = 'latest'
diff --git a/tempest/api/volume/admin/test_user_messages.py b/tempest/api/volume/admin/test_user_messages.py
index 096709c..768c129 100644
--- a/tempest/api/volume/admin/test_user_messages.py
+++ b/tempest/api/volume/admin/test_user_messages.py
@@ -24,7 +24,6 @@
class UserMessagesTest(base.BaseVolumeAdminTest):
"""Test volume messages with microversion greater than 3.2"""
- _api_version = 3
min_microversion = '3.3'
max_microversion = 'latest'
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index f6559f8..9f9fc3b 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -32,7 +32,6 @@
# Set this to True in subclasses to create a default network. See
# https://bugs.launchpad.net/tempest/+bug/1844568
create_default_network = False
- _api_version = 2
credentials = ['primary']
@classmethod
diff --git a/tempest/api/volume/test_versions.py b/tempest/api/volume/test_versions.py
index e065bdf..578be58 100644
--- a/tempest/api/volume/test_versions.py
+++ b/tempest/api/volume/test_versions.py
@@ -19,8 +19,6 @@
class VersionsTest(base.BaseVolumeTest):
"""Test volume versions"""
- _api_version = 3
-
@decorators.idempotent_id('77838fc4-b49b-4c64-9533-166762517369')
@decorators.attr(type='smoke')
def test_list_versions(self):
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 2e78114..fff6a44 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -164,7 +164,6 @@
class VolumesBackupsV39Test(base.BaseVolumeTest):
"""Test volumes backup with volume microversion greater than 3.8"""
- _api_version = 3
min_microversion = '3.9'
max_microversion = 'latest'
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index 7441f1d..d9790f3 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -77,7 +77,6 @@
# details once that microversion is available in Nova.
credentials = ['primary', 'admin']
- _api_version = 3
# NOTE(mriedem): The minimum required volume API version is 3.42 and the
# minimum required compute API microversion is 2.51, but the compute call
# is implicit - Cinder calls Nova at that microversion, Tempest does not.
diff --git a/tempest/api/volume/test_volumes_get.py b/tempest/api/volume/test_volumes_get.py
index 91728ab..28e41bf 100644
--- a/tempest/api/volume/test_volumes_get.py
+++ b/tempest/api/volume/test_volumes_get.py
@@ -143,7 +143,6 @@
class VolumesSummaryTest(base.BaseVolumeTest):
"""Test volume summary"""
- _api_version = 3
min_microversion = '3.12'
max_microversion = 'latest'
diff --git a/tempest/clients.py b/tempest/clients.py
index 9ff02ea..d2fb3eb 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -88,6 +88,13 @@
self.image_v2.NamespacePropertiesClient()
self.namespace_tags_client = self.image_v2.NamespaceTagsClient()
self.image_versions_client = self.image_v2.VersionsClient()
+ # NOTE(danms): If no alternate endpoint is configured,
+ # this client will work the same as the base self.images_client.
+ # If your test needs to know if these are different, check the
+ # 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)
def _set_compute_clients(self):
self.agents_client = self.compute.AgentsClient()
diff --git a/tempest/config.py b/tempest/config.py
index 0df5045..e7dca38 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -657,6 +657,15 @@
choices=['public', 'admin', 'internal',
'publicURL', 'adminURL', 'internalURL'],
help="The endpoint type to use for the image service."),
+ cfg.StrOpt('alternate_image_endpoint',
+ default=None,
+ help="Alternate endpoint name for cross-worker testing"),
+ cfg.StrOpt('alternate_image_endpoint_type',
+ default='publicURL',
+ choices=['public', 'admin', 'internal',
+ 'publicURL', 'adminURL', 'internalURL'],
+ help=("The endpoint type to use for the alternate image "
+ "service.")),
cfg.StrOpt('http_image',
default='http://download.cirros-cloud.net/0.3.1/'
'cirros-0.3.1-x86_64-uec.tar.gz',
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/lib/services/image/v2/images_client.py b/tempest/lib/services/image/v2/images_client.py
index fa3bb8c..abf427c 100644
--- a/tempest/lib/services/image/v2/images_client.py
+++ b/tempest/lib/services/image/v2/images_client.py
@@ -121,6 +121,14 @@
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
+ def show_image_tasks(self, image_id):
+ """Show image tasks."""
+ url = 'images/%s/tasks' % image_id
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
def is_resource_deleted(self, id):
try:
self.show_image(id)
diff --git a/tempest/lib/services/image/v2/versions_client.py b/tempest/lib/services/image/v2/versions_client.py
index 1b7f806..98b4fb6 100644
--- a/tempest/lib/services/image/v2/versions_client.py
+++ b/tempest/lib/services/image/v2/versions_client.py
@@ -30,3 +30,13 @@
self.expected_success(300, resp.status)
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
+
+ def has_version(self, version):
+ """Return True if a version is supported."""
+ version = 'v%s' % version
+ supported = ['SUPPORTED', 'CURRENT']
+ versions = self.list_versions()
+ for version_struct in versions['versions']:
+ if version_struct['id'] == version:
+ return version_struct['status'] in supported
+ return False
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 81bbc38..22d0fd2 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -590,7 +590,7 @@
rules.append(sg_rule)
return rules
- def _create_security_group(self, **kwargs):
+ def create_security_group(self, **kwargs):
"""Create security group and add rules to security group"""
if not kwargs.get('name'):
kwargs['name'] = data_utils.rand_name(self.__class__.__name__)
@@ -1189,7 +1189,7 @@
return subnet
- def _get_server_port_id_and_ip4(self, server, ip_addr=None, **kwargs):
+ def get_server_port_id_and_ip4(self, server, ip_addr=None, **kwargs):
if ip_addr and not kwargs.get('fixed_ips'):
kwargs['fixed_ips'] = 'ip_address=%s' % ip_addr
@@ -1242,7 +1242,7 @@
if not client:
client = self.floating_ips_client
if not port_id:
- port_id, ip4 = self._get_server_port_id_and_ip4(server)
+ port_id, ip4 = self.get_server_port_id_and_ip4(server)
else:
ip4 = None
@@ -1270,7 +1270,7 @@
This wrapper utility attaches the floating_ip for
the respective port_id of server
"""
- port_id, _ = self._get_server_port_id_and_ip4(server)
+ port_id, _ = self.get_server_port_id_and_ip4(server)
kwargs = dict(port_id=port_id)
floating_ip = self.floating_ips_client.update_floatingip(
floating_ip['id'], **kwargs)['floatingip']
@@ -1386,17 +1386,17 @@
self.log_console_output()
self.fail(msg)
- def _create_security_group(self, security_group_rules_client=None,
- project_id=None,
- namestart='secgroup-smoke',
- security_groups_client=None):
+ def create_security_group(self, security_group_rules_client=None,
+ project_id=None,
+ namestart='secgroup-smoke',
+ security_groups_client=None):
if security_group_rules_client is None:
security_group_rules_client = self.security_group_rules_client
if security_groups_client is None:
security_groups_client = self.security_groups_client
if project_id is None:
project_id = security_groups_client.project_id
- secgroup = self._create_empty_security_group(
+ secgroup = self.create_empty_security_group(
namestart=namestart, client=security_groups_client,
project_id=project_id)
@@ -1410,8 +1410,8 @@
self.assertEqual(secgroup['id'], rule['security_group_id'])
return secgroup
- def _create_empty_security_group(self, client=None, project_id=None,
- namestart='secgroup-smoke'):
+ def create_empty_security_group(self, client=None, project_id=None,
+ namestart='secgroup-smoke'):
"""Create a security group without rules.
Default rules will be created:
@@ -1545,7 +1545,7 @@
return rules
- def _get_router(self, client=None, project_id=None, **kwargs):
+ def get_router(self, client=None, project_id=None, **kwargs):
"""Retrieve a router for the given tenant id.
If a public router has been configured, it will be returned.
@@ -1624,8 +1624,8 @@
project_id=project_id,
port_security_enabled=port_security_enabled,
**net_dict)
- router = self._get_router(client=routers_client,
- project_id=project_id)
+ router = self.get_router(client=routers_client,
+ project_id=project_id)
subnet_kwargs = dict(network=network,
subnets_client=subnets_client)
# use explicit check because empty list is a valid option
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index fe42583..5201315 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -78,7 +78,7 @@
self.assertEqual(1, disks.count(CONF.compute.volume_device_name))
def create_and_add_security_group_to_server(self, server):
- secgroup = self._create_security_group()
+ secgroup = self.create_security_group()
self.servers_client.add_security_group(server['id'],
name=secgroup['name'])
self.addCleanup(self.servers_client.remove_security_group,
diff --git a/tempest/scenario/test_network_advanced_server_ops.py b/tempest/scenario/test_network_advanced_server_ops.py
index dbab212..20d2e80 100644
--- a/tempest/scenario/test_network_advanced_server_ops.py
+++ b/tempest/scenario/test_network_advanced_server_ops.py
@@ -60,7 +60,7 @@
def _setup_server(self, keypair):
security_groups = []
if utils.is_extension_enabled('security-group', 'network'):
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
security_groups = [{'name': security_group['name']}]
network, _, _ = self.create_networks()
server = self.create_server(
diff --git a/tempest/scenario/test_network_basic_ops.py b/tempest/scenario/test_network_basic_ops.py
index da1e794..e359c71 100644
--- a/tempest/scenario/test_network_basic_ops.py
+++ b/tempest/scenario/test_network_basic_ops.py
@@ -159,7 +159,7 @@
keypair = self.create_keypair()
self.keypairs[keypair['name']] = keypair
security_groups = [
- {'name': self._create_security_group()['name']}
+ {'name': self.create_security_group()['name']}
]
network = {'uuid': network['id']}
if port_id is not None:
@@ -223,7 +223,7 @@
floating_ip, server = self.floating_ip_tuple
# create a new server for the floating ip
server = self._create_server(self.network)
- port_id, _ = self._get_server_port_id_and_ip4(server)
+ port_id, _ = self.get_server_port_id_and_ip4(server)
floating_ip = self.floating_ips_client.update_floatingip(
floating_ip['id'], port_id=port_id)['floatingip']
self.assertEqual(port_id, floating_ip['port_id'])
diff --git a/tempest/scenario/test_network_v6.py b/tempest/scenario/test_network_v6.py
index 9323628..4f5118b 100644
--- a/tempest/scenario/test_network_v6.py
+++ b/tempest/scenario/test_network_v6.py
@@ -66,7 +66,7 @@
def setUp(self):
super(TestGettingAddress, self).setUp()
self.keypair = self.create_keypair()
- self.sec_grp = self._create_security_group()
+ self.sec_grp = self.create_security_group()
def prepare_network(self, address6_mode, n_subnets6=1, dualnet=False):
"""Prepare network
@@ -85,7 +85,7 @@
namestart='sub4',
ip_version=4)
- router = self._get_router()
+ router = self.get_router()
self.routers_client.add_router_interface(router['id'],
subnet_id=sub4['id'])
diff --git a/tempest/scenario/test_security_groups_basic_ops.py b/tempest/scenario/test_security_groups_basic_ops.py
index 496a371..e078f23 100644
--- a/tempest/scenario/test_security_groups_basic_ops.py
+++ b/tempest/scenario/test_security_groups_basic_ops.py
@@ -197,14 +197,14 @@
tenant.keypair = keypair
def _create_tenant_security_groups(self, tenant):
- access_sg = self._create_empty_security_group(
+ access_sg = self.create_empty_security_group(
namestart='secgroup_access-',
project_id=tenant.creds.project_id,
client=tenant.manager.security_groups_client
)
# don't use default secgroup since it allows in-project traffic
- def_sg = self._create_empty_security_group(
+ def_sg = self.create_empty_security_group(
namestart='secgroup_general-',
project_id=tenant.creds.project_id,
client=tenant.manager.security_groups_client
@@ -534,7 +534,7 @@
new_tenant = self.primary_tenant
# Create empty security group and add icmp rule in it
- new_sg = self._create_empty_security_group(
+ new_sg = self.create_empty_security_group(
namestart='secgroup_new-',
project_id=new_tenant.creds.project_id,
client=new_tenant.manager.security_groups_client)
diff --git a/tempest/scenario/test_server_basic_ops.py b/tempest/scenario/test_server_basic_ops.py
index 60242d5..4c82d84 100644
--- a/tempest/scenario/test_server_basic_ops.py
+++ b/tempest/scenario/test_server_basic_ops.py
@@ -128,7 +128,7 @@
@utils.services('compute', 'network')
def test_server_basic_ops(self):
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
self.md = {'meta1': 'data1', 'meta2': 'data2', 'metaN': 'dataN'}
self.instance = self.create_server(
key_name=keypair['name'],
diff --git a/tempest/scenario/test_shelve_instance.py b/tempest/scenario/test_shelve_instance.py
index ed06898..29612ec 100644
--- a/tempest/scenario/test_shelve_instance.py
+++ b/tempest/scenario/test_shelve_instance.py
@@ -76,7 +76,7 @@
cold_migrate=False):
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
security_groups = [{'name': security_group['name']}]
server = self.create_server(
diff --git a/tempest/scenario/test_snapshot_pattern.py b/tempest/scenario/test_snapshot_pattern.py
index a062d40..d04cb9a 100644
--- a/tempest/scenario/test_snapshot_pattern.py
+++ b/tempest/scenario/test_snapshot_pattern.py
@@ -50,7 +50,7 @@
def test_snapshot_pattern(self):
# prepare for booting an instance
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
# boot an instance and create a timestamp file in it
server = self.create_server(
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index a8e4c30..4b81b9e 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -81,7 +81,7 @@
def test_stamp_pattern(self):
# prepare for booting an instance
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
# boot an instance and create a timestamp file in it
volume = self.create_volume()
diff --git a/tempest/scenario/test_volume_backup_restore.py b/tempest/scenario/test_volume_backup_restore.py
index 8a8c54e..71e6b53 100644
--- a/tempest/scenario/test_volume_backup_restore.py
+++ b/tempest/scenario/test_volume_backup_restore.py
@@ -70,7 +70,7 @@
# Create keypair and security group
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
# Boot a server from the restored backup
bd_map_v2 = [{
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 3b4bbda..5a5cc27 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -64,7 +64,7 @@
LOG.info("Creating keypair and security group")
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
# create an instance from volume
LOG.info("Booting instance 1 from volume")
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index 106500e..57d2a1a 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -100,7 +100,7 @@
def test_volume_retype_attached(self):
LOG.info("Creating keypair and security group")
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
# create volume types
LOG.info("Creating Volume types")
@@ -156,7 +156,7 @@
def test_volume_migrate_attached(self):
LOG.info("Creating keypair and security group")
keypair = self.create_keypair()
- security_group = self._create_security_group()
+ security_group = self.create_security_group()
LOG.info("Creating volume")
# Create a unique volume type to avoid using the backend default
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 428e047..5d63dec 100644
--- a/tempest/tests/lib/cmd/test_check_uuid.py
+++ b/tempest/tests/lib/cmd/test_check_uuid.py
@@ -13,13 +13,13 @@
import ast
import importlib
import os
+import shutil
import sys
import tempfile
from unittest import mock
-import fixtures
-
from tempest.lib.cmd import check_uuid
+from tempest.lib import decorators
from tempest.tests import base
@@ -40,23 +40,24 @@
return tests_file
def test_fix_argument_no(self):
- temp_dir = self.useFixture(fixtures.TempDir(rootdir="."))
- tests_file = self.create_tests_file(temp_dir.path)
-
+ temp_dir = tempfile.mkdtemp(prefix='check-uuid-no', dir=".")
+ self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
+ tests_file = self.create_tests_file(temp_dir)
sys.argv = [sys.argv[0]] + ["--package",
- os.path.relpath(temp_dir.path)]
+ os.path.relpath(temp_dir)]
self.assertRaises(SystemExit, check_uuid.run)
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 = self.useFixture(fixtures.TempDir(rootdir="."))
- tests_file = self.create_tests_file(temp_dir.path)
+ temp_dir = tempfile.mkdtemp(prefix='check-uuid-yes', dir=".")
+ self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True)
+ tests_file = self.create_tests_file(temp_dir)
sys.argv = [sys.argv[0]] + ["--fix", "--package",
- os.path.relpath(temp_dir.path)]
-
+ os.path.relpath(temp_dir)]
check_uuid.run()
with open(tests_file, "r") as f:
self.assertTrue(TestCLInterface.CODE != f.read())
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'))
diff --git a/tempest/tests/lib/services/image/v2/test_images_client.py b/tempest/tests/lib/services/image/v2/test_images_client.py
index 7ee61d2..5b162f8 100644
--- a/tempest/tests/lib/services/image/v2/test_images_client.py
+++ b/tempest/tests/lib/services/image/v2/test_images_client.py
@@ -105,6 +105,44 @@
"first": "/v2/images"
}
+ FAKE_SHOW_IMAGE_TASKS = {
+ "tasks": [
+ {
+ "id": "ee22890e-8948-4ea6-9668-831f973c84f5",
+ "image_id": "dddddddd-dddd-dddd-dddd-dddddddddddd",
+ "request-id": "rrrrrrr-rrrr-rrrr-rrrr-rrrrrrrrrrrr",
+ "user": "uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu",
+ "type": "api_image_import",
+ "status": "processing",
+ "owner": "64f0efc9955145aeb06f297a8a6fe402",
+ "expires_at": None,
+ "created_at": "2020-12-18T05:20:38.000000",
+ "updated_at": "2020-12-18T05:25:39.000000",
+ "deleted_at": None,
+ "deleted": False,
+ "input": {
+ "image_id": "829c729b-ebc4-4cc7-a164-6f43f1149b17",
+ "import_req": {
+ "method": {
+ "name": "copy-image",
+ },
+ "all_stores": True,
+ "all_stores_must_succeed": False,
+ },
+ "backend": [
+ "fast",
+ "cheap",
+ "slow",
+ "reliable",
+ "common",
+ ]
+ },
+ "result": None,
+ "message": "Copied 15 MiB",
+ }
+ ]
+ }
+
FAKE_TAG_NAME = "fake tag"
def setUp(self):
@@ -230,3 +268,11 @@
def test_list_images_with_bytes_body(self):
self._test_list_images(bytes_body=True)
+
+ def test_show_image_tasks(self):
+ self.check_service_client_function(
+ self.client.show_image_tasks,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ self.FAKE_SHOW_IMAGE_TASKS,
+ True,
+ image_id="e485aab9-0907-4973-921c-bb6da8a8fcf8")
diff --git a/tempest/tests/lib/services/image/v2/test_versions_client.py b/tempest/tests/lib/services/image/v2/test_versions_client.py
index 6234b06..98c558a 100644
--- a/tempest/tests/lib/services/image/v2/test_versions_client.py
+++ b/tempest/tests/lib/services/image/v2/test_versions_client.py
@@ -12,6 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
+import fixtures
+
from tempest.lib.services.image.v2 import versions_client
from tempest.tests.lib import fake_auth_provider
from tempest.tests.lib.services import base
@@ -92,3 +94,13 @@
def test_list_versions_with_bytes_body(self):
self._test_list_versions(bytes_body=True)
+
+ def test_has_version(self):
+ mocked_r = self.create_response(self.FAKE_VERSIONS_INFO, False,
+ 300, None)
+ self.useFixture(fixtures.MockPatch(
+ 'tempest.lib.common.rest_client.RestClient.raw_request',
+ return_value=mocked_r))
+
+ self.assertTrue(self.client.has_version('2.1'))
+ self.assertFalse(self.client.has_version('9.9'))