Merge "Update microversion for for the tests which fail due to multiattach enabled" into mcp/caracal
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 44c2197..9b30582 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -857,7 +857,7 @@
# 4.Plain username/password auth, if a password was given.
linux_client = remote_client.RemoteClient(
self.get_server_ip(server, self.validation_resources),
- self.ssh_alt_user,
+ self.ssh_user,
password=None,
pkey=self.validation_resources['keypair']['private_key'],
server=server,
diff --git a/tempest/api/image/v2/admin/test_images.py b/tempest/api/image/v2/admin/test_images.py
index 2077d35..1190c52 100644
--- a/tempest/api/image/v2/admin/test_images.py
+++ b/tempest/api/image/v2/admin/test_images.py
@@ -12,6 +12,7 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
+import time
import io
@@ -235,3 +236,45 @@
observed_image,
stores,
first_image_store_deleted)
+
+
+class ImageWebUploadAdminTest(base.BaseV2ImageAdminTest):
+ @classmethod
+ def skip_checks(cls):
+ super(ImageWebUploadAdminTest, cls).skip_checks()
+ enabled_methods = CONF.image_feature_enabled.enabled_import_methods
+ if "web-download" not in enabled_methods:
+ raise cls.skipException(
+ "Glance image upload via url feature disabled")
+
+ @decorators.idempotent_id('5b2ce43c-924c-4bae-bac0-f5d6ed69d72e')
+ def test_image_upload_via_url(self):
+ # Create image
+ image_name = data_utils.rand_name("image")
+ container_format = CONF.image.container_formats[0]
+ disk_format = CONF.image.disk_formats[0]
+ image = self.create_image(name=image_name,
+ container_format=container_format,
+ disk_format=disk_format,
+ visibility='private')
+ self.assertEqual('queued', image['status'])
+
+ # Upload image via url
+ image_uri = CONF.image.http_image
+ method = {"name": "web-download", "uri": image_uri}
+ self.admin_client.import_image(image_id=image["id"], method=method)
+
+ timeout = CONF.image.build_timeout
+ interval = CONF.image.build_interval
+
+ start_time = int(time.time())
+ while True:
+ body = self.admin_client.show_image(image['id'])
+ if body["status"] == "active":
+ break
+ if int(time.time()) - start_time >= timeout:
+ message = ('Image %(id)s failed to become active within '
+ 'the required time (%(timeout)s s).' %
+ {'id': image['id'], 'timeout': timeout})
+ raise lib_exc.TimeoutException(message)
+ time.sleep(interval)
diff --git a/tempest/api/network/test_tags.py b/tempest/api/network/test_tags.py
index bd3e360..af0a8b0 100644
--- a/tempest/api/network/test_tags.py
+++ b/tempest/api/network/test_tags.py
@@ -113,7 +113,10 @@
# NOTE(felipemonteiro): The supported resource names are plural. Use
# the singular case for the corresponding class resource object.
- SUPPORTED_RESOURCES = ['subnets', 'ports', 'routers', 'subnetpools']
+ if config.is_tungstenfabric_backend_enabled():
+ SUPPORTED_RESOURCES = ['subnets', 'ports', 'routers']
+ else:
+ SUPPORTED_RESOURCES = ['subnets', 'ports', 'routers', 'subnetpools']
@classmethod
def skip_checks(cls):
@@ -134,6 +137,9 @@
cls.port = cls.create_port(cls.network)
cls.router = cls.create_router()
+ if config.is_tungstenfabric_backend_enabled():
+ return
+
subnetpool_name = data_utils.rand_name(
cls.__name__ + '-Subnetpool', prefix=CONF.resource_name_prefix)
prefix = CONF.network.default_network
diff --git a/tempest/api/volume/admin/test_multi_backend.py b/tempest/api/volume/admin/test_multi_backend.py
index 028bf1a..b45824e 100644
--- a/tempest/api/volume/admin/test_multi_backend.py
+++ b/tempest/api/volume/admin/test_multi_backend.py
@@ -30,8 +30,9 @@
raise cls.skipException("Cinder multi-backend feature disabled")
if len(set(CONF.volume.backend_names)) < 2:
- raise cls.skipException("Requires at least two different "
- "backend names")
+ raise cls.skipException(
+ "Requires at least two different "
+ "backend names")
@classmethod
def resource_setup(cls):
@@ -66,21 +67,34 @@
extra_specs = {spec_key_with_prefix: backend_name_key}
else:
extra_specs = {spec_key_without_prefix: backend_name_key}
- cls.create_volume_type(name=type_name,
- extra_specs=extra_specs)
+ cls.create_volume_type(
+ name=type_name, extra_specs=extra_specs)
+ # Pick up AZ from volume_type
+ services = cls.admin_volume_services_client.list_services()
+ vol_svrs = [
+ srv
+ for srv in services.get("services")
+ if srv["binary"] == "cinder-volume" and backend_name_key
+ in srv["host"]
+ ]
+ vol_type_zone = vol_svrs[0]["zone"]
- params = {'name': vol_name, 'volume_type': type_name,
- 'size': CONF.volume.volume_size}
+ params = {
+ "name": vol_name,
+ "volume_type": type_name,
+ "size": CONF.volume.volume_size,
+ "availability_zone": vol_type_zone,
+ }
cls.volume = cls.create_volume(**params)
if with_prefix:
- cls.volume_id_list_with_prefix.append(cls.volume['id'])
+ cls.volume_id_list_with_prefix.append(cls.volume["id"])
else:
- cls.volume_id_list_without_prefix.append(
- cls.volume['id'])
- waiters.wait_for_volume_resource_status(cls.admin_volume_client,
- cls.volume['id'], 'available')
+ cls.volume_id_list_without_prefix.append(cls.volume["id"])
+ waiters.wait_for_volume_resource_status(
+ cls.admin_volume_client, cls.volume["id"], "available"
+ )
- @decorators.idempotent_id('c1a41f3f-9dad-493e-9f09-3ff197d477cc')
+ @decorators.idempotent_id("c1a41f3f-9dad-493e-9f09-3ff197d477cc")
def test_backend_name_reporting(self):
"""Test backend name reporting for volume when type is without prefix
@@ -92,7 +106,7 @@
for volume_id in self.volume_id_list_without_prefix:
self._test_backend_name_reporting_by_volume_id(volume_id)
- @decorators.idempotent_id('f38e647f-ab42-4a31-a2e7-ca86a6485215')
+ @decorators.idempotent_id("f38e647f-ab42-4a31-a2e7-ca86a6485215")
def test_backend_name_reporting_with_prefix(self):
"""Test backend name reporting for volume when type is with prefix
@@ -105,7 +119,7 @@
for volume_id in self.volume_id_list_with_prefix:
self._test_backend_name_reporting_by_volume_id(volume_id)
- @decorators.idempotent_id('46435ab1-a0af-4401-8373-f14e66b0dd58')
+ @decorators.idempotent_id("46435ab1-a0af-4401-8373-f14e66b0dd58")
def test_backend_name_distinction(self):
"""Test volume backend distinction when type is without prefix
@@ -116,7 +130,7 @@
"""
self._test_backend_name_distinction(self.volume_id_list_without_prefix)
- @decorators.idempotent_id('4236305b-b65a-4bfc-a9d2-69cb5b2bf2ed')
+ @decorators.idempotent_id("4236305b-b65a-4bfc-a9d2-69cb5b2bf2ed")
def test_backend_name_distinction_with_prefix(self):
"""Test volume backend distinction when type is with prefix
@@ -128,28 +142,29 @@
self._test_backend_name_distinction(self.volume_id_list_with_prefix)
def _get_volume_host(self, volume_id):
- return self.admin_volume_client.show_volume(
- volume_id)['volume']['os-vol-host-attr:host']
+ return self.admin_volume_client.show_volume(volume_id)["volume"][
+ "os-vol-host-attr:host"
+ ]
def _test_backend_name_reporting_by_volume_id(self, volume_id):
# this test checks if os-vol-attr:host is populated correctly after
# the multi backend feature has been enabled
# if multi-backend is enabled: os-vol-attr:host should be like:
# host@backend_name
- volume = self.admin_volume_client.show_volume(volume_id)['volume']
+ volume = self.admin_volume_client.show_volume(volume_id)["volume"]
- volume1_host = volume['os-vol-host-attr:host']
- msg = ("multi-backend reporting incorrect values for volume %s" %
- volume_id)
+ volume1_host = volume["os-vol-host-attr:host"]
+ msg = ("multi-backend reporting incorrect values for volume %s"
+ % volume_id)
self.assertGreater(len(volume1_host.split("@")), 1, msg)
def _test_backend_name_distinction(self, volume_id_list):
# this test checks that the volumes created at setUp don't
# belong to the same backend (if they are, than the
# volume backend distinction is not working properly)
- volume_hosts = [self._get_volume_host(volume) for volume in
- volume_id_list]
+ volume_hosts = [self._get_volume_host(volume)
+ for volume in volume_id_list]
# assert that volumes are each created on separate hosts:
- msg = ("volumes %s were created in the same backend" % ", "
- .join(volume_hosts))
+ msg = "volumes %s were created in the same backend" % ", ".join(
+ volume_hosts)
self.assertCountEqual(volume_hosts, set(volume_hosts), msg)
diff --git a/tempest/common/credentials_factory.py b/tempest/common/credentials_factory.py
index 8d699ab..2e07c80 100644
--- a/tempest/common/credentials_factory.py
+++ b/tempest/common/credentials_factory.py
@@ -87,7 +87,8 @@
('create_networks', (CONF.auth.create_isolated_networks and not
CONF.network.shared_physical_network)),
('resource_prefix', 'tempest'),
- ('identity_admin_endpoint_type', endpoint_type)
+ ('identity_admin_endpoint_type', endpoint_type),
+ ('networking_timeout_409', CONF.network.timeout_409)
]))
diff --git a/tempest/config.py b/tempest/config.py
index 47667ba..d57864d 100644
--- a/tempest/config.py
+++ b/tempest/config.py
@@ -749,6 +749,9 @@
cfg.BoolOpt('os_glance_reserved',
default=False,
help="Should we check that os_glance namespace is reserved"),
+ cfg.ListOpt('enabled_import_methods',
+ default=[],
+ help="List of enabled image import methods"),
cfg.BoolOpt('manage_locations',
default=False,
help=('Is show_multiple_locations enabled in glance. '
@@ -842,6 +845,10 @@
cfg.IntOpt('service_ports_number',
default=0,
help="Number of neutron service ports created per network"),
+ cfg.IntOpt('timeout_409',
+ default=120,
+ help="Total time in seconds to keep retrying a request that "
+ "returns HTTP 409 (Conflict)."),
]
network_feature_group = cfg.OptGroup(name='network-feature-enabled',
@@ -951,7 +958,7 @@
default="root",
help="User name used to authenticate to an instance."),
cfg.StrOpt('image_alt_ssh_user',
- default="cirros",
+ default="root",
help="User name used to authenticate to an alt instance."),
cfg.StrOpt('image_ssh_password',
default="password",
@@ -1088,6 +1095,18 @@
cfg.ListOpt('scheduler_default_filters',
default=[],
help="The list of enabled scheduler filters.",),
+ cfg.StrOpt('volume_type_luks',
+ default='luks',
+ help="The name of volume type used by tests to create"
+ "volumes with luks encryption.",),
+ cfg.StrOpt('volume_type_luks_v2',
+ default='luks2',
+ help="The name of volume type used by tests to create"
+ "volumes with luks v2 encryption.",),
+ cfg.StrOpt('volume_type_cryptsetup',
+ default='cryptsetup',
+ help="The name of volume type used by tests to create"
+ "volumes with cryptsetup encryption.",),
]
volume_feature_group = cfg.OptGroup(name='volume-feature-enabled',
@@ -1692,6 +1711,17 @@
return _parameters
+def is_tungstenfabric_backend_enabled():
+ """Return True if TungstenFabric is used as a backend."""
+ try:
+ sdn = getattr(CONF, 'sdn')
+ service_name = getattr(sdn, 'service_name')
+ if service_name == 'tungstenfabric':
+ return True
+ except cfg.NoSuchOptError:
+ return False
+
+
def _register_tempest_service_clients():
# Register tempest own service clients using the same mechanism used
# for external plugins.
diff --git a/tempest/lib/common/cred_provider.py b/tempest/lib/common/cred_provider.py
index 2da206f..84f5264 100644
--- a/tempest/lib/common/cred_provider.py
+++ b/tempest/lib/common/cred_provider.py
@@ -13,6 +13,8 @@
# limitations under the License.
import abc
+import time
+
from oslo_log import log as logging
from tempest.lib import auth
@@ -133,11 +135,24 @@
name="default")
secgroups_to_delete = resp_body['security_groups']
for secgroup in secgroups_to_delete:
- try:
- security_group_client.delete_security_group(secgroup['id'])
- except exceptions.NotFound:
- LOG.warning('Security group %s, id %s not found for clean-up',
- secgroup['name'], secgroup['id'])
+ # Workaround for PRODX-4003
+ start_time = time.time()
+ while True:
+ try:
+ security_group_client.delete_security_group(secgroup['id'])
+ break
+ except exceptions.NotFound:
+ LOG.warning('Security group %s, id %s not found for '
+ 'clean-up', secgroup['name'], secgroup['id'])
+ break
+ except exceptions.Conflict:
+ LOG.warning('Conflict with state of security group %s, '
+ 'id %s.', secgroup['name'], secgroup['id'])
+ if (time.time() - self.networking_timeout_409) > \
+ start_time:
+ raise
+ else:
+ time.sleep(5)
class TestResources(object):
diff --git a/tempest/lib/common/dynamic_creds.py b/tempest/lib/common/dynamic_creds.py
index 9994ee6..9eb3c22 100644
--- a/tempest/lib/common/dynamic_creds.py
+++ b/tempest/lib/common/dynamic_creds.py
@@ -76,7 +76,8 @@
neutron_available=False, create_networks=True,
project_network_cidr=None, project_network_mask_bits=None,
public_network_id=None, resource_prefix=None,
- identity_admin_endpoint_type='public', identity_uri=None):
+ identity_admin_endpoint_type='public', identity_uri=None,
+ networking_timeout_409=120):
super(DynamicCredentialProvider, self).__init__(
identity_version=identity_version, identity_uri=identity_uri,
admin_role=admin_role, name=name,
@@ -121,6 +122,7 @@
self.roles_admin_client,
self.domains_admin_client,
self.creds_domain_name)
+ self.networking_timeout_409 = networking_timeout_409
def _get_admin_clients(self, endpoint_type):
"""Returns a tuple with instances of the following admin clients
diff --git a/tempest/lib/services/image/v2/images_client.py b/tempest/lib/services/image/v2/images_client.py
index 0608d47..3963fee 100644
--- a/tempest/lib/services/image/v2/images_client.py
+++ b/tempest/lib/services/image/v2/images_client.py
@@ -55,6 +55,19 @@
body = json.loads(body)
return rest_client.ResponseBody(resp, body)
+ def import_image(self, image_id, **kwargs):
+ """Import image.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/image/v2/#import-an-image
+ """
+ data = json.dumps(kwargs)
+ url = 'images/%s/import' % image_id
+ resp, body = self.post(url, data)
+ self.expected_success(202, resp.status)
+ return rest_client.ResponseBody(resp, body)
+
def deactivate_image(self, image_id):
"""Deactivate image.
diff --git a/tempest/scenario/test_encrypted_cinder_volumes.py b/tempest/scenario/test_encrypted_cinder_volumes.py
index cb5e673..62b2823 100644
--- a/tempest/scenario/test_encrypted_cinder_volumes.py
+++ b/tempest/scenario/test_encrypted_cinder_volumes.py
@@ -60,9 +60,10 @@
@utils.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_luks(self):
"""LUKs v1 decrypts volume through libvirt."""
- volume = self.create_encrypted_volume('luks',
- volume_type='luks',
- wait_until=None)
+ volume = self.create_encrypted_volume(
+ 'luks',
+ volume_type=CONF.volume.volume_type_luks,
+ wait_until=None)
server = self.launch_instance()
waiters.wait_for_volume_resource_status(self.volumes_client,
volume['id'], 'available')
@@ -100,9 +101,10 @@
'plain cryptoprovider is not supported.')
@utils.services('compute', 'volume', 'image')
def test_encrypted_cinder_volumes_cryptsetup(self):
- volume = self.create_encrypted_volume('plain',
- volume_type='cryptsetup',
- wait_until=None)
+ volume = self.create_encrypted_volume(
+ 'plain',
+ volume_type=CONF.volume.volume_type_cryptsetup,
+ wait_until=None)
server = self.launch_instance()
waiters.wait_for_volume_resource_status(self.volumes_client,
volume['id'], 'available')
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 7ef7488..1c3c8bf 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -314,7 +314,9 @@
@utils.services('compute', 'volume')
def test_boot_server_from_encrypted_volume_luks(self):
"""LUKs v1 decrypts volume through libvirt."""
- self._do_test_boot_server_from_encrypted_volume_luks('luks')
+ self._do_test_boot_server_from_encrypted_volume_luks(
+ CONF.volume.volume_type_luks
+ )
@decorators.idempotent_id('5ab6100f-1b31-4dd0-a774-68cfd837ef77')
@testtools.skipIf(CONF.volume.storage_protocol == 'ceph',
@@ -327,4 +329,6 @@
@utils.services('compute', 'volume')
def test_boot_server_from_encrypted_volume_luksv2(self):
"""LUKs v2 decrypts volume through os-brick."""
- self._do_test_boot_server_from_encrypted_volume_luks('luks2')
+ self._do_test_boot_server_from_encrypted_volume_luks(
+ CONF.volume.volume_type_luks_v2
+ )