Merge "Added json.loads(body) to delete_attachment method"
diff --git a/releasenotes/notes/add-image-task-apis-as-tempest-clients-228ccba01f59cbf3.yaml b/releasenotes/notes/add-image-task-apis-as-tempest-clients-228ccba01f59cbf3.yaml
new file mode 100644
index 0000000..cb99a29
--- /dev/null
+++ b/releasenotes/notes/add-image-task-apis-as-tempest-clients-228ccba01f59cbf3.yaml
@@ -0,0 +1,54 @@
+---
+features:
+ - |
+ The following ``tasks_client`` tempest client for glance v2 image
+ task API is implemented in this release.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/releasenotes/notes/remove-nova-network-tests-f694bcd30a97a4ca.yaml b/releasenotes/notes/remove-nova-network-tests-f694bcd30a97a4ca.yaml
new file mode 100644
index 0000000..6ee5691
--- /dev/null
+++ b/releasenotes/notes/remove-nova-network-tests-f694bcd30a97a4ca.yaml
@@ -0,0 +1,11 @@
+---
+prelude: >
+ Tempest remove the nova-network tests and service clients.
+ The nova-network was removed from Rocky release and current
+ Tempest master does not support the Rocky release. Below are
+ the service clients have been removed:
+
+ * floating_ip_pools_client
+ * floating_ips_bulk_client
+ * fixed_ips_client
+ * list_virtual_interfaces
diff --git a/tempest/api/compute/admin/test_assisted_volume_snapshots.py b/tempest/api/compute/admin/test_assisted_volume_snapshots.py
new file mode 100644
index 0000000..5e30444
--- /dev/null
+++ b/tempest/api/compute/admin/test_assisted_volume_snapshots.py
@@ -0,0 +1,63 @@
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.compute import base
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+
+CONF = config.CONF
+
+
+class VolumesAssistedSnapshotsTest(base.BaseV2ComputeAdminTest):
+ """Test volume assisted snapshots"""
+
+ create_default_network = True
+
+ @classmethod
+ def skip_checks(cls):
+ super(VolumesAssistedSnapshotsTest, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ @classmethod
+ def setup_clients(cls):
+ super(VolumesAssistedSnapshotsTest, cls).setup_clients()
+ cls.assisted_v_client = (
+ cls.os_admin.assisted_volume_snapshots_client)
+ cls.volumes_client = cls.os_admin.volumes_client_latest
+ cls.servers_client = cls.os_admin.servers_client
+
+ @decorators.idempotent_id('8aee84a3-1b1f-42e4-9b00-613931ccac24')
+ def test_volume_assisted_snapshot_create_delete(self):
+ """Test create/delete volume assisted snapshot"""
+ volume = self.create_volume()
+ self.addCleanup(self.delete_volume, volume['id'])
+ validation_resources = self.get_class_validation_resources(
+ self.os_primary)
+ server = self.create_test_server(
+ validatable=True,
+ validation_resources=validation_resources,
+ wait_until='SSHABLE'
+ )
+ # Attach created volume to server
+ self.attach_volume(server, volume)
+ snapshot_id = data_utils.rand_uuid()
+ snapshot = self.assisted_v_client.create_assisted_volume_snapshot(
+ volume_id=volume['id'], snapshot_id=snapshot_id,
+ type='qcow2', new_file='new_file')['snapshot']
+ self.assisted_v_client.delete_assisted_volume_snapshot(
+ volume_id=volume['id'], snapshot_id=snapshot['id'])
diff --git a/tempest/api/compute/admin/test_fixed_ips.py b/tempest/api/compute/admin/test_fixed_ips.py
deleted file mode 100644
index 9de3da9..0000000
--- a/tempest/api/compute/admin/test_fixed_ips.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright 2013 IBM Corp
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.api.compute import base
-from tempest.common import utils
-from tempest import config
-from tempest.lib import decorators
-
-CONF = config.CONF
-
-
-class FixedIPsTestJson(base.BaseV2ComputeAdminTest):
- """Test fixed ips API"""
-
- @classmethod
- def skip_checks(cls):
- super(FixedIPsTestJson, cls).skip_checks()
- if CONF.service_available.neutron:
- msg = ("%s skipped as neutron is available" % cls.__name__)
- raise cls.skipException(msg)
- if not utils.get_service_list()['network']:
- raise cls.skipException("network service not enabled.")
-
- @classmethod
- def setup_clients(cls):
- super(FixedIPsTestJson, cls).setup_clients()
- cls.client = cls.os_admin.fixed_ips_client
-
- @classmethod
- def resource_setup(cls):
- super(FixedIPsTestJson, cls).resource_setup()
- server = cls.create_test_server(wait_until='ACTIVE')
- server = cls.servers_client.show_server(server['id'])['server']
- cls.ip = None
- for ip_set in server['addresses']:
- for ip in server['addresses'][ip_set]:
- if ip['OS-EXT-IPS:type'] == 'fixed':
- cls.ip = ip['addr']
- break
- if cls.ip:
- break
- if cls.ip is None:
- raise cls.skipException("No fixed ip found for server: %s"
- % server['id'])
-
- @decorators.idempotent_id('16b7d848-2f7c-4709-85a3-2dfb4576cc52')
- def test_list_fixed_ip_details(self):
- """Test getting fixed ip details"""
- fixed_ip = self.client.show_fixed_ip(self.ip)
- self.assertEqual(fixed_ip['fixed_ip']['address'], self.ip)
-
- @decorators.idempotent_id('5485077b-7e46-4cec-b402-91dc3173433b')
- def test_set_reserve(self):
- """Test reserving fixed ip"""
- self.client.reserve_fixed_ip(self.ip, reserve="None")
-
- @decorators.idempotent_id('7476e322-b9ff-4710-bf82-49d51bac6e2e')
- def test_set_unreserve(self):
- """Test unreserving fixed ip"""
- self.client.reserve_fixed_ip(self.ip, unreserve="None")
diff --git a/tempest/api/compute/admin/test_fixed_ips_negative.py b/tempest/api/compute/admin/test_fixed_ips_negative.py
deleted file mode 100644
index 1629faa..0000000
--- a/tempest/api/compute/admin/test_fixed_ips_negative.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright 2013 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.api.compute import base
-from tempest.common import utils
-from tempest import config
-from tempest.lib import decorators
-from tempest.lib import exceptions as lib_exc
-
-CONF = config.CONF
-
-
-class FixedIPsNegativeTestJson(base.BaseV2ComputeAdminTest):
- """Negative tests of fixed ips API"""
-
- @classmethod
- def skip_checks(cls):
- super(FixedIPsNegativeTestJson, cls).skip_checks()
- if CONF.service_available.neutron:
- msg = ("%s skipped as neutron is available" % cls.__name__)
- raise cls.skipException(msg)
- if not utils.get_service_list()['network']:
- raise cls.skipException("network service not enabled.")
-
- @classmethod
- def setup_clients(cls):
- super(FixedIPsNegativeTestJson, cls).setup_clients()
- cls.client = cls.os_admin.fixed_ips_client
- cls.non_admin_client = cls.fixed_ips_client
-
- @classmethod
- def resource_setup(cls):
- super(FixedIPsNegativeTestJson, cls).resource_setup()
- server = cls.create_test_server(wait_until='ACTIVE')
- server = cls.servers_client.show_server(server['id'])['server']
- cls.ip = None
- for ip_set in server['addresses']:
- for ip in server['addresses'][ip_set]:
- if ip['OS-EXT-IPS:type'] == 'fixed':
- cls.ip = ip['addr']
- break
- if cls.ip:
- break
- if cls.ip is None:
- raise cls.skipException("No fixed ip found for server: %s"
- % server['id'])
-
- @decorators.attr(type=['negative'])
- @decorators.idempotent_id('9f17f47d-daad-4adc-986e-12370c93e407')
- def test_list_fixed_ip_details_with_non_admin_user(self):
- """Test listing fixed ip with detail by non-admin user is forbidden"""
- self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.show_fixed_ip, self.ip)
-
- @decorators.attr(type=['negative'])
- @decorators.idempotent_id('ce60042c-fa60-4836-8d43-1c8e3359dc47')
- def test_set_reserve_with_non_admin_user(self):
- """Test reserving fixed ip by non-admin user is forbidden"""
- self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.reserve_fixed_ip,
- self.ip, reserve="None")
-
- @decorators.attr(type=['negative'])
- @decorators.idempotent_id('f1f7a35b-0390-48c5-9803-5f27461439db')
- def test_set_unreserve_with_non_admin_user(self):
- """Test unreserving fixed ip by non-admin user is forbidden"""
- self.assertRaises(lib_exc.Forbidden,
- self.non_admin_client.reserve_fixed_ip,
- self.ip, unreserve="None")
-
- @decorators.attr(type=['negative'])
- @decorators.idempotent_id('f51cf464-7fc5-4352-bc3e-e75cfa2cb717')
- def test_set_reserve_with_invalid_ip(self):
- """Test reserving invalid fixed ip should fail"""
- # NOTE(maurosr): since this exercises the same code snippet, we do it
- # only for reserve action
- # NOTE(eliqiao): in Juno, the exception is NotFound, but in master, we
- # change the error code to BadRequest, both exceptions should be
- # accepted by tempest
- self.assertRaises((lib_exc.NotFound, lib_exc.BadRequest),
- self.client.reserve_fixed_ip,
- "my.invalid.ip", reserve="None")
-
- @decorators.attr(type=['negative'])
- @decorators.idempotent_id('fd26ef50-f135-4232-9d32-281aab3f9176')
- def test_fixed_ip_with_invalid_action(self):
- """Test operating fixed ip with invalid action should fail"""
- self.assertRaises(lib_exc.BadRequest,
- self.client.reserve_fixed_ip,
- self.ip, invalid_action="None")
diff --git a/tempest/api/compute/admin/test_floating_ips_bulk.py b/tempest/api/compute/admin/test_floating_ips_bulk.py
deleted file mode 100644
index 786c7f0..0000000
--- a/tempest/api/compute/admin/test_floating_ips_bulk.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright 2014 NEC Technologies India Ltd.
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import netaddr
-
-from tempest.api.compute import base
-from tempest.common import utils
-from tempest import config
-from tempest.lib.common.utils import test_utils
-from tempest.lib import decorators
-from tempest.lib import exceptions
-
-CONF = config.CONF
-
-
-# TODO(stephenfin): Remove this test class once the nova queens branch goes
-# into extended maintenance mode.
-class FloatingIPsBulkAdminTestJSON(base.BaseV2ComputeAdminTest):
- """Tests Floating IPs Bulk APIs that require admin privileges.
-
- API documentation - http://docs.openstack.org/api/openstack-compute/2/
- content/ext-os-floating-ips-bulk.html
- """
- max_microversion = '2.35'
- depends_on_nova_network = True
-
- @classmethod
- def setup_clients(cls):
- super(FloatingIPsBulkAdminTestJSON, cls).setup_clients()
- cls.client = cls.os_admin.floating_ips_bulk_client
-
- @classmethod
- def resource_setup(cls):
- super(FloatingIPsBulkAdminTestJSON, cls).resource_setup()
- cls.ip_range = CONF.validation.floating_ip_range
- cls.verify_unallocated_floating_ip_range(cls.ip_range)
-
- @classmethod
- def verify_unallocated_floating_ip_range(cls, ip_range):
- # Verify whether configure floating IP range is not already allocated.
- body = cls.client.list_floating_ips_bulk()['floating_ip_info']
- allocated_ips_list = map(lambda x: x['address'], body)
- for ip_addr in netaddr.IPNetwork(ip_range).iter_hosts():
- if str(ip_addr) in allocated_ips_list:
- msg = ("Configured unallocated floating IP range is already "
- "allocated. Configure the correct unallocated range "
- "as 'floating_ip_range'")
- raise exceptions.InvalidConfiguration(msg)
- return
-
- @decorators.idempotent_id('2c8f145f-8012-4cb8-ac7e-95a587f0e4ab')
- @utils.services('network')
- def test_create_list_delete_floating_ips_bulk(self):
- """Creating, listing and deleting the Floating IPs Bulk"""
- pool = 'test_pool'
- # NOTE(GMann): Reserving the IP range but those are not attached
- # anywhere. Using the below mentioned interface which is not ever
- # expected to be used. Clean Up has been done for created IP range
- interface = 'eth0'
- body = (self.client.create_floating_ips_bulk(self.ip_range,
- pool,
- interface)
- ['floating_ips_bulk_create'])
- self.addCleanup(test_utils.call_and_ignore_notfound_exc,
- self.client.delete_floating_ips_bulk, self.ip_range)
- self.assertEqual(self.ip_range, body['ip_range'])
- ips_list = self.client.list_floating_ips_bulk()['floating_ip_info']
- self.assertNotEmpty(ips_list)
- for ip in netaddr.IPNetwork(self.ip_range).iter_hosts():
- self.assertIn(str(ip), map(lambda x: x['address'], ips_list))
- body = (self.client.delete_floating_ips_bulk(self.ip_range)
- ['floating_ips_bulk_delete'])
- self.assertEqual(self.ip_range, body)
diff --git a/tempest/api/compute/admin/test_live_migration.py b/tempest/api/compute/admin/test_live_migration.py
index 19026d3..a02820a 100644
--- a/tempest/api/compute/admin/test_live_migration.py
+++ b/tempest/api/compute/admin/test_live_migration.py
@@ -304,13 +304,17 @@
min_microversion = '2.6'
max_microversion = 'latest'
+ @classmethod
+ def skip_checks(cls):
+ super(LiveMigrationRemoteConsolesV26Test, cls).skip_checks()
+ if not CONF.compute_feature_enabled.serial_console:
+ skip_msg = ("Serial console not supported.")
+ raise cls.skipException(skip_msg)
+ if not compute.is_scheduler_filter_enabled("DifferentHostFilter"):
+ raise cls.skipException("DifferentHostFilter is not available.")
+
@decorators.attr(type='multinode')
@decorators.idempotent_id('6190af80-513e-4f0f-90f2-9714e84955d7')
- @testtools.skipUnless(CONF.compute_feature_enabled.serial_console,
- 'Serial console not supported.')
- @testtools.skipUnless(
- compute.is_scheduler_filter_enabled("DifferentHostFilter"),
- 'DifferentHostFilter is not available.')
def test_live_migration_serial_console(self):
"""Test the live-migration of an instance which has a serial console
diff --git a/tempest/api/compute/admin/test_servers.py b/tempest/api/compute/admin/test_servers.py
index bc00f8c..321078c 100644
--- a/tempest/api/compute/admin/test_servers.py
+++ b/tempest/api/compute/admin/test_servers.py
@@ -25,6 +25,8 @@
class ServersAdminTestJSON(base.BaseV2ComputeAdminTest):
"""Tests Servers API using admin privileges"""
+ create_default_network = True
+
@classmethod
def setup_clients(cls):
super(ServersAdminTestJSON, cls).setup_clients()
diff --git a/tempest/api/compute/admin/test_volume_swap.py b/tempest/api/compute/admin/test_volume_swap.py
index 36148c5..9576b74 100644
--- a/tempest/api/compute/admin/test_volume_swap.py
+++ b/tempest/api/compute/admin/test_volume_swap.py
@@ -13,7 +13,6 @@
import time
from tempest.api.compute import base
-from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
@@ -33,6 +32,8 @@
@classmethod
def skip_checks(cls):
super(TestVolumeSwapBase, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
if not CONF.compute_feature_enabled.swap_volume:
raise cls.skipException("Swapping volumes is not supported.")
@@ -81,7 +82,6 @@
# so it's marked as such.
@decorators.attr(type='slow')
@decorators.idempotent_id('1769f00d-a693-4d67-a631-6a3496773813')
- @utils.services('volume')
def test_volume_swap(self):
"""Test swapping of volume attached to server with admin user
@@ -183,7 +183,6 @@
# multiple computes but that would just side-step the underlying bug.
@decorators.skip_because(bug='1807723',
condition=CONF.compute.min_compute_nodes > 1)
- @utils.services('volume')
def test_volume_swap_with_multiattach(self):
"""Test swapping volume attached to multiple servers
diff --git a/tempest/api/compute/base.py b/tempest/api/compute/base.py
index ce6cd60..4fdc012 100644
--- a/tempest/api/compute/base.py
+++ b/tempest/api/compute/base.py
@@ -51,6 +51,9 @@
super(BaseV2ComputeTest, cls).skip_checks()
if not CONF.service_available.nova:
raise cls.skipException("Nova is not available")
+ if cls.create_default_network and not CONF.service_available.neutron:
+ raise cls.skipException("Neutron is not available")
+
api_version_utils.check_skip_with_microversion(
cls.min_microversion, cls.max_microversion,
CONF.compute.min_microversion, CONF.compute.max_microversion)
@@ -79,7 +82,6 @@
cls.flavors_client = cls.os_primary.flavors_client
cls.compute_images_client = cls.os_primary.compute_images_client
cls.extensions_client = cls.os_primary.extensions_client
- cls.floating_ip_pools_client = cls.os_primary.floating_ip_pools_client
cls.floating_ips_client = cls.os_primary.compute_floating_ips_client
cls.keypairs_client = cls.os_primary.keypairs_client
cls.security_group_rules_client = (
@@ -94,7 +96,6 @@
cls.snapshots_extensions_client =\
cls.os_primary.snapshots_extensions_client
cls.interfaces_client = cls.os_primary.interfaces_client
- cls.fixed_ips_client = cls.os_primary.fixed_ips_client
cls.availability_zone_client = cls.os_primary.availability_zone_client
cls.agents_client = cls.os_primary.agents_client
cls.aggregates_client = cls.os_primary.aggregates_client
@@ -120,35 +121,6 @@
raise lib_exc.InvalidConfiguration(
'Either api_v1 or api_v2 must be True in '
'[image-feature-enabled].')
- cls._check_depends_on_nova_network()
-
- @classmethod
- def _check_depends_on_nova_network(cls):
- # Since nova-network APIs were removed from Nova in the Rocky release,
- # determine, based on the max version from the version document, if
- # the compute API is >Queens and if so, skip tests that rely on
- # nova-network.
- if not getattr(cls, 'depends_on_nova_network', False):
- return
- versions = cls.versions_client.list_versions()['versions']
- # Find the v2.1 version which will tell us our max version for the
- # compute API we're testing against.
- for version in versions:
- if version['id'] == 'v2.1':
- max_version = api_version_request.APIVersionRequest(
- version['version'])
- break
- else:
- LOG.warning(
- 'Unable to determine max v2.1 compute API version: %s',
- versions)
- return
-
- # The max compute API version in Queens is 2.60 so we cap
- # at that version.
- queens = api_version_request.APIVersionRequest('2.60')
- if max_version > queens:
- raise cls.skipException('nova-network is gone')
@classmethod
def resource_setup(cls):
diff --git a/tempest/api/compute/floating_ips/base.py b/tempest/api/compute/floating_ips/base.py
index 262a3c1..d6c302d 100644
--- a/tempest/api/compute/floating_ips/base.py
+++ b/tempest/api/compute/floating_ips/base.py
@@ -41,4 +41,3 @@
def setup_clients(cls):
super(BaseFloatingIPsTest, cls).setup_clients()
cls.client = cls.floating_ips_client
- cls.pools_client = cls.floating_ip_pools_client
diff --git a/tempest/api/compute/floating_ips/test_list_floating_ips.py b/tempest/api/compute/floating_ips/test_list_floating_ips.py
index 6bfee95..fcbea2f 100644
--- a/tempest/api/compute/floating_ips/test_list_floating_ips.py
+++ b/tempest/api/compute/floating_ips/test_list_floating_ips.py
@@ -66,10 +66,3 @@
self.assertEqual(floating_ip_fixed_ip,
body['fixed_ip'])
self.assertEqual(floating_ip_id, body['id'])
-
- @decorators.idempotent_id('df389fc8-56f5-43cc-b290-20eda39854d3')
- def test_list_floating_ip_pools(self):
- """Test listing floating ip pools"""
- floating_ip_pools = self.pools_client.list_floating_ip_pools()
- self.assertNotEmpty(floating_ip_pools['floating_ip_pools'],
- "Expected floating IP Pools. Got zero.")
diff --git a/tempest/api/compute/images/test_image_metadata_negative.py b/tempest/api/compute/images/test_image_metadata_negative.py
index b9806c7..33a59ae 100644
--- a/tempest/api/compute/images/test_image_metadata_negative.py
+++ b/tempest/api/compute/images/test_image_metadata_negative.py
@@ -14,10 +14,13 @@
# under the License.
from tempest.api.compute import base
+from tempest import config
from tempest.lib.common.utils import data_utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
+CONF = config.CONF
+
class ImagesMetadataNegativeTestJSON(base.BaseV2ComputeTest):
"""Negative tests of image metadata
@@ -28,6 +31,13 @@
max_microversion = '2.38'
@classmethod
+ def skip_checks(cls):
+ super(ImagesMetadataNegativeTestJSON, cls).skip_checks()
+ if not CONF.service_available.glance:
+ skip_msg = ("%s skipped as glance is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ @classmethod
def setup_clients(cls):
super(ImagesMetadataNegativeTestJSON, cls).setup_clients()
cls.client = cls.compute_images_client
diff --git a/tempest/api/compute/images/test_images_oneserver.py b/tempest/api/compute/images/test_images_oneserver.py
index 23f8326..2b859da 100644
--- a/tempest/api/compute/images/test_images_oneserver.py
+++ b/tempest/api/compute/images/test_images_oneserver.py
@@ -24,6 +24,8 @@
class ImagesOneServerTestJSON(base.BaseV2ComputeTest):
"""Test server images API"""
+ create_default_network = True
+
@classmethod
def resource_setup(cls):
super(ImagesOneServerTestJSON, cls).resource_setup()
diff --git a/tempest/api/compute/servers/test_server_actions.py b/tempest/api/compute/servers/test_server_actions.py
index 7afd9c2..f853473 100644
--- a/tempest/api/compute/servers/test_server_actions.py
+++ b/tempest/api/compute/servers/test_server_actions.py
@@ -127,29 +127,23 @@
self.assertGreater(new_boot_time, boot_time,
'%s > %s' % (new_boot_time, boot_time))
- def _test_rebuild_server(self):
+ def _test_rebuild_server(self, server_id):
# Get the IPs the server has before rebuilding it
- original_addresses = (self.client.show_server(self.server_id)['server']
+ original_addresses = (self.client.show_server(server_id)['server']
['addresses'])
# The server should be rebuilt using the provided image and data
meta = {'rebuild': 'server'}
new_name = data_utils.rand_name(self.__class__.__name__ + '-server')
password = 'rebuildPassw0rd'
rebuilt_server = self.client.rebuild_server(
- self.server_id,
+ server_id,
self.image_ref_alt,
name=new_name,
metadata=meta,
adminPass=password)['server']
- # If the server was rebuilt on a different image, restore it to the
- # original image once the test ends
- if self.image_ref_alt != self.image_ref:
- self.addCleanup(self._rebuild_server_and_check, self.image_ref,
- rebuilt_server)
-
# Verify the properties in the initial response are correct
- self.assertEqual(self.server_id, rebuilt_server['id'])
+ self.assertEqual(server_id, rebuilt_server['id'])
rebuilt_image_id = rebuilt_server['image']['id']
self.assertTrue(self.image_ref_alt.endswith(rebuilt_image_id))
self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
@@ -221,23 +215,6 @@
self.assertNotEqual('None', parsed_url.hostname)
self.assertIn(parsed_url.scheme, valid_scheme)
- def _rebuild_server_and_check(self, image_ref, server):
- rebuilt_server = (self.client.rebuild_server(server['id'], image_ref)
- ['server'])
- if CONF.validation.run_validation:
- tenant_network = self.get_tenant_network()
- compute.wait_for_ssh_or_ping(
- server, self.os_primary, tenant_network,
- True, self.validation_resources, "SSHABLE", True)
- else:
- waiters.wait_for_server_status(self.client, server['id'],
- 'ACTIVE')
-
- msg = ('Server was not rebuilt to the original image. '
- 'The original image: {0}. The current image: {1}'
- .format(image_ref, rebuilt_server['image']['id']))
- self.assertEqual(image_ref, rebuilt_server['image']['id'], msg)
-
class ServerActionsTestJSON(ServerActionsBase):
@decorators.idempotent_id('6158df09-4b82-4ab3-af6d-29cf36af858d')
@@ -287,7 +264,18 @@
The server should be rebuilt using the provided image and data.
"""
- self._test_rebuild_server()
+ tenant_network = self.get_tenant_network()
+ _, servers = compute.create_test_server(
+ self.os_primary,
+ wait_until='ACTIVE',
+ tenant_network=tenant_network)
+ server = servers[0]
+
+ self.addCleanup(waiters.wait_for_server_termination,
+ self.client, server['id'])
+ self.addCleanup(self.client.delete_server, server['id'])
+
+ self._test_rebuild_server(server_id=server['id'])
@decorators.idempotent_id('1499262a-9328-4eda-9068-db1ac57498d2')
@testtools.skipUnless(CONF.compute_feature_enabled.resize,
@@ -410,21 +398,27 @@
The server in stop state should be rebuilt using the provided
image and remain in SHUTOFF state.
"""
- server = self.client.show_server(self.server_id)['server']
+ tenant_network = self.get_tenant_network()
+ _, servers = compute.create_test_server(
+ self.os_primary,
+ wait_until='ACTIVE',
+ tenant_network=tenant_network)
+ server = servers[0]
+
+ self.addCleanup(waiters.wait_for_server_termination,
+ self.client, server['id'])
+ self.addCleanup(self.client.delete_server, server['id'])
+ server = self.client.show_server(server['id'])['server']
old_image = server['image']['id']
new_image = (self.image_ref_alt
if old_image == self.image_ref else self.image_ref)
- self.client.stop_server(self.server_id)
- waiters.wait_for_server_status(self.client, self.server_id, 'SHUTOFF')
- rebuilt_server = (self.client.rebuild_server(self.server_id, new_image)
+ self.client.stop_server(server['id'])
+ waiters.wait_for_server_status(self.client, server['id'], 'SHUTOFF')
+ rebuilt_server = (self.client.rebuild_server(server['id'], new_image)
['server'])
- # If the server was rebuilt on a different image, restore it to the
- # original image once the test ends
- if self.image_ref_alt != self.image_ref:
- self.addCleanup(self._rebuild_server_and_check, old_image, server)
# Verify the properties in the initial response are correct
- self.assertEqual(self.server_id, rebuilt_server['id'])
+ self.assertEqual(server['id'], rebuilt_server['id'])
rebuilt_image_id = rebuilt_server['image']['id']
self.assertEqual(new_image, rebuilt_image_id)
self.assert_flavor_equal(self.flavor_ref, rebuilt_server['flavor'])
@@ -436,8 +430,6 @@
rebuilt_image_id = server['image']['id']
self.assertEqual(new_image, rebuilt_image_id)
- self.client.start_server(self.server_id)
-
# NOTE(mriedem): Marked as slow because while rebuild and volume-backed is
# common, we don't actually change the image (you can't with volume-backed
# rebuild) so this isn't testing much outside normal rebuild
@@ -451,29 +443,34 @@
The volume should be attached to the instance after rebuild.
"""
# create a new volume and attach it to the server
- volume = self.create_volume()
+ volume = self.create_volume(wait_for_available=False)
+ network = self.get_tenant_network()
+ validation_resources = self.get_test_validation_resources(
+ self.os_primary)
+ _, servers = compute.create_test_server(
+ self.os_primary, tenant_network=network,
+ validatable=True,
+ validation_resources=validation_resources,
+ wait_until='SSHABLE')
+ server = servers[0]
+ self.addCleanup(waiters.wait_for_server_termination,
+ self.client, server['id'])
+ self.addCleanup(self.client.delete_server, server['id'])
- server = self.client.show_server(self.server_id)['server']
+ server = self.client.show_server(server['id'])['server']
+ waiters.wait_for_volume_resource_status(self.volumes_client,
+ volume['id'], 'available')
self.attach_volume(server, volume)
# run general rebuild test
- self._test_rebuild_server()
+ self._test_rebuild_server(server_id=server['id'])
# make sure the volume is attached to the instance after rebuild
vol_after_rebuild = self.volumes_client.show_volume(volume['id'])
vol_after_rebuild = vol_after_rebuild['volume']
self.assertEqual('in-use', vol_after_rebuild['status'])
- self.assertEqual(self.server_id,
+ self.assertEqual(server['id'],
vol_after_rebuild['attachments'][0]['server_id'])
- if CONF.validation.run_validation:
- linux_client = remote_client.RemoteClient(
- self.get_server_ip(server, self.validation_resources),
- self.ssh_alt_user,
- password=None,
- pkey=self.validation_resources['keypair']['private_key'],
- server=server,
- servers_client=self.client)
- linux_client.validate_authentication()
@decorators.idempotent_id('e6c28180-7454-4b59-b188-0257af08a63b')
@decorators.related_bug('1728603')
@@ -810,9 +807,15 @@
min_microversion = '2.47'
+ @classmethod
+ def skip_checks(cls):
+ if not CONF.service_available.glance:
+ skip_msg = ("%s skipped as glance is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+ super(ServersAaction247Test, cls).skip_checks()
+
@testtools.skipUnless(CONF.compute_feature_enabled.snapshot,
'Snapshotting not available, backup not possible.')
- @utils.services('image')
@decorators.idempotent_id('252a4bdd-6366-4dae-9994-8c30aa660f23')
def test_create_backup(self):
server = self.create_test_server(wait_until='ACTIVE')
@@ -831,6 +834,12 @@
volume_min_microversion = '3.68'
@classmethod
+ def skip_checks(cls):
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
+ return super().skip_checks()
+
+ @classmethod
def setup_credentials(cls):
cls.prepare_instance_network()
super(ServerActionsV293TestJSON, cls).setup_credentials()
@@ -838,25 +847,15 @@
@classmethod
def resource_setup(cls):
super(ServerActionsV293TestJSON, cls).resource_setup()
- cls.server_id = cls.recreate_server(None, validatable=True)
+ cls.server_id = cls.recreate_server(None, volume_backed=True,
+ validatable=True)
- @utils.services('volume')
@decorators.idempotent_id('6652dab9-ea24-4c93-ab5a-93d79c3041cf')
def test_rebuild_volume_backed_server(self):
"""Test rebuilding a volume backed server"""
- # We have to create a new server that is volume-backed since the one
- # from setUp is not volume-backed.
- kwargs = {'volume_backed': True,
- 'wait_until': 'ACTIVE'}
- validation_resources = {}
- 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)
- server = self.servers_client.show_server(server['id'])['server']
- self.addCleanup(self.delete_server, server['id'])
+ self.validation_resources = self.get_class_validation_resources(
+ self.os_primary)
+ server = self.servers_client.show_server(self.server_id)['server']
volume_id = server['os-extended-volumes:volumes_attached'][0]['id']
volume_before_rebuild = self.volumes_client.show_volume(volume_id)
image_before_rebuild = (
@@ -872,10 +871,10 @@
# ~/.ssh/ (if allowed).
# 4.Plain username/password auth, if a password was given.
linux_client = remote_client.RemoteClient(
- self.get_server_ip(server, validation_resources),
+ self.get_server_ip(server, self.validation_resources),
self.ssh_user,
password=None,
- pkey=validation_resources['keypair']['private_key'],
+ pkey=self.validation_resources['keypair']['private_key'],
server=server,
servers_client=self.servers_client)
output = linux_client.exec_command('touch test_file')
@@ -925,10 +924,10 @@
# ~/.ssh/ (if allowed).
# 4.Plain username/password auth, if a password was given.
linux_client = remote_client.RemoteClient(
- self.get_server_ip(rebuilt_server, validation_resources),
+ self.get_server_ip(rebuilt_server, self.validation_resources),
self.ssh_alt_user,
password,
- validation_resources['keypair']['private_key'],
+ self.validation_resources['keypair']['private_key'],
server=rebuilt_server,
servers_client=self.servers_client)
linux_client.validate_authentication()
diff --git a/tempest/api/compute/servers/test_server_addresses.py b/tempest/api/compute/servers/test_server_addresses.py
index 5a3f5d0..978a9da 100644
--- a/tempest/api/compute/servers/test_server_addresses.py
+++ b/tempest/api/compute/servers/test_server_addresses.py
@@ -14,7 +14,6 @@
# under the License.
from tempest.api.compute import base
-from tempest.common import utils
from tempest.lib import decorators
@@ -35,7 +34,6 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('6eb718c0-02d9-4d5e-acd1-4e0c269cef39')
- @utils.services('network')
def test_list_server_addresses(self):
"""Test listing server address
@@ -52,7 +50,6 @@
@decorators.attr(type='smoke')
@decorators.idempotent_id('87bbc374-5538-4f64-b673-2b0e4443cc30')
- @utils.services('network')
def test_list_server_addresses_by_network(self):
"""Test listing server addresses filtered by network addresses
diff --git a/tempest/api/compute/servers/test_server_addresses_negative.py b/tempest/api/compute/servers/test_server_addresses_negative.py
index e7444d2..bb21594 100644
--- a/tempest/api/compute/servers/test_server_addresses_negative.py
+++ b/tempest/api/compute/servers/test_server_addresses_negative.py
@@ -14,7 +14,6 @@
# under the License.
from tempest.api.compute import base
-from tempest.common import utils
from tempest.lib import decorators
from tempest.lib import exceptions as lib_exc
@@ -35,7 +34,6 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('02c3f645-2d2e-4417-8525-68c0407d001b')
- @utils.services('network')
def test_list_server_addresses_invalid_server_id(self):
"""List addresses request should fail if server id not in system"""
self.assertRaises(lib_exc.NotFound, self.client.list_addresses,
@@ -43,7 +41,6 @@
@decorators.attr(type=['negative'])
@decorators.idempotent_id('a2ab5144-78c0-4942-a0ed-cc8edccfd9ba')
- @utils.services('network')
def test_list_server_addresses_by_network_neg(self):
"""List addresses by network should fail if network name not valid"""
self.assertRaises(lib_exc.NotFound,
diff --git a/tempest/api/compute/servers/test_virtual_interfaces.py b/tempest/api/compute/servers/test_virtual_interfaces.py
deleted file mode 100644
index b2e02c5..0000000
--- a/tempest/api/compute/servers/test_virtual_interfaces.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2013 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-import netaddr
-import testtools
-
-from tempest.api.compute import base
-from tempest.common import utils
-from tempest import config
-from tempest.lib import decorators
-from tempest.lib import exceptions
-
-CONF = config.CONF
-
-
-# TODO(mriedem): Remove this test class once the nova queens branch goes into
-# extended maintenance mode.
-class VirtualInterfacesTestJSON(base.BaseV2ComputeTest):
- """Test virtual interfaces API with compute microversion less than 2.44"""
-
- max_microversion = '2.43'
-
- depends_on_nova_network = True
-
- create_default_network = True
-
- @classmethod
- def setup_clients(cls):
- super(VirtualInterfacesTestJSON, cls).setup_clients()
- cls.client = cls.servers_client
-
- @classmethod
- def resource_setup(cls):
- super(VirtualInterfacesTestJSON, cls).resource_setup()
- cls.server = cls.create_test_server(wait_until='ACTIVE')
-
- @decorators.idempotent_id('96c4e2ef-5e4d-4d7f-87f5-fed6dca18016')
- @utils.services('network')
- def test_list_virtual_interfaces(self):
- """Test listing virtual interfaces of a server"""
- if CONF.service_available.neutron:
- with testtools.ExpectedException(exceptions.BadRequest):
- self.client.list_virtual_interfaces(self.server['id'])
- else:
- output = self.client.list_virtual_interfaces(self.server['id'])
- virt_ifaces = output['virtual_interfaces']
- self.assertNotEmpty(virt_ifaces,
- 'Expected virtual interfaces, got 0 '
- 'interfaces.')
- for virt_iface in virt_ifaces:
- mac_address = virt_iface['mac_address']
- self.assertTrue(netaddr.valid_mac(mac_address),
- "Invalid mac address detected. mac address: %s"
- % mac_address)
diff --git a/tempest/api/compute/servers/test_virtual_interfaces_negative.py b/tempest/api/compute/servers/test_virtual_interfaces_negative.py
deleted file mode 100644
index 5667281..0000000
--- a/tempest/api/compute/servers/test_virtual_interfaces_negative.py
+++ /dev/null
@@ -1,50 +0,0 @@
-# Copyright 2013 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.api.compute import base
-from tempest.common import utils
-from tempest.lib.common.utils import data_utils
-from tempest.lib import decorators
-from tempest.lib import exceptions as lib_exc
-
-
-# TODO(mriedem): Remove this test class once the nova queens branch goes into
-# extended maintenance mode.
-class VirtualInterfacesNegativeTestJSON(base.BaseV2ComputeTest):
- """Negative tests of virtual interfaces API
-
- Negative tests of virtual interfaces API for compute microversion less
- than 2.44.
- """
-
- max_microversion = '2.43'
-
- depends_on_nova_network = True
-
- @classmethod
- def setup_credentials(cls):
- # For this test no network resources are needed
- cls.set_network_resources()
- super(VirtualInterfacesNegativeTestJSON, cls).setup_credentials()
-
- @decorators.attr(type=['negative'])
- @decorators.idempotent_id('64ebd03c-1089-4306-93fa-60f5eb5c803c')
- @utils.services('network')
- def test_list_virtual_interfaces_invalid_server_id(self):
- """Test listing virtual interfaces of an invalid server should fail"""
- invalid_server_id = data_utils.rand_uuid()
- self.assertRaises(lib_exc.NotFound,
- self.servers_client.list_virtual_interfaces,
- invalid_server_id)
diff --git a/tempest/api/compute/test_tenant_networks.py b/tempest/api/compute/test_tenant_networks.py
index 17f4b80..da28b9b 100644
--- a/tempest/api/compute/test_tenant_networks.py
+++ b/tempest/api/compute/test_tenant_networks.py
@@ -14,8 +14,11 @@
from tempest.api.compute import base
from tempest.common import utils
+from tempest import config
from tempest.lib import decorators
+CONF = config.CONF
+
class ComputeTenantNetworksTest(base.BaseV2ComputeTest):
"""Test compute tenant networks API with microversion less than 2.36"""
@@ -23,6 +26,14 @@
max_microversion = '2.35'
@classmethod
+ def skip_checks(cls):
+ super(ComputeTenantNetworksTest, cls).skip_checks()
+ if not CONF.service_available.neutron:
+ skip_msg = (
+ "%s skipped as Neutron is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ @classmethod
def resource_setup(cls):
super(ComputeTenantNetworksTest, cls).resource_setup()
cls.client = cls.os_primary.tenant_networks_client
diff --git a/tempest/api/identity/v3/test_users.py b/tempest/api/identity/v3/test_users.py
index dc6dd4a..b95bd75 100644
--- a/tempest/api/identity/v3/test_users.py
+++ b/tempest/api/identity/v3/test_users.py
@@ -31,6 +31,12 @@
"""Test identity user password"""
@classmethod
+ def skip_checks(cls):
+ super(IdentityV3UsersTest, cls).skip_checks()
+ if not CONF.identity_feature_enabled.security_compliance:
+ raise cls.skipException("Security compliance not available.")
+
+ @classmethod
def resource_setup(cls):
super(IdentityV3UsersTest, cls).resource_setup()
cls.creds = cls.os_primary.credentials
@@ -77,8 +83,6 @@
time.sleep(1)
self.non_admin_users_client.auth_provider.set_auth()
- @testtools.skipUnless(CONF.identity_feature_enabled.security_compliance,
- 'Security compliance not available.')
@decorators.idempotent_id('ad71bd23-12ad-426b-bb8b-195d2b635f27')
@testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source,
'Skipped because environment has an '
@@ -107,8 +111,6 @@
user_id=self.user_id,
password=old_pass)
- @testtools.skipUnless(CONF.identity_feature_enabled.security_compliance,
- 'Security compliance not available.')
@decorators.idempotent_id('941784ee-5342-4571-959b-b80dd2cea516')
@testtools.skipIf(CONF.identity_feature_enabled.immutable_user_source,
'Skipped because environment has an '
@@ -142,8 +144,6 @@
# A different password can be set
self._update_password(original_password=new_pass1, password=new_pass2)
- @testtools.skipUnless(CONF.identity_feature_enabled.security_compliance,
- 'Security compliance not available.')
@decorators.idempotent_id('a7ad8bbf-2cff-4520-8c1d-96332e151658')
def test_user_account_lockout(self):
"""Test locking out user account after failure attempts"""
diff --git a/tempest/api/image/v2/admin/test_image_task.py b/tempest/api/image/v2/admin/test_image_task.py
new file mode 100644
index 0000000..9439e91
--- /dev/null
+++ b/tempest/api/image/v2/admin/test_image_task.py
@@ -0,0 +1,140 @@
+# Copyright 2023 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.api.image import base
+from tempest.common import waiters
+from tempest import config
+from tempest.lib.common.utils import data_utils
+from tempest.lib import decorators
+
+CONF = config.CONF
+
+
+class ImageTaskCreate(base.BaseV2ImageAdminTest):
+ """Test image task operations"""
+
+ @classmethod
+ def skip_checks(cls):
+ # TODO(msava): Add additional skipcheck with task conversion_format and
+ # glance ceph backend then will be available
+ # in tempest image service config options.
+ super(ImageTaskCreate, cls).skip_checks()
+ if not CONF.image.http_image:
+ skip_msg = ("%s skipped as http_image is not available " %
+ cls.__name__)
+ raise cls.skipException(skip_msg)
+
+ @classmethod
+ def resource_setup(cls):
+ super(ImageTaskCreate, cls).resource_setup()
+
+ @staticmethod
+ def _prepare_image_tasks_param(type="import",
+ disk_format=['qcow2'],
+ image_from_format=['qcow2'],
+ image_location=CONF.image.http_image):
+ # TODO(msava): Need to add additional disk formats then
+ # task conversion_format and glance Ceph backend will be
+ # available in image service options
+ """Prepare image task params.
+ By default, will create task type 'import'
+
+ The same index is used for both params and creates a task
+ :param type Type of the task.
+ :param disk_format: Each format in the list is a different task.
+ :param image_from_format: Each format in the list is a different task.
+ :param image_location Location to import image from.
+ :return: A list with all task.
+ """
+ i = 0
+ tasks = list()
+ while i < len(disk_format):
+ image_name = data_utils.rand_name("task_image")
+ image_property = {"container_format": "bare",
+ "disk_format": disk_format[0],
+ "visibility": "public",
+ "name": image_name
+ }
+ task = {
+ "type": type,
+ "input": {
+ "image_properties": image_property,
+ "import_from_format": image_from_format[0],
+ "import_from": image_location
+ }
+ }
+ tasks.append(task)
+ i += 1
+ return tasks
+
+ def _verify_disk_format(self, task_body):
+ expected_disk_format = \
+ task_body['input']['image_properties']['disk_format']
+ image_id = task_body['result']['image_id']
+ observed_disk_format = self.admin_client.show_image(
+ image_id)['disk_format']
+ # If glance backend storage is Ceph glance will convert
+ # image to raw format.
+ # TODO(msava): Need to change next lines once task conversion_format
+ # and glance ceph backend will be available in image service options
+ if observed_disk_format == 'raw':
+ return
+ self.assertEqual(observed_disk_format, expected_disk_format,
+ message="Expected disk format not match ")
+
+ @decorators.skip_because(bug='2030527')
+ @decorators.idempotent_id('669d5387-0340-4abf-b62d-7cc89f539c8c')
+ def test_image_tasks_create(self):
+ """Test task type 'import' image """
+
+ # Prepare params for task type 'import'
+ tasks = self._prepare_image_tasks_param()
+
+ # Create task type 'import'
+ body = self.os_admin.tasks_client.create_task(**tasks[0])
+ task_id = body['id']
+ task_body = waiters.wait_for_tasks_status(self.os_admin.tasks_client,
+ task_id, 'success')
+ self.addCleanup(self.admin_client.delete_image,
+ task_body['result']['image_id'])
+ task_image_id = task_body['result']['image_id']
+ waiters.wait_for_image_status(self.client, task_image_id, 'active')
+ self._verify_disk_format(task_body)
+
+ # Verify disk format
+ image_body = self.client.show_image(task_image_id)
+ task_disk_format = \
+ task_body['input']['image_properties']['disk_format']
+ image_disk_format = image_body['disk_format']
+ self.assertEqual(
+ image_disk_format, task_disk_format,
+ message="Image Disc format %s not match to expected %s"
+ % (image_disk_format, task_disk_format))
+
+ @decorators.idempotent_id("ad6450c6-7060-4ee7-a2d1-41c2604b446c")
+ @decorators.attr(type=['negative'])
+ def test_task_create_fake_image_location(self):
+ http_fake_url = ''.join(
+ ["http://", data_utils.rand_name('dummy-img-file'), ".qcow2"])
+ task = self._prepare_image_tasks_param(
+ image_from_format=['qcow2'],
+ disk_format=['qcow2'],
+ image_location=http_fake_url)
+ body = self.os_admin.tasks_client.create_task(**task[0])
+ task_observed = \
+ waiters.wait_for_tasks_status(self.os_admin.tasks_client,
+ body['id'], 'failure')
+ task_observed = task_observed['status']
+ self.assertEqual(task_observed, 'failure')
diff --git a/tempest/api/network/test_service_providers.py b/tempest/api/network/test_service_providers.py
index 5af5244..e203a2c 100644
--- a/tempest/api/network/test_service_providers.py
+++ b/tempest/api/network/test_service_providers.py
@@ -10,8 +10,6 @@
# License for the specific language governing permissions and limitations
# under the License.
-import testtools
-
from tempest.api.network import base
from tempest.common import utils
from tempest.lib import decorators
@@ -20,10 +18,14 @@
class ServiceProvidersTest(base.BaseNetworkTest):
"""Test network service providers"""
+ @classmethod
+ def skip_checks(cls):
+ super(ServiceProvidersTest, cls).skip_checks()
+ if not utils.is_extension_enabled('service-type', 'network'):
+ skip_msg = ("service-type extension not enabled.")
+ raise cls.skipException(skip_msg)
+
@decorators.idempotent_id('2cbbeea9-f010-40f6-8df5-4eaa0c918ea6')
- @testtools.skipUnless(
- utils.is_extension_enabled('service-type', 'network'),
- 'service-type extension not enabled.')
def test_service_providers_list(self):
"""Test listing network service providers"""
body = self.service_providers_client.list_service_providers()
diff --git a/tempest/api/volume/admin/test_encrypted_volumes_extend.py b/tempest/api/volume/admin/test_encrypted_volumes_extend.py
index e85a00d..4506389 100644
--- a/tempest/api/volume/admin/test_encrypted_volumes_extend.py
+++ b/tempest/api/volume/admin/test_encrypted_volumes_extend.py
@@ -14,7 +14,6 @@
from tempest.api.volume import base
from tempest.api.volume import test_volumes_extend as extend
-from tempest.common import utils
from tempest import config
from tempest.lib import decorators
@@ -25,23 +24,25 @@
base.BaseVolumeAdminTest):
"""Tests extending the size of an attached encrypted volume."""
+ @classmethod
+ def skip_checks(cls):
+ super(EncryptedVolumesExtendAttachedTest, cls).skip_checks()
+ if not CONF.service_available.nova:
+ skip_msg = ("%s skipped as Nova is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+ if not CONF.volume_feature_enabled.extend_attached_encrypted_volume:
+ raise cls.skipException(
+ "Attached encrypted volume extend is disabled.")
+
@decorators.idempotent_id('e93243ec-7c37-4b5b-a099-ebf052c13216')
- @testtools.skipUnless(
- CONF.volume_feature_enabled.extend_attached_encrypted_volume,
- "Attached encrypted volume extend is disabled.")
- @utils.services('compute')
def test_extend_attached_encrypted_volume_luksv1(self):
"""LUKs v1 decrypts and extends through libvirt."""
volume = self.create_encrypted_volume(encryption_provider="luks")
self._test_extend_attached_volume(volume)
@decorators.idempotent_id('381a2a3a-b2f4-4631-a910-720881f2cc2f')
- @testtools.skipUnless(
- CONF.volume_feature_enabled.extend_attached_encrypted_volume,
- "Attached encrypted volume extend is disabled.")
@testtools.skipIf(CONF.volume.storage_protocol == 'ceph',
'Ceph only supports LUKSv2 if doing host attach.')
- @utils.services('compute')
def test_extend_attached_encrypted_volume_luksv2(self):
"""LUKs v2 decrypts and extends through os-brick."""
volume = self.create_encrypted_volume(encryption_provider="luks2")
diff --git a/tempest/api/volume/base.py b/tempest/api/volume/base.py
index a31390a..ad8f573 100644
--- a/tempest/api/volume/base.py
+++ b/tempest/api/volume/base.py
@@ -42,6 +42,10 @@
if not CONF.service_available.cinder:
skip_msg = ("%s skipped as Cinder is not available" % cls.__name__)
raise cls.skipException(skip_msg)
+ if cls.create_default_network and not CONF.service_available.neutron:
+ skip_msg = (
+ "%s skipped as Neutron is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
api_version_utils.check_skip_with_microversion(
cls.volume_min_microversion, cls.volume_max_microversion,
diff --git a/tempest/api/volume/test_volumes_backup.py b/tempest/api/volume/test_volumes_backup.py
index 85e4bb2..89ff497 100644
--- a/tempest/api/volume/test_volumes_backup.py
+++ b/tempest/api/volume/test_volumes_backup.py
@@ -116,7 +116,7 @@
is "available" or "in-use".
"""
# Create a server
- volume = self.create_volume()
+ volume = self.create_volume(wait_until=False)
self.addCleanup(self.delete_volume, self.volumes_client, volume['id'])
validation_resources = self.get_test_validation_resources(
self.os_primary)
@@ -124,6 +124,8 @@
validation_resources=validation_resources,
validatable=True)
# Attach volume to instance
+ waiters.wait_for_volume_resource_status(self.volumes_client,
+ volume['id'], 'available')
self.attach_volume(server['id'], volume['id'])
# Create backup using force flag
backup_name = data_utils.rand_name(
diff --git a/tempest/api/volume/test_volumes_extend.py b/tempest/api/volume/test_volumes_extend.py
index c5c94e1..c766db8 100644
--- a/tempest/api/volume/test_volumes_extend.py
+++ b/tempest/api/volume/test_volumes_extend.py
@@ -18,7 +18,6 @@
import testtools
from tempest.api.volume import base
-from tempest.common import utils
from tempest.common import waiters
from tempest import config
from tempest.lib import decorators
@@ -181,10 +180,16 @@
class VolumesExtendAttachedTest(BaseVolumesExtendAttachedTest):
+ @classmethod
+ def skip_checks(cls):
+ super(VolumesExtendAttachedTest, cls).skip_checks()
+ if not CONF.service_available.nova:
+ skip_msg = ("%s skipped as Nova is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+ if not CONF.volume_feature_enabled.extend_attached_volume:
+ raise cls.skipException("Attached volume extend is disabled.")
+
@decorators.idempotent_id('301f5a30-1c6f-4ea0-be1a-91fd28d44354')
- @testtools.skipUnless(CONF.volume_feature_enabled.extend_attached_volume,
- "Attached volume extend is disabled.")
- @utils.services('compute')
def test_extend_attached_volume(self):
volume = self.create_volume()
self._test_extend_attached_volume(volume)
diff --git a/tempest/clients.py b/tempest/clients.py
index 1aa34d0..b640237 100644
--- a/tempest/clients.py
+++ b/tempest/clients.py
@@ -97,6 +97,7 @@
self.image_v2.NamespacePropertiesClient()
self.namespace_tags_client = self.image_v2.NamespaceTagsClient()
self.image_versions_client = self.image_v2.VersionsClient()
+ self.tasks_client = self.image_v2.TaskClient()
# 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
@@ -124,15 +125,12 @@
self.quota_classes_client = self.compute.QuotaClassesClient()
self.flavors_client = self.compute.FlavorsClient()
self.extensions_client = self.compute.ExtensionsClient()
- self.floating_ip_pools_client = self.compute.FloatingIPPoolsClient()
- self.floating_ips_bulk_client = self.compute.FloatingIPsBulkClient()
self.compute_floating_ips_client = self.compute.FloatingIPsClient()
self.compute_security_group_rules_client = (
self.compute.SecurityGroupRulesClient())
self.compute_security_groups_client = (
self.compute.SecurityGroupsClient())
self.interfaces_client = self.compute.InterfacesClient()
- self.fixed_ips_client = self.compute.FixedIPsClient()
self.availability_zone_client = self.compute.AvailabilityZoneClient()
self.aggregates_client = self.compute.AggregatesClient()
self.services_client = self.compute.ServicesClient()
diff --git a/tempest/common/utils/linux/remote_client.py b/tempest/common/utils/linux/remote_client.py
index 4fdf6a4..0d93430 100644
--- a/tempest/common/utils/linux/remote_client.py
+++ b/tempest/common/utils/linux/remote_client.py
@@ -183,7 +183,7 @@
self.exec_command('sudo umount %s' % mount_path)
def make_fs(self, dev_name, fs='ext4'):
- cmd_mkfs = 'sudo mke2fs -t %s /dev/%s' % (fs, dev_name)
+ cmd_mkfs = 'sudo mkfs -t %s /dev/%s' % (fs, dev_name)
try:
self.exec_command(cmd_mkfs)
except tempest.lib.exceptions.SSHExecCommandFailed:
diff --git a/tempest/common/waiters.py b/tempest/common/waiters.py
index d88bc05..291f201 100644
--- a/tempest/common/waiters.py
+++ b/tempest/common/waiters.py
@@ -224,6 +224,24 @@
raise lib_exc.TimeoutException(message)
+def wait_for_tasks_status(client, task_id, status):
+ start = int(time.time())
+ while int(time.time()) - start < client.build_timeout:
+ task = client.show_tasks(task_id)
+ if task['status'] == status:
+ return task
+ time.sleep(client.build_interval)
+ message = ('Task %(task_id)s tasks: '
+ 'failed to reach %(status)s state within the required '
+ 'time (%(timeout)s s).' % {'task_id': task_id,
+ 'status': status,
+ 'timeout': client.build_timeout})
+ caller = test_utils.find_test_caller()
+ if caller:
+ message = '(%s) %s' % (caller, message)
+ raise lib_exc.TimeoutException(message)
+
+
def wait_for_image_imported_to_stores(client, image_id, stores=None):
"""Waits for an image to be imported to all requested stores.
diff --git a/tempest/lib/api_schema/response/compute/v2_1/fixed_ips.py b/tempest/lib/api_schema/response/compute/v2_1/fixed_ips.py
deleted file mode 100644
index a653213..0000000
--- a/tempest/lib/api_schema/response/compute/v2_1/fixed_ips.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2014 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.lib.api_schema.response.compute.v2_1 import parameter_types
-
-get_fixed_ip = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'fixed_ip': {
- 'type': 'object',
- 'properties': {
- 'address': parameter_types.ip_address,
- 'cidr': {'type': 'string'},
- 'host': {'type': 'string'},
- 'hostname': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['address', 'cidr', 'host', 'hostname']
- }
- },
- 'additionalProperties': False,
- 'required': ['fixed_ip']
- }
-}
-
-reserve_unreserve_fixed_ip = {
- 'status_code': [202]
-}
diff --git a/tempest/lib/api_schema/response/compute/v2_1/floating_ips.py b/tempest/lib/api_schema/response/compute/v2_1/floating_ips.py
index 0c66590..274540c 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/floating_ips.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/floating_ips.py
@@ -58,91 +58,6 @@
}
}
-list_floating_ip_pools = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'floating_ip_pools': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'name': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['name'],
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['floating_ip_pools'],
- }
-}
-
add_remove_floating_ip = {
'status_code': [202]
}
-
-create_floating_ips_bulk = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'floating_ips_bulk_create': {
- 'type': 'object',
- 'properties': {
- 'interface': {'type': ['string', 'null']},
- 'ip_range': {'type': 'string'},
- 'pool': {'type': ['string', 'null']},
- },
- 'additionalProperties': False,
- 'required': ['interface', 'ip_range', 'pool'],
- }
- },
- 'additionalProperties': False,
- 'required': ['floating_ips_bulk_create'],
- }
-}
-
-delete_floating_ips_bulk = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'floating_ips_bulk_delete': {'type': 'string'}
- },
- 'additionalProperties': False,
- 'required': ['floating_ips_bulk_delete'],
- }
-}
-
-list_floating_ips_bulk = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'floating_ip_info': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'address': parameter_types.ip_address,
- 'instance_uuid': {'type': ['string', 'null']},
- 'interface': {'type': ['string', 'null']},
- 'pool': {'type': ['string', 'null']},
- 'project_id': {'type': ['string', 'null']},
- 'fixed_ip': parameter_types.ip_address
- },
- 'additionalProperties': False,
- # NOTE: fixed_ip is introduced after JUNO release,
- # So it is not defined as 'required'.
- 'required': ['address', 'instance_uuid', 'interface',
- 'pool', 'project_id'],
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['floating_ip_info'],
- }
-}
diff --git a/tempest/lib/api_schema/response/compute/v2_1/servers.py b/tempest/lib/api_schema/response/compute/v2_1/servers.py
index bd42afd..14e2d3b 100644
--- a/tempest/lib/api_schema/response/compute/v2_1/servers.py
+++ b/tempest/lib/api_schema/response/compute/v2_1/servers.py
@@ -250,33 +250,6 @@
rescue_server_with_admin_pass['response_body'].update(
{'required': ['adminPass']})
-
-list_virtual_interfaces = {
- 'status_code': [200],
- 'response_body': {
- 'type': 'object',
- 'properties': {
- 'virtual_interfaces': {
- 'type': 'array',
- 'items': {
- 'type': 'object',
- 'properties': {
- 'id': {'type': 'string'},
- 'mac_address': parameter_types.mac_address,
- 'OS-EXT-VIF-NET:net_id': {'type': 'string'}
- },
- 'additionalProperties': False,
- # 'OS-EXT-VIF-NET:net_id' is API extension So it is
- # not defined as 'required'
- 'required': ['id', 'mac_address']
- }
- }
- },
- 'additionalProperties': False,
- 'required': ['virtual_interfaces']
- }
-}
-
common_attach_volume_info = {
'type': 'object',
'properties': {
diff --git a/tempest/lib/services/compute/__init__.py b/tempest/lib/services/compute/__init__.py
index da800af..10ec9be 100644
--- a/tempest/lib/services/compute/__init__.py
+++ b/tempest/lib/services/compute/__init__.py
@@ -24,12 +24,7 @@
CertificatesClient
from tempest.lib.services.compute.extensions_client import \
ExtensionsClient
-from tempest.lib.services.compute.fixed_ips_client import FixedIPsClient
from tempest.lib.services.compute.flavors_client import FlavorsClient
-from tempest.lib.services.compute.floating_ip_pools_client import \
- FloatingIPPoolsClient
-from tempest.lib.services.compute.floating_ips_bulk_client import \
- FloatingIPsBulkClient
from tempest.lib.services.compute.floating_ips_client import \
FloatingIPsClient
from tempest.lib.services.compute.hosts_client import HostsClient
@@ -69,10 +64,9 @@
__all__ = ['AgentsClient', 'AggregatesClient', 'AssistedVolumeSnapshotsClient',
'AvailabilityZoneClient', 'BaremetalNodesClient',
- 'CertificatesClient', 'ExtensionsClient', 'FixedIPsClient',
- 'FlavorsClient', 'FloatingIPPoolsClient',
- 'FloatingIPsBulkClient', 'FloatingIPsClient', 'HostsClient',
- 'HypervisorClient', 'ImagesClient', 'InstanceUsagesAuditLogClient',
+ 'CertificatesClient', 'ExtensionsClient', 'FlavorsClient',
+ 'FloatingIPsClient', 'HostsClient', 'HypervisorClient',
+ 'ImagesClient', 'InstanceUsagesAuditLogClient',
'InterfacesClient', 'KeyPairsClient', 'LimitsClient',
'MigrationsClient', 'NetworksClient', 'QuotaClassesClient',
'QuotasClient', 'SecurityGroupDefaultRulesClient',
diff --git a/tempest/lib/services/compute/fixed_ips_client.py b/tempest/lib/services/compute/fixed_ips_client.py
deleted file mode 100644
index 098c856..0000000
--- a/tempest/lib/services/compute/fixed_ips_client.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2013 IBM Corp
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_serialization import jsonutils as json
-
-from tempest.lib.api_schema.response.compute.v2_1 import fixed_ips as schema
-from tempest.lib.common import rest_client
-from tempest.lib.services.compute import base_compute_client
-
-
-class FixedIPsClient(base_compute_client.BaseComputeClient):
-
- def show_fixed_ip(self, fixed_ip):
- url = "os-fixed-ips/%s" % fixed_ip
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.get_fixed_ip, resp, body)
- return rest_client.ResponseBody(resp, body)
-
- def reserve_fixed_ip(self, fixed_ip, **kwargs):
- """Reserve/Unreserve a fixed IP.
-
- For a full list of available parameters, please refer to the official
- API reference:
- https://docs.openstack.org/api-ref/compute/#reserve-or-release-a-fixed-ip
- """
- url = "os-fixed-ips/%s/action" % fixed_ip
- resp, body = self.post(url, json.dumps(kwargs))
- self.validate_response(schema.reserve_unreserve_fixed_ip, resp, body)
- return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/compute/floating_ip_pools_client.py b/tempest/lib/services/compute/floating_ip_pools_client.py
deleted file mode 100644
index aa065b8..0000000
--- a/tempest/lib/services/compute/floating_ip_pools_client.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from urllib import parse as urllib
-
-from oslo_serialization import jsonutils as json
-
-from tempest.lib.api_schema.response.compute.v2_1 import floating_ips as schema
-from tempest.lib.common import rest_client
-from tempest.lib.services.compute import base_compute_client
-
-
-class FloatingIPPoolsClient(base_compute_client.BaseComputeClient):
-
- def list_floating_ip_pools(self, params=None):
- """Gets all floating IP Pools list."""
- url = 'os-floating-ip-pools'
- if params:
- url += '?%s' % urllib.urlencode(params)
-
- resp, body = self.get(url)
- body = json.loads(body)
- self.validate_response(schema.list_floating_ip_pools, resp, body)
- return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/compute/floating_ips_bulk_client.py b/tempest/lib/services/compute/floating_ips_bulk_client.py
deleted file mode 100644
index 5f06009..0000000
--- a/tempest/lib/services/compute/floating_ips_bulk_client.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2012 OpenStack Foundation
-# All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from oslo_serialization import jsonutils as json
-
-from tempest.lib.api_schema.response.compute.v2_1 import floating_ips as schema
-from tempest.lib.common import rest_client
-from tempest.lib.services.compute import base_compute_client
-
-
-class FloatingIPsBulkClient(base_compute_client.BaseComputeClient):
-
- def create_floating_ips_bulk(self, ip_range, pool, interface):
- """Allocate floating IPs in bulk."""
- post_body = {
- 'ip_range': ip_range,
- 'pool': pool,
- 'interface': interface
- }
- post_body = json.dumps({'floating_ips_bulk_create': post_body})
- resp, body = self.post('os-floating-ips-bulk', post_body)
- body = json.loads(body)
- self.validate_response(schema.create_floating_ips_bulk, resp, body)
- return rest_client.ResponseBody(resp, body)
-
- def list_floating_ips_bulk(self):
- """Gets all floating IPs in bulk."""
- resp, body = self.get('os-floating-ips-bulk')
- body = json.loads(body)
- self.validate_response(schema.list_floating_ips_bulk, resp, body)
- return rest_client.ResponseBody(resp, body)
-
- def delete_floating_ips_bulk(self, ip_range):
- """Deletes the provided floating IPs in bulk."""
- post_body = json.dumps({'ip_range': ip_range})
- resp, body = self.put('os-floating-ips-bulk/delete', post_body)
- body = json.loads(body)
- self.validate_response(schema.delete_floating_ips_bulk, resp, body)
- return rest_client.ResponseBody(resp, body)
diff --git a/tempest/lib/services/compute/servers_client.py b/tempest/lib/services/compute/servers_client.py
index d2bdb6e..7e3b99f 100644
--- a/tempest/lib/services/compute/servers_client.py
+++ b/tempest/lib/services/compute/servers_client.py
@@ -676,14 +676,6 @@
self.validate_response(schema.get_remote_consoles, resp, body)
return rest_client.ResponseBody(resp, body)
- def list_virtual_interfaces(self, server_id):
- """List the virtual interfaces used in an instance."""
- resp, body = self.get('/'.join(['servers', server_id,
- 'os-virtual-interfaces']))
- body = json.loads(body)
- self.validate_response(schema.list_virtual_interfaces, resp, body)
- return rest_client.ResponseBody(resp, body)
-
def rescue_server(self, server_id, **kwargs):
"""Rescue the provided server.
diff --git a/tempest/lib/services/image/v2/__init__.py b/tempest/lib/services/image/v2/__init__.py
index a2f5bdc..5e303e3 100644
--- a/tempest/lib/services/image/v2/__init__.py
+++ b/tempest/lib/services/image/v2/__init__.py
@@ -27,9 +27,11 @@
from tempest.lib.services.image.v2.resource_types_client import \
ResourceTypesClient
from tempest.lib.services.image.v2.schemas_client import SchemasClient
+from tempest.lib.services.image.v2.tasks_client import TaskClient
from tempest.lib.services.image.v2.versions_client import VersionsClient
+
__all__ = ['ImageMembersClient', 'ImagesClient', 'ImageCacheClient',
'NamespaceObjectsClient', 'NamespacePropertiesClient',
'NamespaceTagsClient', 'NamespacesClient', 'ResourceTypesClient',
- 'SchemasClient', 'VersionsClient']
+ 'SchemasClient', 'TaskClient', 'VersionsClient']
diff --git a/tempest/lib/services/image/v2/tasks_client.py b/tempest/lib/services/image/v2/tasks_client.py
new file mode 100644
index 0000000..2cb33eb
--- /dev/null
+++ b/tempest/lib/services/image/v2/tasks_client.py
@@ -0,0 +1,70 @@
+# Copyright 2023 Red Hat, Inc.
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+
+from urllib import parse as urllib
+
+from oslo_serialization import jsonutils as json
+
+from tempest.lib.common import rest_client
+
+CHUNKSIZE = 1024 * 64 # 64kB
+
+
+class TaskClient(rest_client.RestClient):
+ api_version = "v2"
+
+ def create_task(self, **kwargs):
+ """Create a task.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/image/v2/#create-task
+ """
+ data = json.dumps(kwargs)
+ resp, body = self.post('tasks', data)
+ self.expected_success(201, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def list_tasks(self, **kwargs):
+ """List tasks.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://developer.openstack.org/api-ref/image/v2/#list-tasks
+ """
+ url = 'tasks'
+
+ if kwargs:
+ url += '?%s' % urllib.urlencode(kwargs)
+
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
+
+ def show_tasks(self, task_id):
+ """Show task details.
+
+ For a full list of available parameters, please refer to the official
+ API reference:
+ https://docs.openstack.org/api-ref/image/v2/#show-task-details
+ """
+ url = 'tasks/%s' % task_id
+ resp, body = self.get(url)
+ self.expected_success(200, resp.status)
+ body = json.loads(body)
+ return rest_client.ResponseBody(resp, body)
diff --git a/tempest/scenario/manager.py b/tempest/scenario/manager.py
index 4d35bbb..1469bcf 100644
--- a/tempest/scenario/manager.py
+++ b/tempest/scenario/manager.py
@@ -1129,7 +1129,7 @@
def create_timestamp(self, ip_address, dev_name=None, mount_path='/mnt',
private_key=None, server=None, username=None,
- fs='ext4'):
+ fs='vfat'):
"""Creates timestamp
This wrapper utility does ssh, creates timestamp and returns the
diff --git a/tempest/scenario/test_minimum_basic.py b/tempest/scenario/test_minimum_basic.py
index 5513f4d..6372c6b 100644
--- a/tempest/scenario/test_minimum_basic.py
+++ b/tempest/scenario/test_minimum_basic.py
@@ -38,6 +38,12 @@
* check command outputs
"""
+ @classmethod
+ def skip_checks(cls):
+ super(TestMinimumBasicScenario, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
+
def nova_show(self, server):
got_server = (self.servers_client.show_server(server['id'])
['server'])
diff --git a/tempest/scenario/test_server_advanced_ops.py b/tempest/scenario/test_server_advanced_ops.py
index 990b325..1c2246d 100644
--- a/tempest/scenario/test_server_advanced_ops.py
+++ b/tempest/scenario/test_server_advanced_ops.py
@@ -14,7 +14,6 @@
# under the License.
from oslo_log import log as logging
-import testtools
from tempest.common import utils
from tempest.common import waiters
@@ -36,14 +35,21 @@
"""
@classmethod
+ def skip_checks(cls):
+ super(TestServerAdvancedOps, cls).skip_checks()
+ if not CONF.service_available.nova:
+ skip_msg = ("%s skipped as Nova is not available" % cls.__name__)
+ raise cls.skipException(skip_msg)
+ if not CONF.compute_feature_enabled.suspend:
+ raise cls.skipException("Suspend is not available.")
+
+ @classmethod
def setup_credentials(cls):
cls.set_network_resources(network=True, subnet=True)
super(TestServerAdvancedOps, cls).setup_credentials()
@decorators.attr(type='slow')
@decorators.idempotent_id('949da7d5-72c8-4808-8802-e3d70df98e2c')
- @testtools.skipUnless(CONF.compute_feature_enabled.suspend,
- 'Suspend is not available.')
@utils.services('compute')
def test_server_sequence_suspend_resume(self):
# We create an instance for use in this test
diff --git a/tempest/scenario/test_server_volume_attachment.py b/tempest/scenario/test_server_volume_attachment.py
index 1d0d0d0..076b835 100644
--- a/tempest/scenario/test_server_volume_attachment.py
+++ b/tempest/scenario/test_server_volume_attachment.py
@@ -26,6 +26,13 @@
class BaseAttachmentTest(manager.ScenarioTest):
+
+ @classmethod
+ def skip_checks(cls):
+ super(BaseAttachmentTest, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
+
@classmethod
def setup_clients(cls):
super().setup_clients()
diff --git a/tempest/scenario/test_stamp_pattern.py b/tempest/scenario/test_stamp_pattern.py
index 82f0341..92dbffb 100644
--- a/tempest/scenario/test_stamp_pattern.py
+++ b/tempest/scenario/test_stamp_pattern.py
@@ -51,6 +51,8 @@
@classmethod
def skip_checks(cls):
super(TestStampPattern, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
if not CONF.volume_feature_enabled.snapshot:
raise cls.skipException("Cinder volume snapshots are disabled")
diff --git a/tempest/scenario/test_volume_backup_restore.py b/tempest/scenario/test_volume_backup_restore.py
index d0885cf..07ca38a 100644
--- a/tempest/scenario/test_volume_backup_restore.py
+++ b/tempest/scenario/test_volume_backup_restore.py
@@ -41,6 +41,8 @@
@classmethod
def skip_checks(cls):
super(TestVolumeBackupRestore, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
if not CONF.volume_feature_enabled.backup:
raise cls.skipException('Backup is not enable.')
diff --git a/tempest/scenario/test_volume_boot_pattern.py b/tempest/scenario/test_volume_boot_pattern.py
index 5c5033a..6ebee48 100644
--- a/tempest/scenario/test_volume_boot_pattern.py
+++ b/tempest/scenario/test_volume_boot_pattern.py
@@ -31,6 +31,12 @@
# breathing room to get through deletes in the time allotted.
TIMEOUT_SCALING_FACTOR = 2
+ @classmethod
+ def skip_checks(cls):
+ super(TestVolumeBootPattern, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
+
def _delete_server(self, server):
self.servers_client.delete_server(server['id'])
waiters.wait_for_server_termination(self.servers_client, server['id'])
diff --git a/tempest/scenario/test_volume_migrate_attached.py b/tempest/scenario/test_volume_migrate_attached.py
index 57d2a1a..5005346 100644
--- a/tempest/scenario/test_volume_migrate_attached.py
+++ b/tempest/scenario/test_volume_migrate_attached.py
@@ -48,6 +48,8 @@
@classmethod
def skip_checks(cls):
super(TestVolumeMigrateRetypeAttached, cls).skip_checks()
+ if not CONF.service_available.cinder:
+ raise cls.skipException("Cinder is not available")
if not CONF.volume_feature_enabled.multi_backend:
raise cls.skipException("Cinder multi-backend feature disabled")
diff --git a/tempest/tests/lib/services/compute/test_fixedIPs_client.py b/tempest/tests/lib/services/compute/test_fixedIPs_client.py
deleted file mode 100644
index 65bda45..0000000
--- a/tempest/tests/lib/services/compute/test_fixedIPs_client.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2015 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.lib.services.compute import fixed_ips_client
-from tempest.tests.lib import fake_auth_provider
-from tempest.tests.lib.services import base
-
-
-class TestFixedIPsClient(base.BaseServiceTest):
- FIXED_IP_INFO = {"fixed_ip": {"address": "10.0.0.1",
- "cidr": "10.11.12.0/24",
- "host": "localhost",
- "hostname": "OpenStack"}}
-
- def setUp(self):
- super(TestFixedIPsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.fixedIPsClient = (fixed_ips_client.
- FixedIPsClient
- (fake_auth, 'compute',
- 'regionOne'))
-
- def _test_show_fixed_ip(self, bytes_body=False):
- self.check_service_client_function(
- self.fixedIPsClient.show_fixed_ip,
- 'tempest.lib.common.rest_client.RestClient.get',
- self.FIXED_IP_INFO, bytes_body,
- status=200, fixed_ip='Identifier')
-
- def test_show_fixed_ip_with_str_body(self):
- self._test_show_fixed_ip()
-
- def test_show_fixed_ip_with_bytes_body(self):
- self._test_show_fixed_ip(True)
-
- def _test_reserve_fixed_ip(self, bytes_body=False):
- self.check_service_client_function(
- self.fixedIPsClient.reserve_fixed_ip,
- 'tempest.lib.common.rest_client.RestClient.post',
- {}, bytes_body,
- status=202, fixed_ip='Identifier')
-
- def test_reserve_fixed_ip_with_str_body(self):
- self._test_reserve_fixed_ip()
-
- def test_reserve_fixed_ip_with_bytes_body(self):
- self._test_reserve_fixed_ip(True)
diff --git a/tempest/tests/lib/services/compute/test_floating_ip_pools_client.py b/tempest/tests/lib/services/compute/test_floating_ip_pools_client.py
deleted file mode 100644
index 6278df4..0000000
--- a/tempest/tests/lib/services/compute/test_floating_ip_pools_client.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2015 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.lib.services.compute import floating_ip_pools_client
-from tempest.tests.lib import fake_auth_provider
-from tempest.tests.lib.services import base
-
-
-class TestFloatingIPPoolsClient(base.BaseServiceTest):
-
- FAKE_FLOATING_IP_POOLS = {
- "floating_ip_pools":
- [
- {"name": '\u3042'},
- {"name": '\u3044'}
- ]
- }
-
- def setUp(self):
- super(TestFloatingIPPoolsClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = floating_ip_pools_client.FloatingIPPoolsClient(
- fake_auth, 'compute', 'regionOne')
-
- def test_list_floating_ip_pools_with_str_body(self):
- self.check_service_client_function(
- self.client.list_floating_ip_pools,
- 'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_FLOATING_IP_POOLS)
-
- def test_list_floating_ip_pools_with_bytes_body(self):
- self.check_service_client_function(
- self.client.list_floating_ip_pools,
- 'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_FLOATING_IP_POOLS, to_utf=True)
diff --git a/tempest/tests/lib/services/compute/test_floating_ips_bulk_client.py b/tempest/tests/lib/services/compute/test_floating_ips_bulk_client.py
deleted file mode 100644
index ace76f8..0000000
--- a/tempest/tests/lib/services/compute/test_floating_ips_bulk_client.py
+++ /dev/null
@@ -1,88 +0,0 @@
-# Copyright 2015 NEC Corporation. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may
-# not use this file except in compliance with the License. You may obtain
-# a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations
-# under the License.
-
-from tempest.tests.lib import fake_auth_provider
-
-from tempest.lib.services.compute import floating_ips_bulk_client
-from tempest.tests.lib.services import base
-
-
-class TestFloatingIPsBulkClient(base.BaseServiceTest):
-
- FAKE_FIP_BULK_LIST = {"floating_ip_info": [{
- "address": "10.10.10.1",
- "instance_uuid": None,
- "fixed_ip": None,
- "interface": "eth0",
- "pool": "nova",
- "project_id": None
- },
- {
- "address": "10.10.10.2",
- "instance_uuid": None,
- "fixed_ip": None,
- "interface": "eth0",
- "pool": "nova",
- "project_id": None
- }]}
-
- def setUp(self):
- super(TestFloatingIPsBulkClient, self).setUp()
- fake_auth = fake_auth_provider.FakeAuthProvider()
- self.client = floating_ips_bulk_client.FloatingIPsBulkClient(
- fake_auth, 'compute', 'regionOne')
-
- def _test_list_floating_ips_bulk(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_floating_ips_bulk,
- 'tempest.lib.common.rest_client.RestClient.get',
- self.FAKE_FIP_BULK_LIST,
- to_utf=bytes_body)
-
- def _test_create_floating_ips_bulk(self, bytes_body=False):
- fake_fip_create_data = {"floating_ips_bulk_create": {
- "ip_range": "192.168.1.0/24", "pool": "nova", "interface": "eth0"}}
- self.check_service_client_function(
- self.client.create_floating_ips_bulk,
- 'tempest.lib.common.rest_client.RestClient.post',
- fake_fip_create_data,
- to_utf=bytes_body,
- ip_range="192.168.1.0/24", pool="nova", interface="eth0")
-
- def _test_delete_floating_ips_bulk(self, bytes_body=False):
- fake_fip_delete_data = {"floating_ips_bulk_delete": "192.168.1.0/24"}
- self.check_service_client_function(
- self.client.delete_floating_ips_bulk,
- 'tempest.lib.common.rest_client.RestClient.put',
- fake_fip_delete_data,
- to_utf=bytes_body,
- ip_range="192.168.1.0/24")
-
- def test_list_floating_ips_bulk_with_str_body(self):
- self._test_list_floating_ips_bulk()
-
- def test_list_floating_ips_bulk_with_bytes_body(self):
- self._test_list_floating_ips_bulk(True)
-
- def test_create_floating_ips_bulk_with_str_body(self):
- self._test_create_floating_ips_bulk()
-
- def test_create_floating_ips_bulk_with_bytes_body(self):
- self._test_create_floating_ips_bulk(True)
-
- def test_delete_floating_ips_bulk_with_str_body(self):
- self._test_delete_floating_ips_bulk()
-
- def test_delete_floating_ips_bulk_with_bytes_body(self):
- self._test_delete_floating_ips_bulk(True)
diff --git a/tempest/tests/lib/services/compute/test_servers_client.py b/tempest/tests/lib/services/compute/test_servers_client.py
index a82b255..8df82f7 100644
--- a/tempest/tests/lib/services/compute/test_servers_client.py
+++ b/tempest/tests/lib/services/compute/test_servers_client.py
@@ -789,21 +789,6 @@
length='fake-length'
)
- def test_list_virtual_interfaces_with_str_body(self):
- self._test_list_virtual_interfaces()
-
- def test_list_virtual_interfaces_with_bytes_body(self):
- self._test_list_virtual_interfaces(True)
-
- def _test_list_virtual_interfaces(self, bytes_body=False):
- self.check_service_client_function(
- self.client.list_virtual_interfaces,
- 'tempest.lib.common.rest_client.RestClient.get',
- {'virtual_interfaces': [self.FAKE_VIRTUAL_INTERFACES]},
- bytes_body,
- server_id=self.server_id
- )
-
def test_rescue_server_with_str_body(self):
self._test_rescue_server()
diff --git a/tempest/tests/lib/services/image/v2/test_image_tasks_client.py b/tempest/tests/lib/services/image/v2/test_image_tasks_client.py
new file mode 100644
index 0000000..6e3b3b5
--- /dev/null
+++ b/tempest/tests/lib/services/image/v2/test_image_tasks_client.py
@@ -0,0 +1,86 @@
+# Copyright 2023 Red Hat, Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+from tempest.lib.services.image.v2 import tasks_client
+from tempest.tests.lib import fake_auth_provider
+from tempest.tests.lib.services import base
+
+
+class TestImageTaskClient(base.BaseServiceTest):
+ def setUp(self):
+ super(TestImageTaskClient, self).setUp()
+ fake_auth = fake_auth_provider.FakeAuthProvider()
+ self.client = tasks_client.TaskClient(
+ fake_auth, 'image', 'regionOne')
+
+ def test_list_task(self):
+ fake_result = {
+
+ "first": "/v2/tasks",
+ "schema": "/v2/schemas/tasks",
+ "tasks": [
+ {
+ "id": "08b7e1c8-3821-4f54-b3b8-d6655d178cdf",
+ "owner": "fa6c8c1600f4444281658a23ee6da8e8",
+ "schema": "/v2/schemas/task",
+ "self": "/v2/tasks/08b7e1c8-3821-4f54-b3b8-d6655d178cdf",
+ "status": "processing",
+ "type": "import"
+ },
+ {
+ "id": "231c311d-3557-4e23-afc4-6d98af1419e7",
+ "owner": "fa6c8c1600f4444281658a23ee6da8e8",
+ "schema": "/v2/schemas/task",
+ "self": "/v2/tasks/231c311d-3557-4e23-afc4-6d98af1419e7",
+ "status": "processing",
+ "type": "import"
+ }
+ ]
+ }
+ self.check_service_client_function(
+ self.client.list_tasks,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ fake_result,
+ mock_args=['tasks'])
+
+ def test_create_task(self):
+ fake_result = {
+ "type": "import",
+ "input": {
+ "import_from":
+ "http://download.cirros-cloud.net/0.6.1/ \
+ cirros-0.6.1-x86_64-disk.img",
+ "import_from_format": "qcow2",
+ "image_properties": {
+ "disk_format": "qcow2",
+ "container_format": "bare"
+ }
+ }
+ }
+ self.check_service_client_function(
+ self.client.create_task,
+ 'tempest.lib.common.rest_client.RestClient.post',
+ fake_result,
+ status=201)
+
+ def test_show_task(self):
+ fake_result = {
+ "task_id": "08b7e1c8-3821-4f54-b3b8-d6655d178cdf"
+ }
+ self.check_service_client_function(
+ self.client.show_tasks,
+ 'tempest.lib.common.rest_client.RestClient.get',
+ fake_result,
+ status=200,
+ task_id="e485aab9-0907-4973-921c-bb6da8a8fcf8")
diff --git a/tools/generate-tempest-plugins-list.py b/tools/generate-tempest-plugins-list.py
index b96bbe4..0b6b342 100644
--- a/tools/generate-tempest-plugins-list.py
+++ b/tools/generate-tempest-plugins-list.py
@@ -77,6 +77,9 @@
'x/ranger-tempest-plugin'
'x/tap-as-a-service-tempest-plugin'
'x/trio2o'
+ # No changes are merging in this
+ # https://review.opendev.org/q/project:x%252Fnetworking-fortinet
+ 'x/networking-fortinet'
]
url = 'https://review.opendev.org/projects/'
diff --git a/zuul.d/integrated-gate.yaml b/zuul.d/integrated-gate.yaml
index 8ac0b42..2d4b8d9 100644
--- a/zuul.d/integrated-gate.yaml
+++ b/zuul.d/integrated-gate.yaml
@@ -88,6 +88,11 @@
required-projects:
- openstack/horizon
vars:
+ # NOTE(gmann): Default concurrency is higher (number of cpu -2) which
+ # end up 6 in upstream CI. Higher concurrency means high parallel
+ # requests to services and can cause more oom issues. To avoid the
+ # oom issue, setting the concurrency to 4 in this job.
+ tempest_concurrency: 4
tox_envlist: integrated-full
devstack_localrc:
USE_PYTHON3: true
@@ -143,6 +148,11 @@
subset of 'tempest-full-py3' job and run Nova, Neutron, Cinder (except backup tests)
and Glance related tests. This is meant to be run on Nova gate only.
vars:
+ # NOTE(gmann): Default concurrency is higher (number of cpu -2) which
+ # end up 6 in upstream CI. Higher concurrency means high parallel
+ # requests to services and can cause more oom issues. To avoid the
+ # oom issue, setting the concurrency to 4 in this job.
+ tempest_concurrency: 4
tox_envlist: integrated-compute
tempest_exclude_regex: ""
devstack_localrc:
@@ -181,6 +191,11 @@
subset of 'tempest-full-py3' job and run Nova and Neutron
related tests. This is meant to be run on Placement gate only.
vars:
+ # NOTE(gmann): Default concurrency is higher (number of cpu -2) which
+ # end up 6 in upstream CI. Higher concurrency means high parallel
+ # requests to services and can cause more oom issues. To avoid the
+ # oom issue, setting the concurrency to 4 in this job.
+ tempest_concurrency: 4
tox_envlist: integrated-placement
devstack_localrc:
USE_PYTHON3: true
@@ -246,6 +261,11 @@
# This job runs on ubuntu Jammy and after stable/zed.
branches: ^(?!stable/(pike|queens|rocky|stein|train|ussuri|victoria|wallaby|xena|yoga|zed)).*$
vars:
+ # NOTE(gmann): Default concurrency is higher (number of cpu -2) which
+ # end up 6 in upstream CI. Higher concurrency means high parallel
+ # requests to services and can cause more oom issues. To avoid the
+ # oom issue, setting the concurrency to 4 in this job.
+ tempest_concurrency: 4
devstack_localrc:
USE_PYTHON3: true
devstack_plugins: